<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>z00m__in.log</title>
        <link>https://velog.io/</link>
        <description>우당탕탕 기록지</description>
        <lastBuildDate>Mon, 25 Dec 2023 11:05:10 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. z00m__in.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/z00m__in" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[실전머신러닝] 셋째마당: 트리 모델을 이용한 지도 학습]]></title>
            <link>https://velog.io/@z00m__in/%EC%8B%A4%EC%A0%84%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D-%EC%85%8B%EC%A7%B8%EB%A7%88%EB%8B%B9-%ED%8A%B8%EB%A6%AC-%EB%AA%A8%EB%8D%B8%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EC%A7%80%EB%8F%84-%ED%95%99%EC%8A%B5</link>
            <guid>https://velog.io/@z00m__in/%EC%8B%A4%EC%A0%84%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D-%EC%85%8B%EC%A7%B8%EB%A7%88%EB%8B%B9-%ED%8A%B8%EB%A6%AC-%EB%AA%A8%EB%8D%B8%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EC%A7%80%EB%8F%84-%ED%95%99%EC%8A%B5</guid>
            <pubDate>Mon, 25 Dec 2023 11:05:10 GMT</pubDate>
            <description><![CDATA[<p>셋째마당 : 트리 모델을 이용한 지도 학습</p>
<ul>
<li>각 트리 모델 별로 특성을 구분하며 기억할 것</li>
<li>성능 또한 우수하고 머신러닝 전반에 응용할 수 있는 다양한 영역을 학습 할 수 있는 장점이 있어 실무적으로도 적용이 잘 되는 모델임.</li>
</ul>
<h1 id="chap-06-결정-트리-모델">CHAP 06. 결정 트리 모델</h1>
<h2 id="사전-지식">사전 지식</h2>
<h3 id="그리디-알고리즘">그리디 알고리즘</h3>
<ul>
<li>각 단계에서의 최선의 결정을 반복하며 얻게된 결과를 최선의 해답으로 가정</li>
<li>전역 탐색 알고리즘 vs 지역 탐색 알고리즘 중 후자<ul>
<li>전역-“완전탐색” : 모든 경우의 수에 대한 무차별 탐색</li>
<li>전역-“컨벡스 최적화” : 컨벡스 함수에 대한 경사 하강법 (극점이 1개)</li>
</ul>
</li>
<li>항상 전역 최적값을 보장할 수는 없지만, 최선의 해를 도출하는 알고리즘</li>
</ul>
<h3 id="트리-자료-구조">트리 자료 구조</h3>
<p>: 각 노드가 나뭇가지처럼 연결된 계층 자료 구조 (재귀적인 형태)</p>
<p>핵심 용어 &gt; 루트, 부모, 자식, 형제, 리프, 내부, 깊이, 오더</p>
<ul>
<li>트리 자료 구조 구현<ul>
<li>max depth에 대해 최대 노드 개수는 $2^{maxdepth+1}-1$이므로,
리스트 변수 tree에 대해 tree[ $2^{maxdepth+1}-1$ ] 까지 노드 부여</li>
</ul>
</li>
</ul>
<h2 id="결정-트리-모델이란">결정 트리 모델이란?</h2>
<h3 id="개념">개념</h3>
<ul>
<li>입력과 출력값의 관계를 트리 자료 구조 모양으로 모델링하는 지도 학습 기법</li>
<li>각 샘플은 노드에서 피처에 대한 질문을 받으며, 질문의 대답에 해당하는 간선을 거쳐 다음 노드에 도착하기를 반복. 리프 노드에 도달하면 클래스 결정되는 구조.</li>
<li>즉, 이진 질문을 여러 차례 반복하다 마지막 단계에서 해당 피처에 대한 출력값을 맞추는 문제를 학습하는 형태</li>
</ul>
<h3 id="특징">특징</h3>
<ul>
<li>트리가 깊어짐에 따라 학습 데이터에만 적합하도록 과도하게 불규칙한 패턴을 학습하며 과적합에 취약해질 수 있음</li>
<li>편향은 낮으며 분산은 높음</li>
<li>분류 문제를 푸는 <strong>“분류 트리”</strong>와 회귀 문제를 푸는 “회귀 트리”로 구분됨</li>
<li>모델 구조가 직관적이고 결과를 해석하기 쉬움</li>
<li>이후 구조인 랜덤 포레스트나 gbt 모델과도 연결됨</li>
</ul>
<h2 id="결정-트리-모델-구현하기">결정 트리 모델 구현하기</h2>
<h3 id="결정-트리-분류-모델의-이론">결정 트리 분류 모델의 이론</h3>
<ul>
<li>그리디 알고리즘 중 TIDT 전략을 사용<ul>
<li>각 루트노드에서 분기 규칙에 따라 자식 노드로 분기하기를 노드의 정지 규칙에 도달할 때까지 반복하는 형태</li>
</ul>
</li>
<li>정지규칙의 예시
: 한 가지 클래스로만 이루어져 학습이 불필요 / 남은 피처에 대한 출력값들이 모두 동일해 분할이 무의미 / 과도한 분할로 인한 과적합</li>
<li>분기 규칙
: 분할 이후 각 노드에서 종속 변수의 동질성이 최대화 되도록. → 동질성에 대한 정의는 분기 기준의 정의에 따름</li>
<li>분기 기준 : 지니 불순도를 최소화하거나 정보 이득을 최대화 하는 분기법 중 하나로,<ul>
<li>지니 불순도를 최소화<ul>
<li>지니 불순도 : 클래스가 잘못 분류될 확률의 가중 평균
개념적 ⇒ 클래스가 잘못 분류되지 않도록 하는 분기법</li>
</ul>
</li>
<li><strong>정보 이득</strong>을 최대화<ul>
<li>수학적으로,
분할 전의 엔트로피에서 분할 후의 엔트로피를 뺀 것</li>
<li>개념적으로,
모호성이 줄어들고 정보가 뚜렷해지도록 하는 분기법</li>
<li>실제로 트리를 생성할 때는,
남은 피처에 대해 분할할 시 발생할 정보 이득을 계산하고
정보 이득이 그 중 최대인 피처를 이용해 노드를 분할</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="패키지로-표현하기">패키지로 표현하기</h2>
<p>sklearn.tree.DecisionTreeClassifier 클래스 ⇒ CART 알고리즘을 구현</p>
<h2 id="결정-트리-모델-보충-수업">결정 트리 모델 보충 수업</h2>
<h3 id="회귀-트리">회귀 트리</h3>
<ul>
<li><p>최종적으로는 주어진 테스트 샘플 피처에 대한 목표 변수의 기댓값을 계산해 반환하는 형태</p>
</li>
<li><p>분기에 따른 각각 두 자식 노드에서
평균제곱오차(msa), 평균절대오차(mae) 등 연속변수에서의 흩어짐 정도를 계산하고
이의 가중합을 구한 결과값을 최소화하는 로직</p>
</li>
<li><p>회귀 트리에서의 다양한 분기 기준</p>
<ul>
<li><p>MSE 기준에서의 비용함수</p>
</li>
<li><p>푸아송 편차 절반 기준에서의 비용함수</p>
</li>
<li><p>MAE 기준에서의 비용함수</p>
</li>
</ul>
</li>
</ul>
<h3 id="그리드-서치">그리드 서치</h3>
<ul>
<li>가장 직관적인 하이퍼파라미터 튜닝 기법<ul>
<li>하이퍼파라미터 튜닝
: 데이터셋을 학습/검증/테스트 데이터로 분할한 뒤
학습, 검증 데이터의 쌍을 이용해 여러 하이퍼파라미터 조합을 시도하며
검증 데이터셋을 기준으로 가장 좋은 성능을 산출하는 하이퍼파라미터를
최종 하이퍼파라미터로 선택
= 즉, 최적의 하이퍼 파라미터를 조합을 찾는 방법</li>
</ul>
</li>
<li>가능한 모든 후보값의 조합을 탐색하며 그 중 최고의 성능을 산출하는 하이퍼파라미터 조합을 선택하는 방식</li>
</ul>
<h3 id="피처-중요도">피처 중요도</h3>
<p>: 피처별로 학습 모델 구축에 영향을 끼친 정도</p>
<h1 id="chap07-랜덤-포레스트-모델">CHAP07. 랜덤 포레스트 모델</h1>
<h2 id="사전-지식-1">사전 지식</h2>
<h3 id="부트스트래핑">부트스트래핑</h3>
<ul>
<li>주어진 데이터가 모집단 그 자체라 가정하고 이를 이용한 다양한 시뮬레이션 샘플을 만들어내는 기법.</li>
<li>모집단을 가정하므로, 데이터를 구성할 때는 복원 추출을 사용.
→ 복원 추출이란 꺼냈던 1개 표본(원소)을 다시 넣는 것을 의미하고, 결국 n&#39;개로 이루어진 표본을 만든다는 뜻</li>
<li>통계 검정 중 신뢰 구간을 추산할 때 자주 사용</li>
<li>비교되는 “K-fold  교차검증법”<ul>
<li>모집단을 K개의 파티션으로 나누고, k-1개는 학습데이터로, 1개는 검증 데이터로.</li>
</ul>
</li>
</ul>
<h3 id="앙상블-학습-기법">앙상블 학습 기법</h3>
<p>: 여러 개의 베이스 학습기를 준비해 학습을 수행하고, 그 학습 결과를 종합해 최종 결과를 예측하는 기법</p>
<ul>
<li>일반화 가능성이 높고 강건성이 있음</li>
<li>사용되는 대표적인 종류는 “배깅”과 “부스팅”</li>
<li>배깅<ul>
<li>데이터셋으로 수많은 부트스트랩 샘플을 생성해 각각 다수의 학습기를 만들어 <strong>병렬</strong>로 학습하고, 얻은 예측값들에 최종 연산을 해 최종 예측값을 산출</li>
<li>베이스 학습기가 낮은 편향과 높은 분산을 보일 때 유용 (bcz 분산이 감소하는 효과)</li>
<li>최대 깊이가 큰 결정트리, 다층 퍼셉트론(MLP), 서포트 벡터 머신(SVM), (KNN) 등의 베이스 학습기가 있음</li>
<li>가장 대표적인 건 결정트리를 베이스 학습기로 구축한 “랜덤 포레스트”</li>
</ul>
</li>
<li>부스팅<ul>
<li>여러 베이스 학습기를 만들어 이들을 순차적으로 학습하는 <strong>직렬</strong> 앙상블 모델.</li>
<li><strong>각 학습기의 취약점을, 다음 베이스 학습기로 넘겨서 편향을 줄이는 것이 목표</strong></li>
<li>분산이 낮고 편향이 상대적으로 높은 베이스 학습기에 유용</li>
<li>최대 깊이가 낮은 결정 트리, 로지스틱 회귀 모델, K가 큰 KNN 모델 등의 베이스 학습기</li>
<li>가장 대적인 건 에이다부스, 그레이디언트 부스팅 트리 등</li>
</ul>
</li>
</ul>
<h2 id="랜덤-포레스트-모델이란">랜덤 포레스트 모델이란?</h2>
<h3 id="개념-1">개념</h3>
<ul>
<li>여러 개의 결정 트리를 학습하고 그 결과를 종합하는 앙상블 학습 모델 중 하나</li>
<li>데이터 셋으로 부트 스트랩 샘플을 생성해 병렬로 학습하는 “배깅” 기법 사용</li>
<li>주로 분류, 회귀의 지도 학습에 사용되며 비지도 학습에도 적용 가능<ul>
<li>분류 &gt; 트리를 생성하는 과정에서, 예측 클래스 레이블을 투표한 후 최다 득표 레이블을 선택</li>
<li>회귀 &gt; ‘각 결정 트리 예측값의 평균’ 을 예측값으로 함</li>
</ul>
</li>
</ul>
<h3 id="특징-1">특징</h3>
<ul>
<li>(앙상블) 일반화 가능성은 우수하나 해석력이 떨어짐</li>
<li>배깅을 사용해 모델의 편향을 증가시키지 않은 채로 분산을 감소시킴</li>
<li>결정 트리의 과적합 문제를 줄일 수 있음</li>
<li>일반적으로 결정 트리보다는 우수하고 GBT 보다는 떨어지는 성능을 가짐</li>
<li>예측 결과에 대한 해석이 어려운 블랙 박스 모델</li>
</ul>
<h2 id="랜덤-포레스트-모델-구현하기">랜덤 포레스트 모델 구현하기</h2>
<h3 id="랜덤-포레스트-모델의-기본-이론">랜덤 포레스트 모델의 기본 이론</h3>
<ul>
<li>학습 데이터를 다르게 샘플링 해 각각 깊은 결정 트리를 학습한 뒤,
그 결과를 최종적으로 종합해 출력값을 계산하므로
모델의 해석력은 줄지만 일반화 가능성은 결정 트리에 비해 매우 높음</li>
<li>학습 알고리즘<ul>
<li>트리의 병렬 학습<ul>
<li>트리 개수는 일반적으로 수백에서 수천 개로 설정하며,</li>
<li>교차검증법 등의 기법으로 최적값을 찾음</li>
</ul>
</li>
<li>피처 배깅<ul>
<li>피처를 랜덤 샘플링하는 것</li>
<li>랜덤 포레스트에서 각각의 분기 규칙을 계산할 때 전체 피처의 무작위 부분 집합을 사용하는 것</li>
<li>부트스트랩 샘플을 사용할 때의 발생할 수 있는 트리의 상관관계를 줄여줌</li>
</ul>
</li>
</ul>
</li>
<li>시간 복잡도</li>
<li>피처 배깅</li>
</ul>
<h2 id="패키지로-표현하기-1">패키지로 표현하기</h2>
<ul>
<li>sklearn.ensemble.RandomForestClassifier 클래스 사용</li>
<li>sklearn.tree.DecisionTreeClassifier 클래스의 하이퍼파라미터를 포함</li>
</ul>
<h2 id="랜덤-포레스트-모델-보충-수업">랜덤 포레스트 모델 보충 수업</h2>
<h3 id="랜덤-포레스트-회귀-모델">랜덤 포레스트 회귀 모델</h3>
<ul>
<li>sklearn.ensemble.RandomForestRegressor 클래스 사용
→ DecisionTreeRegressor의 확장</li>
</ul>
<h3 id="oob-점수">OOB 점수</h3>
<ul>
<li>복원추출을 통해 선택되지 않고 버려지는 데이터들을 이용해,
모델 성능을 검증하는 작업을 트리별로 반복하며
별도의 테스트 데이터셋 없이 모델의 성능 파악한 점수</li>
</ul>
<h3 id="extratrees">ExtraTrees</h3>
<ul>
<li>랜덤 포레스트처럼 개별 결정 트리의 앙상블을 형성하는 형태이나,
각 트리가 부트스트랩 샘플이 아닌 전체 샘플을 이용해 학습하며,
하향식 방식의 분기를 학습하는 과정이 랜덤화 된 모델</li>
<li>대상 피처의 동질성을 모두 비교한 후 지역 최적값을 계산하는 방식으로 분기 결정</li>
</ul>
<h3 id="피처-중요도-1">피처 중요도</h3>
<ul>
<li>피처별로 목표 변수의 예측에 기여한 중요도를 계산한 값으로, 여러 정의가 존재</li>
<li>MDI 기반<ul>
<li>트리 기반 모델에서 불순도를 이용하여 정의하는 피처 중요도 기법</li>
<li>자식 노드로 분기될 때 동질성은 늘어나게 되는데,
이 때의 동질성의 증가 크기에 따라 피처 중요도가 정의됨
⇒ 동질성을 크게 증가시키는 피처가 중요한 피처</li>
<li>학습 데이터셋 기준 중요도 산출 방법</li>
</ul>
</li>
<li>퍼뮤테이션 기반<ul>
<li>모델에 검증 데이터를 투입해 성능을 먼저 계산하고,
특정 피처의 값만 무작위로 바꾼 뒤 다시 성능을 계산한 뒤
두 성능의 차이가 해당 피처의 중요도를 나타내는 것</li>
<li>검증 데이터셋 기준 중요도 산출 방법</li>
</ul>
</li>
</ul>
<h1 id="chap08-그레이디언트-부스팅-트리gbt-모델">CHAP08. 그레이디언트 부스팅 트리(GBT) 모델</h1>
<h2 id="사전-지식-2">사전 지식</h2>
<p>부스팅 기법 중 GBT는,
에이다부스트 이후의 모델이면서
XGBoost와 LightGBM보다는 이전 모델</p>
<h3 id="에이다부스트-모델-이론">에이다부스트 모델 이론</h3>
<ul>
<li>앞쪽 모델에서 <strong>틀린 샘플의 추출 확률을 높임</strong>으로써,
앞 단계의 모델이 잘 풀지 못하는 어려운 케이스에 집중한다는 차이점</li>
<li>한 모델이 끝난 후에 그 모델의 성능을 바탕으로 다음 모델을 구축해야 하므로 병렬 학습이 불가능.</li>
<li>매 단계의 학습 트리는 매우 약한 학습기로 구성됨</li>
<li>sklearn.ensemble 모듈의 AdaBoostClassifier, AdaBoostRegressor 클래스로 각각 분류 모델과 회귀 모델 구현</li>
<li>에이다부스트 알고리즘</li>
</ul>
<h2 id="그레이디언트-부스팅-트리-모델이란">그레이디언트 부스팅 트리 모델이란?</h2>
<h3 id="개념-2">개념</h3>
<ul>
<li>부스팅 기법 중 하나인 GBM(Gradient Boosting Machine)을 결정트리에 적용한 앙상블 모델</li>
<li>회귀와 분류 문제 모두에 적용할 수 있으며 높은 성능을 보임</li>
<li>단계별로 샘플의 가중치를 조절하는 에이다부스트와 달리,</li>
<li><em>이전 단계에서 학습하지 못한 잔차를 새로운 목표 변수*</em>로 두고 학습<ul>
<li>잔차 : 적합선과 샘플 사이의 오차</li>
</ul>
</li>
</ul>
<h3 id="gbt-모델의-아이디어">GBT 모델의 아이디어</h3>
<ul>
<li>첫 번째 : $y \leftarrow h_1(x)$</li>
<li>두 번째 : $y-h_1(x) \leftarrow h_2(x)$</li>
<li>세 번째 : $y-h_1(x)-h_2(x) \leftarrow h_3(x)$</li>
<li>M 번째 : $y-\sum_{m=1}^{M-1}h_m(x) \leftarrow h_M(x)$</li>
<li>최종 : $\hat{y}=\sum_{m=1}^{M}h_m(x)$</li>
</ul>
<h2 id="그레이디언트-부스팅-트리-모델-구현하기">그레이디언트 부스팅 트리 모델 구현하기</h2>
<h3 id="gbt-의-이론">GBT 의 이론</h3>
<ul>
<li>GBT 회귀 모델<ul>
<li>GBT는 기본적으로 직렬로 학습하는 가산 모델</li>
<li>GBT가 연속적인 손실함수를 최소화하는 방식으로 업데이트</li>
<li>다양한 형태의 손실 함수<ul>
<li>제곱 오차 손실</li>
</ul>
</li>
</ul>
</li>
</ul>
<pre><code>    - 절대 오차 손실


    - Huber 손실


    - 분위수 손실</code></pre><ul>
<li>GBT 분류 모델<ul>
<li>예측값을 클래스 또는 클래스의 확률값으로 변환하는 과정을 추가로 진행</li>
<li>어떤 손실 함수를 선택하느냐에 따라 변환 방법이 달라짐</li>
</ul>
</li>
</ul>
<h3 id="부스팅-트리-회귀-모델-구현하기">부스팅 트리 회귀 모델 구현하기</h3>
<h2 id="패키지로-표현하기-2">패키지로 표현하기</h2>
<ul>
<li>sklearn.ensemble 모듈의 GradientBoostingClassifier, GradientBoostingRegressor 클래스로 각각 GBT 분류 모델과 GBT 회귀 모델을 구현</li>
<li>랜덤포레스트에서는 분류 모델이 결정트리Classifier, 회귀 모델이 Regressor클래스 기반으로 구현되었지만</li>
<li>GBT 분류와 회귀는 모두 DecissionTreeRegressor 클래스를 기반으로 함
⇒ GBT 회귀 모델이 가장 기본적인 구현법</li>
</ul>
<h2 id="그레이디언트-부스팅-트리-모델-보충-수업">그레이디언트 부스팅 트리 모델 보충 수업</h2>
<h3 id="설명-가능-인공지능xai">설명 가능 인공지능(XAI)</h3>
<ul>
<li>실제 실무에서는 해석력이 중요하기 때문에, 같은 성능이라면 해석력이 높은 화이트 박스 모델을 선호하는 경향</li>
<li>성능과 해석력을 모두 높이고자 제안된 XAI
⇒ 이미 학습한 모델을 사후에 분석하여 예측값 계산 근거를 제공하는 메커니즘</li>
</ul>
<h3 id="gbt-모델-이후의-부스팅-기법">GBT 모델 이후의 부스팅 기법</h3>
<ul>
<li>XGBoost<ul>
<li>GBT에 병렬처리, 하드웨어 최적화, 과적합 규제 패널티 등의 여러 개념을 도입해 최적화한 모델</li>
<li>한 결정 트리를 학습할 때,
데이터셋을 수많은 서브데이터의 구획으로 분할한 뒤,
그 서브데이터 내에서의 최적값을 각 병렬환경에서 찾는 방식</li>
<li>근사법이기 때문에 편향성은 다소 증가하되 시간 복잡도는 낮아짐</li>
</ul>
</li>
<li>LightGBM<ul>
<li>XGBoost의 장점은 계승하고 단점은 보완하는 방식으로 개발</li>
<li>GOSS, EFB 등의 방식의 사용으로, 학습에 걸리는 시간과 메모리 사용량이 줄었으며 다양한 기능이 추가로 구현된 가벼운 GBT 모델을 제공</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[실전머신러닝] 둘째마당: 선형 모델을 이용한 지도 학습]]></title>
            <link>https://velog.io/@z00m__in/%EC%8B%A4%EC%A0%84%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D-%EB%91%98%EC%A7%B8%EB%A7%88%EB%8B%B9-%EC%84%A0%ED%98%95-%EB%AA%A8%EB%8D%B8%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EC%A7%80%EB%8F%84-%ED%95%99%EC%8A%B5</link>
            <guid>https://velog.io/@z00m__in/%EC%8B%A4%EC%A0%84%EB%A8%B8%EC%8B%A0%EB%9F%AC%EB%8B%9D-%EB%91%98%EC%A7%B8%EB%A7%88%EB%8B%B9-%EC%84%A0%ED%98%95-%EB%AA%A8%EB%8D%B8%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EC%A7%80%EB%8F%84-%ED%95%99%EC%8A%B5</guid>
            <pubDate>Sun, 10 Dec 2023 12:28:41 GMT</pubDate>
            <description><![CDATA[<h1 id="chap02-최소-제곱법-모델">CHAP02. 최소 제곱법 모델</h1>
<h2 id="ols의-정의">OLS의 정의</h2>
<p>: 피처행렬 X가 주어졌을 때, 비용함수가 MSE(평균제곱오차)인 모델
⇒ |예측값-목푯값|이 최소이도록 예측값을 만드는 파라미터 w 찾는 것</p>
<h2 id="정규-방정식으로-ols-구현">정규 방정식으로 OLS 구현</h2>
<p>: OLS를 푸는 가장 기본적이고 직관적인 방법
→ 연립방정식에 가까운 형태로,
→ 역행렬 계산에서 과다한 메모리 사용 문제 &amp; 행렬이 특이행렬에 가까울 수록 수치적인 불안전성
⇒ 정규방정식보다 SVD 사용 </p>
<h2 id="특잇값-분해를-이용한-ols-구현">특잇값 분해를 이용한 OLS 구현</h2>
<p>: X = U<em>Σ</em>Vt의 세 행렬의 곱으로 분해하는 것
(U, V는 직교행렬, Σ는 대각행렬</p>
<h2 id="tsvd-ols를-이용한-ols-구현">TSVD-OLS를 이용한 OLS 구현</h2>
<p>: k 개의 가장 큰 특이값만 선택한 뒤 SVD
파라미터 크기를 규제함으로서 피처 행렬을 안정적인 형태로 근사하기 위함
⇒ 최적해가 아닌 편향된 해이나, 불안정한 피처 행렬에도 강건한 성질</p>
<h2 id="패키지로-표현">패키지로 표현</h2>
<p>sklearn.linear_model.LinearRegression 클래스 사용하며,
해당 패키지는 OLS 기반.</p>
<h1 id="chap-03-로지스틱-회귀-모델">CHAP 03. 로지스틱 회귀 모델</h1>
<h2 id="사전-지식">사전 지식</h2>
<ul>
<li>경사 하강법
: 지역 혹은 전역 최솟값을 구하는 수학적 최적화를 수행하는 방법
: 경사의 역방향으로 입력값을 이동하며 목푯값을 달성<ul>
<li>최대하강법 : iter마다 grad 구해서 역방향으로 상수배만큼 이동</li>
<li>뉴턴법, BFGS 등…</li>
</ul>
</li>
<li>컨벡스 함수 : 지역최솟값이 전역최솟값이 되는 함수<h2 id="로지스틱-회귀-모델이란">로지스틱 회귀 모델이란?</h2>
$$
log(p(y_i|x_i, w)/1-p(y_i|x_i, w))
$$
: 분류 문제를 해결하는 가장 기본적인 ML 모델<h2 id="로지스틱-회귀-모델-구현하기">로지스틱 회귀 모델 구현하기</h2>
</li>
<li>이진 목푯값 y에 대해 1일 확률 p(y)과 x사이 관계를 모델링</li>
<li>비용함수 또한 컨벡스</li>
<li>단변수 로지스틱 회귀 모델
→ 비용함수의 편미분값을 구한 뒤 경사 하강법 적용해 최적화 구할 수 있음</li>
<li>뉴턴법 이용한 다중 로지스틱 회귀 모델
→ iter 폭이 너무 커 발산할 수 있음<h2 id="패키지로-표현하기">패키지로 표현하기</h2>
sklearn.linear_model.LogisticRegression 클래스 사용.
⇒ 이진, 다중 클래스 분류 뿐만 아니라 L1, L2, 엘라스틱 넷 규제 적용 가능</li>
</ul>
<h1 id="chap-04-라쏘-모델">CHAP 04. 라쏘 모델</h1>
<h2 id="사전-지식-1">사전 지식</h2>
<ul>
<li>피처 선택법
: 전체 피처가 아닌 일부 피처를 정형화된 방법을 통해 예측 모델에서 제외하는 것
(sklearn.feature_selection 모듈 사용)<ul>
<li>필터 기반 (sklearn.feature_selection.SelectKBest)
: 단일 피처 대상으로, 설정한 기준을 만족하는 피처만 모델에 포함.
⇒ 목표변수와 대상피처가 수치형/범주형인지에 따라 선택법의 종류 달라짐</li>
<li>래퍼 기반 (sklearn.feature_selection.RFE)
: 적절한 필처 집합을 그리디 알고리즘을 이용해 찾는 방법
⇒ iter마다 피처를 추가하는 전진 선택법과 줄여가는 후진 소거법이 있음.
⇒ 정지 조건 : 피처의 갯수 / 성능값의 변화량 의 두가지 방법.</li>
<li>임베디드 기반
: 모델링 결과와 함께 피처 선택을 같이 진행.</li>
</ul>
</li>
<li>하방미분
: 절댓값 함수를 미분할 때 사용하는 개념
→ 다변량 데이터셋에서는 닫힌 형태의 해를 가질 수 없어, 좌표 하강법을 함께 적용함
⇒ 한 피처에서만 업데이트가 일어나며 나머지 피처는 상수로 고정<h2 id="라쏘-모델이란">라쏘 모델이란?</h2>
: 모델에 “피처 선택법”을 적용해 과적합 현상을 방지한 모델</li>
</ul>
<p>$$
J_L(w) = ||y-Xw||^2_2/2n + α||w||_1
$$</p>
<p>⇒ 수학적으로는 OLS  비용함수에 L1 규제항을 더한 형태
⇒ α값이 커질수록 피처 계수가 0으로 감쇄</p>
<h2 id="라쏘-모델-구현하기">라쏘 모델 구현하기</h2>
<ul>
<li>하방미분과 좌표 하강법으로 최적화.</li>
<li>라쏘모델 또한 컨벡스 함수</li>
<li>α값이 커집에 따라 점점 많은 파라미터가 0으로 감쇄해ㅏ므로,
적당한 α를 선택한 후 감쇄되는 파라미터는 영향이 적다 가정하고 배제<h2 id="패키지로-표현하기-1">패키지로 표현하기</h2>
sklearn.linear_model.Lasso 클래스에서 좌표 하강법을 통해 최적화</li>
<li>sklearn.linear_model.LassoLars 클래스를 해용하면 좌표 하강법이 아닌 lars 모델을 이용한 최적화</li>
</ul>
<h1 id="chap-05-릿지-회귀-모델">CHAP 05. 릿지 회귀 모델</h1>
<h2 id="사전-지식-2">사전 지식</h2>
<ul>
<li>BFGS 알고리즘 : 비제약 비선형 최적화 문제 푸는 iter 기반 기법
→ 2계 도함수인 헤시안 행렬과 그 역행렬을 사용해 파라미터 업데이트
⇒ scipy.optimize.minimize() 함수</li>
<li>L-BFGS 알고리즘: BFGS에서 제한된 메모리만 사용하도록 변형</li>
<li>L-BFGS-B 알고리즘: L-BFGS를 확장
⇒ sklearn에서 solver 하이퍼 파라미터 값을 lbfgs로 언급해 알고리즘 호출</li>
<li>SAG알고리즘: 특정 조건 만족하는 여러 컨벡스 함수의 유한 합을 최적화
:: BFGS는 작은 데이터셋. SAG는 큰 데이터에서 사용
→ 피처 스케일의 전처리를 먼저 수행해야 함.
⇒ sklearn패키지의 solver 하이퍼파라미터의 값을 sag으로 설정해 호출</li>
<li>SAGA알고리즘: SAG에서 편향을없애고 보완한 변형 알고리즘
⇒ sklearn패키지의 solver 하이퍼파라미터의 값을 saga로 설정해 호출<h2 id="릿지-회귀-모델이란">릿지 회귀 모델이란?</h2>
L2 규제 페널티를 적용하는 모델
⇒ L2 규제항은 미분 가능하므로 최적화 방법은 OLS와 유사
⇒ 규제의 의미는 라쏘 모델과 유사
→ 라쏘에 비해 파라미터가 점진적으로 감쇄하는 경향.</li>
<li>OLS에 비해 분산은 줄지만 편향성은 증가하는 효과</li>
<li>OLS는 샘플 개수가 적을 때 학습한 모델 파라미터의 변동성에 큰 영향</li>
<li>릿지는 규제를 통해 파라미터의 크기를 감쇄시켜 변동성을 줄임</li>
<li>데이터의 선형성이 매우 높다면 릿지는 OLS보다 성능이 떨어짐.<h2 id="패키지로-표현하기-2">패키지로 표현하기</h2>
sklearn.linear_model.Ridge 클래스로 구현.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[🗺️ 리액트 네이티브와 카카오 지도 API 연동하기 : 안드로이드]]></title>
            <link>https://velog.io/@z00m__in/%EB%A6%AC%EC%95%A1%ED%8A%B8-%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8C%EC%99%80-%EC%B9%B4%EC%B9%B4%EC%98%A4-%EC%A7%80%EB%8F%84-API-%EC%97%B0%EB%8F%99%ED%95%98%EA%B8%B0-%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C</link>
            <guid>https://velog.io/@z00m__in/%EB%A6%AC%EC%95%A1%ED%8A%B8-%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8C%EC%99%80-%EC%B9%B4%EC%B9%B4%EC%98%A4-%EC%A7%80%EB%8F%84-API-%EC%97%B0%EB%8F%99%ED%95%98%EA%B8%B0-%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C</guid>
            <pubDate>Tue, 16 May 2023 14:55:43 GMT</pubDate>
            <description><![CDATA[<h1 id="시작하며">시작하며</h1>
<h2 id="시작하기-전">시작하기 전</h2>
<p>카카오 지도 API 사용 시 안드로이드 스튜디오 AVD 에뮬레이터 실행이 안된다...😭
즉, 가상기기가 아닌 실제 안드로이드 디바이스를 연결해야만 한다.
그러니 혹시 이 포스트를 참고하며 카카오 지도 API 연동을 시도하실 분들이 계시다면,
실제 기기를 먼저 준비해주시길 추천드린다.</p>
<h2 id="프로젝트-개요">프로젝트 개요</h2>
<p>개발 툴은 VS Code와 Android Studio.
React Native를 이용해 안드로이드 앱을 개발하는 프로젝트이다.</p>
<h2 id="카카오지도-api">카카오지도 API</h2>
<p>현재 진행하고 있는 프로젝트에서 지도를 load 하고, 주소를 검색하고 선택한 점포에 대해 위도와 경도를 끌어와야 하는 기능이 필요했다.
그래서 지도 API를 연동하기로 했다.
이 API를 연동하게 되면 나의 프로젝트 안에 카카오 지도가 구현되는 것이다.
처음 연결하는 것이다 보니 시간이 오래 소요됐는데...
삽질하게 됐던 과정들은 모두 가지치기 하고 결과론적으로 성공적이었던 내용만 담아보려 한다.</p>
<h1 id="1-애플리케이션-등록">1. 애플리케이션 등록</h1>
<h2 id="1-카카오-developers에서-애플리케이션-추가">1) 카카오 developers에서 애플리케이션 추가</h2>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/37a689de-e18d-4462-8a54-1a08782bc2af/image.png" alt=""></p>
<p><a href="https://developers.kakao.com/">카카오 개발자 사이트</a>에서 로그인을 한 뒤 상단의 &#39;내 애플리케이션&#39;에서 카카오 API를 연동할 프로젝트를 추가해보겠다.</p>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/5f9e6979-b142-431a-b976-7cb046940f52/image.png" alt="">
&#39;내 애플리케이션&#39; 을 누르면 위와 같은 버튼이 나온다.
애플리케이션 추가하기 를 누른 다음,</p>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/bc9bdb4c-994e-40cd-9a4c-ff743ff0eb78/image.png" alt=""></p>
<p>위 내용을 채워준 뒤 저장을 하면 된다.
그러면 &#39;내 애플리케이션&#39; 에 방금 작성한 애플리케이션이 추가된 걸 확인할 수 있을 것이다.
그걸 클릭하면,
<img src="https://velog.velcdn.com/images/z00m__in/post/48f7e15f-3dd3-4af7-8bbb-2c409ab550ee/image.png" alt=""></p>
<p>이처럼 자동으로 발급되는 앱 키를 확인할 수 있다.</p>
<h2 id="2-안드로이드-플랫폼-등록">2) 안드로이드 플랫폼 등록</h2>
<p>앱 키를 알려주는 화면에서 스크롤을 조금 내리면,</p>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/ab386f27-cb40-4722-9814-1254f53d1580/image.png" alt="">
플랫폼을 설정하라는 화면이 나온다.</p>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/3c32155a-07b8-403f-8884-a2de2756ef25/image.png" alt=""></p>
<p>안드로이드, iOS, Web의 플랫폼을 설정할 수 있는데
우리는 안드로이드를 등록해보도록 하겠다.</p>
<p>안드로이드 플랫폼을 누르면,
<img src="https://velog.velcdn.com/images/z00m__in/post/7e96c034-5eb7-4b49-af85-095451f8c514/image.png" alt="">
이런 내용을 채운 뒤 저장을 하면 되는데...</p>
<p>패키지명은 안드로이드 스튜디오에서 바로 확인하면 되지만,
키 해시가 뭔지 나는 생소했고 좀 어려웠기 때문에...
이 부분은 따로 적어보도록 하겠다.</p>
<h1 id="2-키-해시-등록">2. 키 해시 등록</h1>
<h2 id="1-키해시란">1) 키해시란?</h2>
<p>우선, 카카오 자체에서 제공하는 <a href="https://developers.kakao.com/docs/latest/ko/getting-started/sdk-android#add-key-hash">키 해시</a>에 대한 문서를 확인하길 추천한다.</p>
<p>설명하자면, 나는 카카오 API를 사용할 건데
카카오 입장에서는 내가 카카오가 허가된 대상인지 아닌지 확인하는 과정이 필요할 것이다.
그 과정에서 사용되는 것이 키 해시 이다.</p>
<p>쉽게 말하면 API를 사용하기 위한 신분증이라고 이해하면 된다.</p>
<h2 id="2-openssl-설치">2) openssl 설치</h2>
<p>터미널에서 키 해시를 구하는 방법도 있고 코드로 구하는 방법도 있지만,
나는 터미널에서 디버그 키 해시와 릴리즈 키 해시를 구할 예정이다.</p>
<p>이 과정에서 openssl 설치가 필수이기 때문에, <a href="https://code.google.com/archive/p/openssl-for-windows/downloads">openssl-for-windows</a> 링크에 접속해 사전에 설치해주면 된다.</p>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/67f9fcff-4d13-4b06-b9b7-943319a4b18c/image.png" alt=""></p>
<p>링크에 접속하면 위와같은 화면이 나오는데, 이 중 본인의 환경에 맞는 zip 파일을 설치하면 된다.</p>
<p>설치한 뒤 본인이 설치한 openssl이 저장된 디렉토리를 확인해둔다.
나의 경우 다음 디렉토리였다.</p>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/7db60f62-f161-4606-b98d-d629dadae7b8/image.png" alt=""></p>
<h2 id="2-디버그-키해시">2) 디버그 키해시</h2>
<p>두 가지 키해시 중 &quot;디버그&quot; 키해시는,
프로젝트를 처음 생성하거나 디버그할 때 안드로이드 스튜디오에서 개발 환경에 맞게 자동으로 생성해준 인증서에서 해시한 값이다.</p>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/db2355c1-4974-418e-88f3-92ec6ddc7367/image.png" alt=""></p>
<p>이제 &quot;C:\Users\USER.android&quot;의 경로에서 debug.keystore가 있는지 확인해준다.</p>
<p>해당 파일이 있는 것이 확인 됐다면 다음 명령어를 이용해 해당 디렉토리로 이동한다. </p>
<pre><code>cd C:\Program Files\Android\Android Studio\jre\bin</code></pre><p>단, 사용자의 환경에 따라 절대적으로 이 경로가 일치하는 건 아니다.
나의 경우, Scoop을 이용해 Android Studio를 설치했기 때문에</p>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/015538a0-ded6-456d-91b1-8cefe23016cc/image.png" alt=""></p>
<p>의 경로를 입력해야 했다.
각자 환경에 따라 android studio 디렉토리를 찾아보며 수정하면 될듯하다.</p>
<p>이렇게 위의 명령어로 해당 디렉토리로 이동했다면</p>
<pre><code>keytool -exportcert 
-alias androiddebugkey 
-keystore C:\Users\User\.android\debug.keystore 
-storepass android -keypass android 
| C:\Users\USER\openssl-0.9.8k_X64\bin\openssl sha1 -binary 
| C:\Users\USER\openssl-0.9.8k_X64\bin\openssl base64</code></pre><p>다음 명령어를 입력하면 된다.
본인의 환경에 따라 debug.keystore의 디렉토리, openssl의 디렉토리는 수정하면 된다.</p>
<p>그러면 키해시 값을 바로 띄워준다!</p>
<h2 id="3-릴리즈-키해시">3) 릴리즈 키해시</h2>
<p>&quot;릴리즈&quot; 키해시는,
스토어에 앱을 배포하기 위해 생성한 릴리즈 인증서로부터 해시한 값이다.</p>
<p>터미널에 아래 사항을 입력해주면 된다.</p>
<pre><code>keytool -exportcert
-alias &quot;ptect&quot;
-keystore ptect.jks
| C:\Users\USER\openssl-0.9.8k_X64\bin\openssl sha1 -binary
| C:\Users\USER\openssl-0.9.8k_X64\bin\openssl base64</code></pre><p>alias 이후에는 RELEASE KEY ALIAS라고 릴리즈 키의 별칭, 
keystore 이후에는 REALEASE KEY PATH라고 키스토어의 경로가 들어가면 된다.</p>
<h1 id="3-카카오-sdk-설치">3. 카카오 SDK 설치</h1>
<h2 id="1-sdk-설치">1) SDK 설치</h2>
<p>이제 &#39;내 애플리케이션&#39; 추가가 완료되었다면,
API를 본격적으로 설치해볼 것이다.</p>
<p><a href="https://apis.map.kakao.com/android/guide/">카카오 맵 API 공식 가이드 페이지</a>에 접속하여 SDK를 설치한다.</p>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/824b8631-4e15-48a1-ad27-dae96c28cee5/image.png" alt=""></p>
<p>위 링크에 접속한 뒤 Download SDK를 해주면 된다.
설치를 완료한 뒤 zip 파일 압축을 해제한다면</p>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/fd8504e4-59de-4344-aa7f-cf2e694bcc5c/image.png" alt=""></p>
<p>다음 내용이 들어있음을 확인할 수 있다.</p>
<h2 id="2-sdk-앱에-넣기">2) SDK 앱에 넣기</h2>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/d4da6749-49a2-4e0b-9955-7a250c8015d8/image.png" alt=""></p>
<p>실제 나의 디렉토리를 캡처한 내용이다.
위 사진처럼 파일을 넣어두면 된다.</p>
<p>윗 단계에서 압축해제했을 때 보이는 폴더와 파일을 확인해보자.</p>
<p><code> libDaumMapAndroid.jar</code> 파일은 /app/libs/의 디렉토리에,
<code>arm64-v8a</code> , <code>armeabi</code> , <code>armeabi-v7a</code> 폴더들은 /app/source/main/jniLibs 의 디렉토리에 모두 넣어주면 된다.</p>
<h1 id="4-androidmanifestxml-수정">4. AndroidManifest.xml 수정</h1>
<h2 id="1-permission-추가">1) permission 추가</h2>
<p>당연히 알겠지만... AndroidManifext.xml은 <code>\android\app\src\main </code> 디렉토리 하에 있다!</p>
<p>permission을 부여하는 uses-permission 태그는 manifest 하에 바로 작성하면 된다.</p>
<pre><code>&lt;uses-permission android:name=&quot;android.permission.INTERNET&quot; /&gt;
&lt;uses-permission android:name=&quot;android.permission.ACCESS_COARSE_LOCATION&quot; /&gt;</code></pre><h2 id="2-appkey-추가">2) appkey 추가</h2>
<p>다음으로는 appkey를 추가해야 한다.</p>
<p>이 단계는 manifest 바로 하위 단계가 아니라, manifest 아래의 application 하에 작성해 주면 된다.
android:value에는 <a href="https://developers.kakao.com/">카카오 개발자 사이트</a> 에서 추가한 애플리케이션의 네이티브 앱 키를 넣어준다.</p>
<pre><code>&lt;meta-data android:name=&quot;com.kakao.sdk.AppKey&quot; android:value=&quot;네이티브 앱 키&quot;/&gt;</code></pre><h1 id="5-jar-파일-추가">5. jar 파일 추가</h1>
<h2 id="1-buildgradleapp에-코드-수정">1) build.gradle(:app)에 코드 수정</h2>
<p>이제 실행 시 /app/libs에 넣어둔 jar가 실행될 수 있도록, build.gradle 파일을 수정해보자.</p>
<p>Android Studio의 Project Structure에서 jar dependency를 추가하는 방법도 있다고 하는데, 업데이트된 것인지 jar depencency를 추가하는 화면이 보이지 않아 직접 코드를 수정해주기로 하였다. </p>
<p>build.gradle이 여러 개 있을 수 있는데, 그 중 app의 하위 단계에 있는 파일을 선택하고
dependency 하위에 다음 코드를 추가한다.</p>
<pre><code>implementation fileTree(include: [&#39;*.jar&#39;], dir: &#39;libs&#39;)
implementation files(&#39;libs/libDaumMapAndroid.jar&#39;)</code></pre><h1 id="6-지도를-불러와보자">6. 지도를 불러와보자</h1>
<p>이제 기본 세팅이 완료된 것이고, 각 프로젝트에 맞게 지도를 활용해주면 된다.
우선 아주 간단한 코드를 작성해 기초적으로 화면이 돌아가는지 확인해보겠다.</p>
<p>다음 두 코드는 Mapview를 띄우는 과정으로, 지도 화면이 보여지도록 하는 코드다.</p>
<h2 id="1-layout--activity_mainxml">1) layout : activity_main.xml</h2>
<pre><code>&lt;!-- xml layout --&gt;
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;RelativeLayout
android:background=&quot;@color/white&quot;
xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    android:orientation=&quot;vertical&quot; android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot;&gt;

    &lt;RelativeLayout
        android:id=&quot;@+id/map_view&quot;
        android:layout_width=&quot;match_parent&quot;
        android:layout_height=&quot;match_parent&quot; /&gt;
&lt;/RelativeLayout&gt;</code></pre><h2 id="2-java--mainactivityjava">2) java : MainActivity.java</h2>
<pre><code class="language-java">import net.daum.mf.map.api.MapView;
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        MapView mapView = new MapView(this);
        ViewGroup mapViewContainer = findViewById(R.id.map_view);
        mapViewContainer.addView(mapView);
    }
}</code></pre>
<h1 id="7-완료">7. 완료!</h1>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/984e276a-21f2-4dd9-97e8-79d287de4b20/image.png" alt=""></p>
<p>내 디바이스에서 보여지는 화면이다.
여기에 마커를 추가하는 등 개인 커스텀을 해주면 되겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[모두를 위한 딥러닝2] Basic Machine Learning : Softmax classification]]></title>
            <link>https://velog.io/@z00m__in/%EB%AA%A8%EB%91%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EB%94%A5%EB%9F%AC%EB%8B%9D2-Basic-Machine-Learning-Softmax-classification</link>
            <guid>https://velog.io/@z00m__in/%EB%AA%A8%EB%91%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EB%94%A5%EB%9F%AC%EB%8B%9D2-Basic-Machine-Learning-Softmax-classification</guid>
            <pubDate>Tue, 27 Dec 2022 03:01:44 GMT</pubDate>
            <description><![CDATA[<p>본 게시물은 <a href="https://deeplearningzerotoall.github.io/season2/lec_tensorflow.html">&quot;모두를 위한 딥러닝 2&quot;</a> 강의 수강을 바탕으로 작성된 포스트이다.</p>
<hr>
<h1 id="복습">복습</h1>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/334f4856-d4c3-4215-b6d2-07198d4e09ce/image.png" alt=""></p>
<ul>
<li>Linear vs Logistic = 실수 vs 정수</li>
<li>Logistic regression: 직관적으로, 두 가지로 구분하는 선을 찾아내는 것.
실제 차원에서는 &#39;hyper plane&#39;이라 부름.</li>
<li></li>
</ul>
<hr>
<h1 id="multinomial-classification">Multinomial classification</h1>
<h2 id="multinomial-classification-이란">multinomial classification 이란?</h2>
<p>Multinomial classification이란 여러 개의 class가 있다는 의미다. 앞선 logistic regression에서는 두 가지를 구분하는 선을 찾아내는 것이 목표였다면 이제부터는 두 가지가 아닌 세 개 이상이 목표가 된다는 의미다. 
간단한 예시로, Pass와 Fail로 grade가 매겨지는 것이 아닌 A, B, C의 등급제인 경우를 생각해보자. 최종 output이 0 또는 1로 나뉘는 것이 아니라 세 개 이상이 된다. 이 경우가 multinomial에 해당한다. </p>
<h2 id="학습-과정">학습 과정</h2>
<p>STEP 1. data의 output의 분포를 fix
<img src="https://velog.velcdn.com/images/z00m__in/post/545ad20d-5849-4c18-91c4-e7440a1df977/image.png" alt=""></p>
<p>STEP 2. 각 output에 대해 각각의 binary classification을 생성
<img src="https://velog.velcdn.com/images/z00m__in/post/1613c6ef-ad02-4716-8f94-93029f63813b/image.png" alt=""></p>
<p>STEP3. 각 binary classification에 따라 독립된 H(x) 생성됨.
<img src="https://velog.velcdn.com/images/z00m__in/post/e18160b8-ed8c-4fea-8107-4ad42fe9895f/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/b818e17e-1380-4487-b103-f427a60e134c/image.png" alt=""></p>
<p>STEP4. 독립된 matrix를 하나로 묶어, 각각의 H(X)를 한 번에 추출
<img src="https://velog.velcdn.com/images/z00m__in/post/93b7d7b0-0ff0-492a-9cd0-3e4a21aa7bce/image.png" alt=""></p>
<h2 id="softmax">Softmax</h2>
<p>A,B,C에 대해 각각 출력된 H(X) 결과는 현재 실수인 상태이며 0과 1사이도 아니다. 따라서 Sigmoid 과정을 거칠 필요가 있다. 하지만 두 개가 아닌 여러 개이기 때문에 단순 비율로 따지기도 힘든 상황. 이럴 땐 어떻게 해야 할까?</p>
<p>이럴 땐, 각  A B C에 대해 부여되는 값들의 합이 1이 되도록 숫자를 조정하면 된다. 그렇다면 저절로 0과 1 사이의 값으로 맞추어질 것이기 때문이며, 각각에 대한 &#39;확률&#39;로 표현되는 셈이기도 하기 때문이다.</p>
<p>이 과정이 &quot;softmax&quot;이다.</p>
<p>이후에는 &quot;ONE-HOT encoding&quot; 기법을 사용해 0 또는 1로 환산한다. 제일 큰 값만 1로 설정하고 나머지는 다 0으로 죽이는 것이다.</p>
<h2 id="cost-function">Cost function</h2>
<p>예측한 값과 실제 값이 얼마나 차이나는지를 나타내는 cost function. </p>
<h3 id="cross-entropy">Cross-entropy</h3>
<p>실제 Label(Y에 해당)과 예측값 사이의 차이를 Cross-entropy라는 함수를 통해 구한다. 우리의 목적은 예측이 맞는 경우 cost를 적게 출력하고 예측이 틀린 경우 cost를 많이 출력하는 것이다. 
<img src="https://velog.velcdn.com/images/z00m__in/post/e5842d52-7b6e-47d2-843b-c99e5fba3c96/image.png" alt=""></p>
<p>예측값은 softmax를 통과했기 때문에 0과 1 사이의 값을 가진다. 거기에 log를 씌우고 -를 붙이면, 오른쪽 아래로 내려가는 함수에 해당한다. 그 값에 실제 Y값을 곱하면 그게 cross-entry이다.</p>
<p>실제로 예측이 맞을 때와 틀릴 때 cost값이 어떻게 달라지는지를 확인해보자.
<img src="https://velog.velcdn.com/images/z00m__in/post/1389a32b-daee-4e09-8eca-d14a21b09292/image.png" alt=""></p>
<h3 id="logistic-cost-vs-cross-entropy">Logistic Cost vs Cross Entropy</h3>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/8eee3b54-cd54-4861-912c-b0dfc5571a6c/image.png" alt=""></p>
<p>Logistic cost function에서는 길고 복잡했던 식으로 정리했었는데, 그걸 이렇게 단순한 cross entropy만으로 표현하자니 뭔가 불안하다. 과연 충분히 표현된 cost function일까?</p>
<p>정답은 &#39;맞다&#39;이다. 사실은 logistic cost가 사실상 cross entropy 였기 때문이다. </p>
<h3 id="정리된-cost-function">정리된 cost function</h3>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/865ab7bf-ade6-4910-95b7-b59d5f4e6298/image.png" alt=""></p>
<p>이제 cross entropy를 활용한 cost function의 형태를 보자. 단순하다. cross entropy를 한 뒤 그 평균을 내주면 된다. </p>
<h2 id="gradient-descent">Gradient descent</h2>
<p>Cost를 구하는 방법을 찾았다면, 이제 그 cost를 최소화하는 방법을 강구해야 한다. 그건 당연하게도 gradient descent. 볼록한 cost function에서는 어느 점에서 시작하든 상관없이 최저점에 도달하게 되는데, 순서대로 함수를 미분하면 되는 수순이었다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[모두를 위한 딥러닝2] Basic Machine Learning : Logistic Regression]]></title>
            <link>https://velog.io/@z00m__in/%EB%AA%A8%EB%91%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EB%94%A5%EB%9F%AC%EB%8B%9D2-Basic-Machine-Learning-Logistic-Regression-1b7hqfry</link>
            <guid>https://velog.io/@z00m__in/%EB%AA%A8%EB%91%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EB%94%A5%EB%9F%AC%EB%8B%9D2-Basic-Machine-Learning-Logistic-Regression-1b7hqfry</guid>
            <pubDate>Tue, 27 Dec 2022 03:00:51 GMT</pubDate>
            <description><![CDATA[<p>본 게시물은 <a href="https://deeplearningzerotoall.github.io/season2/lec_tensorflow.html">&quot;모두를 위한 딥러닝 2&quot;</a> 강의 수강을 바탕으로 작성된 포스트이다.</p>
<hr>
<h1 id="logistic-regression">Logistic Regression</h1>
<h2 id="what-is-logistic-regression">What is logistic Regression?</h2>
<p>Logistic Regression은 분류 기법 주의 하나로, 다른 특징을 가진 것을 서로 분류하는 데에 많이 사용되는 알고리즘이다. </p>
<h3 id="classification">Classification</h3>
<p>Machine learning의 기초로 알아야 하는 분류 기법인 Binary Classification은, &#39;그렇다&#39;와 &#39;그렇지 않다&#39;로 구분되어 positive와 negative 또는 0과 1로 귀결될 수 있는 분류 기법을 말한다. 이 결과인 0과 1의 집합들을 바탕으로 logistic regression을 만들 수 있는 것이다. </p>
<h3 id="logistic-vs-linear">Logistic vs Linear</h3>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/fac36247-4734-4cb9-b4b3-9f7f859df332/image.png" alt=""></p>
<p>Linear은 전체 data의 &#39;경향성&#39;을 대표하는 것인 반면, Logistic이란 두 가지의 경우를 &#39;구분&#39;하는 것이다. 
Linear는 연속적인 data로, 시간이나 무게 또는 높이처럼 실수단위이다.
Logistic은 각각의 data가 셀 수 있고, 흩어져 있기 때문에 신발 사이즈나 인원수처럼 뚝뚝 끊기는 정수단위로 생각하면 좋다. </p>
<h2 id="hypothesis-representation">Hypothesis Representation</h2>
<p>: Logistic Regression의 가설 설정
<img src="https://velog.velcdn.com/images/z00m__in/post/c3df3645-2dd3-4e77-9d60-eacfdfb8928d/image.png" alt=""></p>
<p>Logistic에서는 Linear와 달리, 결과값을 0과 1로 구분해내는 가설을 세팅해야 한다. 어떻게 만들어야 하는 것일까?
먼저, Linear function을 통해 H(x)값을 도출해내야 한다. 그 이후에 Logistic function을 거쳐 값을 0과 1 사이로 만져주고, decision boundary (경계값)을 만들어 그 값보다 크거나 작으면 0 또는 1로 최종 Y값을 만들도록 하면 된다. 이 step이 Logistic 가설을 만드는 단계라 생각하면 되겠다. </p>
<h3 id="sigmoidlogistic-function">Sigmoid/Logistic Function</h3>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/70badaba-e9d1-4b32-9a9b-49cad088364b/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/1ec1b176-4ca2-4f0c-b60d-3b84c5acc502/image.png" alt=""></p>
<p>Logistic function 보다는 Sigmoid로 부르는 데에 익숙해지도록 하자. Sigmoid function은 위의 g(z)에 해당하는 함수이다. Linear를 통해 도출한 수치화 값을 특수한 모양새로 변경하는 것이다. 이 모양새로 만들려는 이유는 그 결과값이 0과 1사이로 수렴되기 때문이다.</p>
<h3 id="decision-boundary">Decision Boundary</h3>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/5fd967a7-57e3-4695-908b-38497692cfad/image.png" alt=""></p>
<p>Sigmoid function을 통해 값을 0과 1 사이로 제한시켰으니 그 중 결과값을 0으로 도출하는 구간과 1로 도출하는 구간을 나눠야 한다. 그 구간의 경계를 기준으로 한 쪽을 0으로, 반대 쪽을 1로 변환하면 되는데 이것을 decision boundary라고 한다. 예를 들어, 일차함수보다 아래 또는 위에 위치하는 경우나 원의 안에 또는 밖에 위치하는 경우가 있다.</p>
<h2 id="cost-function">Cost Function</h2>
<p>기본적인 개념과 원리는 비슷함. Cost는 비용. θ는 weight에 해당하기 때문에 초기값은 랜덤하게 설정되나 추후 조정. 이 때, 0과 1의 구분이 잘 되도록 하는 θ를 찾아가는 것이 cost function이라 할 수 있음. </p>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/05375a55-39e1-4d5c-ba28-487e3b653062/image.png" alt=""></p>
<p>Linear cost function에 이 식을 대입해본다고 해보자. Cost값을 최소화하기 위한 과정은, 실제 가설을 통해 나온 sigmoid한 값에서 0과 1이 계단처럼 분류된 실제 라벨 값의 차이가 가장 적도록 만들어야 한다. 이 과정을 살펴보면, 0과 1 사이의 &#39;실수값&#39;을 갖는 sigmoid한 결과에서 계단형의 0 또는 1의 &#39;정수값&#39;을 빼면 꼬불꼬불한 값이 cost로 도출될 수밖에 없는 것이다.</p>
<p>따라서 우리는 logistic regression cost가 convex하게 볼록한 구조를 갖도록 만들어야 한다. 즉, 그 꼬불꼬불한 결과값을 convex하도록 바꿔주는 것이 Logistic cost function의 역할이다. </p>
<p>실제 라벨 값인 &#39;실수값&#39;이 0인지 1인지에 따라 볼록한 값을 갖게 하는 log의 형태가 달라지는 모양새이다. </p>
<h3 id="optimization-gradient-descent">Optimization (Gradient Descent)</h3>
<p>Cost 함수를 최소화하는 과정이 optimization. Linear의 gradient descent와 흐름이 같다. Learning rate와 cost를 미분한 값을 곱한 것을 뺀 것을 새로운 경사값으로 update하며 최적의 모델을 찾아가는 것이다.</p>
<pre><code class="language-python">def grad(hypothesis, labels):
    # hypothesis, label을 넣었을 때의 loss값의 차이인 loss_value와 [W,b]를 바탕으로 tape.gradient 실행.
    with tf.GradientTape() as tape:
        loss_value = loss_fn(hypothesis, labels)
    return tape.gradient(loss_value, [W,b])
#GradientDescentOptimizer를 주어진 learning rate로 실행
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
#그 optimizer에 선언한 함수 grad 값과 [W,b]를 구하는 것...?
optimizer.apply_gradients(grads_and_vars=zip(grads,[W,b]))
</code></pre>
<hr>
<h1 id="실습">실습</h1>
<p>다음 링크는 logistic regression을 실습해 본 결과이다.
<a href="https://colab.research.google.com/drive/1Gmeb-jNAEPFwZtOkW-7M0g7i9G8iVeS5?usp=sharing">https://colab.research.google.com/drive/1Gmeb-jNAEPFwZtOkW-7M0g7i9G8iVeS5?usp=sharing</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[모두를 위한 딥러닝2] Basic Machine Learning : Multi-variable Linear Regression]]></title>
            <link>https://velog.io/@z00m__in/%EB%AA%A8%EB%91%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EB%94%A5%EB%9F%AC%EB%8B%9D2-Basic-Machine-Learning-Multi-variable-Linear-Regression</link>
            <guid>https://velog.io/@z00m__in/%EB%AA%A8%EB%91%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EB%94%A5%EB%9F%AC%EB%8B%9D2-Basic-Machine-Learning-Multi-variable-Linear-Regression</guid>
            <pubDate>Tue, 27 Dec 2022 02:58:40 GMT</pubDate>
            <description><![CDATA[<p>본 게시물은 <a href="https://deeplearningzerotoall.github.io/season2/lec_tensorflow.html">&quot;모두를 위한 딥러닝 2&quot;</a> 강의 수강을 바탕으로 작성된 포스트이다.</p>
<hr>
<h1 id="복습">복습</h1>
<ul>
<li><p>Hypothesis : Data의 분포를 가장 잘 대변하는 직선의 예측인 가설 함수
  W는 weight, b는 bias에 해당. 추후 간략화해서 H(x)=Wx로만으로도 표현.
<img src="https://velog.velcdn.com/images/z00m__in/post/3ebf175b-1141-464c-832c-7a28bd8b593d/image.png" alt=""></p>
</li>
<li><p>Cost function : 예측과 실제 값의 차이. 음수의 값이 나오지 않도록 하기 위해 제곱의 평균을 계산.
머신러닝의 핵심인 &quot;학습 과정&quot;이라 할 수 있음.
<img src="https://velog.velcdn.com/images/z00m__in/post/cca6b6d5-dcbb-45d9-806b-4cddfcebcf3e/image.png" alt=""></p>
</li>
<li><p>Gradient descent : 최소의 cost를 만드는 W를 찾아내는 기법.
이전의 W값에서, gradient에 α를 곱한 값을 뺀 것을 새로운 W로 업데이트. 
업데이트한 W 값에 대한 cost가 최소이도록 하는 과정.
<img src="https://velog.velcdn.com/images/z00m__in/post/7b2a54d5-9b7d-43e7-9d3e-4fd611a8d674/image.png" alt=""></p>
</li>
</ul>
<hr>
<h1 id="multi-variable-linear-regression">Multi-variable linear regression</h1>
<p>: 하나가 아닌 여러 개의 변수를 사용하는 다변수 선형회귀</p>
<h2 id="one-variable--multi-variable">One-variable &amp; Multi-variable</h2>
<h3 id="one-variable">One-variable</h3>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/ac966a82-cf05-429a-80d1-58bea0a4f0fd/image.png" alt=""></p>
<p>One-variable이라 함은 하나의 예측값이 도출되는 과정에서 고려되는 입력값이 하나라는 의미다.
간단한 예시로는, &#39;투자한 시간&#39;에 따라 다르게 예측되는 &#39;시험 점수&#39;를 생각해볼 수 있다. 이 때 투자한 시간이 변수에 해당하므로 하나의 variable(feature)를 갖는다 할 수 있다. </p>
<h3 id="multi-variable">Multi-variable</h3>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/f0efdbaf-4dbe-4f61-b9f5-bc874a03a63b/image.png" alt=""></p>
<p>Multi-variable은 하나의 예측값이 도출되는 과정에서 고려되는 입력 값이 하나가 아닌 여러 개라는 의미다. One-variable에 비해 다양한 상황을 고려하게 되므로 예측의 결과가 보다 정확해지는 prediction power(예측력)를 가진다.
간단한 예시로는, &#39;퀴즈 1&#39;, &#39;퀴즈 2&#39;, &#39;중간고사&#39;의 성적에 따라 예측되는 &#39;기말고사 성적&#39;을 생각해볼 수 있다. 이 때 두 개의 퀴즈와 중간고사가 변수에 해당하므로 3개의 variable(feature)를 갖는다 할 수 있다.</p>
<h2 id="multi-variable-hypothesis">Multi-variable Hypothesis</h2>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/921aaf4b-5e5f-48ea-9db7-a6d4ffdb2ef1/image.png" alt="">
각 변수에 따라 다른 가중치를 가져야 한다. 따라서 변수의 갯수만큼 가중치의 갯수가 늘어난 새로운 식이 도출된다. 변수가 늘어날 경우 하나의 긴 식으로 나열하는 것이 비효율적이므로 행렬의 dot product를 주로 사용한다. </p>
<h3 id="hypothesis-using-matrix">Hypothesis using matrix</h3>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/67642ed8-c821-4991-9308-0e9ecb0f0ce1/image.png" alt=""></p>
<p>X : 변수의 matrix. 변수의 쌍이 여러 개인 경우, X의 행이 그만큼 늘어난다. 사진은 총 다섯 쌍의 변수에 대한 행렬으로 5개의 행이 존재한다.
W : 가중치의 matrix</p>
<h3 id="hypothesis-matrix의-확장">Hypothesis matrix의 확장</h3>
<h4 id="변수의-쌍이-많아지는-경우">변수의 쌍이 많아지는 경우</h4>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/91a52079-a954-4b52-9b35-f237a2a1405a/image.png" alt=""></p>
<p>변수의 쌍이 5개가 아니라 계속해서 늘어난다고 가정하자. 모든 경우를 다 나열하기엔 버거울 것이다. 그렇다면 각 행렬의 행과 열의 구조를 나타내며 간편하게 표현하면 된다! </p>
<h4 id="output이-하나가-아닌-여러-개인-경우">output이 하나가 아닌 여러 개인 경우</h4>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/0705d1e1-b9a2-4ff9-bcdf-e30e00f34fc6/image.png" alt=""></p>
<p>최종으로 예측하고자 하는 예측값이 여러 개인 경우이다. 먼저 입력 data인 X 행렬과 최종 출력에 해당하는 H 행렬을 완성해보면, W 행렬의 구조를 파악할 수 있다. 위 사진은 두 개의 출력값을 도출하고자 하는 경우다.</p>
<h3 id="wx와-xw의-차이">WX와 XW의 차이</h3>
<p>WX는 식이 어떻게 생겨야 하는지 이론적으로 보여줄 때 사용되는 반면, XW는 실제로 Tensorflow로 구현할 때 연산을 위해 사용된다. </p>
<h2 id="multi-variable-cost-function">Multi-variable Cost function</h2>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/7f3e6083-f7c0-4fcb-ab1b-dbdda852be6b/image.png" alt=""></p>
<p>Hypothesis 결과에서 실제 값의 차이를 바탕으로 도출해야 하기 때문에, cost를 구하는 식은 동일하다. 그 안에 들어가게 되는 H(x)의 내용이 바뀔 뿐이다.</p>
<hr>
<h1 id="실습">실습</h1>
<p>이 링크는 multi-variable linear regression를 matrix를 활용하지 않을 때와 matrix를 사용할 때에 대해 모두 실습해 본 결과이다.
<a href="https://colab.research.google.com/drive/1bKERqMoHj2mO_ynnRo0smzSN0Xj4owya?usp=sharing">https://colab.research.google.com/drive/1bKERqMoHj2mO_ynnRo0smzSN0Xj4owya?usp=sharing</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[모두를 위한 딥러닝2] Basic Machine Learning : Linear Regression and How to minimize cost]]></title>
            <link>https://velog.io/@z00m__in/%EB%AA%A8%EB%91%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EB%94%A5%EB%9F%AC%EB%8B%9D2-Basic-Machine-Learning-Linear-Regression-and-How-to-minimize-cost</link>
            <guid>https://velog.io/@z00m__in/%EB%AA%A8%EB%91%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EB%94%A5%EB%9F%AC%EB%8B%9D2-Basic-Machine-Learning-Linear-Regression-and-How-to-minimize-cost</guid>
            <pubDate>Sat, 10 Dec 2022 08:21:13 GMT</pubDate>
            <description><![CDATA[<p>본 게시물은 <a href="https://deeplearningzerotoall.github.io/season2/lec_tensorflow.html">&quot;모두를 위한 딥러닝 2&quot;</a> 강의 수강을 바탕으로 작성된 포스트이다.</p>
<hr>
<h1 id="복습">복습</h1>
<ul>
<li>Linear Regression
  : Data의 분포를 반영하여 이에 가장 오차가 적도록 하는 &quot;y=ax+b&quot;의 직선을 만드는 것</li>
<li>Hypothesis:Data의 분포를 가장 잘 대변하는 직선의 예측
  ==&gt; H(x) = Wx + b ==&gt; 요약해 H(x) = Wx 로 표현</li>
<li>Cost: 실제 data와 가설의 차이
  ==&gt; 참고로 1/2m에서 2m의 값은 뭐가 되든 상관 없다. 추후 미분에 용이하기 위해 m이 아닌 2m으로 설정한 것
   <img src="https://velog.velcdn.com/images/z00m__in/post/9203c3af-8293-4614-93be-5265949532ef/image.png" alt=""></li>
</ul>
<hr>
<h1 id="gradient-descent-algorithm">Gradient Descent Algorithm</h1>
<h2 id="w에-따른-costw-변화">W에 따른 cost(W) 변화</h2>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/1928f132-7a92-4354-989f-9a84e46c964f/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/bf539391-7a62-4d71-830e-de8b9abdad9f/image.png" alt=""></p>
<p>x, y의 값이 정해져 있으므로, cost(W)는 W에 따른 함수로 해석할 수 있다. 위 사진은 W의 값에 따른 cost의 변화이다. 그래프로 표현하면 최소의 cost를 갖는 W 값을 단번에 확인할 수 있다. 그렇다면 최소의 cost를 찾을 수 있는 방법은 없을까?</p>
<h2 id="gradient-descent-algorithm-1">Gradient Descent Algorithm</h2>
<p>Gradient descent algorithm이 대표적인 minimize cost function, 즉 최소의 cost를 찾아내는 기법이다.
Gradient는 경사, Descent는 하강을 의미하며, 경사를 따라 내려가면서 최저점을 찾도록 설계된 알고리즘이다.
참고로 변수가 하나가 아니라 두 개 이상일 때도 사용될 수 있다!</p>
<h3 id="how-it-works">How it works?</h3>
<ol>
<li>최초의 initial point를 설정한다. 랜덤이어도 좋고, 원점이어도 좋다.</li>
<li>Cost가 줄어들 수 있는 방향으로 W와 b값을 지속적으로 바꾸며,
 바꿀 때마다 기울기 값을 구하고 cost가 최소가 되는 방향으로 업데이트를 한다.</li>
<li>최소점에 도달했다고 생각이 들 때까지 2번 과정을 반복한다. <h3 id="formal-definition">Formal Definition</h3>
<img src="https://velog.velcdn.com/images/z00m__in/post/4061fdfc-586f-4919-8fa3-2b13703c2ae5/image.png" alt="">
 α: learning rate. 기울기 값을 얼마나 반영할지를 나타내는 상수다. 매우 작은 상수로 설정.
 ∂: 편미분 기호. 여기선 W에 대해서만 미분한다는 의미!
사진의 마지막 줄이 gradient descent algorithm이다.
정리하자면 cost function을 미분한 값, 즉 gradient에 α만큼 곱한 뒤 이 값을 W에서 빼서 업데이트한 것이다.
미분에 대한 공식은 <a href="https://www.derivative-calculator.net/">derivative-calculator</a> 또는 <a href="https://www.wolframalpha.com/">wolframalpha</a> 같은 사이트에서 계산할 수 있기 때문에, 실제 계산은 우리의 목시 아니니 안심해도 된다.</li>
</ol>
<h2 id="convex-function">Convex function</h2>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/a75d5566-ee7e-4982-808e-54dc80c92ad5/image.png" alt=""></p>
<p>위 사진처럼 초기 시작 점이 어디냐에 따라서, local minimum일 수는 있어도 전체의 minimum이 아닐 가능성이 있다. 이런 상황에서는 Gradient descent algorithm을 적용하기 어렵다. </p>
<h1 id="실습">실습</h1>
<p>이 링크는 cost function 실습을 진행해 본 결과이며,
<a href="https://colab.research.google.com/drive/1FrfdHRXiKJX3To5rKc4FOqwVLOO-jVXC?usp=sharing">https://colab.research.google.com/drive/1FrfdHRXiKJX3To5rKc4FOqwVLOO-jVXC?usp=sharing</a></p>
<p>이 링크는 gradient descending 실습을 진행한 결과이다!
<a href="https://colab.research.google.com/drive/1wgGGXlr58qL8Z-Dy4T9l5ikKYHL_jwQS?usp=sharing">https://colab.research.google.com/drive/1wgGGXlr58qL8Z-Dy4T9l5ikKYHL_jwQS?usp=sharing</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[모두를 위한 딥러닝2] Basic Machine Learning : Simple Linear Regression]]></title>
            <link>https://velog.io/@z00m__in/%EB%AA%A8%EB%91%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EB%94%A5%EB%9F%AC%EB%8B%9D2-Basic-Machine-Learning-Simple-Linear-Regression</link>
            <guid>https://velog.io/@z00m__in/%EB%AA%A8%EB%91%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EB%94%A5%EB%9F%AC%EB%8B%9D2-Basic-Machine-Learning-Simple-Linear-Regression</guid>
            <pubDate>Sat, 10 Dec 2022 06:38:29 GMT</pubDate>
            <description><![CDATA[<p>본 게시물은 <a href="https://deeplearningzerotoall.github.io/season2/lec_tensorflow.html">&quot;모두를 위한 딥러닝 2&quot;</a> 강의 수강을 바탕으로 작성된 포스트이다.</p>
<hr>
<h1 id="linear-regression">Linear Regression</h1>
<h2 id="regression">Regression</h2>
<p>&quot;Regression toward the mean&quot;에서의 Regression을 의미한다.
전체의 평균으로 되돌아간다ㅏ.
굉장히 크거나 작은 data들이 나오더라도 결과적으로 data들은 전체의 평균으로 되돌아가려는 특징이 있다는 통계적 원리를 설명하는 말이다. </p>
<h2 id="linear-regression-1">Linear Regression</h2>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/1a1ff9d2-a341-4789-a02b-ed99ce4d029c/image.png" alt="">
Linear Regression, 즉 선형 회귀는 data를 가장 잘 대변하는 직선의 방정식을 찾는 것이다. Data의 분포를 반영하여 이에 가장 오차가 적도록 하는 &quot;y=ax+b&quot;의 직선을 만드는 것이라 할 수 있다.</p>
<h3 id="다시-regression이란">다시, Regression이란?</h3>
<p>Linear Regression에서의 regression을 다시 해석해보자. 이 때의 Regression은 Data가 선형적으로 증/감하는 관계에 있을 때, 그 관계를 해석하는 것이라 볼 수 있다.</p>
<h2 id="hypothesis">Hypothesis</h2>
<p>말 그대로 &#39;가설&#39;이다. Linear Regression에서의 hypothesis란, &#39;data의 분포를 가장 잘 대변하는 직선은 이것이다&#39; 하는 &quot;H(x)=Wx+b&quot;의 직선의 방정식이 된다. 가설은 꼭 정답이 아니어도 된다. 그러므로,
<img src="https://velog.velcdn.com/images/z00m__in/post/df2ad087-5a37-4a27-a05d-e802328c6a66/image.png" alt="">
위 사진처럼 한 data set에 대해 3개 이상의 가설이 존재할 수 있는 것이다.</p>
<h3 id="cost">Cost</h3>
<p>많은 가설 중 가장 오차가 적은 가설을 찾아내야 한다. 이 때의 오차가 &#39;Cost&#39;이다. Cost를 구하는 방법에 대해 알아보자.
<img src="https://velog.velcdn.com/images/z00m__in/post/fa993119-dc45-4b46-bcc2-c550d250e9f5/image.png" alt="">
사진에 빨간색으로 표시된 부분인 각 data마다의 y값의 차가 각각의 오차가 될 것이다. H(x) 자체의 오차는 이 것을 더하면 되므로, 다음과 같은 Cost function을 도출할 수 있다.</p>
<h3 id="cost-function">Cost Function</h3>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/3dbf41f5-5e7a-4516-bcb7-f54f2f8b4418/image.png" alt="">
복잡해보이나? 별 거 없다. 오차의 제곱의 합을 구하고 data의 갯수대로 평균을 내면 된다. 오차의 &#39;제곱&#39;을 구하는 이유는 오차가 양수일 수도 음수일 수도 있기 때문이다.</p>
<h3 id="goal-minimize-cost">Goal: Minimize cost</h3>
<p>이 과정에서의 목표는, 가장 cost가 적게 만드는 함수를 찾는 것이다.
Training data에 가장 fit한 line을 찾는 것이 목적임을 잊어선 안된다!</p>
<hr>
<p>아래 링크는 실습을 실행 결과이다.</p>
<p><a href="https://colab.research.google.com/drive/1WfEtvKdGl-55KiM0Xf0hi0xST6P8dsmN?usp=sharing">https://colab.research.google.com/drive/1WfEtvKdGl-55KiM0Xf0hi0xST6P8dsmN?usp=sharing</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[모두를 위한 딥러닝2] Basic Machine Learning :  기본적인 Machine Learning 의 용어와 개념 설명]]></title>
            <link>https://velog.io/@z00m__in/%EB%AA%A8%EB%91%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EB%94%A5%EB%9F%AC%EB%8B%9D2-Basic-Machine-Learning-%EA%B8%B0%EB%B3%B8%EC%A0%81%EC%9D%B8-Machine-Learning-%EC%9D%98-%EC%9A%A9%EC%96%B4%EC%99%80-%EA%B0%9C%EB%85%90-%EC%84%A4%EB%AA%85</link>
            <guid>https://velog.io/@z00m__in/%EB%AA%A8%EB%91%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EB%94%A5%EB%9F%AC%EB%8B%9D2-Basic-Machine-Learning-%EA%B8%B0%EB%B3%B8%EC%A0%81%EC%9D%B8-Machine-Learning-%EC%9D%98-%EC%9A%A9%EC%96%B4%EC%99%80-%EA%B0%9C%EB%85%90-%EC%84%A4%EB%AA%85</guid>
            <pubDate>Sat, 10 Dec 2022 06:04:26 GMT</pubDate>
            <description><![CDATA[<p>본 게시물은 <a href="https://deeplearningzerotoall.github.io/season2/lec_tensorflow.html">&quot;모두를 위한 딥러닝 2&quot;</a> 강의 수강을 바탕으로 작성된 포스트이다.</p>
<hr>
<h1 id="machine-learning머신러닝ml이란">Machine Learning(머신러닝=ML)이란?</h1>
<h2 id="머신러닝">머신러닝</h2>
<p>머신러닝이란, 일종의 &quot;SOFTWARE&quot;, 즉 &quot;PROGRAM&quot;이다.
입력을 바탕으로 데이터를 보여주는 &quot;EXPLICIT programming&quot;이라 할 수 있다.</p>
<h3 id="기존-explicit-programming의-한계점">기존 explicit programming의 한계점</h3>
<p>기존에는 개발자가 미리 모든 경우에 대해 대비해 각 도출 결과를 작성해야 했기에 모든 경우를 예측하기 어려웠다. (ex. 스팸 필터, 자율주행)
이에, 일일히 프로그래밍하지 말고 현장에서 자동으로 학습하는 프로그램인 ML 개발.</p>
<h2 id="learning-기법">LEARNING 기법</h2>
<h3 id="supervised">SUPERVISED</h3>
<p>이미 정해져있는 data, 즉 labeling이 완료된 training set을 바탕으로 학습하는 것이다. 대개의 LEARNING이 여기에 속한다고 보면 된다.</p>
<h3 id="unsupervised">UNSUPERVISED</h3>
<p>Un-labeled data를 학습하는 것으로, data를 보고 스스로 학습하는 종류이다.
(ex. 뉴스를 분류하는 것, 유사한 단어를 묶는 것)</p>
<h1 id="supervised-learning이란">SUPERVISED LEARNING이란?</h1>
<h2 id="예시">예시</h2>
<p>SUPERVISED Learning이 기본적으로 ML에서 가장 일반적인 유형이다. 예시를 보는 것이 가장 직관적이므로 다음 경우들을 확인해보자.</p>
<ul>
<li>Image Labeling</li>
<li>Email spam filter
  : label 시켜둔 걸 바탕으로 학습 시키는 것</li>
<li>Predicting exam score ==&gt; REGRESSION
  : 이전 시험에 대해 사용된 시간을 label하는 등의 방식</li>
<li>Predicting exam P/F ==&gt; BINARY classification</li>
<li>Predicting exam letter grade ==&gt; MULTI-LABEL classification<h2 id="training-data-set">Training data set</h2>
Supervised Learning에서 train의 대상이 data set. 즉, ML에 넣는 Labeling이 완료된 data set이다. 이 training data set을 넣어서 학습을 시킨다고 보면 된다.<h3 id="알파고의-training-data-set은">&quot;알파고&quot;의 training data set은?</h3>
우리가 잘 알고 있는 알파고를 예로 들어보자. 알파고는 기존 모든 바둑기법 data를 학습한 ML이다.
알파고의 경우, 기존 바둑기법들이 training data set이 된다.<h3 id="사용-용어">사용 용어</h3>
training data set은 일종의 함수다. 학습 대상이 있고, 그 결과가 있다.</li>
<li>x : 학습 대상인 data (사진, 메일, 공부시간 등)</li>
<li>y : 도출해내는 결과값 data (분류, 점수, 등급 등)<h3 id="model-type">Model type</h3>
<h4 id="regression">Regression</h4>
결과값이 0~100 등 실수 범위처럼 많은 유형<h4 id="binary-classification">Binary classification</h4>
결과값이 P/F 처럼 둘 중 하나인 유형<h4 id="multi-label-classification">Multi-label classification</h4>
결과값이 A부터 F의 등급처럼 여러개로 한정되는 유형</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[모두를 위한 딥러닝2] Docker Installation]]></title>
            <link>https://velog.io/@z00m__in/%EB%AA%A8%EB%91%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EB%94%A5%EB%9F%AC%EB%8B%9D2-Docker-Installation</link>
            <guid>https://velog.io/@z00m__in/%EB%AA%A8%EB%91%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EB%94%A5%EB%9F%AC%EB%8B%9D2-Docker-Installation</guid>
            <pubDate>Sat, 10 Dec 2022 05:49:15 GMT</pubDate>
            <description><![CDATA[<p>본 게시물은 <a href="https://deeplearningzerotoall.github.io/season2/lec_tensorflow.html">&quot;모두를 위한 딥러닝 2&quot;</a> 강의 수강을 바탕으로 작성된 포스트이다.</p>
<hr>
<h1 id="what-is-docker">What is Docker?</h1>
<h4 id="도커의-장점">도커의 장점</h4>
<ul>
<li>모두에게 동일한 실습 환경을 제공한.<h2 id="도커란">&#39;도커&#39;란?</h2>
&#39;도커&#39;란 CONTAINER-BASED VIRTUALIZATION SYSTEM, 즉, 컨테이너 기반의 가상화 시스템이다. 용어를 하나씩 설명하자면,<h3 id="virtualization--가상화">VIRTUALIZATION = 가상화</h3>
가상화, 실제로 있지 않은 것을 마치 있는 것처럼 보이게 해주는 기술이다.
현실에 존재하지 않은 것을 있는 것처럼 보여주는 것도 당연히 가상화지만, 내 컴퓨터에 실제로 하나밖에 없는 하드디스크를 파티션을 나눠 두 개의 드라이브가 있는 것처럼 보이는 것 역시 가상화이다.
여기서 나아가 컴퓨터 안에 가상의 컴퓨터를 만들어거나 Windows 안에 Windows, Mac에서 Windows를 띄우는 경우도 있는데, 이러한 경우는 가상머신이라 할 수 있다. 
요약하자면, 물리적인 서버 하나를 여러 개의 가상 서버로 쪼갤 수 있는 기술인 것이다. 자연스럽게 클라우드 시장의 핵심기술이 되는 것이다.<h3 id="container">CONTAINER</h3>
<img src="https://velog.velcdn.com/images/z00m__in/post/4de815c1-86d4-40e3-a880-ddf4f036f5b7/image.png" alt="">
위 사진처럼 각각의 머신이 분리되어있는 것이 아니라,
<img src="https://velog.velcdn.com/images/z00m__in/post/a14fb153-f2ff-4565-99bc-fd2c95cc230d/image.png" alt="">
운영체제 자체는 통일하고, 그 위 필요한 부분만 묶어 가상화하는 것을 Container-Applications라 한다.<h2 id="다시-도커란">다시, 도커란?</h2>
Container 유형의 가상환경을 제공할 수 있도록 해주는 오픈소스 가상화 플랫폼이다.<h1 id="docker-installation---windows">Docker Installation - Windows</h1>
</li>
</ul>
<p>Docker 자체는 linux를 기반으로 만들었던 것이기 때문에, MacOS나 Windows에서는 Linux만큼의 성능을 기대하기는 힘들다는 것을 기억하기!
지금은 Virtualbox 가상머신을 포함하는 Docker Toolbox를 설치해 볼 것이다.</p>
<p>아래 깃허브 링크에 접속하여서,
<a href="https://github.com/docker-archive/toolbox/releases">https://github.com/docker-archive/toolbox/releases</a></p>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/d7abbab2-45fe-450b-9f5e-eebd86b02c31/image.png" alt="">
사진의 맨 위에 있는 exe 파일을 설치하면 된다.</p>
<p>다운로드 후 그냥 다 next 누르면 설치 완료!</p>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/5eecebe4-c776-425d-a5b7-1af1e6dd6988/image.png" alt="">
설치가 완료되면 이런 Shortcut이 생성된다. 이걸 마우스 우클릭을 누른 다음 &#39;관리자 권한으로 실행&#39;해보자.</p>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/7520f97e-b8ca-4d95-8389-9c0af45e2365/image.png" alt="">
실행 후 기다려주면 이런 귀여운 고래가 뜬다!</p>
<p>그러면 hello-world 이미지를 다운받는 아주 간단한 실습을 해보자.
<img src="https://velog.velcdn.com/images/z00m__in/post/7243f257-37a8-48b1-82e6-09125f41fc37/image.png" alt=""></p>
<pre><code class="language-linux">$ docker run hello-world</code></pre>
<p>명령어를 작성하고 사진처럼 가운데에 &#39;Hello from Docker!&#39;가 떠있다면 성공한 것이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Spring] 스프링 기본 Section 9 : 빈 스코프]]></title>
            <link>https://velog.io/@z00m__in/Spring-%EC%8A%A4%ED%94%84%EB%A7%81-%EA%B8%B0%EB%B3%B8-Section-9-%EB%B9%88-%EC%8A%A4%EC%BD%94%ED%94%84</link>
            <guid>https://velog.io/@z00m__in/Spring-%EC%8A%A4%ED%94%84%EB%A7%81-%EA%B8%B0%EB%B3%B8-Section-9-%EB%B9%88-%EC%8A%A4%EC%BD%94%ED%94%84</guid>
            <pubDate>Tue, 28 Jun 2022 12:04:17 GMT</pubDate>
            <description><![CDATA[<h1 id="스코프">스코프</h1>
<p>스프링이 지원하는 다양한 스코프</p>
<ul>
<li>싱글톤: 기본 스코프, 스프링 컨테이너의 시작과 종료까지 유지되는 가장 넓은 범위의 스코프</li>
<li>프로토타입: 스프링 컨테이너는 프로토타입 빈의 생성과 의존관계 주입까지만 관여하고 더는 관리하지 않는 매우 짧은 범위의 스코프</li>
<li>웹 관련 스코프<ul>
<li>request: 웹 요청이 들어오고 나갈때 까지 유지되는 스코프</li>
<li>session: 웹 세션이 생성되고 종료될 때 까지 유지되는 스코프</li>
<li>application: 웹의 서블릿 컨텍스트와 같은 범위로 유지되는 스코프<h1 id="프로토타입-스코프">프로토타입 스코프</h1>
: 프로토타입 스코프를 스프링 컨테이너에 조회하면 스프링 컨테이너는 항상 새로운 인스턴스를 생성해서 반환. 스프링 컨테이너는 프로토타입 빈을 생성하고, 의존관계 주입, 초기화까지만 처리<h4 id="싱글톤-빈-요청">싱글톤 빈 요청</h4>
<img src="https://velog.velcdn.com/images/z00m__in/post/ec9eff07-0031-449c-928d-73d98533e9a6/image.PNG" alt=""></li>
</ul>
</li>
</ul>
<ol>
<li>싱글톤 스코프의 빈을 스프링 컨테이너에 요청</li>
<li>스프링 컨테이너는 본인이 관리하는 스프링 빈을 반환</li>
<li>이후에 스프링 컨테이너에 같은 요청이 와도 같은 객체 인스턴스의 스프링 빈을 반환<h4 id="프로토타입-빈-요청1">프로토타입 빈 요청1</h4>
<img src="https://velog.velcdn.com/images/z00m__in/post/697c627c-2326-4f1f-b6d4-9f3a650538ba/image.PNG" alt=""></li>
<li>프로토타입 스코프의 빈을 스프링 컨테이너에 요청</li>
<li>스프링 컨테이너는 이 시점에 프로토타입 빈을 생성하고, 필요한 의존관계를 주입<h4 id="프로토타입-빈-요청2">프로토타입 빈 요청2</h4>
<img src="https://velog.velcdn.com/images/z00m__in/post/4373bf4f-c5af-4927-b161-7adda101b84e/image.png" alt=""></li>
<li>스프링 컨테이너는 생성한 프로토타입 빈을 클라이언트에 반환</li>
<li>이후에 스프링 컨테이너에 같은 요청이 오면 항상 새로운 프로토타입 빈을 생성해서 반환<h3 id="프로토타입-빈의-특징-정리">프로토타입 빈의 특징 정리</h3>
</li>
</ol>
<ul>
<li>스프링 컨테이너에 요청할 때 마다 새로 생성</li>
<li>스프링 컨테이너는 프로토타입 빈의 생성과 의존관계 주입 그리고 초기화까지만 관여</li>
<li>종료 메서드가 호출되지 않음</li>
<li>그래서 프로토타입 빈은 프로토타입 빈을 조회한 클라이언트가 관리해야 함. 종료 메서드에 대한 호출도 클라이언트가 직접 해야함</li>
</ul>
<h1 id="프로토타입-스코프---싱글톤-빈과-함께-사용시-문제점">프로토타입 스코프 - 싱글톤 빈과 함께 사용시 문제점</h1>
<h3 id="스프링-컨테이너에-프로토타입-빈-직접-요청">스프링 컨테이너에 프로토타입 빈 직접 요청</h3>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/39ee9c53-309b-4d72-b0fb-aaf4ed13e71c/image.PNG" alt=""></p>
<ol>
<li>클라이언트A는 스프링 컨테이너에 프로토타입 빈을 요청</li>
<li>스프링 컨테이너는 프로토타입 빈을 새로 생성해서 반환(x01)한다. 해당 빈의 count 필드 값은 0</li>
<li>클라이언트는 조회한 프로토타입 빈에 addCount() 를 호출하면서 count 필드를 +1
결과적으로 프로토타입 빈(x01)의 count는 1
<img src="https://velog.velcdn.com/images/z00m__in/post/15529427-9e2a-4c8a-9da9-b1afc03f7f33/image.png" alt=""></li>
<li>클라이언트B는 스프링 컨테이너에 프로토타입 빈을 요청</li>
<li>스프링 컨테이너는 프로토타입 빈을 새로 생성해서 반환(x02). 해당 빈의 count 필드 값은 0.</li>
<li>클라이언트는 조회한 프로토타입 빈에 addCount() 를 호출하면서 count 필드를 +1
결과적으로 프로토타입 빈(x02)의 count는 1<h3 id="싱글톤-빈에서-프로토타입-빈-사용">싱글톤 빈에서 프로토타입 빈 사용</h3>
<img src="https://velog.velcdn.com/images/z00m__in/post/10c741ef-103a-422d-bc46-659beb602519/image.png" alt="">
clientBean 은 싱글톤이므로, 보통 스프링 컨테이너 생성 시점에 함께 생성되고, 의존관계 주입도 발생</li>
<li>clientBean 은 의존관계 자동 주입을 사용. 주입 시점에 스프링 컨테이너에 프로토타입 빈을
요청</li>
<li>스프링 컨테이너는 프로토타입 빈을 생성해서 clientBean 에 반환. 프로토타입 빈의 count 필드 값은 0
이제 clientBean 은 프로토타입 빈을 내부 필드에 보관한다.
<img src="https://velog.velcdn.com/images/z00m__in/post/e8f46b8f-3394-4ee4-b333-9b2f12a056a4/image.png" alt="">
클라이언트 A는 clientBean 을 스프링 컨테이너에 요청해서 받는다.싱글톤이므로 항상 같은
clientBean 이 반환된다.</li>
<li>클라이언트 A는 clientBean.logic() 을 호출한다.</li>
<li>clientBean 은 prototypeBean의 addCount() 를 호출해서 프로토타입 빈의 count를 증가한다. 
count값이 1이 됨</li>
</ol>
<h1 id="프로토타입-스코프---싱글톤-빈과-함께-사용시-provider로-문제-해결">프로토타입 스코프 - 싱글톤 빈과 함께 사용시 Provider로 문제 해결</h1>
<p>: 사용할 때 마다 항상 새로운 프로토타입 빈을 생성해야 함</p>
<h4 id="스프링-컨테이너에-요청">스프링 컨테이너에 요청</h4>
<h4 id="objectfactory-objectprovider">ObjectFactory, ObjectProvider</h4>
<ul>
<li>ObjectFactory: 기능이 단순, 별도의 라이브러리 필요 없음, 스프링에 의존</li>
<li>ObjectProvider: ObjectFactory 상속, 옵션, 스트림 처리등 편의 기능이 많고, 별도의 라이브러리 필요 없음, 스프링에 의존<h4 id="jsr-330-provide">JSR-330 Provide</h4>
</li>
<li>get() 메서드 하나로 기능이 매우 단순</li>
<li>별도의 라이브러리가 필요</li>
<li>자바 표준이므로 스프링이 아닌 다른 컨테이너에서도 사용할 수 있음</li>
</ul>
<h1 id="웹-스코프">웹 스코프</h1>
<h4 id="웹-스코프의-특징">웹 스코프의 특징</h4>
<ul>
<li>웹 스코프는 웹 환경에서만 동작</li>
<li>웹 스코프는 프로토타입과 다르게 스프링이 해당 스코프의 종료시점까지 관리한다. 따라서 종료 메서드가 호출</li>
</ul>
<h4 id="웹-스코프-종류">웹 스코프 종류</h4>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/9a26a18d-f75d-479d-a0d5-a85793044bb7/image.png" alt=""></p>
<ul>
<li>request: HTTP 요청 하나가 들어오고 나갈 때 까지 유지되는 스코프, 각각의 HTTP 요청마다 별도의 빈 인스턴스가 생성되고, 관리됨</li>
<li>session: HTTP Session과 동일한 생명주기를 가지는 스코프</li>
<li>application: 서블릿 컨텍스트( ServletContext )와 동일한 생명주기를 가지는 스코프</li>
<li>websocket: 웹 소켓과 동일한 생명주기를 가지는 스코프</li>
</ul>
<h1 id="스코프와-프록시">스코프와 프록시</h1>
<ul>
<li>프록시 객체 덕분에 클라이언트는 마치 싱글톤 빈을 사용하듯이 편리하게 request scope를 사용할 수 있음</li>
<li>핵심 아이디어는 진짜 객체 조회를 꼭 필요한 시점까지 지연처리 한다는 점</li>
<li>단지 애노테이션 설정 변경만으로 원본 객체를 프록시 객체로 대체할 수 있음.</li>
<li>꼭 웹 스코프가 아니어도 프록시는 사용할 수 있음<h4 id="주의점">주의점</h4>
</li>
<li>마치 싱글톤을 사용하는 것 같지만 다르게 동작하기 때문에 결국 주의해서 사용해야 함</li>
<li>이런 특별한 scope는 꼭 필요한 곳에만 최소화해서 사용해야 함.</li>
<li>무분별하게 사용하면 유지보수하기 어려워짐</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Spring] 스프링 기본 Section 8 : 빈 생명주기 콜백]]></title>
            <link>https://velog.io/@z00m__in/Spring-%EC%8A%A4%ED%94%84%EB%A7%81-%EA%B8%B0%EB%B3%B8-Section-8-%EB%B9%88-%EC%83%9D%EB%AA%85%EC%A3%BC%EA%B8%B0-%EC%BD%9C%EB%B0%B1</link>
            <guid>https://velog.io/@z00m__in/Spring-%EC%8A%A4%ED%94%84%EB%A7%81-%EA%B8%B0%EB%B3%B8-Section-8-%EB%B9%88-%EC%83%9D%EB%AA%85%EC%A3%BC%EA%B8%B0-%EC%BD%9C%EB%B0%B1</guid>
            <pubDate>Tue, 28 Jun 2022 12:04:15 GMT</pubDate>
            <description><![CDATA[<h1 id="빈-생명주기-콜백-시작">빈 생명주기 콜백 시작</h1>
<ul>
<li>스프링 빈은 간단하게 [객체 생성 --&gt; 의존관계 주입]의 라이프사이클을 가짐.</li>
<li>스프링은 의존관계 주입이 완료되면 스프링 빈에게 콜백 메서드를 통해서 초기화 시점을 알려주는 다양한 기능을 제공</li>
<li>스프링은 스프링 컨테이너가 종료되기 직전에 소멸 콜백<h4 id="스프링-빈의-이벤트-라이프사이클">스프링 빈의 이벤트 라이프사이클</h4>
: 스프링 컨테이너 생성 / 스프링 빈 생성 / 의존관계 주입 / 초기화 콜백 / 사용 / 소멸전 콜백 / 스프링 종료</li>
<li>초기화 콜백: 빈이 생성되고, 빈의 의존관계 주입이 완료된 후 호출</li>
<li>소멸전 콜백: 빈이 소멸되기 직전에 호출<h4 id="빈-생명주기-콜백-지원-방법">빈 생명주기 콜백 지원 방법</h4>
</li>
<li>인터페이스(InitializingBean, DisposableBean)</li>
<li>설정 정보에 초기화 메서드, 종료 메서드 지정</li>
<li>@PostConstruct, @PreDestroy 애노테이션 지</li>
</ul>
<h1 id="인터페이스-initializingbean-disposablebean">인터페이스 InitializingBean, DisposableBean</h1>
<ul>
<li>InitializingBean 은 afterPropertiesSet() 메서드로 초기화를 지원한다.</li>
<li>DisposableBean 은 destroy() 메서드로 소멸을 지원</li>
</ul>
<p>초기화, 소멸 인터페이스 단점</p>
<ul>
<li>해당 코드가 스프링 전용 인터페이스에 의존</li>
<li>초기화, 소멸 메서드의 이름을 변경할 수 없음</li>
<li>내가 코드를 고칠 수 없는 외부 라이브러리에 적용할 수 없음</li>
</ul>
<h1 id="빈-등록-초기화-소멸-메서드-지정">빈 등록 초기화, 소멸 메서드 지정</h1>
<p>: 설정 정보에 초기화, 소멸 메서드를 지정 가능</p>
<h4 id="설정-정보-사용-특징">설정 정보 사용 특징</h4>
<ul>
<li>메서드 이름을 자유롭게</li>
<li>스프링 빈이 스프링 코드에 의존하지 않음</li>
<li>코드가 아니라 설정 정보를 사용하기 때문에 코드를 고칠 수 없는 외부 라이브러리에도 초기화, 종료 메서드를 적용할 수 있음<h4 id="종료-메소드-추론">종료 메소드 추론</h4>
</li>
<li>@Bean의 destroyMethod 는 기본값이 (inferred) (추론)으로 등록되어 있음</li>
<li>이 추론 기능은 close , shutdown 라는 이름의 메서드를 자동으로 호출함.</li>
<li>즉, 이름 그대로 종료 메서드를 추론해서 호출</li>
<li>따라서 직접 스프링 빈으로 등록하면 종료 메서드는 따로 적어주지 않아도 잘 동작<h1 id="애노테이션-postconstruct-predestroy">애노테이션 @PostConstruct, @PreDestroy</h1>
</li>
</ul>
<p>@PostConstruct, @PreDestroy 애노테이션 특징</p>
<ul>
<li>최신 스프링에서 가장 권장하는 방법으로, 애노테이션 하나만 붙이면 되므로 매우 편리</li>
<li>스프링에 종속적인 기술이 아니라 JSR-250 라는 자바 표준이므로 스프링이 아닌 다른 컨테이너에서도 동작</li>
<li>컴포넌트 스캔과 잘 어울림</li>
<li>유일한 단점은 외부 라이브러리에는 적용하지 못한다는 것.</li>
<li>외부 라이브러리를 초기화, 종료 해야 하면 @Bean의 기능을 사용</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Spring] 스프링 기본 Section 7 : 의존관계 자동 주입]]></title>
            <link>https://velog.io/@z00m__in/Spring-%EC%8A%A4%ED%94%84%EB%A7%81-%EA%B8%B0%EB%B3%B8-Section-7-%EC%9D%98%EC%A1%B4%EA%B4%80%EA%B3%84-%EC%9E%90%EB%8F%99-%EC%A3%BC%EC%9E%85</link>
            <guid>https://velog.io/@z00m__in/Spring-%EC%8A%A4%ED%94%84%EB%A7%81-%EA%B8%B0%EB%B3%B8-Section-7-%EC%9D%98%EC%A1%B4%EA%B4%80%EA%B3%84-%EC%9E%90%EB%8F%99-%EC%A3%BC%EC%9E%85</guid>
            <pubDate>Tue, 28 Jun 2022 12:04:13 GMT</pubDate>
            <description><![CDATA[<h1 id="다양한-의존관계-주입-방법">다양한 의존관계 주입 방법</h1>
<h4 id="생성자-주입">생성자 주입</h4>
<p>: 생성자를 통해서 의존 관계를 주입 받는 방법</p>
<ul>
<li>생성자 호출시점에 딱 1번만 호출되는 것이 보장</li>
<li>불변, 필수 의존관계에 사용</li>
<li>생성자가 딱 1개만 있으면 @Autowired를 생략해도 자동 주입 가능<h4 id="수정자-주입setter-주입">수정자 주입(setter 주입)</h4>
: setter라 불리는 필드의 값을 변경하는 수정자 메서드를 통해서 의존관계를 주입하는 방법</li>
<li>선택, 변경 가능성이 있는 의존관계에 사용</li>
<li>자바빈 프로퍼티 규약의 수정자 메서드 방식을 사용하는 방법<h4 id="필드-주입">필드 주입</h4>
: 필드에 바로 주입하는 방법</li>
<li>코드가 간결함</li>
<li>실질적으로는 외부에서 변경이 불가능해서 테스트 하기 힘들다는 치명적인 단점</li>
<li>DI 프레임워크가 없으면 아무것도 할 수 없음</li>
<li>그냥 사용하지 말자 --&gt; 테스트코드나 @Configuration같은 곳에서만<h4 id="일반-메서드-주입">일반 메서드 주입</h4>
: 일반 메서드를 통해서 주입</li>
<li>한번에 여러 필드를 주입 받을 수 있음</li>
<li>일반적으로 잘 사용하지는 않음</li>
</ul>
<h1 id="옵션-처리">옵션 처리</h1>
<ul>
<li>주입할 스프링 빈이 없어도 동작해야 할 때, @Autowired만 사용하면 required 옵션의 기본값이 true 로 되어 있어서 자동 주입 대상이 없으므로 오류 발생</li>
<li>이때, 자동 주입 대상을 옵션으로 처리해야 함<ul>
<li>@Autowired(required=false) : 자동 주입할 대상이 없으면 수정자 메서드 자체가 호출 안됨</li>
<li>org.springframework.lang.@Nullable : 자동 주입할 대상이 없으면 null이 입력됨</li>
<li>Optional&lt;&gt; : 자동 주입할 대상이 없으면 Optional.empty 가 입력됨</li>
</ul>
</li>
</ul>
<h1 id="생성자-주입을-선택해라">생성자 주입을 선택해라!</h1>
<p>과거는 수정자 주입과 필드 주입, 최근에는 생성자 주입을 권장. 권장하는 이유는 다음과 같음</p>
<h4 id="불변">불변</h4>
<ul>
<li>대부분의 의존관계는 애플리케이션 종료 전까지 변하면 안됨. 즉, 불변해야 함.</li>
<li>수정자 주입을 사용하면, setXxx 메서드를 public으로 열어두어야 하는데 변경하면 안되는 메서드를 열어두는 것은 좋은 설계 방법이 아님.</li>
<li>생성자 주입은 객체를 생성할 때 딱 1번만 호출되므로 이후에 호출되는 일이 없어서 불변하게 설계할수 있다<h4 id="누락">누락</h4>
생성자 주입을 사용하면 주입 데이터를 누락 했을 때 컴파일 오류가 발생함.<h4 id="final-키워드">final 키워드</h4>
필드에 final 키워드를 넣어 생성자에서 혹시라도 값이 설정되지 않는 오류를 컴파일 시점에 막아줌.</li>
</ul>
<h1 id="롬복과-최신-트랜드">롬복과 최신 트랜드</h1>
<ul>
<li>최근에는 생성자를 딱 1개 두고, @Autowired 를 생략하는 방법을 주로 사용</li>
<li>여기에 Lombok 라이브러리의 @RequiredArgsConstructor 함께 사용하면 기능은 다 제공하면서, 코드는 깔끔하게 사용 가능<h4 id="롬복-라이브러리-적용-방법">롬복 라이브러리 적용 방법</h4>
</li>
</ul>
<ol>
<li>Preferences(윈도우 File Settings) plugin lombok 검색 설치 실행 (재시작)</li>
<li>Preferences Annotation Processors 검색 Enable annotation processing 체크 (재시작)</li>
<li>임의의 테스트 클래스를 만들고 @Getter, @Setter 확인</li>
</ol>
<h1 id="조회-빈이-2개-이상---문제">조회 빈이 2개 이상 - 문제</h1>
<p>@Autowired 는 타입(Type)으로 조회하므로 선택된 빈이 2개 이상일 때 문제가 발생. 해결방법은 아래와 같음</p>
<h3 id="autowired-필드-명-매칭">@Autowired 필드 명 매칭</h3>
<ol>
<li>타입 매칭</li>
<li>타입 매칭의 결과가 2개 이상일 때 필드 명, 파라미터 명으로 빈 이름 매칭<h3 id="qualifier----qualifier끼리-매칭-빈-이름-매칭">@Qualifier --&gt; @Qualifier끼리 매칭 빈 이름 매칭</h3>
@Qualifier : 추가 구분자를 붙여주는 방법으로, 추가적인 방법을 제공하는 것이지 빈 이름을
변경하는 것은 아님</li>
<li>@Qualifier끼리 매칭</li>
<li>빈 이름 매칭</li>
<li>NoSuchBeanDefinitionException 예외 발생</li>
</ol>
<h3 id="primary-사용">@Primary 사용</h3>
<p>@Primary 는 우선순위를 정하는 방법으로, @Autowired 시에 여러 빈이 매칭되면 @Primary 가 우선권을 가짐</p>
<h1 id="조회한-빈이-모두-필요할-때-list-map">조회한 빈이 모두 필요할 때, List, Map</h1>
<p>해당 타입의 스프링 빈이 다 필요한 경우 사용</p>
<h1 id="자동-수동의-올바른-실무-운영-기준">자동, 수동의 올바른 실무 운영 기준</h1>
<h4 id="편리한-자동-기능을-기본으로-사용하자">편리한 자동 기능을 기본으로 사용하자</h4>
<h4 id="수동-빈-등록은-업무-로직-빈-또는-기술-지원-빈에-사용">수동 빈 등록은 업무 로직 빈 또는 기술 지원 빈에 사용</h4>
<ul>
<li>업무 로직 빈: 웹을 지원하는 컨트롤러, 핵심 비즈니스 로직이 있는 서비스, 데이터 계층의 로직을 처리하는 리포지토리 등. 보통 비즈니스 요구사항을 개발할 때 추가되거나 변경됨</li>
<li>기술 지원 빈: 기술적인 문제나 공통 관심사(AOP)를 처리할 때 주로 사용. 데이터베이스 연결이나, 공통 로그 처리 처럼 업무 로직을 지원하기 위한 하부 기술이나 공통 기술<h4 id="애플리케이션에-광범위하게-영향을-미치는-기술-지원-객체는-수동-빈으로-등록해서-설정-정보에-바로-나타나게-하는-것이-유지보수-하기-좋다">애플리케이션에 광범위하게 영향을 미치는 기술 지원 객체는 수동 빈으로 등록해서 설정 정보에 바로 나타나게 하는 것이 유지보수 하기 좋다.</h4>
<h4 id="비즈니스-로직-중에서-다형성을-적극-활용할-때-특정-패키지에-같이-묶어-두기">비즈니스 로직 중에서 다형성을 적극 활용할 때 특정 패키지에 같이 묶어 두기</h4>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Spring] 스프링 기본 Section 6 : 컴포넌트 스캔]]></title>
            <link>https://velog.io/@z00m__in/Spring-%EC%8A%A4%ED%94%84%EB%A7%81-%EA%B8%B0%EB%B3%B8-Section-6-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EC%8A%A4%EC%BA%94</link>
            <guid>https://velog.io/@z00m__in/Spring-%EC%8A%A4%ED%94%84%EB%A7%81-%EA%B8%B0%EB%B3%B8-Section-6-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EC%8A%A4%EC%BA%94</guid>
            <pubDate>Tue, 28 Jun 2022 12:04:10 GMT</pubDate>
            <description><![CDATA[<h1 id="컴포넌트-스캔과-의존관계-자동-주입-시작하기">컴포넌트 스캔과 의존관계 자동 주입 시작하기</h1>
<ul>
<li>스프링 빈을 등록할 때, 자바 코드의 @Bean이나 XML의 bean 등을 통해서 설정 정보에 직접 등록할 스프링 빈을 나열한다면 불필요한 반복이 많아짐</li>
<li>컴포넌트 스캔 기능 : 설정 정보가 없어도 자동으로 스프링 빈을 등록하는 기능
  -&gt; @Component 애노테이션이 붙은 클래스를 스캔해서 스프링 빈으로 등록</li>
<li>@Autowired 기능 : 의존관계도 자동으로 주입하는 기능
  -&gt; 생성자에서 여러 의존관계도 한번에 주입받을 수 있음
<img src="https://velog.velcdn.com/images/z00m__in/post/71e76610-6378-40b8-8e64-5a1a529c2422/image.png" alt="">
<img src="https://velog.velcdn.com/images/z00m__in/post/7acea5a5-3882-438f-aa2d-356bb1341f54/image.png" alt=""></li>
</ul>
<h1 id="탐색-위치와-기본-스캔-대상">탐색 위치와 기본 스캔 대상</h1>
<h4 id="탐색할-패키지의-시작-위치-지정">탐색할 패키지의 시작 위치 지정</h4>
<p>모든 클래스를 스캔하려면 오래 걸리니 꼭 필요한 위치부터 탐색해야 함
패키지 위치를 지정하지 않고, 설정 정보 클래스의 위치를 프로젝트 최상단에 두는 것을 추천</p>
<ul>
<li>bsePackages : 탐색할 패키지의 시작 위치를 지정한다. 이 패키지를 포함해서 하위 패키지를 모두 탐색</li>
<li>basePackageClasses : 지정한 클래스의 패키지를 탐색 시작 위치로 지정.</li>
<li>지정된 바 없을 시, @ComponentScan 붙은 패키지가 시작 위치<h4 id="컴포넌트-스캔-대상">컴포넌트 스캔 대상</h4>
: @Component 뿐만 아니라 아래 내용 포함</li>
<li>@Component : 컴포넌트 스캔에서 사용 / 스프링 MVC 컨트롤러로 인식 기능 포함</li>
<li>@Controlller : 스프링 MVC 컨트롤러에서 사용</li>
<li>@Service : 스프링 비즈니스 로직에서 사용</li>
<li>@Repository : 스프링 데이터 접근 계층에서 사용 / 스프링 데이터 접근 계층으로 인식하고, 데이터 계층의 예외를 스프링 예외로 변환하는 기능 포함</li>
<li>@Configuration : 스프링 설정 정보에서 사용 / 스프링 설정 정보로 인식하고, 스프링 빈이 싱글톤을 유지하도록 추가 처리하는 기능 포함<h1 id="필터">필터</h1>
</li>
<li>includeFilters : 컴포넌트 스캔 대상을 추가로 지정</li>
<li>excludeFilters : 컴포넌트 스캔에서 제외할 대상을 지정<h4 id="filtertype-옵션">FilterType 옵션</h4>
</li>
<li>ANNOTATION: 기본값, 애노테이션을 인식해서 동작한다.</li>
<li>ASSIGNABLE_TYPE: 지정한 타입과 자식 타입을 인식해서 동작한다.</li>
<li>ASPECTJ: AspectJ 패턴 사용</li>
<li>REGEX: 정규 표현식</li>
<li>CUSTOM: TypeFilter 이라는 인터페이스를 구현해서 처리<h1 id="중복-등록과-충돌">중복 등록과 충돌</h1>
같은 빈 이름을 등록할 때의 충돌</li>
<li>자동 빈 등록과 자동 빈 등록이 충돌된다면, ConflictingBeanDefinitionException 예외 발생</li>
<li>자동 빈 등록과 수동 빈 등록이 충돌된다면, 수동 빈 등록이 우선권을 가짐</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Spring] 스프링 기본 Section 5 : 싱글톤 컨테이너]]></title>
            <link>https://velog.io/@z00m__in/Spring-%EC%8A%A4%ED%94%84%EB%A7%81-%EA%B8%B0%EB%B3%B8-Section-5-%EC%8B%B1%EA%B8%80%ED%86%A4-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88</link>
            <guid>https://velog.io/@z00m__in/Spring-%EC%8A%A4%ED%94%84%EB%A7%81-%EA%B8%B0%EB%B3%B8-Section-5-%EC%8B%B1%EA%B8%80%ED%86%A4-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88</guid>
            <pubDate>Tue, 28 Jun 2022 12:04:07 GMT</pubDate>
            <description><![CDATA[<h1 id="웹-애플리케이션과-싱글톤">웹 애플리케이션과 싱글톤</h1>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/c980fa2c-76c4-4a2a-afcc-159c0b14a5da/image.PNG" alt=""></p>
<ul>
<li><p>스프링은 기업용 온라인 서비스 기술을 지원하기 위해 탄생</p>
</li>
<li><p>대부분의 스프링 애플리케이션은 웹 애플리케이션 (다른 애플리케이션도 다수)</p>
</li>
<li><p>웹 애플리케이션은 보통 여러 고객의 동시 요청</p>
</li>
<li><p>기존에 생성했던 AppConfig의 문제점
: 메모리 낭비가 심함 (요청을 할 때 마다 객체를 새로 생성)</p>
</li>
<li><p>해결책: 해당 객체가 딱 1개만 생성되고, 공유하도록 설계 ==&gt; 싱글톤</p>
<h1 id="싱글톤-패턴">싱글톤 패턴</h1>
</li>
<li><p>클래스의 인스턴스가 딱 1개만 생성되는 것을 보장하는 디자인 패턴</p>
</li>
<li><p>객체 인스턴스를 2개 이상 생성하지 못하도록 막아야 함</p>
</li>
<li><p>private 생성자를 사용해서 외부에서 임의로 new 키워드를 사용하지 못하도록 막아야 함</p>
</li>
</ul>
<h4 id="싱글톤-패턴-구현하는-방법">싱글톤 패턴 구현하는 방법</h4>
<ul>
<li>고객의 요청이 올 때 마다 객체를 생성하는 것이 아니라, 이미 만들어진 객체를 공유</li>
</ul>
<h4 id="싱글톤-패턴의-문제점">싱글톤 패턴의 문제점</h4>
<ul>
<li>싱글톤 패턴을 구현하는 코드 자체가 많이 들어감</li>
<li>의존관계상 클라이언트가 구체 클래스에 의존하므로 DIP를 위반</li>
<li>클라이언트가 구체 클래스에 의존해서 OCP 원칙을 위반할 가능성이 높음</li>
<li>테스트하기 어려움</li>
<li>내부 속성을 변경하거나 초기화 하기 어려움</li>
<li>private 생성자로 자식 클래스를 만들기 어려움</li>
<li>결론적으로 유연성이 떨어짐</li>
<li>안티패턴으로 불리기도 함</li>
</ul>
<h1 id="싱글톤-컨테이너">싱글톤 컨테이너</h1>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/06446d41-020f-4776-a620-9dfa98dd868a/image.png" alt=""></p>
<ul>
<li>스프링 컨테이너: 싱글턴 패턴을 적용하지 않아도, 객체 인스턴스를 싱글톤으로 관리함. 객체를 하나만 생성해서 관리하기 때문.</li>
<li>즉, 스프링 컨테이너는 싱글톤 컨테이너 역할을 함.</li>
<li>이렇게 싱글톤 객체를 생성하고 관리하는 기능을 싱글톤 레지스트리라 함</li>
<li>스프링 컨테이너의 이런 기능 덕분에<ul>
<li>싱글톤 패턴을 위한 지저분한 코드가 들어가지 않아도 됨</li>
<li>DIP, OCP, 테스트, private 생성자로 부터 자유롭게 싱글톤을 사용할 수 있다</li>
<li>객체를 싱글톤으로 유지할 수 있음<h1 id="싱글톤-방식의-주의점">싱글톤 방식의 주의점</h1>
</li>
</ul>
</li>
<li>여러 클라이언트가 하나의 같은 객체 인스턴스를 공유하기 때문에, 싱글톤 객체는 상태를 유지(stateful)하게 설계하면 안되며 무상태(stateless)로 설계해야 함<ul>
<li>특정 클라이언트에 의존적인 필드가 있으면 안됨</li>
<li>특정 클라이언트가 값을 변경할 수 있는 필드가 있으면 안됨</li>
<li>가급적 읽기만 가능해야 함</li>
<li>필드 대신에 자바에서 공유되지 않는, 지역변수, 파라미터, ThreadLocal 등을 사용해야 함</li>
</ul>
</li>
<li>즉, 스프링 빈의 필드에 공유 값을 설정하면 안됨<h1 id="configuration과-싱글톤">@Configuration과 싱글톤</h1>
</li>
</ul>
<h1 id="configuration과-바이트코드-조작의-마법">@Configuration과 바이트코드 조작의 마법</h1>
<p>스프링 컨테이너는 싱글톤 레지스트리이므로 스프링 빈이 싱글톤이 되도록 보장해주어야 함.</p>
<ul>
<li>@Bean만 사용해도 스프링 빈으로 등록되지만, 싱글톤을 보장하지 않는다.</li>
<li>memberRepository() 처럼 의존관계 주입이 필요해서 메서드를 직접 호출할 때 싱글톤을 보장하지 않는 것</li>
<li>크게 고민할 것이 없이 스프링 설정 정보는 항상 @Configuration 을 사용하면 됨</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Spring] 스프링 기본 Section 4 : 스프링 컨테이너와 스프링 빈]]></title>
            <link>https://velog.io/@z00m__in/Spring-%EC%8A%A4%ED%94%84%EB%A7%81-%EA%B8%B0%EB%B3%B8-Section-4-%EC%8A%A4%ED%94%84%EB%A7%81-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88%EC%99%80-%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B9%88</link>
            <guid>https://velog.io/@z00m__in/Spring-%EC%8A%A4%ED%94%84%EB%A7%81-%EA%B8%B0%EB%B3%B8-Section-4-%EC%8A%A4%ED%94%84%EB%A7%81-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88%EC%99%80-%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B9%88</guid>
            <pubDate>Mon, 20 Jun 2022 22:48:26 GMT</pubDate>
            <description><![CDATA[<h1 id="스프링-컨테이너-생성과정">스프링 컨테이너 생성과정</h1>
<h2 id="스프링-컨테이너-생성">스프링 컨테이너 생성</h2>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/b506d5c5-957f-4f55-9e2d-107c4682daf4/image.PNG" alt=""></p>
<h2 id="스프링-빈-등록">스프링 빈 등록</h2>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/d528fe16-2140-4515-8569-f942e4565bba/image.png" alt=""></p>
<h2 id="스프링-빈-의존관계-설정---준비">스프링 빈 의존관계 설정 - 준비</h2>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/e9f51ae4-3904-4c00-afd3-894d09f4bba0/image.PNG" alt=""></p>
<h2 id="스프링-빈-의존관계-설정---완료">스프링 빈 의존관계 설정 - 완료</h2>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/bd321c28-65f5-4d9f-b4eb-b3e4b9fdbbbb/image.png" alt=""></p>
<h1 id="스프링-빈-조회---기본">스프링 빈 조회 - 기본</h1>
<ul>
<li>스프링 빈 찾는 가장 기본적인 조회 방법
  ac.getBean(빈이름, 타입)
  ac.getBean(타입)</li>
</ul>
<h1 id="스프링-빈-조회---동일한-타입이-둘-이상">스프링 빈 조회 - 동일한 타입이 둘 이상</h1>
<p>타입으로 조회시 같은 타입의 스프링 빈이 둘 이상이면 오류 발생
==&gt; 빈 이름을 지정
==&gt; ac.getBeansOfType() 을 사용하면 해당 타입의 모든 빈을 조회</p>
<h1 id="스프링-빈-조회---상속관계">스프링 빈 조회 - 상속관계</h1>
<p>: 부모 타입으로 조회하면, 자식 타입도 함께 조회
    자바 객체의 최고 부모인 Object 타입으로 조회하면, 모든 스프링 빈을 조회</p>
<h1 id="beanfactory와-applicationcontext">BeanFactory와 ApplicationContext</h1>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/3c085895-a520-4a1e-8a59-33accc1ad27f/image.png" alt=""></p>
<h2 id="beanfactory">BeanFactory</h2>
<ul>
<li>스프링 컨테이너의 최상위 인터페이스</li>
<li>스프링 빈을 관리하고 조회하는 역할을 담당</li>
<li>getBean() 을 제공<h2 id="applicationcontext">ApplicationContext</h2>
</li>
<li>BeanFactory 기능을 모두 상속받아서 제공</li>
<li>애플리케이션을 개발할 때는 빈을 관리하고 조회하는 기능은 물론이고, 수 많은 부가기능이 필요
<img src="https://velog.velcdn.com/images/z00m__in/post/d420a68f-5da1-4272-8aaf-bde5480a26f1/image.png" alt=""></li>
</ul>
<h1 id="다양한-설정-형식-지원---자바-코드-xml">다양한 설정 형식 지원 - 자바 코드, XML</h1>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/1c574fd8-ffd8-48df-9369-5ddd3213a73b/image.png" alt=""></p>
<h1 id="스프링-빈-설정-메타-정보---beandefinition">스프링 빈 설정 메타 정보 - BeanDefinition</h1>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/f64f663b-e847-4097-8e20-a807bb9164d2/image.png" alt=""></p>
<h2 id="beandefinition">BeanDefinition</h2>
<hr>
<p>본 포스트는 김영하의 <em><strong>&lt;스프링 핵심 원리 - 기본편&gt;</strong></em> 강좌를 바탕으로 작성한 포스트입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Spring] 스프링 기본 Section 3 : 스프링 핵심 원리 이해2 - 객체 지향 원리 적용]]></title>
            <link>https://velog.io/@z00m__in/Spring-%EC%8A%A4%ED%94%84%EB%A7%81-%EA%B8%B0%EB%B3%B8-Section-3-%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EC%9D%B4%ED%95%B42-%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5-%EC%9B%90%EB%A6%AC-%EC%A0%81%EC%9A%A9</link>
            <guid>https://velog.io/@z00m__in/Spring-%EC%8A%A4%ED%94%84%EB%A7%81-%EA%B8%B0%EB%B3%B8-Section-3-%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EC%9D%B4%ED%95%B42-%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5-%EC%9B%90%EB%A6%AC-%EC%A0%81%EC%9A%A9</guid>
            <pubDate>Mon, 20 Jun 2022 22:48:17 GMT</pubDate>
            <description><![CDATA[<h1 id="새로운-할인-정책-개발">새로운 할인 정책 개발</h1>
<h2 id="새로운-할인-정책-확장">새로운 할인 정책 확장</h2>
<p>기존: 고객의 랭크에 따라 할인율 --&gt; 금액마다 일괄적인 퍼센테지 적용
변경: 금액당 할인하는 정률% 할인
    ex) 만원 주문시 천원 할인, 이만원 주문시 이천원 할인</p>
<h2 id="ratediscountpolicy-추가">RateDiscountPolicy 추가</h2>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/34b95f12-aa9a-4fbb-824a-1c7d47a12250/image.PNG" alt=""></p>
<h2 id="테스트-작성">테스트 작성</h2>
<h1 id="새로운-할인-정책-적용과-문제점">새로운 할인 정책 적용과 문제점</h1>
<h2 id="새로운-할인-정책-적용">새로운 할인 정책 적용</h2>
<p>클라이언트의 OrderServiceImpl 코드 수정</p>
<h2 id="문제점">문제점</h2>
<ul>
<li>역할과 구현의 분리</li>
<li>다형성 활용, 인터페이스와 구현 객체의 분리</li>
<li>DIP 객체지향 설계 원칙 준수?
  ==&gt; 클래스 의존관계 상, 인터페이스(추상) 뿐만 아니라 구현(구체) 클래스에도 의존중<pre><code>  * 추상: DiscountPolicy
  * 구체: FixDiscountPolicy, RateDiscountPolicy</code></pre></li>
<li>OCP 객체지향 설계 원칙 준수?
  ==&gt; 기능을 확장해서 변경하면 클라이언트 코드에 영향을 주므로 OCP 위반<h2 id="의존관계-분석">의존관계 분석</h2>
<h4 id="예상-의존관계">예상 의존관계</h4>
: DiscountPolicy 에만 의존
<img src="https://velog.velcdn.com/images/z00m__in/post/aa3fb3f4-f821-4ed2-996a-a59df00e6674/image.PNG" alt=""></li>
</ul>
<h4 id="실제-의존관계">실제 의존관계</h4>
<p>: DiscountPolicy 뿐만 아니라 FixDiscountPolicy에도 함께 의존하므로 DIP 위반
<img src="https://velog.velcdn.com/images/z00m__in/post/12c7df2b-e78f-42c7-bc44-84d25096bf25/image.PNG" alt=""></p>
<h2 id="정책-변경-시">정책 변경 시</h2>
<p>: FixDiscountPolicy 를 RateDiscountPolicy 로 변경하면 OrderServiceImpl 의 소스 코드도 함께 변경해야 하므로 OCP 위반
<img src="https://velog.velcdn.com/images/z00m__in/post/a849f212-5743-4de6-9805-ad9c5ce608e0/image.PNG" alt=""></p>
<h2 id="해결---의존관계-변경">해결 - 의존관계 변경</h2>
<p>: DIP를 위반하지 않도록 추상 인터페이스에만 의존하도록 의존관계를 변경
<img src="https://velog.velcdn.com/images/z00m__in/post/08e6ba2e-06f4-41e6-9e83-a7ac67c847a3/image.PNG" alt=""></p>
<ul>
<li>구현체가 없으므로, 코드 실행을 위해선
누군가가 클라이언트인 OrderServiceImpl 에 DiscountPolicy 의 구현 객체를
대신 생성하고 주입해주어야 함</li>
</ul>
<h1 id="관심사의-분리">관심사의 분리</h1>
<p>추상과 구현의 보다 명확한 분리가 필요함</p>
<h1 id="appconfig-등장">AppConfig 등장</h1>
<p>: 구현 객체를 생성하고, 연결하는 책임을 가지는 별도의 설정 클래스 생성</p>
<h2 id="appconfig">AppConfig</h2>
<ul>
<li>실제 동작에 필요한 구현 객체 생성<pre><code>  * MemberServiceImpl
  * MemoryMemberRepository
  * OrderServiceImpl
  * FixDiscountPolicy</code></pre></li>
<li>생성한 객체 인스턴스의 참조를 생성자를 통해서 주입<pre><code>  * MemberServiceImpl --&gt; MemoryMemberRepository
  * OrderServiceImpl --&gt; MemoryMemberRepository , FixDiscountPolicy</code></pre></li>
</ul>
<h2 id="memberserviceimpl---생성자-주입">MemberServiceImpl - 생성자 주입</h2>
<ul>
<li>생성자를 통해 어떤 구현 객체가 들어올지(주입될지)는 알 수 없으며, 오직 외부( AppConfig )에서 결정됨</li>
<li>즉, 의존관계에 대한 고민은 외부에 맡기고 실행에만 집중</li>
</ul>
<h2 id="클래스-다이어그램">클래스 다이어그램</h2>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/00819821-34de-4b87-bc8a-30a4a840c885/image.PNG" alt=""></p>
<ul>
<li>생성과 연결은 AppConfig 가 담당</li>
<li>DIP 완성: MemberServiceImpl 은 MemberRepository 인 추상에만 의존하면 되고, 구체 클래스를 몰라도 됨</li>
<li>관심사의 분리: 객체를 생성하고 연결하는 역할과 실행하는 역할이 명확히 분리</li>
</ul>
<h2 id="회원-객체-인스턴스-다이어그램">회원 객체 인스턴스 다이어그램</h2>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/6637a1cb-04be-4a46-ab3e-db89be605ea0/image.PNG" alt=""></p>
<ul>
<li>appConfig 객체는 memoryMemberRepository 객체를 생성하고 그 참조값을 memberServiceImpl 을 생성하면서 생성자로 전달</li>
<li>클라이언트인 memberServiceImpl 입장에서 보면 의존관계를 마치 외부에서 주입해주는 것 같다고 해서 DI(Dependency Injection) 우리말로 의존관계 주입 또는 의존성 주입이라 함</li>
</ul>
<h2 id="orderserviceimpl---생성자-주입">OrderServiceImpl - 생성자 주입</h2>
<ul>
<li>설계 변경으로 OrderServiceImpl 은 FixDiscountPolicy 를 의존하지 않고 DiscountPolicy 인터페이스만 의존</li>
</ul>
<h1 id="appconfig-실행">AppConfig 실행</h1>
<p>==&gt; 관심사를 확실히 분리해, AppConfic는 구체 클래스를 선택하는 역할</p>
<h2 id="사용-클래스---memberapp">사용 클래스 - MemberApp</h2>
<h2 id="사용-클래스---orderapp">사용 클래스 - OrderApp</h2>
<h2 id="오류-수정">오류 수정</h2>
<h2 id="정리">정리</h2>
<ul>
<li>문제: 중복이 있고, 역할에 따른 구현이 잘 안보임</li>
</ul>
<h1 id="appconfig-리팩터링">AppConfig 리팩터링</h1>
<h2 id="기대하는-그림">기대하는 그림</h2>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/42def2b7-1795-4fa0-ab71-96fa6cab9bda/image.png" alt=""></p>
<h2 id="리팩터링-결과">리팩터링 결과</h2>
<p>중복 제거, 역할에 따른 구현 보이도록</p>
<h1 id="새로운-구조와-할인-정책-적용">새로운 구조와 할인 정책 적용</h1>
<p>: 정액 할인 정책(FixDiscountPolicy)을 정률% 할인 정책(RateDiscountPolicy)으로 변경</p>
<h2 id="사용영역과-구성영역의-분리">사용영역과 구성영역의 분리</h2>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/92587e00-c9fa-46f6-af76-c460e9324e33/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/4a1db12b-f232-4dc9-a0a4-b37813a1c6c5/image.png" alt=""></p>
<h1 id="전체-흐름-정리">전체 흐름 정리</h1>
<h2 id="새로운-할인-정책-개발-1">새로운 할인 정책 개발</h2>
<p>다형성 덕분에 새로운 정률 할인 정책 코드를 추가로 개발하는 것 자체는 아무 문제가 없음</p>
<h2 id="새로운-할인-정책-적용과-문제점-1">새로운 할인 정책 적용과 문제점</h2>
<p>DIP 위반
     ==&gt; 주문 서비스 클라이언트가 인터페이스인 DiscountPolicy 뿐만 아니라, 구체 클래스인
FixDiscountPolicy 도 함께 의존</p>
<h2 id="관심사의-분리-1">관심사의 분리</h2>
<p>: 클라이언트 객체는 자신의 역할을 실행하는 것만 집중, 권한이 줄어듬(책임이 명확해짐)</p>
<h2 id="appconfig-리팩터링-1">AppConfig 리팩터링</h2>
<p>:구성 정보에서 역할과 구현을 명확하게 분리 --&gt; 역할 잘 드러나고 중복 제거</p>
<h2 id="새로운-구조와-할인-정책-적용-1">새로운 구조와 할인 정책 적용</h2>
<ul>
<li>정액 할인 정책 정률% 할인 정책</li>
<li>AppConfig의 등장으로 애플리케이션이 크게 사용 영역과, 객체를 생성하고 구성(Configuration)하는
영역으로 분리</li>
<li>할인 정책을 변경해도 AppConfig가 있는 구성 영역만 변경</li>
</ul>
<h1 id="좋은-객체-지향-설계의-5가지-원칙의-적용">좋은 객체 지향 설계의 5가지 원칙의 적용</h1>
<h2 id="srp-단일-책임-원칙br---한-클래스는-하나의-책임만-가져야-한다">SRP 단일 책임 원칙<br> - 한 클래스는 하나의 책임만 가져야 한다.</h2>
<p>: 클라이언트 객체는 직접 구현 객체를 생성하고, 연결하고, 실행하는 다양한 책임</p>
<h2 id="dip-의존관계-역전-원칙br---의존성-주입은-이-원칙을-따르는-방법-중-하나다">DIP 의존관계 역전 원칙<br> - 의존성 주입은 이 원칙을 따르는 방법 중 하나다</h2>
<p>: AppConfig가 FixDiscountPolicy 객체 인스턴스를 클라이언트 코드 대신 생성해서 클라이언트
코드에 의존관계를 주입</p>
<h2 id="ocpbr---소프트웨어-요소는-확장에는-열려-있으나-변경에는-닫혀-있어야-한다">OCP<br> - 소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다</h2>
<p>: 다형성 사용하고 클라이언트가 DIP를 지킴 ~ 소프트웨어 요소를 새롭게 확장해도 사용 영역의 변경은 닫혀</p>
<h1 id="ioc-di-그리고-컨테이너">IoC, DI, 그리고 컨테이너</h1>
<h2 id="제어의-역전-ioc">제어의 역전 IoC</h2>
<p>: 프로그램의 제어 흐름을 직접 제어하는 것이 아니라 외부에서 관리하는 것</p>
<h4 id="프레임워크-vs-라이브러리">프레임워크 vs 라이브러리</h4>
<ul>
<li>프레임워크: 내가 작성한 코드를 제어하고, 대신 실행</li>
<li>라이브러리: 내가 작성한 코드가 직접 제어의 흐름을 담당<h2 id="의존관계-주입-di">의존관계 주입 DI</h2>
</li>
<li><blockquote>
<p>정적인 클래스 의존 관계와, 실행 시점에 결정되는 동적인 객체(인스턴스) 의존 관계 둘을
분리</p>
</blockquote>
<h4 id="정적인-클래스-의존관계">정적인 클래스 의존관계</h4>
:애플리케이션을 실행하지 않아도 클래스 다이어그램으로 분석 가능, 단, 실제 어떤 객체가 OrderServiceImpl 에 주입 될지 알 수 없음<h4 id="클래스-다이어그램-1">클래스 다이어그램</h4>
<img src="https://velog.velcdn.com/images/z00m__in/post/20ed32a0-2884-4007-bd61-bfa2d1980598/image.png" alt=""><h4 id="동적인-객체-인스턴스-의존-관계">동적인 객체 인스턴스 의존 관계</h4>
:애플리케이션 실행 시점에 실제 생성된 객체 인스턴스의 참조가 연결된 의존 관계<h4 id="객체-다이어그램">객체 다이어그램</h4>
<img src="https://velog.velcdn.com/images/z00m__in/post/98977dae-7add-4479-ba5b-f024f76fb699/image.png" alt=""></li>
</ul>
<h2 id="ioc-컨테이너-di-컨테이너">IoC 컨테이너, DI 컨테이너</h2>
<p>:AppConfig 처럼 객체를 생성하고 관리하면서 의존관계를 연결해 주는 것
    (DI : 의존관계 주입에 초점)</p>
<h1 id="스프링으로-전환하기">스프링으로 전환하기</h1>
<h2 id="appconfig-스프링-기반으로-변경">AppConfig 스프링 기반으로 변경</h2>
<h2 id="memberapp에-스프링-컨테이너-적용">MemberApp에 스프링 컨테이너 적용</h2>
<h2 id="orderapp에-스프링-컨테이너-적용">OrderApp에 스프링 컨테이너 적용</h2>
<h2 id="스프링-컨테이너">스프링 컨테이너</h2>
<hr>
<p>본 포스트는 김영하의 <em><strong>&lt;스프링 핵심 원리 - 기본편&gt;</strong></em> 강좌를 바탕으로 작성한 포스트입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Spring] 스프링 기본 Section 2 : 스프링 핵심 원리 이해1 - 예제 만들기]]></title>
            <link>https://velog.io/@z00m__in/Spring-%EC%8A%A4%ED%94%84%EB%A7%81-%EA%B8%B0%EB%B3%B8-Section-2-%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EC%9D%B4%ED%95%B41-%EC%98%88%EC%A0%9C-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@z00m__in/Spring-%EC%8A%A4%ED%94%84%EB%A7%81-%EA%B8%B0%EB%B3%B8-Section-2-%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EC%9D%B4%ED%95%B41-%EC%98%88%EC%A0%9C-%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Mon, 30 May 2022 22:17:03 GMT</pubDate>
            <description><![CDATA[<p>포인트 : 인터페이스와 객체를 나누어 개발</p>
<h1 id="프로젝트-생성">프로젝트 생성</h1>
<p><a href="https://velog.io/@z00m__in/Spring-%EC%8A%A4%ED%94%84%EB%A7%81-%EC%9E%85%EB%AC%B8-Section-1-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%ED%99%98%EA%B2%BD-%EC%84%A4%EC%A0%95">https://velog.io/@z00m__in/Spring-%EC%8A%A4%ED%94%84%EB%A7%81-%EC%9E%85%EB%AC%B8-Section-1-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%ED%99%98%EA%B2%BD-%EC%84%A4%EC%A0%95</a>
위 링크의 &lt;프로젝트 생성&gt; 참고</p>
<h1 id="비즈니스-요구사항과-설계">비즈니스 요구사항과 설계</h1>
<h2 id="회원">회원</h2>
<ul>
<li>회원을 가입하고 조회할 수 있다.</li>
<li>회원은 일반과 VIP 두 가지 등급이 있다.</li>
<li>회원 데이터는 자체 DB를 구축할 수 있고, 외부 시스템과 연동할 수 있다. (미확정)<h2 id="주문과-할인정책">주문과 할인정책</h2>
</li>
<li>회원은 상품을 주문할 수 있다.</li>
<li>회원 등급에 따라 할인 정책을 적용할 수 있다.</li>
<li>할인 정책은 모든 VIP는 1000원을 할인해주는 고정 금액 할인을 적용해달라. (나중에 변경 될 수 있다.)</li>
<li>할인 정책은 변경 가능성이 높다. 회사의 기본 할인 정책을 아직 정하지 못했고, 오픈 직전까지 고민을 미루고 싶다. 최악의 경우 할인을 적용하지 않을 수 도 있다. (미확정)</li>
</ul>
<h1 id="회원-도메인-설계">회원 도메인 설계</h1>
<h2 id="회원-도메인-요구사항">회원 도메인 요구사항</h2>
<ul>
<li>회원을 가입하고 조회할 수 있다.</li>
<li>회원은 일반과 VIP 두 가지 등급이 있다.</li>
<li>회원 데이터는 자체 DB를 구축할 수 있고, 외부 시스템과 연동할 수 있다.<h2 id="회원-도메인-협력관계">회원 도메인 협력관계</h2>
<img src="https://velog.velcdn.com/images/z00m__in/post/dcf6cabe-b4e1-40c0-b9c1-87b1eb44cf97/image.PNG" alt=""></li>
</ul>
<h2 id="회원-클래스-다이어그램">회원 클래스 다이어그램</h2>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/f7b3a8d7-b355-4918-80e5-311113b488c8/image.PNG" alt=""></p>
<h2 id="회원-객체-다이어그램">회원 객체 다이어그램</h2>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/1abd7542-9836-4cbb-be35-b33517f51fe7/image.PNG" alt=""></p>
<h1 id="회원-도메인-개발">회원 도메인 개발</h1>
<h2 id="회원-엔티티">회원 엔티티</h2>
<h3 id="회원-등급">회원 등급</h3>
<h3 id="회원-엔티티-1">회원 엔티티</h3>
<h2 id="회원-저장소">회원 저장소</h2>
<h3 id="회원-저장소-인터페이스">회원 저장소 인터페이스</h3>
<h3 id="메모리-회원-저장소-구현체">메모리 회원 저장소 구현체</h3>
<h2 id="회원서비스">회원서비스</h2>
<h3 id="회원-서비스-인터페이스">회원 서비스 인터페이스</h3>
<h3 id="회원-서비스-구현체">회원 서비스 구현체</h3>
<h1 id="회원-도메인-실행과-테스트">회원 도메인 실행과 테스트</h1>
<h3 id="회원-도메인---회원-가입-main">회원 도메인 - 회원 가입 MAIN</h3>
<h3 id="회원-도메인---회원-가입-테스트">회원 도메인 - 회원 가입 테스트</h3>
<h1 id="주문과-할인-도메인-설계">주문과 할인 도메인 설계</h1>
<h2 id="요구사항">요구사항</h2>
<ul>
<li>회원은 상품을 주문할 수 있다.</li>
<li>회원 등급에 따라 할인 정책을 적용할 수 있다.</li>
<li>할인 정책은 모든 VIP는 1000원을 할인해주는 고정 금액 할인을 적용해달라. (나중에 변경 될 수 있다.)</li>
<li>할인 정책은 변경 가능성이 높다. 회사의 기본 할인 정책을 아직 정하지 못했고, 오픈 직전까지 고민을 미루고 싶다. 최악의 경우 할인을 적용하지 않을 수 도 있다. (미확정)<h3 id="주문-도메인-협력-역할-책임">주문 도메인 협력, 역할, 책임</h3>
<img src="https://velog.velcdn.com/images/z00m__in/post/5b43e2b1-6d27-4bd0-b283-a92090fa22fd/image.PNG" alt=""></li>
</ul>
<h3 id="주문-도메인-전체">주문 도메인 전체</h3>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/03ee71cc-ea0b-4f73-bd2d-f7c64083a3aa/image.PNG" alt=""></p>
<h3 id="주문-도메인-클래스-다이어그램">주문 도메인 클래스 다이어그램</h3>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/7497baa0-9d51-4c31-b0fb-8dee05a60179/image.PNG" alt=""></p>
<h3 id="주문-도메인-객체-다이어그램-1">주문 도메인 객체 다이어그램 1</h3>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/43f02db6-f564-4935-beaf-c273dc5980dd/image.PNG" alt=""></p>
<h3 id="주문-도메인-객체-다이어그램-2">주문 도메인 객체 다이어그램 2</h3>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/8b456ae5-e2cd-4495-934d-d6828207d944/image.PNG" alt=""></p>
<h1 id="주문과-할인-도메인-개발">주문과 할인 도메인 개발</h1>
<h3 id="할인-정책-인터페이스">할인 정책 인터페이스</h3>
<h3 id="정액-할인-정책-구현체">정액 할인 정책 구현체</h3>
<h3 id="주문-엔티티">주문 엔티티</h3>
<h3 id="주문-서비스-인터페이스">주문 서비스 인터페이스</h3>
<h3 id="주문-서비스-구현체">주문 서비스 구현체</h3>
<h1 id="주문과-할인-도메인-실행과-테스트">주문과 할인 도메인 실행과 테스트</h1>
<h2 id="주문과-할인-정책-실행">주문과 할인 정책 실행</h2>
<h2 id="주문과-할인-정책-테스트">주문과 할인 정책 테스트</h2>
<hr>
<p>본 포스트는 김영하의 <em><strong>&lt;스프링 핵심 원리 - 기본편&gt;</strong></em> 강좌를 바탕으로 작성한 포스트입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Spring] 스프링 기본 Section 1 : 객체지향 설계와 스프링]]></title>
            <link>https://velog.io/@z00m__in/Spring-%EC%8A%A4%ED%94%84%EB%A7%81-%EA%B8%B0%EB%B3%B8-Section-1-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%EC%84%A4%EA%B3%84%EC%99%80-%EC%8A%A4%ED%94%84%EB%A7%81</link>
            <guid>https://velog.io/@z00m__in/Spring-%EC%8A%A4%ED%94%84%EB%A7%81-%EA%B8%B0%EB%B3%B8-Section-1-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%EC%84%A4%EA%B3%84%EC%99%80-%EC%8A%A4%ED%94%84%EB%A7%81</guid>
            <pubDate>Mon, 30 May 2022 22:16:54 GMT</pubDate>
            <description><![CDATA[<h1 id="스프링">스프링</h1>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/60a8f7b4-fc44-4c67-ba63-31ac32997572/image.PNG" alt=""></p>
<h2 id="스프링-프레임워크">스프링 프레임워크</h2>
<p>: 스프링에서 가장 중요한 부분</p>
<ul>
<li>핵심 기술:모든 라이브러리가 허용하는 스프링의 가장 핵심 기술
  스프링 DI 컨테이너, AOP, 이벤트, 기타</li>
<li>웹 기술: 웹 관련 기술
  스프링 MVC, 스프링 WebFlux</li>
<li>데이터 접근 기술: DB 관련 기술
  트랜잭션, JDBC, ORM 지원, XML 지원</li>
<li>기술 통합: 
  캐시, 이메일, 원격접근, 스케줄링</li>
<li>테스트: 
  스프링 기반 테스트 지원</li>
<li>언어: 여러 언어 다루는 것
  코틀린, 그루비<h2 id="스프링-부트">스프링 부트</h2>
: 스프링을 편리하게 사용할 수 있도록 사용되는 것인데 최근에는 기본적으로 모두 사용한다 보면 됨</li>
<li>단독으로 실행할 수 있는 스프링 애플리케이션을 쉽게 생성</li>
<li>Tomcat 같은 웹 서버를 내장해서 별도의 웹 서버를 설치하지 않아도 됨</li>
<li>손쉬운 빌드 구성을 위한 starter 종속성 제공</li>
<li>스프링과 3rd parth(외부) 라이브러리 자동 구성</li>
<li>메트릭, 상태 확인, 외부 구성 같은 프로덕션 준비 기능 제공</li>
<li>관례에 의한 간결한 설정</li>
</ul>
<h2 id="선택-부분">선택 부분</h2>
<p><a href="https://spring.io/projects">https://spring.io/projects</a></p>
<h3 id="스프링-데이터">스프링 데이터</h3>
<p>: 스프링 Database를 편리하게 사용할 수 있도록 도와주는 것 (대표적으로 Jpring Data JPA)</p>
<h3 id="스프링-세션">스프링 세션</h3>
<p>: 세션 기능을 편리하게 사용할 수 있도록 도와주는 것</p>
<h3 id="스프링-시큐리티">스프링 시큐리티</h3>
<p>: 보안 관련</p>
<h3 id="스프링-rest-docs">스프링 Rest Docs</h3>
<p>: API 문서 관련 편리하게 하는 것</p>
<h3 id="스프링-배치">스프링 배치</h3>
<p>: 데이터의 배치 처리 (실시간 업데이트)</p>
<h3 id="-data의-배치처리">: Data의 배치처리</h3>
<p>: 클라우드 관련 처리</p>
<h1 id="객체지향-프로그래밍과-스프링">객체지향 프로그래밍과 스프링</h1>
<p>스프링은 자바 언어 기반으로, 객체 지향 언어가 가진 강력한 특징을 살려내는 프레임워크.</p>
<h2 id="객체지향의-특징---다형성">객체지향의 특징 - 다형성</h2>
<p>: 실세계와 가깝게 구현하는 특징으로, 역할과 구현을 분리하여 세상이 단순해지고, 유연해지며 변경도 편리함</p>
<h3 id="역할과-구현의-분리-특징">역할과 구현의 분리 특징</h3>
<p>역할은 인터페이스, 구현은 인터페이스를 구현한 클래스로 구현 객체에 해당</p>
<ul>
<li>클라이언트는 대상의 역할(인터페이스)만 알면 된다. </li>
<li>클라이언트는 구현 대상의 내부 구조를 몰라도 된다.</li>
<li>클라이언트는 구현 대상의 내부 구조가 변경되어도 영향을 받지 않는다.</li>
<li>클라이언트는 구현 대상 자체를 변경해도 영향을 받지 않는다.<h3 id="클라이언트와-서버">클라이언트와 서버</h3>
<img src="https://velog.velcdn.com/images/z00m__in/post/81ff89fc-e18d-4453-9304-ed03a0341362/image.PNG" alt="">
<img src="https://velog.velcdn.com/images/z00m__in/post/d2d5735f-4686-4c2d-9f4b-2e1bcc3674f0/image.PNG" alt="">
<img src="https://velog.velcdn.com/images/z00m__in/post/33899a5a-99fa-45c6-8bc8-d234d8ff508e/image.PNG" alt=""></li>
<li>클라이언트가 요청하고 서버가 응답하는 구조에서, 수 많은 객체 클라이언트와 객체 서버는 서로 협력 관계를 가진다. 그 요청 응답 과정에서 사용되는 자바의 특징은 &#39;오버라이딩&#39;</li>
<li>클라이언트를 변경하지 않고, 서버의 구현 기능을 유연하게 변경 가능<h2 id="객체지향-프로그래밍과-스프링-1">객체지향 프로그래밍과 스프링</h2>
</li>
<li>(문제) 다형성만으로는 추후 서술된 5원칙 중 OCP, DIP를 지킬 수 없음</li>
<li>(해걸) 의존관계, 의존성 주입(Dependency Injection)을 가능하도록 DI 컨테이너를 지원하는 것이 바로 스프링이다.
클라이언트 코드의 변경 없이 기능을 확장할 수 있다.</li>
</ul>
<h1 id="좋은-객체지향설계의-5가지-원칙">좋은 객체지향설계의 5가지 원칙</h1>
<h2 id="srp-단일-책임-원칙single-responsibility-principle">SRP: 단일 책임 원칙(single responsibility principle)</h2>
<ul>
<li>모든 하나의 클래스는 하나의 책임만 가져야 한다.</li>
<li>변경이 있을 때 파급 효과가 적으면 단일 책임 원칙을 잘 따른 것.</li>
</ul>
<h2 id="ocp-개방-폐쇄-원칙-openclosed-principle">OCP: 개방-폐쇄 원칙 (Open/closed principle)</h2>
<ul>
<li>가장 중요한 원칙으로, 다형성을 활용함.</li>
<li>소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다.</li>
<li>다형성을 사용했어도 OCP 원칙을 지킬 수 없는 경우, 객체를 생성하고, 연관관계를 맺어주는 별도의 조립, 설정자로 문제점을 해결할 수 있다.</li>
</ul>
<h2 id="lsp-리스코프-치환-원칙-liskov-substitution-principle">LSP: 리스코프 치환 원칙 (Liskov substitution principle)</h2>
<ul>
<li>프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀
수 있어야 한다.</li>
<li>다형성에서 하위 클래스는 인터페이스 규약을 다 지켜야 한다는 것, 다형성을 지원하기 위
한 원칙, 인터페이스를 구현한 구현체는 믿고 사용하려면, 이 원칙이 필요하다.</li>
</ul>
<h2 id="isp-인터페이스-분리-원칙-interface-segregation-principle">ISP: 인터페이스 분리 원칙 (Interface segregation principle)</h2>
<ul>
<li>범용 인터페이스 하나 보다는 특정 클라이언트를 위한 인터페이스 여러 개로 분리</li>
<li>인터페이스가 명확해지고, 대체 가능성이 높아지는 장점</li>
</ul>
<h2 id="dip-의존관계-역전-원칙-dependency-inversion-principle">DIP: 의존관계 역전 원칙 (Dependency inversion principle)</h2>
<ul>
<li>구현 클래스에 의존하지 말고, 인터페이스에 의존해야 함</li>
<li>물론, 때때로 위반되는 경우도 있음</li>
</ul>
<hr>
<p>본 포스트는 김영하의 <em><strong>&lt;스프링 핵심 원리 - 기본편&gt;</strong></em> 강좌를 바탕으로 작성한 포스트입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Spring] 스프링 입문 Section 7 : AOP]]></title>
            <link>https://velog.io/@z00m__in/Spring-%EC%8A%A4%ED%94%84%EB%A7%81-%EC%9E%85%EB%AC%B8-Section-7-AOP</link>
            <guid>https://velog.io/@z00m__in/Spring-%EC%8A%A4%ED%94%84%EB%A7%81-%EC%9E%85%EB%AC%B8-Section-7-AOP</guid>
            <pubDate>Mon, 23 May 2022 21:48:25 GMT</pubDate>
            <description><![CDATA[<h1 id="aopaspect-oriented-programming">AOP(Aspect Oriented Programming)</h1>
<h2 id="aop가-필요한-상황">AOP가 필요한 상황</h2>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/bdfc7118-b286-488b-bdea-78d07565dc18/image.PNG" alt=""></p>
<p>모든 메소드의 호출 시간을 측정
공통 관심 사항(cross-cutting concern) vs 핵심 관심 사항(core concern)
회원 가입 시간, 회원 조회 시간을 측정</p>
<h4 id="회원-조회-시간-측정-추가">회원 조회 시간 측정 추가</h4>
<h4 id="문제점">문제점</h4>
<ul>
<li>회원가입, 회원 조회에 시간을 측정하는 기능은 핵심 관심 사항이 아니다. --&gt; 핵심관심사항이라 부름</li>
<li>시간을 측정하는 로직은 공통 관심 사항이다. --&gt; 공통관심사항이라고 부름</li>
<li>시간을 측정하는 로직과 핵심 비즈니스의 로직이 섞여서 유지보수가 어렵다</li>
<li>시간을 측정하는 로직을 별도의 공통 로직으로 만들기 매우 어렵다.</li>
<li>시간을 측정하는 로직을 변경할 때 모든 로직을 찾아가면서 변경해야 한다.</li>
</ul>
<h2 id="aop-적용">AOP 적용</h2>
<p>:공통과 핵심 관심 사항의 분리로 다루기 쉬워짐
<img src="https://velog.velcdn.com/images/z00m__in/post/2b4afb68-f6ec-47b9-9700-9f02b657e8e7/image.PNG" alt=""></p>
<h4 id="해결">해결</h4>
<ul>
<li>회원가입, 회원 조회등 핵심 관심사항과 시간을 측정하는 공통 관심 사항을 분리한다.</li>
<li>시간을 측정하는 로직을 별도의 공통 로직으로 만들었다.</li>
<li>핵심 관심 사항을 깔끔하게 유지할 수 있다.</li>
<li>변경이 필요하면 이 로직만 변경하면 된다.</li>
<li>원하는 적용 대상을 선택할 수 있다.</li>
</ul>
<h4 id="시간측정-aop-등록">시간측정 AOP 등록</h4>
<p>위치: java/hello/hello.spring/aop/TimeTraceApp.java 생성
이 파일 수정으로 여러 변경 사항 한 번에 실행 가능</p>
<h3 id="스프링의-aop-동작방식-설명">스프링의 aop 동작방식 설명</h3>
<h4 id="aop-적용-전-의존관계">AOP 적용 전 의존관계</h4>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/2e980169-0a75-425c-af8b-f401c35365f6/image.PNG" alt=""></p>
<h4 id="aop-적용-후-의존관계">AOP 적용 후 의존관계</h4>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/28473789-e3cd-407d-93a8-a3f28df3e8f7/image.PNG" alt=""></p>
<h4 id="aop-적용-후-전체-그림">AOP 적용 후 전체 그림</h4>
<p><img src="https://velog.velcdn.com/images/z00m__in/post/25c40b55-495f-430a-b662-9006a7a862cc/image.PNG" alt=""></p>
<hr>
<p>본 포스트는 김영하의 <em><strong>&lt;스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술&gt;</strong></em> 강좌를 바탕으로 작성한 포스트입니다.</p>
]]></description>
        </item>
    </channel>
</rss>