<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>woohee_.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Sat, 20 Apr 2024 03:33:57 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>woohee_.log</title>
            <url>https://velog.velcdn.com/images/woohee_/profile/838a4351-2193-49aa-8cbb-edb7e1734ffa/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. woohee_.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/woohee_" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[정처기 실기 개념정리 (3) 컴퓨터 구조]]></title>
            <link>https://velog.io/@woohee_/%EC%A0%95%EC%B2%98%EA%B8%B0-%EC%8B%A4%EA%B8%B0-%EA%B0%9C%EB%85%90%EC%A0%95%EB%A6%AC-3-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B5%AC%EC%A1%B0</link>
            <guid>https://velog.io/@woohee_/%EC%A0%95%EC%B2%98%EA%B8%B0-%EC%8B%A4%EA%B8%B0-%EA%B0%9C%EB%85%90%EC%A0%95%EB%A6%AC-3-%EC%BB%B4%ED%93%A8%ED%84%B0-%EA%B5%AC%EC%A1%B0</guid>
            <pubDate>Sat, 20 Apr 2024 03:33:57 GMT</pubDate>
            <description><![CDATA[<h2 id="용어정리">용어정리</h2>
<blockquote>
<h4 id="레지스터">레지스터</h4>
<p>CPU 내에서 발생 및 사용되는 데이터를 일시적으로 저장하는 저장장치이다.
가격대비 용량이 작고 기억장치 중 속도가 가장 빠르다.</p>
</blockquote>
<blockquote>
<h4 id="memristor">Memristor</h4>
<p>메모리와 레지스터의 합성어로, 전기가 없는 상태에서도 전사 상태를 저장할 수 있다.</p>
</blockquote>
<hr>
<h2 id="1-레지스터-종류">1. 레지스터 종류</h2>
<h4 id="제어장치cu의-레지스터">제어장치(CU)의 레지스터</h4>
<p>: 명령어 수행에 필요한 데이터를 저장하는 레지스터</p>
<h4 id="연산장치alu의-레지스터">연산장치(ALU)의 레지스터</h4>
<p>: 산술 및 논리 연산 등의 연산기능을 수행할 때 사용되는 레지스터</p>
<hr>
<h2 id="2-내부버스--외부버스">2. 내부버스 &amp; 외부버스</h2>
<h4 id="내부버스">내부버스</h4>
<p>CPU 내부 요소 사이의 정보를 전송한다.</p>
<h4 id="외부버스">외부버스</h4>
<p>CPU와 주변장치 사이의 정보를 전송한다.</p>
<h4 id="외부-버스의-종류-3가지">외부 버스의 종류 3가지</h4>
<ul>
<li>주소 버스</li>
<li>데이터 버스</li>
<li>제어 버스</li>
</ul>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[정처기 실기 개념정리 (2) 소프트웨어 개발 보안 구축]]></title>
            <link>https://velog.io/@woohee_/%EC%A0%95%EC%B2%98%EA%B8%B0-%EC%8B%A4%EA%B8%B0-%EA%B0%9C%EB%85%90%EC%A0%95%EB%A6%AC-2-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EA%B0%9C%EB%B0%9C-%EB%B3%B4%EC%95%88-%EA%B5%AC%EC%B6%95</link>
            <guid>https://velog.io/@woohee_/%EC%A0%95%EC%B2%98%EA%B8%B0-%EC%8B%A4%EA%B8%B0-%EA%B0%9C%EB%85%90%EC%A0%95%EB%A6%AC-2-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EA%B0%9C%EB%B0%9C-%EB%B3%B4%EC%95%88-%EA%B5%AC%EC%B6%95</guid>
            <pubDate>Thu, 18 Apr 2024 11:03:03 GMT</pubDate>
            <description><![CDATA[<h2 id="1-정보-보호의-목표-5가지">1. 정보 보호의 목표 5가지</h2>
<ul>
<li><h4 id="기밀성">기밀성</h4>
인가되지 않은 접근에 정보 공개 및 노출을 차단</li>
<li><h4 id="무결성">무결성</h4>
정당한 방법 외로 데이터 변경 x, 데이터의 훼손을 방어</li>
<li><h4 id="가용성">가용성</h4>
권한을 가진 사용자가 원하는 서비스를 지속 사용할 수 있도록 보장</li>
<li><h4 id="인증성">인증성</h4>
</li>
<li><h4 id="책임성">책임성</h4>
</li>
</ul>
<hr>
<h2 id="2-컴퓨터-바이러스의-시스템-공격-유형">2. 컴퓨터 바이러스의 시스템 공격 유형</h2>
<ul>
<li><h4 id="가로막기">가로막기</h4>
</li>
<li><h4 id="가로채기">가로채기</h4>
</li>
<li><h4 id="수정">수정</h4>
</li>
<li><h4 id="위조">위조</h4>
</li>
</ul>
<hr>
<h2 id="3-네트워크-공격-기술">3. 네트워크 공격 기술</h2>
<blockquote>
<h4 id="피싱">피싱</h4>
<p>개인정보와 낚시의 합성어로, 불특정 다수에게 지인 또는 신뢰할 수 있는 기관으로 가정하여 이메일, 문자 메시지(스미싱), 전화(보이스피싱) 등으로 개인정보 및 금융정보를 불법으로 뽑아내는 공격 방식이다.</p>
</blockquote>
<hr>
<h2 id="4-시큐어-코딩">4. 시큐어 코딩</h2>
<blockquote>
<h4 id="시큐어-코딩">시큐어 코딩</h4>
<p>초기 설계 단계부터 보안 요소를 고려하여 잠재적인 보안 취약점을 제거하는 개발 방식이다.</p>
</blockquote>
<hr>
<h2 id="5-암호화-방식">5. 암호화 방식</h2>
<h4 id="블록-암호">블록 암호</h4>
<p>평문을 일정한 단위로 나누어서 단위마다 암호화 과정을 수행하여 암호문을 얻는 방법이다.</p>
<hr>
<h2 id="6-기타-용어">6. 기타 용어</h2>
<blockquote>
<h4 id="그레이웨어">그레이웨어</h4>
<p>소프트웨어를 제공하는 입장에서는 악의성이 없더라도 사용자 입장에서는 유용하지 않거나 악의적이라고 판단될 수 있는 애드웨어, 공유웨어, 스파이웨어 등의 총칭이다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[정처기 실기 개념정리 (1) 애플리케이션 테스트 관리]]></title>
            <link>https://velog.io/@woohee_/%EC%A0%95%EC%B2%98%EA%B8%B0-%EC%8B%A4%EA%B8%B0-%EA%B0%9C%EB%85%90%EC%A0%95%EB%A6%AC-1-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EA%B4%80%EB%A6%AC</link>
            <guid>https://velog.io/@woohee_/%EC%A0%95%EC%B2%98%EA%B8%B0-%EC%8B%A4%EA%B8%B0-%EA%B0%9C%EB%85%90%EC%A0%95%EB%A6%AC-1-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EA%B4%80%EB%A6%AC</guid>
            <pubDate>Thu, 18 Apr 2024 10:31:42 GMT</pubDate>
            <description><![CDATA[<h4 id="정보처리기사-실기-시험이-9일-남은-시점에-나올-만한-개념들을-깔끔하게-정리해보려고-한다-필기-공부할-때-공부했던-개념서는-너무-양이-방대해서-나올만한-개념들로만-정리할-것이다">정보처리기사 실기 시험이 9일 남은 시점에 나올 만한 개념들을 깔끔하게 정리해보려고 한다! 필기 공부할 때 공부했던 개념서는 너무 양이 방대해서 나올만한 개념들로만 정리할 것이다!</h4>
<hr>
<h2 id="1-화이트박스-테스트--블랙박스-테스트">1. 화이트박스 테스트 &amp; 블랙박스 테스트</h2>
<p>자주 출제되는 개념 중 하나이다. 구분해서 알아두면 좋아서 같이 정리한다.</p>
<blockquote>
<h4 id="화이트박스-테스트구조-테스트">화이트박스 테스트(구조 테스트)</h4>
<p>원시 코드의 논리적인 모든 경로를 테스트하여 테스트 케이스를 설계하는 방법이다.</p>
</blockquote>
<h3 id="종류">종류</h3>
<ul>
<li><h4 id="기초경로검사">기초경로검사</h4>
<p>테스트 케이스 설계자가 절차적 설계의 논리적 복잡성을 측정할 수 있게 해주는 테스트 기법</p>
</li>
<li><h4 id="제어구조검사">제어구조검사</h4>
<ul>
<li>조건 검사 : 소스 코드의 논리적 조건을 테스트</li>
<li>루프 검사 : 소스 코드의 반복 구조를 중점적으로 테스트</li>
<li>데이터 흐름 검사 : 소스 코드의 변수 정의, 사용을 중점적으로 테스트</li>
</ul>
</li>
</ul>
<blockquote>
<h4 id="블랙박스-테스트기능-테스트">블랙박스 테스트(기능 테스트)</h4>
<p>  프로그램의 기능을 중심으로 테스트를 진행하는 방법이다.</p>
</blockquote>
<h3 id="종류-1">종류</h3>
<ul>
<li><h4 id="동등분할-테스트">동등분할 테스트</h4>
유효&amp;무효 값을 균등하게 설계한다.</li>
<li><h4 id="경계값-분석">경계값 분석</h4>
경계에서 오류가 발생할 확률이 높다는 점을 활용한다.</li>
<li><h4 id="원인-효과-그래프">원인-효과 그래프</h4>
입력 데이터 간의 관계와 출력에 미치는 영향을 분석한다.</li>
<li><h4 id="오류-예측">오류 예측</h4>
과거의 경험이나 확인자의 감각에 의존한다.</li>
<li><h4 id="비교테스트">비교테스트</h4>
여러 버전의 프로그램에 동일한 테스트 자료를 제공한다.</li>
</ul>
<hr>
<h2 id="2-인수테스트알파테스트--베타테스트">2. 인수테스트(알파테스트 &amp; 베타테스트)</h2>
<p>  인수테스트의 종류 중 알파테스트와 베타테스트를 비교하는 문제가 자주 출제된다.</p>
<blockquote>
<h4 id="알파테스트">알파테스트</h4>
<p> 개발자의 장소에서 사용자가 개발자 앞에서 행하는 테스트 기법이며 오류와 사용상의 문제점을 사용자와 개발자가 함께 확인하면서 기록하는 테스트 방법이다.</p>
</blockquote>
<blockquote>
<h4 id="베타테스트">베타테스트</h4>
<p>  다수의 사용자에게 제한되지 않은 환경에서 프로그램을 사용하게 하고 오류가 발견되면 개발자에게 통보하는 방식의 테스트 방법이다.</p>
</blockquote>
<hr>
<h2 id="3-테스트-오라클">3. 테스트 오라클</h2>
<blockquote>
<h4 id="테스트-오라클">테스트 오라클</h4>
<p>  테스트 결과가 올바른지 판단하기 위해 사전에 정의된 참 값을 대입하여 비교하는 기법 및 활동을 말한다.</p>
</blockquote>
<p>  테스트 오라클에는 종류는 총 4가지이다.</p>
<h4 id="참-오라클">참 오라클</h4>
<p>  모든 테스트 케이스의 입력값에 대해 기대 결과를 제공하고 발생되는 모든 오류를 검출할 수 있다.</p>
<h4 id="샘플링-오라클">샘플링 오라클</h4>
<p>  특정한 몇몇 테스트 케이스의 입력값들에 대해서만 기대 결과를 제공한다.</p>
<h4 id="추정-오라클">추정 오라클</h4>
<p>  샘플링 오라클을 개선한 오라클이다.</p>
<h4 id="일관성-검사-오라클">일관성 검사 오라클</h4>
<p>  테스트 케이스의 수행 전과 후가 동일한지 확인하는 오라클이다.</p>
<h3 id="테스트-오라클의-특징-3가지">테스트 오라클의 특징 3가지</h3>
<ul>
<li><h4 id="제한된-검증">제한된 검증</h4>
테스트 오라클은 모든 테스트 케이스에 적용할 수 없다.</li>
<li><h4 id="수학적-기법">수학적 기법</h4>
테스트 오라클의 기대 값을 수학적 기법으로 산출함을 뜻함.</li>
<li><h4 id="자동화-기능">자동화 기능</h4>
테스트 대상 프로그램의 실행, 결과 비교, 커버리지 측정 등을 자동화함을 의미한다.</li>
</ul>
<hr>
<h2 id="4-테스트-프로세스">4. 테스트 프로세스</h2>
<ol>
<li>계획</li>
<li>분석 및 디자인</li>
<li>케이스 및 시나리오 작성</li>
<li>수행</li>
<li>결과 평가 및 보고서 작성</li>
<li>결함 추적 및 관리</li>
</ol>
<hr>
<h2 id="5-테스트-자동화">5. 테스트 자동화</h2>
<blockquote>
<h4 id="쉽고-효율적인-테스트-수행을-위해-사람이-반복적으로-수행하던-테스트-절차를-스크립트-형태로-구현하는-자동화-도구를-적용하는-것이다">쉽고 효율적인 테스트 수행을 위해 사람이 반복적으로 수행하던 테스트 절차를 스크립트 형태로 구현하는 자동화 도구를 적용하는 것이다.</h4>
<p>  휴먼 에러를 줄이고 테스트 정확성을 유지하면서 테스트 품질을 향상시킨다.</p>
</blockquote>
<h3 id="테스트-자동화-도구-유형">테스트 자동화 도구 유형</h3>
<ul>
<li><h4 id="정적-분석-도구">정적 분석 도구</h4>
실행하지 않고 분석하는 도구</li>
<li><h4 id="테스트-실행-도구">테스트 실행 도구</h4>
스크립트 언어를 사용하여 테스트를 실행하는 방법</li>
<li><h4 id="성능-테스트-도구">성능 테스트 도구</h4>
처리량, 응답시간, 경과시간, 자원 사용륭 등 성능 목표 달성 여부 확인</li>
<li><h4 id="테스트-통제-도구">테스트 통제 도구</h4>
테스트 계획 및 관리, 테스트 수행, 결함 관리 등을 수행하는 도구</li>
<li><h4 id="테스트-하네스-도구">테스트 하네스 도구</h4>
테스트가 실행될 환경을 시뮬레이션하여 컴포턴트 및 모듈이 정상적으로 테스트 되도록 함.</li>
</ul>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring 회원 프로젝트(8) 회원정보 상세조회]]></title>
            <link>https://velog.io/@woohee_/Spring-%ED%9A%8C%EC%9B%90-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B88-%ED%9A%8C%EC%9B%90%EC%A0%95%EB%B3%B4-%EC%83%81%EC%84%B8%EC%A1%B0%ED%9A%8C</link>
            <guid>https://velog.io/@woohee_/Spring-%ED%9A%8C%EC%9B%90-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B88-%ED%9A%8C%EC%9B%90%EC%A0%95%EB%B3%B4-%EC%83%81%EC%84%B8%EC%A1%B0%ED%9A%8C</guid>
            <pubDate>Tue, 09 Apr 2024 06:48:50 GMT</pubDate>
            <description><![CDATA[<h4 id="🔖지난-포스트에서-회원목록을-불러오는-것까지-진행했다-이번-포스트에서는-목록에서-각각의-회원을-조회하는-과정을-수행하겠다">🔖지난 포스트에서 회원목록을 불러오는 것까지 진행했다. 이번 포스트에서는 목록에서 각각의 회원을 조회하는 과정을 수행하겠다!</h4>
<hr>
<h2 id="membercontroller-수정">MemberController 수정</h2>
<p>회원 조회 페이지를 요청한다.</p>
<pre><code> @GetMapping(&quot;/member/{id}&quot;)
    public String findById(@PathVariable Long id, Model model){
        MemberDTO memberDTO = memberService.findById(id);
        model.addAttribute(&quot;member&quot;,memberDTO);
        return &quot;detail&quot;;
    }</code></pre><ul>
<li>각각의 회원은 id값으로 구분하고 id값으로 페이지를 요청한다.</li>
<li>memberService에 findById 메서드를 추가하고 해당 id의 회원을 찾는다.</li>
<li>model에 회원정보를 추가한다.</li>
<li>조회 페이지를 요청한다.</li>
</ul>
<h2 id="memberservice-수정">MemberService 수정</h2>
<p>findById 메서드 구현</p>
<pre><code> public MemberDTO findById(Long id) {
        Optional&lt;MemberEntity&gt; optionalMemberEntity = memberRepository.findById(id);
        if(optionalMemberEntity.isPresent()){
            return MemberDTO.toMemberDTO(optionalMemberEntity.get());
        }else{
            return null;
        }
    }</code></pre><ul>
<li>memberRepository에서 아이디를 찾고 엔티티에 넣어준다.</li>
<li>optionalMemberEntity에서 엔티티 정보를 가져오고 dto로 변환하여 리턴한다.</li>
<li>회원정보가 없으면 null을 리턴한다.</li>
</ul>
<h2 id="detailhtml-생성">detail.html 생성</h2>
<pre><code>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot; xmlns:th=&quot;http://www.thymeleaf.org&quot;&gt;

&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;title&gt;detail&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;table&gt;
    &lt;tr&gt;
        &lt;th&gt;id&lt;/th&gt;
        &lt;th&gt;email&lt;/th&gt;
        &lt;th&gt;password&lt;/th&gt;
        &lt;th&gt;name&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td th:text=&quot;${member.id}&quot;&gt;&lt;/td&gt;
        &lt;td th:text=&quot;${member.memberEmail}&quot;&gt;&lt;/td&gt;
        &lt;td th:text=&quot;${member.memberPassword}&quot;&gt;&lt;/td&gt;
        &lt;td th:text=&quot;${member.memberName}&quot;&gt;&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre><ul>
<li>회원 정보의 아이디, 이베일, 비밀번호, 이름 정보를 가져온다.</li>
</ul>
<h2 id="✅실행">✅실행</h2>
<p>목록에서 각 회원의 조회를 누르면 상세정보로 넘어간다!
<img src="https://velog.velcdn.com/images/woohee_/post/7e4be216-4b69-4c44-9b48-fba86476388a/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/woohee_/post/71d89a1c-81f1-4867-a602-50d88847962e/image.png" alt=""></p>
<hr>
<p>다음 포스트에서는 회원정보를 수정해보겠다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring 회원 프로젝트(7) 회원목록 출력하기]]></title>
            <link>https://velog.io/@woohee_/Spring-%ED%9A%8C%EC%9B%90-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B87-%ED%9A%8C%EC%9B%90%EB%AA%A9%EB%A1%9D-%EC%B6%9C%EB%A0%A5%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@woohee_/Spring-%ED%9A%8C%EC%9B%90-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B87-%ED%9A%8C%EC%9B%90%EB%AA%A9%EB%A1%9D-%EC%B6%9C%EB%A0%A5%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 09 Apr 2024 06:16:58 GMT</pubDate>
            <description><![CDATA[<h4 id="🔖지난-포스트까지-회원가입-로그인을-끝마쳤다-이번-포스트에서는-회원목록을-출력해보겠다">🔖지난 포스트까지 회원가입, 로그인을 끝마쳤다. 이번 포스트에서는 회원목록을 출력해보겠다!!</h4>
<hr>
<h2 id="indexhtml-수정">index.html 수정</h2>
<p>초기 화면에서 목록 페이지를 추가한다. </p>
<pre><code>&lt;body&gt;
    &lt;h2&gt;Hello Spring Boot!!&lt;/h2&gt;
    &lt;a href=&quot;/member/save&quot;&gt;회원가입&lt;/a&gt;
    &lt;a href=&quot;/member/login&quot;&gt;로그인&lt;/a&gt;
    &lt;a href=&quot;/member/&quot;&gt;목록&lt;/a&gt;
&lt;/body&gt;</code></pre><h2 id="membercontroller-수정">MemberController 수정</h2>
<p>목록 페이지를 띄우려면 일단 controller에서 GetMapping을 해주어야 한다.</p>
<pre><code>    @GetMapping(&quot;/member/&quot;)
    public String findAll(Model model){
       List&lt;MemberDTO&gt; memberDTOList = memberService.findAll();
       // 어떠한 html로 가져갈 데이터가 있다면 model 사용 (model을 사용하는건 가장 기본적인 방법)
       model.addAttribute(&quot;memberList&quot;, memberDTOList);
       return &quot;list&quot;;
    }</code></pre><ul>
<li>목록 페이지(list.html)에 회원목록을 출력해야 한다. -&gt; Spring에서 제공하는 model을 넘겨준다.
요즘에는 자바스크립트로도 많이들 넘겨주지만 model을 사용하는게 가장 기본적인 방법이다.</li>
<li>회원목록은 하나가 아닌 다수이므로 List를 생성한다.</li>
<li>memberService에 findAll 메서드를 추가해서 회원 목록을 model에 추가해준다.</li>
<li>list.html을 요청한다.</li>
</ul>
<h2 id="memberservice-수정">MemberService 수정</h2>
<pre><code>public List&lt;MemberDTO&gt; findAll() {
        List&lt;MemberEntity&gt; memberEntityList = memberRepository.findAll();
        List&lt;MemberDTO&gt; memberDTOList = new ArrayList&lt;&gt;();
        for(MemberEntity memberEntity : memberEntityList){
            memberDTOList.add(MemberDTO.toMemberDTO(memberEntity));
        }
        return memberDTOList;
    }</code></pre><ul>
<li>memberRepository에서 회원 리스트 가져오기</li>
<li>Repository는 Entity객체만 가지므로 dto 객체로 변환해야 한다.</li>
<li>회원 목록은 회원이 여러명이기 때문에 for문으로 Entity 객체 하나를 dto 객체 하나로 변환한다.</li>
<li>memberDTOList에 변환한 dto객체를 추가하고 리스트를 리턴한다.</li>
</ul>
<h2 id="listhtml-생성">list.html 생성</h2>
<p>회원목록을 띄울 list.html을 생성한다.</p>
<pre><code>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot; xmlns:th=&quot;http://www.thymeleaf.org&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;title&gt;Title&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h2&gt;list.html&lt;/h2&gt;
&lt;table&gt;
    &lt;tr&gt;
        &lt;th&gt;id&lt;/th&gt;
        &lt;th&gt;memberEmail&lt;/th&gt;
        &lt;th&gt;memberPassword&lt;/th&gt;
        &lt;th&gt;memberName&lt;/th&gt;
        &lt;th&gt;상세조회&lt;/th&gt;
        &lt;th&gt;삭제&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr th:each=&quot;member: ${memberList}&quot;&gt;
        &lt;td th:text=&quot;${member.id}&quot;&gt;&lt;/td&gt;
        &lt;td th:text=&quot;${member.memberEmail}&quot;&gt;&lt;/td&gt;
        &lt;td th:text=&quot;${member.memberPassword}&quot;&gt;&lt;/td&gt;
        &lt;td th:text=&quot;${member.memberName}&quot;&gt;&lt;/td&gt;
        &lt;td&gt;
            &lt;!-- query string /member?id=1
                rest api /member/1 --&gt;
            &lt;a th:href=&quot;@{|/member/${member.id}|}&quot;&gt;조회&lt;/a&gt;
        &lt;/td&gt;
        &lt;td&gt;
            &lt;a th:href=&quot;@{|/member/delete/${member.id}|}&quot;&gt;삭제&lt;/a&gt;
        &lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre><h2 id="실행">실행</h2>
<p>목록에 들어가면 다음과 같이 db에 저장된 회원 목록을 가져온다.
<img src="https://velog.velcdn.com/images/woohee_/post/06c6f22a-2da2-43ef-8c5a-f27d906fa5cb/image.png" alt=""></p>
<hr>
<p>다음 포스트부터는 회원정보를 상세조회하는 과정을 추가하겠다!!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring 회원 프로젝트(6) 로그인하기]]></title>
            <link>https://velog.io/@woohee_/Spring-%ED%9A%8C%EC%9B%90-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B86-%EB%A1%9C%EA%B7%B8%EC%9D%B8%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@woohee_/Spring-%ED%9A%8C%EC%9B%90-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B86-%EB%A1%9C%EA%B7%B8%EC%9D%B8%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 09 Apr 2024 05:37:43 GMT</pubDate>
            <description><![CDATA[<h4 id="🔖지난-포스트까지-회원가입-하는-과정을-거쳤다-이제-사용자-정보를-가져와-로그인을-수행해보자">🔖지난 포스트까지 회원가입 하는 과정을 거쳤다. 이제 사용자 정보를 가져와 로그인을 수행해보자!!</h4>
<hr>
<h2 id="loginhtml-생성">login.html 생성</h2>
<p>login 과정은 간단하게 이메일, 비밀번호만 입력받아 로그인해보겠다.</p>
<pre><code>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;title&gt;login&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;form action=&quot;/member/login&quot; method=&quot;post&quot;&gt;
  이메일: &lt;input type =&quot;text&quot; name =&quot;memberEmail&quot;&gt;&lt;br&gt;
  비밀번호: &lt;input type=&quot;password&quot; name =&quot;memberPassword&quot;&gt;&lt;br&gt;
  &lt;input type =&quot;submit&quot; value=&quot;로그인&quot;&gt;
&lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre><h2 id="membercontroller-수정">MemberController 수정</h2>
<h4 id="login-페이지-요청과정-추가">login 페이지 요청과정 추가</h4>
<pre><code> @GetMapping(&quot;/member/login&quot;)
    public String loginFrom(){
        return &quot;login&quot;;
    }</code></pre><h4 id="사용자-로그인-정보-받아오기">사용자 로그인 정보 받아오기</h4>
<p>memberService에 login 메서드 추가 </p>
<pre><code> @PostMapping(&quot;/member/login&quot;)
    public String login(@ModelAttribute MemberDTO memberDTO, HttpSession session){
        MemberDTO loginResult= memberService.login(memberDTO);
        if(loginResult!=null){
            //login 성공
            session.setAttribute(&quot;loginEmail&quot;,loginResult.getMemberEmail());
            return &quot;main&quot;;
        }else{
            //login 실패
            return &quot;login&quot;;
        }
    }</code></pre><h2 id="memberrepository-수정">MemberRepository 수정</h2>
<p>메서드 추가</p>
<pre><code>   // 이메일로 회원 정보 조회(select * from member_table where member_email=?)
    Optional&lt;MemberEntity&gt; findByMemberEmail(String memberEmail);</code></pre><h2 id="memberdto-수정">MemberDTO 수정</h2>
<p> MemberService는 dto 객체로 변환하는 메서드이므로 entity-&gt;dto로 변환하는 메서드 추가</p>
<pre><code>  public static MemberDTO toMemberDTO(MemberEntity memberEntity){
        MemberDTO memberDTO = new MemberDTO();
        memberDTO.setId(memberEntity.getId());
        memberDTO.setMemberEmail(memberEntity.getMemberEmail());
        memberDTO.setMemberPassword(memberEntity.getMemberPassword());
        memberDTO.setMemberName(memberEntity.getMemberName());
        return memberDTO;
    }</code></pre><h2 id="memberservice-수정">MemberService 수정</h2>
<pre><code>     public MemberDTO login(MemberDTO memberDTO) {
        /*
            1. 회원이 입력한 이메일로 DB에서 조회를 함
            2. DB에서 조회한 비밀번호와 사용자가 입력한 비밀번호가 일치하는지 판단
         */
        Optional&lt;MemberEntity&gt; byMemberEmail = memberRepository.findByMemberEmail(memberDTO.getMemberEmail());
        if(byMemberEmail.isPresent()){
            //조회 결과가 있다(해당 이메일을 가진 회원 정보가 있다)
            MemberEntity memberEntity = byMemberEmail.get();
            if(memberEntity.getMemberPassword().equals(memberDTO.getMemberPassword())){
                //비밀번호 일치
                // entity -&gt; dto 변환 후 리턴
                MemberDTO dto = MemberDTO.toMemberDTO(memberEntity);
                return dto;
            }
            else{
                //비밀번호 불일치
                return null;
            }
        }else{
            //조회 결과가 없다(해당 이메일을 가진 회원 정보가 없다)
            return null;
        }
    }</code></pre><ul>
<li>memberRepository의 findByMemberEmail()메서드를 통해 회원 이메일을 가져오기</li>
<li>이메일 정보를 가진 회원이 존재한다면 memberEntity에 회원 정보 가져오기</li>
<li>memberEntity의 패스워드와 memberDTO의 패스워드가 같으면 entity-&gt;dto 변환 후 리턴</li>
<li>비밀번호가 불일치하거나 이메일 정보가 없을 경우 null 리턴</li>
</ul>
<h2 id="mainhtml-생성">main.html 생성</h2>
<pre><code>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot; xmlns:th=&quot;http://www.thymeleaf.org&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;title&gt;main&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
  session 값 확인 : &lt;p th:text=&quot;${session.loginEmail}&quot;&gt;&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre><h2 id="세션-값-확인">세션 값 확인</h2>
<p><img src="https://velog.velcdn.com/images/woohee_/post/8e72057b-4062-4522-8566-825fbbf1739e/image.png" alt=""></p>
<p>로그인까지 성공!</p>
<hr>
<p>다음 포스트에서는 회원 목록을 조회하는 과정을 수행할 것이다!!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring 회원 프로젝트(6) 사용자 정보 저장]]></title>
            <link>https://velog.io/@woohee_/Spring-%ED%9A%8C%EC%9B%90-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B86-%EC%82%AC%EC%9A%A9%EC%9E%90-%EC%A0%95%EB%B3%B4-%EC%A0%80%EC%9E%A5</link>
            <guid>https://velog.io/@woohee_/Spring-%ED%9A%8C%EC%9B%90-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B86-%EC%82%AC%EC%9A%A9%EC%9E%90-%EC%A0%95%EB%B3%B4-%EC%A0%80%EC%9E%A5</guid>
            <pubDate>Sun, 07 Apr 2024 08:36:23 GMT</pubDate>
            <description><![CDATA[<h4 id="🔖-지난-포스트에서-db를-연동시키고-회원-테이블-생성까지-마쳤다-이번-포스트에서는-사용자가-이메일-비밀번호-이름을-입력하여-회원가입을-하면-해당-정보가-db-회원-테이블에-저장되는-과정을-수행해보겠다">🔖 지난 포스트에서 DB를 연동시키고 회원 테이블 생성까지 마쳤다. 이번 포스트에서는 사용자가 이메일, 비밀번호, 이름을 입력하여 회원가입을 하면 해당 정보가 DB 회원 테이블에 저장되는 과정을 수행해보겠다!</h4>
<hr>
<h2 id="memberentity-수정">MemberEntity 수정</h2>
<p>DB 테이블과 연관된 클래스는 MemberEntity이다. 회원가입을 하면 회원 정보가 MemberDTO에 저장된다. 하지만 거기서 멈추면 회원 정보가 DB에 저장되지 않는다. 즉 MemberEntity도 수정해주어야 한다.</p>
<p><strong>MemberDTO 값을 MemberEntity로 넘겨줘야 한다. 해당 코드를 MemberEntity에 추가해보자.</strong></p>
<pre><code>  public static MemberEntity toMemberEntity(MemberDTO memberDTO){
        MemberEntity memberEntity = new MemberEntity();
        memberEntity.setMemberEmail(memberDTO.getMemberEmail());
        memberEntity.setMemberPassword(memberDTO.getMemberPassword());
        memberEntity.setMemberName(memberDTO.getMemberName());
        return memberEntity;
    }</code></pre><ul>
<li>MemberEntity를 반환하는 메서드이다. <h2 id="memberservice-수정">MemberService 수정</h2>
</li>
<li><ul>
<li>MemberService에서 MemberRepository에 수정된 MemberEntity 저장**<pre><code> public void save(MemberDTO memberDTO) {
     // 1. dto -&gt; entity 변환
     // 2. repository의 save 메서드 호출
     MemberEntity memberEntity = MemberEntity.toMemberEntity(memberDTO);
     memberRepository.save(memberEntity);
     //repository의 save 메서드 호출 (조건. entity 객체를 넘겨줘야 함)
 }</code></pre></li>
</ul>
</li>
<li>jpa가 자동으로 insert query문을 작성해준다.</li>
<li>localhost:8081로 접속해서 회원가입을 해보자.</li>
</ul>
<h2 id="✅-결과-확인">✅ 결과 확인</h2>
<p><img src="https://velog.velcdn.com/images/woohee_/post/d25bd012-7a9d-4ae7-9721-14d159efa743/image.png" alt=""></p>
<hr>
<p>회원 정보를 저장하는 과정까지 수행하였다. 다음 포스트에서는 로그인 처리 하는 과정을 수행할 것이다!!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring 회원 프로젝트(5) 회원 엔티티 생성 및 DB 연동하기]]></title>
            <link>https://velog.io/@woohee_/Spring-%ED%9A%8C%EC%9B%90-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B85-DB-%EC%97%B0%EB%8F%99%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@woohee_/Spring-%ED%9A%8C%EC%9B%90-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B85-DB-%EC%97%B0%EB%8F%99%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 07 Apr 2024 07:42:59 GMT</pubDate>
            <description><![CDATA[<h4 id="🔖지난-포스트까지는-회원가입-페이지를-요청하고-생성하여-사용자가-입력한-정보-값을-가져오는-것까지-수행하였다-이번에는-가져온-값을-db에-저장하기-위해서-회원-entity를-생성하고-db를-연동하는-과정을-해볼-것이다">🔖지난 포스트까지는 회원가입 페이지를 요청하고 생성하여 사용자가 입력한 정보 값을 가져오는 것까지 수행하였다. 이번에는 가져온 값을 DB에 저장하기 위해서 회원 entity를 생성하고 DB를 연동하는 과정을 해볼 것이다!</h4>
<hr>
<h2 id="📖dto-entity-repository-service-개념">📖DTO, Entity, Repository, Service 개념</h2>
<h3 id="dto">DTO</h3>
<blockquote>
<p>Data Transfer Object로 데이터 전송 객체이다.</p>
</blockquote>
<ul>
<li>데이터 저장 담당 클래스</li>
<li>계층간에 데이터를 교환할 때 주로 사용된다.</li>
<li>객체지향에 매우 적합하기에 사용한다.</li>
<li>로직을 갖고 있지 않고 순수한 데이터 객체이다. </li>
<li>오직 getter,setter 메소드만을 가지고 있다.</li>
</ul>
<h3 id="entity">Entity</h3>
<blockquote>
<p>DB에 접근하는 객체</p>
</blockquote>
<h4 id="entity와-dto를-분리하는-이유">Entity와 DTO를 분리하는 이유?</h4>
<p>하나로 쓰게 되면 변경된 값이 DB에 들어갈 수 있다. 그래서 변경이 많은 경우에는 Entity아 DTO를 구분하는게 좋다.</p>
<h3 id="repository">Repository</h3>
<blockquote>
<p>DB에 CRUD 명령을 실행하게 만드는 인터페이스</p>
</blockquote>
<ul>
<li>DB 관리(연결, 해제, 자원 관리)</li>
<li>&#39;저장소&#39;라는 뜻을 가진 단어로 JPA에서 Repository 인터페이스를 생성한 후, JpaRepository&lt;Entity, 기본키 타입&gt;을 상속받으면 기본적인 CRUD가 자동으로 생성된다.</li>
</ul>
<h3 id="service">Service</h3>
<blockquote>
<p>repository와 controller 사이 미들웨어</p>
</blockquote>
<ul>
<li><p>controller에서 받은 데이터를 가공해서 db에 보내거나 db에서 가져온 데이터를 가공해서 사용자에게 보내준다.</p>
</li>
<li><p>사용자 요구사항을 처리하는 곳</p>
</li>
<li><p>DB 정보가 필요할 때 repostiroy에게 요청한다.</p>
<h2 id="📖jpa란">📖JPA란?</h2>
<blockquote>
<p>Jpa는 Java Persistence API의 약자이며, 자바 영속성 API를 뜻한다.</p>
</blockquote>
</li>
<li><p>JDBC를 이용하여 데이터베이스를 관리하는 인터페이스이고 이를 구현한 구현체로 대표적인 것이 Hibernate이다.</p>
</li>
<li><p>자바 ORM 기술의 표준 API이다.</p>
</li>
</ul>
<h3 id="orm이란">ORM이란?</h3>
<blockquote>
<p>Object-Relational Mapping의 약자로 객체와 관계형 데이터베이스의 데이터를 자동으로 매핑해주는 것을 말한다.</p>
</blockquote>
<ul>
<li>객체를 통해 간접적으로 데이터베이스 데이터를 다룬다.</li>
<li>ORM을 사용하면 SQL Query가 아닌 직관적인 코드(메서드)로서 데이터를 조작할 수 있다.</li>
</ul>
<h3 id="spring-data-jpa란">Spring Data JPA란?</h3>
<blockquote>
<p>JPA를 더 추상화시켜 개발 용이성을 올려주는 인터페이스이다.</p>
</blockquote>
<ul>
<li>Repository라는 인터페이스를 제공한다.</li>
<li>Repository를 정해진 규칙으로 인터페이스를 선언하기만 해도 자동으로 내부에서 구현체를 만들어 동작시켜준다.</li>
<li>자주 사용하는 메서드들을 별도로 선언하지 않아도 사용할 수 있다. ex(findAll(), save(), delete())<pre><code>public interface MemberRepository extends JpaRepository&lt;Member, Long&gt; {
  List&lt;Member&gt; findByUsername(String username);
}</code></pre></li>
<li>JpaRepository&lt;엔티티, PK type&gt;</li>
<li>findByUsername(String username): 인터페이스를 선언하면 해당 메서드를 내부에서 자동으로 만들어 준다.</li>
</ul>
<h3 id="jdbc란">JDBC란?</h3>
<blockquote>
<p>DB에 접근할 수 있도록 자바에서 제공하는 API</p>
</blockquote>
<ul>
<li>application.yml에 다음 코드를 추가하여 DB와 통신할 수 있다.<pre><code>spring:
datasource:
  url: jdbc:h2:tcp://localhost/~/datajpa
 username: sa
  password:
  driver-class-name: org.h2.Driver</code></pre></li>
</ul>
<hr>
<p>🗝️위의 개념을 알기 전에는 MySQL에서 Sql문을 통해서 테이블을 생성하고 Springboot와 DB를 연결하는 줄 알았다. 물론 그렇게 사용하는 경우도 있지만 우리는 지금 Spring Data JPA를 사용할 것이므로 query문을 직접 작성하지 않고 엔티티를 활용함으로써 테이블을 생성할 수 있다는 것을 새롭게 알게 됐다!</p>
<h2 id="🖥️-회원-엔티티-dto-repository-service-생성">🖥️ 회원 엔티티, dto, repository, service 생성</h2>
<p>member 폴더 아래에 dto, entity, repository, service 폴더를 각각 생성해주자.
각각의 폴더에 들어가는 자바 클래스는 아래와 같다.</p>
<p><strong>MemberDTO.java</strong></p>
<pre><code>@Getter
@Setter
@NoArgsConstructor //기본생성자 생성
@AllArgsConstructor   // 모든 필드를 가지는 생성자 생성
@ToString
public class MemberDTO {
    private Long id;
    private String memberEmail;
    private String memberPassword;
    private String memberName;
}</code></pre><ul>
<li>로직이 없고 순수한 데이터 객체이다.</li>
<li>id, memberEmail, memberPassword, memberName 의 필드를 가지고 있다.</li>
</ul>
<p><strong>MemberEntity.java</strong></p>
<pre><code>@Entity
@Setter
@Getter
@Table(name =&quot;member_table&quot;)
public class MemberEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) //auto_increment
    private Long id;

    @Column(unique =true) //unique 제약조건 추가
    private String memberEmail;

    @Column
    private String memberName;
}</code></pre><ul>
<li>member_table이라는 회원 테이블 생성</li>
<li>type과 pk 지정하여 테이블 생성</li>
</ul>
<p>Repository는 interface로 구현한다.</p>
<p><strong>MemberRepository.java</strong></p>
<pre><code>public interface MemberRepository extends JpaRepository&lt;MemberEntity, Long&gt; {
}</code></pre><ul>
<li>JpaRepository를 상속받는 MemberRepository 생성</li>
<li>CRUD를 자동으로 생성해준다.</li>
</ul>
<p><strong>MemberService.java</strong></p>
<pre><code>@Service
@RequiredArgsConstructor
public class MemberService {
    private final MemberRepository memberRepository;
    public void save(MemberDTO memberDTO) {

    }
}</code></pre><h2 id="⛓️db-연동">⛓️DB 연동</h2>
<h3 id="dependencies-추가">Dependencies 추가</h3>
<pre><code>implementation &#39;org.springframework.boot:spring-boot-starter-data-jpa&#39;
runtimeOnly &#39;mysql:mysql-connector-java:8.0.33&#39;</code></pre><ul>
<li>jpa와 mysql 의존성 추가</li>
<li>jar 버전에 따라 8.0.33 -&gt; 본인 버전 으로 수정하면 된다.</li>
</ul>
<h3 id="applicationyml-수정">application.yml 수정</h3>
<pre><code>server:
  port: 8081

# database 연동 설정
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    #    각자 PC에 만들어놓은 Database이름을 써야 합니다.
    url: jdbc:mysql://localhost:3306/member_project?serverTimezone=Asia/Seoul&amp;characterEncoding=UTF-8
    #    mysql에 생성한 사용자 계정 정보를 써야 합니다.
    username: user_woohee
    password: 1234
  thymeleaf:
    cache: false

  # spring data jpa 설정
  jpa:
    database-platform: org.hibernate.dialect.MySQLDialect
    open-in-view: false
    show-sql: true
    hibernate:
      ddl-auto: create</code></pre><ul>
<li>com.mysql.cj.jdbc.Driver에서 오류가 무척 많이 났다..
일단 jar파일을 라이브러리에 추가하지 않아서 문제가 발생했고 추가했지만 버전이 맞지 않아서 오류가 계속 났다.
특히 MySQLDialect가 원래는 MySQL5~였는데 MySQL8로 고쳐도 오류가 났었다. 하지만 MySQLDialect로 통합되어서 수정하니까 오류가 발생하지 않았다.</li>
</ul>
<h2 id="✅-테이블-확인">✅ 테이블 확인</h2>
<p><img src="https://velog.velcdn.com/images/woohee_/post/0bc61f3a-9b4a-4b93-a1db-d2ecf9a5f571/image.png" alt="">
실행시키고 보니 mysql에 테이블이 생성된 것을 확인할 수 있다.</p>
<hr>
<p>이렇게 DB연동까지 마쳤다. 
DB연동이 안돼서 오류 수정하느라 시간이 많이 소요 됐다...
다음 포스트부터는 db에 값을 넣어보겠다!!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Springboot 회원 프로젝트(4) 회원가입 정보 가져오기]]></title>
            <link>https://velog.io/@woohee_/Springboot-%ED%9A%8C%EC%9B%90-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B84-%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85-%EC%A0%95%EB%B3%B4-%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0</link>
            <guid>https://velog.io/@woohee_/Springboot-%ED%9A%8C%EC%9B%90-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B84-%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85-%EC%A0%95%EB%B3%B4-%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0</guid>
            <pubDate>Sat, 06 Apr 2024 07:31:48 GMT</pubDate>
            <description><![CDATA[<h4 id="🔖지난-시간에는-회원가입-페이지를-요청하고-생성해보았다-회원가입-페이지에서-입력한-정보를-가져오는-과정을-수행해보겠다">🔖지난 시간에는 회원가입 페이지를 요청하고 생성해보았다. 회원가입 페이지에서 입력한 정보를 가져오는 과정을 수행해보겠다.</h4>
<hr>
<h2 id="membersave-페이지에서-정보-가져오기">/member/save 페이지에서 정보 가져오기</h2>
<h3 id="membercontroller에-postmapping-추가">MemberController에 PostMapping 추가</h3>
<p> @GetMapping아래에 받아오는 PostMapping()도 추가해보자.</p>
<pre><code>    @PostMapping(&quot;/member/save&quot;)
    public String save(){
        System.out.println(&quot;MemberController.save&quot;);
        return null;
    }</code></pre><p> 에러가 뜰거지만 해당 메서드를 잘 실행함을 아래와 같이 알 수 있다.
<img src="https://velog.velcdn.com/images/woohee_/post/d31d2b87-6efa-451e-a680-a1c502904d31/image.png" alt=""></p>
<h3 id="정보-가져오기">정보 가져오기</h3>
<p>이제 회원가입 창에서 이메일, 비밀번호, 이름을 입력한 값을 가져와보자.</p>
<pre><code> @PostMapping(&quot;/member/save&quot;)
    public String save(@RequestParam(&quot;memberEmail&quot;) String memberEmail,
                       @RequestParam(&quot;memberPassword&quot;) String memberPassword,
                       @RequestParam(&quot;memberName&quot;) String memberName) {
        System.out.println(&quot;MemberController.save&quot;);
        System.out.println(&quot;memberEmail = &quot; + memberEmail + &quot;, memberPassword = &quot; + memberPassword + &quot;, memberName = &quot; + memberName);
        return &quot;index&quot;;
    }</code></pre><ul>
<li>@RequestParam은 save.html에서 변수로 지정한 값을 요청하는 것이다.</li>
<li>memberEmail을 요청하고 memberEmail 변수에 저장하겠다는 의미이다.<h3 id="출력">출력</h3>
회원가입 정보를 입력하고 회원가입 버튼을 누르면 다음과 같이 정보를 가져온다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/woohee_/post/654e205d-3126-4f91-b6b0-8a27272607bb/image.png" alt=""></p>
<hr>
<p>다음 포스트에서는 Spring을 더 활용하여 코드를 수정해보겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Springboot 회원 프로젝트(3) 회원가입 페이지 요청하기]]></title>
            <link>https://velog.io/@woohee_/Springboot-%ED%9A%8C%EC%9B%90-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B83-%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85-%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%9A%94%EC%B2%AD%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@woohee_/Springboot-%ED%9A%8C%EC%9B%90-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B83-%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85-%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%9A%94%EC%B2%AD%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sat, 06 Apr 2024 07:09:51 GMT</pubDate>
            <description><![CDATA[<h4 id="🔖지난-포스트까지-개발환경-세팅-기본-주소-요청까지-실습을-거쳤다-이번-포스트에서는-회원가입을-수행하는-회원가입-페이지를-요청하는-과정을-수행해보자">🔖지난 포스트까지 개발환경 세팅, 기본 주소 요청까지 실습을 거쳤다. 이번 포스트에서는 회원가입을 수행하는 회원가입 페이지를 요청하는 과정을 수행해보자!</h4>
<hr>
<h2 id="indexhtml-수정">index.html 수정</h2>
<p>첫 페이지에서 회원가입과 로그인 창을 구별해서 접속할 것이다.
다음과 같이 코드를 수정해보자.</p>
<pre><code>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;title&gt;index&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h2&gt;Hello Spring Boot!!&lt;/h2&gt;
    &lt;a href=&quot;/member/save&quot;&gt;회원가입&lt;/a&gt;
    &lt;a href=&quot;/member/login&quot;&gt;로그인&lt;/a&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre><ul>
<li>/member/save는 회원가입을 하는 주소</li>
<li>/member/login은 로그인을 하는 주소</li>
<li>이제 각 주소에서 띄울 페이지를 요청하고 생성해보자.<h2 id="membercontroller-생성">MemberController 생성</h2>
controller 패키지 안에 MemberController를 추가해보자.
MemberController에서는 회원가입페이지를 요청하는 메서드를 추가할 것이다.<pre><code>@Controller
public class MemberController {
  //회원가입 페이지 출력 요청
  @GetMapping(&quot;/member/save&quot;)
  public String saveForm(){
      return &quot;save&quot;;
  }
}</code></pre>지난 포스트에서 기본 페이지를 요청하듯이 메서드를 실행시키면 save.html을 찾아간다.</li>
<li>/member/save 주소에 save 페이지를 띄우는 것이다.</li>
<li>save.html을 만들어보자.</li>
</ul>
<h2 id="savehtml">save.html</h2>
<p>/member/save페이지에 띄워질 save.html은 간단한 회원가입 형식을 가질 것이다.
이메일, 비밀번호, 이름 세 가지만 입력받는 창을 만들어보자.</p>
<pre><code>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;title&gt;save&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;!--action 속성: form에 작성한 데이터를 어디로 보낼지 지정 --&gt;
&lt;form action=&quot;/member/save&quot; method =&quot;post&quot;&gt;
    &lt;!-- name 속성: 서버로 전송할 때 변수이름의 역할 --&gt;
    이메일: &lt;input type=&quot;text&quot; name=&quot;memberEmail&quot;&gt;&lt;br&gt;
    비밀번호:&lt;input type=&quot;password&quot; name=&quot;memberPassword&quot;&gt;&lt;br&gt;
    이름:&lt;input type=&quot;text&quot; name=&quot;memberName&quot;&gt;&lt;br&gt;
    &lt;input type=&quot;submit&quot; value=&quot;회원가입&quot;&gt;
&lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre><h2 id="실행">실행</h2>
<ul>
<li><h4 id="처음-기본-페이지">처음 기본 페이지</h4>
<p><img src="https://velog.velcdn.com/images/woohee_/post/4d340eb8-3577-43a0-8f94-96c7ed4efc1d/image.png" alt=""></p>
</li>
<li><h4 id="회원가입-페이지">회원가입 페이지</h4>
<p><img src="https://velog.velcdn.com/images/woohee_/post/93926200-bb57-4c61-93a8-8ac04a3f0bb0/image.png" alt="">
save.html에서 비밀번호 속성을 password로 설정했기 때문에 비밀번호가 가려진다. </p>
</li>
<li><h4 id="회원가입-버튼-클릭">회원가입 버튼 클릭</h4>
<p><img src="https://velog.velcdn.com/images/woohee_/post/670e2e62-66cc-4805-a32a-7c7d26146c5e/image.png" alt="">
405 에러가 뜬다.
405 에러는 페이지는 있는데 방식이 잘못되었을 때 출력되는 에러이다.</p>
</li>
<li><h4 id="초기-창에서-로그인-버튼-클릭">초기 창에서 로그인 버튼 클릭</h4>
<p><img src="https://velog.velcdn.com/images/woohee_/post/3d65eb84-e7e4-4fe5-b72c-3d12afdfcfb0/image.png" alt="">
404 에러가 뜬다.
404 에러는 페이지가 없을 때 출력되는 에러이다.
에러 메세지를 잘 알아두면 에러를 해결하기 수월할 것이다.</p>
</li>
</ul>
<hr>
<p>이번 포스트에서는 회원가입 페이지를 요청하고 생성해보았다. 다음 포스트에서는 회원가입 정보를 controller에서 받아주는 실습을 진행해보겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Springboot 회원 프로젝트(2) 기본 주소 요청하기]]></title>
            <link>https://velog.io/@woohee_/Springboot-%ED%9A%8C%EC%9B%90-%EA%B4%80%EB%A6%AC-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B82-%EA%B8%B0%EB%B3%B8-%EC%A3%BC%EC%86%8C-%EC%9A%94%EC%B2%AD%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@woohee_/Springboot-%ED%9A%8C%EC%9B%90-%EA%B4%80%EB%A6%AC-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B82-%EA%B8%B0%EB%B3%B8-%EC%A3%BC%EC%86%8C-%EC%9A%94%EC%B2%AD%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sat, 06 Apr 2024 06:37:48 GMT</pubDate>
            <description><![CDATA[<h4 id="🔖지난-포스트에서-개발환경-세팅을-마쳤다-이번-포스트에서는-controller를-생성하여-기본-주소를-요청하는-과정을-수행해보겠다">🔖지난 포스트에서 개발환경 세팅을 마쳤다. 이번 포스트에서는 controller를 생성하여 기본 주소를 요청하는 과정을 수행해보겠다!</h4>
<hr>
<h2 id="spring-mvc란">Spring MVC란?</h2>
<blockquote>
<p>MVC 는 Model, View, Controller의 약자이며, 어플리케이션을 구성하는 요소를 역할에 따라 3가지 모듈로 나누어 구분한 패턴이다.</p>
</blockquote>
<ul>
<li>독립적인 역할을 나눔으로써 개발과 유지보수를 가능케 했다.</li>
</ul>
<h3 id="model">Model</h3>
<blockquote>
<p>웹 애플리케이션이 클라이언트의 요청을 받으면 요청 사항을 처리하기 위한 작업을 수행한다.</p>
</blockquote>
<ul>
<li>클라이언트에게 응답을 돌려주는 작업의 처리 결과 데이터이다.</li>
</ul>
<h3 id="view">View</h3>
<blockquote>
<p>Model을 이용하여 웹 브라우저와 같은 애플리케이션의 화면에 보이는 Resource를 제공하는 역할을 수행한다.</p>
</blockquote>
<ul>
<li>Html 페이지 출력</li>
<li>PDF, Excel 등의 문서 형태로 출력</li>
<li>XML, JSON 등 특정 형식의 포맷으로 변환</li>
</ul>
<h3 id="controller">Controller</h3>
<blockquote>
<p>클라이언트 측의 요청을 직접적으로 전달받는 엔드포인트로써 Model과 View의 중간에서 상호작용을 해주는 역할을 수행한다.</p>
</blockquote>
<ul>
<li>클라이언트 요청을 받아 로직을 거친 후, Model 데이터가 만들어지면 Model 데이터를 View로 전달하는 역할을 한다.</li>
</ul>
<h3 id="spring-mvc-패턴-구조">Spring MVC 패턴 구조</h3>
<p><img src="https://velog.velcdn.com/images/woohee_/post/fbcff1a8-cf51-4625-897e-e4b380db86b3/image.png" alt="">
이미지를 기반으로 이해하면 좀 수월할 것이다.
이제 controller를 생성해보자.</p>
<h2 id="controller-생성">controller 생성</h2>
<p>member -&gt; package생성 -&gt; controller 생성
controller -&gt; java class 생성-&gt; HomeController  생성</p>
<h3 id="homecontrollerjava">HomeController.java</h3>
<p> 기본페이지를 요청하는 메서드이다.</p>
<pre><code> @Controller
public class HomeController {
    //기본페이지 요청 메서드
    @GetMapping(&quot;/&quot;)
    public String index(){
        return &quot;index&quot;;   //=&gt;templates 폴더의 index.html을 찾아감
    }
}</code></pre><ul>
<li>&quot;/&quot;은 제일 기본 페이지를 뜻한다.</li>
<li>메서드를 실행시키면 index.html을 찾아가고 띄우게 된다.</li>
</ul>
<h3 id="indexhtml">index.html</h3>
<p>resources -&gt;templates -&gt; index.html 생성
코드는 다음과 같이 수정한다.</p>
<pre><code>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;title&gt;index&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h2&gt;Hello Spring Boot!!&lt;/h2&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre><ul>
<li>어떤 파일이 실행되었는지 확인하기 위해 title을 파일 이름으로 지정한다.</li>
<li>index.html 파일이 실행되면 Hello Spring Boot!! 라는 내용이 출력될 것을 예상해본다.</li>
</ul>
<h3 id="실행">실행</h3>
<p>어플리케이션을 실행시키면 다음과 같이 출력될 것이다.
<img src="https://velog.velcdn.com/images/woohee_/post/985ad8d2-09a4-43dd-a3d7-7632cd70bc3e/image.png" alt=""></p>
<ul>
<li>포트 번호가 8081로 설정됨을 확인할 수 있다.</li>
<li>localhost:8081로 접속해보자.</li>
</ul>
<h3 id="접속">접속</h3>
<p><img src="https://velog.velcdn.com/images/woohee_/post/9f5254db-e1c4-4a73-ba05-d52377e31010/image.png" alt=""></p>
<ul>
<li>예상한 바와 같이 출력된다.</li>
<li>지금 개발하고 있는 pc가 일종의 서버가 된 것이다.</li>
<li>다른 pc에서 해당 주소를 접속하는 것은 불가능하다.</li>
</ul>
<hr>
<p>다음 포스트에서는 이를 기반으로 회원가입 페이지를 요청하는 실습을 할 것이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Springboot 회원 프로젝트(1) 개발환경 세팅]]></title>
            <link>https://velog.io/@woohee_/Springboot-%ED%9A%8C%EC%9B%90-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B81-%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD-%EC%84%B8%ED%8C%85</link>
            <guid>https://velog.io/@woohee_/Springboot-%ED%9A%8C%EC%9B%90-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B81-%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD-%EC%84%B8%ED%8C%85</guid>
            <pubDate>Sat, 06 Apr 2024 06:24:49 GMT</pubDate>
            <description><![CDATA[<h4 id="springboot를-활용한-첫-프로젝트이다-간단하게-회원-관리-프로젝트를-만들-것이고-회원가입-회원-정보-조회-등의-기능을-가지는-프로젝트를-진행해보려-한다">Springboot를 활용한 첫 프로젝트이다. 간단하게 회원 관리 프로젝트를 만들 것이고 회원가입, 회원 정보 조회 등의 기능을 가지는 프로젝트를 진행해보려 한다.</h4>
<h4 id="이번-포스트에서는-개발환경-세팅을-진행할-것이다">이번 포스트에서는 개발환경 세팅을 진행할 것이다.</h4>
<hr>
<h2 id="⚙️개발환경-세팅">⚙️개발환경 세팅</h2>
<h3 id="spring-initilizer-사이트-접속">Spring initilizer 사이트 접속</h3>
<p><img src="https://velog.velcdn.com/images/woohee_/post/ee403a1d-e153-4d05-9509-0e4a7023ff0c/image.png" alt="">
Generate 후에 인텔리제이에서 build.gradle파일을 열어보자.
처음 생성할 때는 시간이 지연된다.</p>
<h2 id="applicationyml">application.yml</h2>
<p>처음에 생성된 파일을 보면, resources -&gt; application.properties 파일이 보일 것이다.
파일을 삭제하고 application.yml 파일을 생성하자.
application.yml파일 안에 코드는 다음과 같다.</p>
<pre><code>server:
  port: 8081</code></pre><p>사용할 포트 번호는 대게 8080이지만 8081로 설정하겠다.</p>
<p>기본적인 세팅은 끝났고 다음 포스트부터는 본격적인 개발을 시작해보겠다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[웹 개발 프로젝트(4) Springboot 환경세팅 및 프로젝트 생성]]></title>
            <link>https://velog.io/@woohee_/%EC%9B%B9-%EA%B0%9C%EB%B0%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B84-Springboot-%ED%99%98%EA%B2%BD%EC%84%B8%ED%8C%85-%EB%B0%8F-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%83%9D%EC%84%B1</link>
            <guid>https://velog.io/@woohee_/%EC%9B%B9-%EA%B0%9C%EB%B0%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B84-Springboot-%ED%99%98%EA%B2%BD%EC%84%B8%ED%8C%85-%EB%B0%8F-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%83%9D%EC%84%B1</guid>
            <pubDate>Tue, 02 Apr 2024 16:56:45 GMT</pubDate>
            <description><![CDATA[<h3 id="⚙️웹-개발-환경을-세팅하고-intellij에서-springboot-프로젝트를-생성하는-과정을-정리해보겠다">⚙️웹 개발 환경을 세팅하고 intellij에서 Springboot 프로젝트를 생성하는 과정을 정리해보겠다!</h3>
<hr>
<h2 id="1-스프링-스타터로-프로젝트-생성">1. 스프링 스타터로 프로젝트 생성</h2>
<p><a href="https://start.spring.io/">spring starter</a> 사이트로 이동해서 생성하거나, intellij에서 new project로 생성하는 방법이 있다.
본인은 사이트에서 여러번 생성해보았으므로 , intellij에서 생성해보겠다!</p>
<p><img src="https://velog.velcdn.com/images/woohee_/post/34f54b11-0709-45c5-8931-afadc9817794/image.png" alt=""></p>
<ul>
<li><p>Name : 프로젝트 이름</p>
<ul>
<li>Gradle을 사용하고 JDK 버전 &amp; java 버전 : 17 사용</li>
</ul>
<p><img src="https://velog.velcdn.com/images/woohee_/post/90e61a8f-9a89-4f6d-ab45-a6c7a5a69f4b/image.png" alt=""></p>
<ul>
<li>Dependencies는 일단 Spring Web, Thymeleaf를 사용할 것이다.
나중에 필요한 것들은 추가할 수 있으므로 일단은 이렇게 시작해보자 !</li>
</ul>
</li>
</ul>
<h2 id="2-controller-생성">2. controller 생성</h2>
<p><img src="https://velog.velcdn.com/images/woohee_/post/348b4dd0-ba74-47b3-bebe-ebf59c3c3151/image.png" alt=""></p>
<ul>
<li>com.example.timeflow 아래에 controller package생성</li>
<li>controller 패키지 안에 HomeController.java 파일 생성</li>
</ul>
<p><strong>HomeController.java</strong></p>
<pre><code>@Controller
public class HomeController {
    @GetMapping(&quot;/&quot;)
    public String index(){
        return &quot;index&quot;;
    }
}</code></pre><ul>
<li>HomeController.java 소스코드는 다음과 같다.</li>
<li>index.html 파일을 부르므로 index.html 파일을 생성해보자.</li>
</ul>
<p><strong>index.html</strong>
resources -&gt; templates -&gt; index.html생성</p>
<ul>
<li>소스 코드는 다음과 같다.<pre><code>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;UTF-8&quot;&gt;
  &lt;title&gt;Index&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;h1&gt;Index Page!&lt;/h1&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></li>
</ul>
<h2 id="application-실행">application 실행</h2>
<ul>
<li>timeflowApplication.java 실행
<img src="https://velog.velcdn.com/images/woohee_/post/51866a84-e3ba-4d5e-b205-577ab54ff00f/image.png" alt="">
<img src="https://velog.velcdn.com/images/woohee_/post/5abad5c1-9647-4d22-b091-d06ae29e2da9/image.png" alt=""></li>
<li>실행이 정상적으로 되고, 포트 번호는 8080임을 알 수 있다.</li>
<li>localhost:8080으로 접속해보자!</li>
</ul>
<p><img src="https://velog.velcdn.com/images/woohee_/post/582df8e7-8526-4049-984c-a084088a836f/image.png" alt=""></p>
<ul>
<li>index.html에 입력한 내용이 페이지에 출력됨을 확인해보았다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[웹 개발 프로젝트(3) ERD 작성]]></title>
            <link>https://velog.io/@woohee_/%EC%9B%B9-%EA%B0%9C%EB%B0%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B83-ERD-%EC%9E%91%EC%84%B1</link>
            <guid>https://velog.io/@woohee_/%EC%9B%B9-%EA%B0%9C%EB%B0%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B83-ERD-%EC%9E%91%EC%84%B1</guid>
            <pubDate>Tue, 02 Apr 2024 16:56:19 GMT</pubDate>
            <description><![CDATA[<p>fdafda</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[스프링 컨테이너와 스프링 빈(1) 스프링 컨테이너 생성]]></title>
            <link>https://velog.io/@woohee_/%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%881-%EC%8A%A4%ED%94%84%EB%A7%81-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88-%EC%83%9D%EC%84%B1</link>
            <guid>https://velog.io/@woohee_/%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%881-%EC%8A%A4%ED%94%84%EB%A7%81-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88-%EC%83%9D%EC%84%B1</guid>
            <pubDate>Sat, 30 Mar 2024 14:56:46 GMT</pubDate>
            <description><![CDATA[<h2 id="스프링-컨테이너-생성">스프링 컨테이너 생성</h2>
<pre><code>ApplicationContext applicationContext =
                new AnnotationConfigApplicationContext(AppConfig.class);</code></pre><ul>
<li>ApplicationContext 를 스프링 컨테이너라 한다.</li>
<li>ApplicationContext 는 인터페이스이다.</li>
<li>스프링 컨테이너는 xml 기반으로 만들 수 있고, 애노테이션 기반의 자바 설정 클래스로 만들 수 있다.</li>
<li>AppConfig를 사용했던 방식이 애노테이션 기반의 자바 설정 클래스로 스프링 컨테이너를 만든 것이다.</li>
<li>AnnotationConfigApplicationContext()는 ApplicationContext의 인터페이스 구현체이다.</li>
</ul>
<p>더 알아볼 것 : 스프링 컨테이너는 BeanFactory와 ApplicationContext로 구분한다. 일반적으로는 ApplicationContext를 스프링 컨테이너라고 한다.</p>
<h3 id="스프링-컨테이너의-생성-과정">스프링 컨테이너의 생성 과정</h3>
<p><strong>1. 스프링 컨테이너 생성</strong>
<img src="https://velog.velcdn.com/images/woohee_/post/cd1c146f-f1e3-47dc-97f4-3e93bba95f2f/image.png" alt=""></p>
<ul>
<li>스프링컨테이너를 생성할 때는 구성 정보를 저장해야 한다.</li>
<li>여기서는 AppConfig.class를 구성 정보로 지정했다.</li>
</ul>
<p><strong>2. 스프링 빈 등록</strong>
<img src="https://velog.velcdn.com/images/woohee_/post/0ea72e68-ddb4-4652-ae36-c6dd9b4e56e5/image.png" alt=""></p>
<ul>
<li>스프링 컨테이너는 파라미터로 넘어온 설정 클래스 정보를 사용해서 스프링 빈을 등록한다.</li>
</ul>
<p><strong>빈 이름</strong></p>
<ul>
<li>빈 이름은 메서드 이름을 사용한다.</li>
<li>빈 이름을 직접 부여할 수 있다. @Bean(name =&quot;memberService2&quot;)</li>
<li>빈 이름은 항상 다른 이름으로 부여해야 한다.</li>
</ul>
<p><strong>3. 스프링 빈 의존관계 설정 -준비</strong>
<img src="https://velog.velcdn.com/images/woohee_/post/9505d12c-a327-40fc-87a7-870d67e9f6d0/image.png" alt=""></p>
<p><strong>4. 스프링 빈 의존관계 설정 -완료</strong>
<img src="blob:https://velog.io/8511a20f-aac6-4d76-8d4d-0071e1a4bb84" alt="업로드중.."></p>
<ul>
<li>스프링 컨테이너는 설정 정보를 참고해서 의존관계를 주입(DI)한다.</li>
<li>단순히 자바 코드를 호출하는 것 같지만 차이가 존재한다. 싱글톤 컨테이너에서 설명할 것이다.</li>
</ul>
<p>스프링 컨테이너를 생성하고, 설정 정보를 참고해 스프링 빈을 등록하고 의존관계도 설정했다.
이제 스프링 컨테이너에서 데이터를 조회해보자</p>
<hr>
<h2 id="📜summary">📜Summary</h2>
<ul>
<li>스프링 컨테이너의 생성과정은 스프링 컨테이너 생성, 스프링 빈 등록, 스프링 빈 의존관계 설정으로 진행된다.</li>
<li>스프링 빈을 등록하는 과정과 의존관계 설정은 따로 이루어진다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring 객체지향 원리 적용(6) 스프링으로 전환]]></title>
            <link>https://velog.io/@woohee_/Spring-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%EC%9B%90%EB%A6%AC-%EC%A0%81%EC%9A%A96-%EC%8A%A4%ED%94%84%EB%A7%81%EC%9C%BC%EB%A1%9C-%EC%A0%84%ED%99%98</link>
            <guid>https://velog.io/@woohee_/Spring-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%EC%9B%90%EB%A6%AC-%EC%A0%81%EC%9A%A96-%EC%8A%A4%ED%94%84%EB%A7%81%EC%9C%BC%EB%A1%9C-%EC%A0%84%ED%99%98</guid>
            <pubDate>Sat, 30 Mar 2024 14:19:29 GMT</pubDate>
            <description><![CDATA[<h4 id="🔖이전까지는-순수한-자바-코드만으로-di를-적용했다-이젠-스프링을-사용해보자">🔖이전까지는 순수한 자바 코드만으로 DI를 적용했다. 이젠 스프링을 사용해보자.</h4>
<hr>
<h2 id="스프링으로-전환하기">스프링으로 전환하기</h2>
<p><strong>appConfig</strong></p>
<pre><code>@Configuration
public class AppConfig {
    @Bean
    public MemberService memberService(){
        return new MemberServiceImpl(memberRepository());
    }
    @Bean
    public static MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }
    @Bean
    public OrderService orderService(){
        return new OrderServiceImpl(memberRepository(),discountPolicy());
    }
    @Bean
    public DiscountPolicy discountPolicy(){
//        return new FixDiscountPolicy();
        return new RateDiscountPolicy();
    }
}</code></pre><p><strong>MemberApp</strong></p>
<pre><code>public class MemberApp {
    public static void main(String[] args) {
//        AppConfig appConfig = new AppConfig();
//        MemberService memberService = appConfig.memberService();

        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
       MemberService memberService =  applicationContext.getBean(&quot;memberService&quot;, MemberService.class);

        Member member = new Member(1L, &quot;memberA&quot;, Grade.VIP);
        memberService.join(member);

        Member findMember = memberService.findMember(1L);
        System.out.println(&quot;new member = &quot;+member.getName());
        System.out.println(&quot;find Member = &quot;+findMember.getName());
    }
}</code></pre><p><strong>OrderApp</strong></p>
<pre><code>public class OrderApp {
    public static void main(String[] args) {
//        AppConfig appConfig = new AppConfig();
//        MemberService memberService = appConfig.memberService();
//        OrderService orderService = appConfig.orderService();

        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
        MemberService memberService = applicationContext.getBean(&quot;memberService&quot;,MemberService.class);
        OrderService orderService = applicationContext.getBean(&quot;orderService&quot;,OrderService.class);

        Long memberId = 1L;
        Member member = new Member(memberId, &quot;memberA&quot;, Grade.VIP);
        memberService.join(member);

        Order order = orderService.createOrder(memberId, &quot;itemA&quot;, 20000);

        System.out.println(&quot;order=&quot; + order);
        System.out.println(&quot;order.calculate= &quot;+order.calculatorPrice());
    }
}</code></pre><h4 id="스프링-컨테이너">스프링 컨테이너</h4>
<ul>
<li>ApplicationContext를 스프링 컨테이너라 한다.</li>
<li>기존에는 개발자가 AppConfig를 사용하여 직접 객체를 생성하고 DI를 했지만, 이제부터는 스프링 컨테이너를 사용한다.</li>
<li>스프링 컨테이너는 <strong>@Configuration</strong>이 붙은 AppConfig를 설정 정보로 사용한다. 여기서 <strong>@Bean</strong>이 적힌 메서드는 모두 호출해서 반환된 객체를 스프링 컨테이너에 등록한다. </li>
<li>스프링 빈은 @Bean이 붙은 메서드 명을 스프링 빈의 이름으로 사용한다.</li>
<li>이전에는 개발자가 필요한 객체를 AppConfig를 사용해서 직접 조회했지만, 이제부터는 스프링 컨테이너를 통해서 필요한 스프링 빈을 찾아야 한다. <strong>applicationContext.getBean()</strong> 메서드를 사용해서 찾을 수 있다.</li>
<li>기존에는 개발자가 직접 자바코드로 모든 것을 했다면 이젠 스프링 컨테이너에 객체를 스프링 빈으로 등록하고, 스프링 컨테이너에서 스프링 빈을 찾아서 사용하도록 변경되었다.</li>
</ul>
<p>질문을 던져보자. <strong>스프링 컨테이너를 사용함으로써 장점이 뭐가 있을까?</strong>
다음 포스트부터 본격적으로 스프링의 장점과 기능을 사용할 것이다!</p>
<hr>
<h2 id="📜summary">📜Summary</h2>
<ul>
<li>다형성만으로는 OCP,DIP를 만족할 수 없다. </li>
<li>AppConfig보다 SpringContainer가 더 낫다(다음 포스트부터 설명)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring 객체 지향 원리 적용(5) IoC, DI, 컨테이너]]></title>
            <link>https://velog.io/@woohee_/Spring-%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5-%EC%9B%90%EB%A6%AC-%EC%A0%81%EC%9A%A95-IoC-DI-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88</link>
            <guid>https://velog.io/@woohee_/Spring-%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5-%EC%9B%90%EB%A6%AC-%EC%A0%81%EC%9A%A95-IoC-DI-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88</guid>
            <pubDate>Sat, 30 Mar 2024 13:47:09 GMT</pubDate>
            <description><![CDATA[<h2 id="제어의-역전-iocinversion-of-control">제어의 역전 IoC(Inversion of Control)</h2>
<blockquote>
<p>프로그램의 제어 흐름을 직접 제어하는 것이 아니라 외부에서 관리하는 것을 뜻한다.</p>
</blockquote>
<ul>
<li>이전에 실행했던 예제에서는 appConfig가 권한을 가지고 있다.</li>
<li>appConfig가 제어 흐름에 대한 권한을 가지고 있으므로 이를 제어의 역전이라 한다.</li>
</ul>
<h2 id="의존관계-주입-didependency-injection">의존관계 주입 DI(Dependency Injection)</h2>
<ul>
<li><p>OrderServiceImpl은 DiscountPolicy 인터페이스에 의존한다. 실제로 어떤 구현 객체가 사용될지는 모른다.</p>
</li>
<li><p>의존관계는 정적인 클래스 의존 관계와, 실행 시점에 결정되는 동적인 객체 의존 관계 둘을 분리해서 생각해야 한다.</p>
</li>
</ul>
<h4 id="정적인-클래스-의존관계">정적인 클래스 의존관계</h4>
<ul>
<li><p>클래스가 사용하는 import 만으로 의존관계를 쉽게 판단할 수 있다.</p>
</li>
<li><p>애플리케이션을 실행하지 않아도 분석할 수 있다.</p>
</li>
</ul>
<h4 id="동적인-객체-인스턴스-의존-관계">동적인 객체 인스턴스 의존 관계</h4>
<ul>
<li><p>실행 시점에 외부에서 실제 구현 객체를 생성하고 클라이언트에 전달해서 클라이언트와 서버의 실제 의존관계가 연결되는 것을 <strong>의존관계 주입</strong>이라 한다.</p>
</li>
<li><p>의존관계 주입을 사용하면 클라이언트 코드를 변경하지 않고, 클라이언트가 호출하는 대상의 타입 인스턴스를 변경할 수 있다.</p>
</li>
<li><p>의존관계 주입을 사용하면 정적인 클래스 의존관계를 변경하지 않고, 동적인 객체 인스턴스 의존관계를 쉽게 변경할 수 있다.</p>
</li>
</ul>
<h2 id="ioc-컨테이너-di-컨테이너">IoC 컨테이너, DI 컨테이너</h2>
<blockquote>
<p>AppConfig처럼 객체를 생성하고 관리하면서 의존관계를 연결해주는 것을 IoC 컨테이너, DI 컨테이너라고 한다.</p>
</blockquote>
<ul>
<li>의존관계 주입에 초점을 맞추어 최근에는 주로 DI 컨테이라 한다.</li>
<li>어샘블러, 오브젝트 팩토리 등으로 불리기도 한다.</li>
</ul>
<hr>
<h2 id="📜summary">📜Summary</h2>
<ul>
<li><p>프로그램의 제어 흐름을 외부에서 관리하는 것을 제어의 역전이라 한다.</p>
</li>
<li><p>의존관계 주입에는 정적 의존관계, 동적 의존관계 둘 다 생각해야 한다.</p>
</li>
<li><p>정적 의존관계는 실행하지 않고도 분석할 수 있다.</p>
</li>
<li><p>동적인 의존관계는 실행 시점에 외부에서 객체를 생성하고 전달하여 연결되는 것이다.</p>
</li>
<li><p>IoC 컨테이너와 DI 컨테이너는 비슷한 의미로 쓰이고 최근에는 DI 컨테이너라고 많이 불린다. ex) appConfig</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring 객체지향 원리 적용(4) 새로운 구조와 할인 정책 적용 & 전체 흐름 정리 & SOLID 원칙의 적용]]></title>
            <link>https://velog.io/@woohee_/Spring-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%EC%9B%90%EB%A6%AC-%EC%A0%81%EC%9A%A94-%EC%83%88%EB%A1%9C%EC%9A%B4-%EA%B5%AC%EC%A1%B0%EC%99%80-%ED%95%A0%EC%9D%B8-%EC%A0%95%EC%B1%85-%EC%A0%81%EC%9A%A9-%EC%A0%84%EC%B2%B4-%ED%9D%90%EB%A6%84-%EC%A0%95%EB%A6%AC-SOLID-%EC%9B%90%EC%B9%99%EC%9D%98-%EC%A0%81%EC%9A%A9</link>
            <guid>https://velog.io/@woohee_/Spring-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%EC%9B%90%EB%A6%AC-%EC%A0%81%EC%9A%A94-%EC%83%88%EB%A1%9C%EC%9A%B4-%EA%B5%AC%EC%A1%B0%EC%99%80-%ED%95%A0%EC%9D%B8-%EC%A0%95%EC%B1%85-%EC%A0%81%EC%9A%A9-%EC%A0%84%EC%B2%B4-%ED%9D%90%EB%A6%84-%EC%A0%95%EB%A6%AC-SOLID-%EC%9B%90%EC%B9%99%EC%9D%98-%EC%A0%81%EC%9A%A9</guid>
            <pubDate>Sat, 30 Mar 2024 07:06:05 GMT</pubDate>
            <description><![CDATA[<h4 id="🔖지난-포스트까지-fixdiscountpolicy만-적용한-할인만-구현하였다-이번-포스트에서는-ratediscountpolicy를-적용한-할인으로-변경해보자">🔖지난 포스트까지 FixDiscountPolicy만 적용한 할인만 구현하였다. 이번 포스트에서는 RateDiscountPolicy를 적용한 할인으로 변경해보자.</h4>
<hr>
<h2 id="새로운-구조와-할인-정책-적용">새로운 구조와 할인 정책 적용</h2>
<ul>
<li>정액 할인 정책을 정률 할인 정책으로 변경해보자.</li>
<li>FixDiscountPolicy - &gt; RateDiscountPolicy</li>
<li>어떤 부분을 변경해야 될까?</li>
</ul>
<p><strong>사용, 구성의 분리</strong>
<img src="https://velog.velcdn.com/images/woohee_/post/ee832864-1f62-49de-90c0-59bdbe4d792a/image.png" alt=""></p>
<p><strong>할인 정책의 변경</strong>
<img src="https://velog.velcdn.com/images/woohee_/post/cd130be5-4aa6-4eb8-9420-ad3e2dc4538f/image.png" alt=""></p>
<pre><code>public class AppConfig {
    public MemberService memberService(){
        return new MemberServiceImpl(memberRepository());
    }
    private static MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }

    public OrderService orderService(){
        return new OrderServiceImpl(memberRepository(),discountPolicy());
    }
    public DiscountPolicy discountPolicy(){
//        return new FixDiscountPolicy();
        return new RateDiscountPolicy();
    }
}</code></pre><ul>
<li>변경 후 20000으로 변경하고 실행하면 할인 금액이 2000원으로 적용된다.</li>
<li>사용 영역은 코드를 변경할 필요가 없다.</li>
<li>구성 영역은 당연히 변경된다. </li>
</ul>
<hr>
<h2 id="전체-흐름-정리">전체 흐름 정리</h2>
<p>지금까지의 흐름을 정리해보자.</p>
<p><strong>새로운 할인 정책 개발</strong></p>
<ul>
<li>다형성을 사용했으므로 정률 할인 정책을 추가로 개발하는 것은 문제가 없다.</li>
</ul>
<p><strong>새로운 할인 정책 적용과 문제점</strong></p>
<ul>
<li>새로 개발한 정률 할인 정책을 적용하면 클라이언트 코드인 주문 서비스 구현체도 함께 변경해야 한다.</li>
<li>DiscountPolicy + FixDiscountPolicy 모두 의존한다. -&gt; DIP 위반</li>
</ul>
<p>** 관심사의 분리**</p>
<ul>
<li>애플리케이션을 하나의 공연으로 생각해보자.</li>
<li>기존에는 배우가 공연도 하고, 여자 주인공도 직접 초빙하는 다양한 책임을 가진다.</li>
<li>공연을 구성하고, 배우를 섭외하고, 지정하는 책임을 담당하는 <strong>공연기획자</strong>가 필요하다.</li>
<li>공연 기획자를 AppConfig로 설정하고 이는 구현 객체를 생성, 연결하는 책임을 가진다.</li>
<li>클라이언트 객체는 자신의 역할을 실행하는 역할만 한다. (책임이 명확해짐)</li>
</ul>
<p><strong>AppConfig 리팩터링</strong></p>
<ul>
<li>구성 정보에서 역할과 구현을 명확히 분리한다.</li>
<li>역할이 잘 드러나고 중복을 제거한다.</li>
</ul>
<p><strong>새로운 구조와 할인 정책 적용</strong></p>
<ul>
<li>정액 할인 정책 -&gt; 정률 할인 정책으로 변경한다.</li>
<li>AppConfig의 등장으로 사용영역과 구성영역으로 분리한다.</li>
<li>할인 정책을 변경해도 AppConfig가 있는 구성 영역만 변경하면 된다. 클라이언트 코드는 전혀 변경되지 않는다.</li>
</ul>
<hr>
<h2 id="좋은-객체-지향-설계의-5가지-원칙-적용">좋은 객체 지향 설계의 5가지 원칙 적용</h2>
<p>3가지 SRP, DIP, OCP 적용</p>
<h4 id="srp-단일-책임-원칙">SRP 단일 책임 원칙</h4>
<p>한 클래스는 하나의 책임만 가져야 한다.</p>
<blockquote>
<ul>
<li>클라이언트는 직접 구현 객체를 생성하고 연결하고 실행하는 다양한 책임을 가지고 있음.</li>
<li>SRP 단일 책임 원칙을 따르면서 관심사를 분리함.</li>
<li>구현 개게를 생성하고 연결하는 책임은 AppConfig가 담당</li>
<li>클라이언트 객체는 실행하는 책임만 담당</li>
</ul>
</blockquote>
<h4 id="dip-의존관계-역전-원칙">DIP 의존관계 역전 원칙</h4>
<p>프로그래머는 추상화에 의존해야지, 구체화에 의존하면 안된다.
의존성 주입은 이 원칙을 따르는 방법 중 하나이다.</p>
<blockquote>
<ul>
<li>새로운 할인 정책을 적용할 때, 클라이언트 코드도 함께 변경해야 했다. DIP를 지키는 것처럼 보였지만 클라이언트 코드가 FixDiscountPolicy라는 구체 클래스에도 함께 의존했다.</li>
<li>클라이언트 코드가 DiscountPolicy에만 의존하도록 코드를 변경했다.</li>
<li>AppConfig가 FixDiscountPolicy 객체 인스턴스를 클라이언트 코드 대신 생성해서 클라이언트 코드에 의존관계를 주입했다. DIP 원칙을 따르면서 문제를 해결했다.</li>
</ul>
</blockquote>
<h4 id="ocp">OCP</h4>
<p>소프트웨어 요소는 확정에는 열려 있으나 변경에는 닫혀 있어야 한다.</p>
<blockquote>
<ul>
<li>다형성을 사용하고 클라이언트가 DIP를 지킴</li>
<li>애플리케이션을 사용영역과 구성영역으로 나눔</li>
<li>AppConfig가 할인 정책을 변경하여 클라이언트 코드에 주입하므로 클라이언트 코드는 변경되지 않는다.</li>
<li>소프트웨어 요소를 새롭게 확장해도 사용 영역의 변경에는 닫혀 있다.</li>
</ul>
</blockquote>
<hr>
<h2 id="📜summary">📜Summary</h2>
<ul>
<li>역할과 구현을 명확히 분리하면 변경에 용이하다.</li>
<li>SOLID 원칙을 만족하면 좋은 객체 지향 설계가 가능하다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring 객체지향 원리 적용(3) AppConfig 리팩터링]]></title>
            <link>https://velog.io/@woohee_/Spring-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%EC%9B%90%EB%A6%AC-%EC%A0%81%EC%9A%A93-AppConfig-%EB%A6%AC%ED%8C%A9%ED%84%B0%EB%A7%81</link>
            <guid>https://velog.io/@woohee_/Spring-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%EC%9B%90%EB%A6%AC-%EC%A0%81%EC%9A%A93-AppConfig-%EB%A6%AC%ED%8C%A9%ED%84%B0%EB%A7%81</guid>
            <pubDate>Sat, 30 Mar 2024 06:29:30 GMT</pubDate>
            <description><![CDATA[<h4 id="🔖지난-포스트에서-appconfig-생성하여-객체를-생성하고-역할을-부여하도록-구현하였고-solid-법칙을-만족하도록-구현하였다-이번-포스트에서는-appconfig를-리팩터링-해보자">🔖지난 포스트에서 AppConfig 생성하여 객체를 생성하고 역할을 부여하도록 구현하였고, SOLID 법칙을 만족하도록 구현하였다. 이번 포스트에서는 AppConfig를 리팩터링 해보자.</h4>
<p>AppConfig의 역할이 뚜렷하게 보이지 않아서 리팩터링하여 역할을 드러나게 구현해보자.</p>
<hr>
<h2 id="appconfig-리팩터링">AppConfig 리팩터링</h2>
<blockquote>
<p>리팩터링이란?
결과의 변경 없이 코드의 구조를 재조정함을 뜻한다.</p>
</blockquote>
<p>지금 현재의 appConfig 코드만 봐서는 다음 다이어그램이 한눈에 들어오지 않는다.
<img src="https://velog.velcdn.com/images/woohee_/post/64464302-2e7d-4064-8919-aa039d2cb325/image.png" alt=""></p>
<ul>
<li>appConfig 코드를 리팩터링해보자.</li>
<li>appConfig의 역할이 한 눈에 들어오기 위한 코드는 다음과 같다.</li>
</ul>
<pre><code>public class AppConfig {
    public MemberService memberService(){
        return new MemberServiceImpl(memberRepository());
    }
    private static MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }

    public OrderService orderService(){
        return new OrderServiceImpl(memberRepository(),discountPolicy());
    }
    public DiscountPolicy discountPolicy(){
        return new FixDiscountPolicy();
    }
}</code></pre><ul>
<li>MemoryRepository를 다른 구현체로 변경할 때 한 부분만 변경하면 된다.</li>
<li>AppConfig를 보면 역할과 구현 클래스가 한 눈에 들어온다. 전체 구성을 빠르게 파악할 수 있다.</li>
</ul>
<hr>
<h2 id="📜summary">📜Summary</h2>
<ul>
<li>클래스의 역할이 한 눈에 들어오지 않을 때 리팩터링을 하자.</li>
<li>리팩터링을 통해 애플리케이션 구성을 빠르게 파악할 수 있다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring 객체지향 원리 적용(2) 관심사의 분리]]></title>
            <link>https://velog.io/@woohee_/Spring-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%EC%9B%90%EB%A6%AC-%EC%A0%81%EC%9A%A92-%EA%B4%80%EC%8B%AC%EC%82%AC%EC%9D%98-%EB%B6%84%EB%A6%AC</link>
            <guid>https://velog.io/@woohee_/Spring-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%EC%9B%90%EB%A6%AC-%EC%A0%81%EC%9A%A92-%EA%B4%80%EC%8B%AC%EC%82%AC%EC%9D%98-%EB%B6%84%EB%A6%AC</guid>
            <pubDate>Sat, 30 Mar 2024 05:58:29 GMT</pubDate>
            <description><![CDATA[<h3 id="🔖solid-법칙을-만족시켜보자">🔖SOLID 법칙을 만족시켜보자.</h3>
<hr>
<h2 id="🧩-관심사의-분리">🧩 관심사의 분리</h2>
<p>다양한 책임을 가지지 않고 각각의 책임을 확실히 분리하자.</p>
<p><strong>App Config</strong></p>
<pre><code>public class AppConfig {
    public MemberService memberService(){
        return new MemberServiceImpl(new MemoryMemberRepository());
    }

    public OrderService orderService(){
        return new OrderServiceImpl(new MemoryMemberRepository(),new FixDiscountPolicy());
    }
}</code></pre><ul>
<li>실제 동작에 필요한 구현 객체를 생성한다.</li>
<li>생성한 객체 인스턴스의 참조를 생성자를 통해서 주입해준다.</li>
</ul>
<p><strong>MemberServiceImpl 생성자 주입</strong></p>
<pre><code>  private final MemberRepository memberRepository;

    public MemberServiceImpl(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }</code></pre><ul>
<li>MemberServiceImpl- &gt; MemortyMemberRepository 에 의존하지 않는다.</li>
<li>MemberServiceImpl은 어떤 구현 객체가 들어올지 알 수 없다.</li>
<li>MemberServiceImpl의 생성자를 통해 어떤 객체를 주입할지는 AppConfig에서 결정된다</li>
<li>MemerServiceImpl은 실행에만 집중하면 된다.</li>
</ul>
<p><strong>클래스 다이어그램</strong></p>
<p> <img src="https://velog.velcdn.com/images/woohee_/post/3925d515-2e8b-4abd-b81e-bb7d74b8408c/image.png" alt=""></p>
<ul>
<li>AppConfig는 객체 생성과 연결을 담당한다.</li>
<li>관심사의 분리 : 객체를 생성하고 연결하는 역할과 실행하는 역할이 명확히 분리되었다.</li>
</ul>
<p><strong>객체 다이어그램</strong>
 <img src="https://velog.velcdn.com/images/woohee_/post/009c3eb2-4509-4957-84ed-b4ce0cd3cef6/image.png" alt=""></p>
<ul>
<li>memberServiceImpl 입장에서 의존관계를 외부에서 주입해주는 것 같다고 하여 
DI(의존성 주입)이라 한다.</li>
</ul>
<p><strong>OrderServiceImpl 생성자 주입</strong></p>
<pre><code> private final MemberRepository memberRepository;
    private  DiscountPolicy discountPolicy;

    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }</code></pre><ul>
<li>OrderServiceImpl -&gt; FixDiscountPolicy 의존하지 않는다.</li>
<li>DiscountPolicy 인터페이스만 의존한다.</li>
<li>OrderServiceImpl 입장에서 어떤 구현 객체가 들어올지 알 수 없다.</li>
<li>OrderServiceImpl 생성자를 통해서 어떤 구현 객체가 들어올지는 오직 AppConfig에서 결정한다.</li>
<li>OrderServiceImpl은 실행에만 집중한다.</li>
</ul>
<h3 id="최종-실행-코드">최종 실행 코드</h3>
<pre><code>public class MemberApp {
    public static void main(String[] args) {
        AppConfig appConfig = new AppConfig();
        MemberService memberService = appConfig.memberService();
        Member member = new Member(1L, &quot;memberA&quot;, Grade.VIP);
        memberService.join(member);

        Member findMember = memberService.findMember(1L);
        System.out.println(&quot;new member = &quot;+member.getName());
        System.out.println(&quot;find Member = &quot;+findMember.getName());
    }
}</code></pre><pre><code>public class OrderApp {

    public static void main(String[] args) {
        AppConfig appConfig = new AppConfig();
        MemberService memberService = appConfig.memberService();
        OrderService orderService = appConfig.orderService();

        Long memberId = 1L;
        Member member = new Member(memberId, &quot;memberA&quot;, Grade.VIP);
        memberService.join(member);

        Order order = orderService.createOrder(memberId, &quot;itemA&quot;, 10000);

        System.out.println(&quot;order=&quot; + order);
        System.out.println(&quot;order.calculate= &quot;+order.calculatorPrice());
    }
}</code></pre><hr>
<h2 id="📜summary">📜Summary</h2>
<ul>
<li>AppConfig를 통해 관심사를 분리했다.</li>
<li>배역과 배우로 생각해보면 AppConfig는 공연 기획자이다.</li>
<li>AppConfig는 구체 클래스를 선택하고 배역에 맞는 배우를 선택한다. </li>
<li>각 배우들은 담당 기능을 실행하는 책임만 지면 된다.</li>
<li>OrderServiceImpl은 기능을 실행하는 책임만 지면 된다.</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>