<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>dong_geon_kim.log</title>
        <link>https://velog.io/</link>
        <description>한 줄에 의미를, 한 줄에 고민을</description>
        <lastBuildDate>Thu, 14 Oct 2021 17:38:06 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>dong_geon_kim.log</title>
            <url>https://images.velog.io/images/dong_geon_kim/profile/9746c9eb-5743-4ec5-82a5-619a315c347e/social.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. dong_geon_kim.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/dong_geon_kim" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[동건의 컨벤션]]></title>
            <link>https://velog.io/@dong_geon_kim/%EB%8F%99%EA%B1%B4%EC%9D%98-%EC%BB%A8%EB%B2%A4%EC%85%98</link>
            <guid>https://velog.io/@dong_geon_kim/%EB%8F%99%EA%B1%B4%EC%9D%98-%EC%BB%A8%EB%B2%A4%EC%85%98</guid>
            <pubDate>Thu, 14 Oct 2021 17:38:06 GMT</pubDate>
            <description><![CDATA[<h3 id="convention에-대하여">Convention에 대하여</h3>
<p>지금까지 프로젝트를 진행하면서, 나만의 컨벤션에 대해 고민해 보지 않은 것 같습니다..
그렇기 때문에 항상 구글링 또는 다른 사람들의 코드를 보며 맞춰서 작성한 것 같아요</p>
<p>공부를 하면 할수록, 내 주장이 들어간 코드를 작성하고 싶은 욕구가 뿜뿜했습니다!!</p>
<p>그래서 이번 기회에 나만의 Convention!을 정해보자! 생각했습니다!</p>
<p>물론, 어떤 집단에 들어간다면 팀원과 함께 정해야겠지만요~</p>
<h3 id="database">DATABASE</h3>
<ol>
<li>DATABASE의 쿼리는 전부 소문자로 작성한다!<pre><code class="language-sql">select * from member;</code></pre>
</li>
<li>DATABASE의 TABLE 네이밍 전략은 단수형을 사용한다!<pre><code class="language-sql">create table member(
)</code></pre>
</li>
<li>DATABASE의 컬럼 네이밍 전략은 TABLE_COLUMN을 사용한다!<pre><code class="language-sql">create table member(
 member_id int,
 member_name varchar
)</code></pre>
</li>
</ol>
<h3 id="spring-layer">Spring Layer</h3>
<p>기본적인 Layer 규칙은 아래와 같다! Member를 예시로!</p>
<pre><code>- config
- error
    + exception
- common
- util
- member
    + application
    + presentation
    + infrastructure
    + domain
        + vo
    + converter
    + dto
        + request
        + response
        + bundle</code></pre><h3 id="layer간-data-통신">Layer간 Data 통신</h3>
<ol>
<li>View -&gt; Controller (원시값을 가진 requestDTO) -&gt; MemberSignRequestDto</li>
<li>Controller -&gt; Service (requestDto -&gt; dto (원시값을 VO로 바꾼 DTO, 또는 원시데이터를 valid한 데이터!) -&gt; MemberSignServiceDto</li>
<li>Service -&gt; Controller (dto -&gt; responseDto) -&gt; MemberSignResponseDto</li>
</ol>
<p>아래의 방향대로~~</p>
<pre><code>view -&gt; controller
MemberSignRequestDto.java

MemberSignRequestDto(){
    private String name;
    private String age;
}</code></pre><pre><code>controller -&gt; service
MemberSignServiceDto.java

MemberSignServiceDto(){
    private Name name;
    private Age age;
}</code></pre><pre><code>service -&gt; controller
MemberSignResponseDto.java

MemberSignResponseDto(){
    private String name;
    private String age;</code></pre><h3 id="네이밍-전략">네이밍 전략!</h3>
<ol>
<li>Controller<ul>
<li>sign, edit, insert, delete</li>
</ul>
</li>
<li>Service<ul>
<li>create, delete, update, find, findAll</li>
</ul>
</li>
<li>Repository<ul>
<li>JPA Naming 전략을 따른다.</li>
</ul>
</li>
</ol>
<h3 id="허용되는-lombok-사용">허용되는 Lombok 사용</h3>
<ul>
<li>@RequiredArgsConstructor</li>
<li>@AllArgsConstructor</li>
<li>@Builder (필드가 3개 이상이면!)</li>
<li>@NonNull</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[포레스트....for rest?]]></title>
            <link>https://velog.io/@dong_geon_kim/%ED%8F%AC%EB%A0%88%EC%8A%A4%ED%8A%B8....for-rest</link>
            <guid>https://velog.io/@dong_geon_kim/%ED%8F%AC%EB%A0%88%EC%8A%A4%ED%8A%B8....for-rest</guid>
            <pubDate>Fri, 08 Oct 2021 01:01:43 GMT</pubDate>
            <description><![CDATA[<p>이번에 프로그래머스 교육과정과 졸업논문을 진행하면서, 공통적으로 REST로 백엔드를 구현하게 되었습니다!</p>
<p>항상 SSR로 thymeleaf를 렌더링을 통해 진행했었는데, client의 상황을 고려해야 하는 REST 방식을 사용한다는게 미숙한 점도 많았고, 모르는 점도 많았습니다!!</p>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/01e4b195-197b-4f3d-8547-c94c73ac4c25/image.png" alt=""></p>
<p>그래도 나는 할 수 있다! 라는 마인드로 인프런 강의를 들으며 코드를 작성했지만,,,,REST를 REST스럽게 짜지 못했다는게 결론이 되었습니다...</p>
<p>단순하게, json 타입으로 데이터를 전달하면 REST API인 줄 알았지만, 실상은 달랐습니다. REST를 REST답게 사용할려면 꼭 지켜야 하는 규칙이 존재함을 알게 되었습니다.</p>
<p>그래서 이번에는 제가 현 상황에서 최대한 REST를 어떻게 REST답게 구현할려고 했는지에 대해 작성하려고 합니다!!</p>
<p>서두가 길었네요!! 바로 시작하겠습니다!!!</p>
<h3 id="기존-제가-짠-방식은">기존 제가 짠 방식은?</h3>
<p>프로그래머스에서 진행하는 Spring-Baord 토이 프로젝트를 예로 현재 제가 어떻게 진행했고, 어떻게 수정할지에 대해 보여드리겠습니다!</p>
<p>아래의 코드는 회원가입을 진행했을 때 format 형태입니다.</p>
<ul>
<li><p>url</p>
<pre><code>http://localhost:8080/api/member</code></pre></li>
<li><p>header</p>
<pre><code>Content-Type : application/json</code></pre></li>
<li><p>body</p>
<pre><code>{
&quot;status&quot;: 201,
&quot;message&quot;: &quot;MEMBER_SIGN_SUCCESS&quot;,
&quot;data&quot;: null
}</code></pre></li>
</ul>
<p>위의 코드를 살펴보면, header에는 content-type이 존재하고 body에는 상태, 메세지, 데이터가 전달됨을 확인할 수 있습니다.</p>
<p>혹시 해당 스펙에서 어떤 점이 REST스럽지 못하다고 생각하실까요?
.
.
.
.
.
.
.
.
.
.
.
.
.
.
제 코드가 RESTFUL하지 않은 이유!!는 아래와 같습니다!</p>
<p>1) Non Cacheable
2) Non Uniform Interface</p>
<ul>
<li>self-descriptive messages</li>
<li>hypermedia as the engine of application state(HATEOAS)</li>
</ul>
<p>제가 기획한 api는 Rest를 모방한, REST스럽지 못하고 REST가 아닌 코드가 되었습니다.ㅜㅜㅜ</p>
<h3 id="그래서-rest란">그래서 Rest란?</h3>
<p>Representational State Transfer의 약자로서 <code>인터넷에서 컴퓨터 시스템 간의 상호 운용성을 제공하는 방법</code>입니다.</p>
<p>로이 필딩이 HTTP 기획 작업에 참여하면서 웹 환경의 정합성과 상호 운영성 등을 개선하기 위해서 만든 모델이 <code>HTTP Object Model</code>이라고 합니다. 그리고 이것이 REST의 시초가 되었다고 합니다!</p>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/aacdc963-be7a-4156-82ec-b1c5c3d7afed/image.png" alt=""></p>
<p>REST는 SOAP과 다르게 프로토콜이 아닌 아키텍쳐입니다. 하나의 구성이자, 약속이므로 필딩이 트위터와 블로그에 계속 언급하다시피, REST의 제약조건을 따르지 않으면, REST가 될 수 없습니다
... 그저 단순한 api?</p>
<h3 id="for-restful-with-architectural-constraints">For Restful with Architectural Constraints</h3>
<p>REST 공식 홈페이지에서 나와 있는 것 처럼, REST의 제약조건은 크게 6가지로 지정되어 있습니다.</p>
<ol>
<li>Uniform interface</li>
<li>Client–server</li>
<li>Stateless</li>
<li>Cacheable</li>
<li>Layered system</li>
<li>Code on demand (optional)</li>
</ol>
<h3 id="uniform-interface">Uniform interface</h3>
<blockquote>
<p>URL로 지정된 리소스에 대한 조작을 통일하고 한정된 인터페이스로 수행하는 아키텍쳐 스타일, 이렇게 추상적으로 정의를 내린 이유는 추가적인 확장에 있어 느슨한 결합을 유지하기 위함입니다!</p>
</blockquote>
<p>Uniform interface에는 4가지의 세부사항이 존재합니다!</p>
<ol>
<li>identification of resources
각각의 리소스(비디오, 문서, 이미지 등)가 하나 이상의 유일성을 가진 특정 URI를 가져야 함을 의미합니다.</li>
</ol>
<p>Resouce가 단일한 URL에 매핑되어 리소스에 대한 관리가 진행될 때 Rest 제약조건을 갖추게 됩니다.</p>
<p>여기서 파생된 규칙은 URL를 명칭할때 동사가 아닌, 명사형으로 URL를 구분해야 한다고 합니다.</p>
<pre><code>GET /member/delete/id/1 (X)</code></pre><p>위의 코드처럼 동사형으로 URL를 가져가는 것이 아니라, 
아래의 코드처럼 적절한 HTTP METHOD와 자원을 식별할 수 있는 명사형 명칭을 통해 URI를 구성해야 합니다!</p>
<pre><code>DELETE /member/1</code></pre><p>해당 규칙의 경우에는 일반적으로 HTTP Method를 사용할 때 지켜지는 것 같습니다. 대부분의 개발자분들이 해당 규칙은 지킨다고 생각합니다.</p>
<ol start="2">
<li>manipulation of resources through representations
리소스를 요청할 때 서버는 리소스 표현으로 응답해야 하는 것을 의미합니다. </li>
</ol>
<p>공식문서에 따르면, 표현은 해당 바이트를 설명하는 메타데이터<code>어떤 목적을 가지고 만들어진 데이터</code>와 함께 바이트 시퀀스를 통해 클라이언트가 식별할 수 있는 리소스를 제공해야 함을 의미합니다.</p>
<p>이 메타데이터를 표현하는 미디어 유형(HTML, JSON 및 XML)이라고 합니다. </p>
<p>클라이언트는 서버가 보낸 리소스가 무엇인지 알 수 없습니다. 추론 또는 상황에 맞추어 판단할 뿐, 이것이 실제 무엇인지는 확신할 수 없게 됩니다.</p>
<p>그렇기 때문에 아래의 코드처럼 특정 리소스를 표현하는 방식을 header에 담아서 요청하고, 응답함으로서 해당 리소스가 어떠한 유형으로 제공되는지 알 수 있게 됩니다.</p>
<p>표현 방식의 유연성과 확실한 미디어 매체 정보를 알려줄 수 있게 됩니다.</p>
<pre><code>Accept: application/json

or

Accept: text/plain</code></pre><p>--&gt; 해당 부분도 대다수의 사람들이 까먹지 않고, 구현하는 부분인 것 같네용</p>
<ol start="3">
<li>self-descriptive messages<blockquote>
<p>자기 설명 메시지??</p>
</blockquote>
</li>
</ol>
<p>말그대로 본인을 해석할 수 있는 정보를 본인이 갖고 있어야 함을 의미합니다!</p>
<p>아래의 코드는 앞서 보여드렸던 제 토이 프로젝트 코드입니다.</p>
<pre><code>http://localhost:8080/api/member

Content-Type : application/json

{
  &quot;status&quot;: 201,
  &quot;message&quot;: &quot;MEMBER_SIGN_SUCCESS&quot;,
  &quot;data&quot;: null
}</code></pre><p>여기서 스스로에 대한 정보를 해석할 수 없는 부분은 status, message, data가 있습니다. client는 미디어 타입에 대해 추론할 수는 있지만, 실제로 정확하게 이 데이터가 무엇인지 알 수 없습니다.</p>
<p>그렇기 때문에 해당 정보를 클라이언트에게 알려주기 위해 미디어 타입 문서를 작성하거나, 혹은 프로파일을 통해 미디어 타입에 대한 정보를 제공해야 합니다.</p>
<p>아래의 두가지 버전은 self-descriptive를 만족시키는 방법입니다.</p>
<pre><code>http://localhost:8080/api/member

Content-Type : application/donggeon+json

{
  &quot;status&quot;: 201,
  &quot;message&quot;: &quot;MEMBER_SIGN_SUCCESS&quot;,
  &quot;data&quot;: null
}</code></pre><pre><code>http://localhost:8080/api/member

Content-Type : application/json
Link: &lt;http//donggeon.github.io/docs/rest&gt;; rel=&quot;profile&quot;

{
  &quot;status&quot;: 201,
  &quot;message&quot;: &quot;MEMBER_SIGN_SUCCESS&quot;,
  &quot;data&quot;: null
}</code></pre><p>--&gt; 이 부분에 대해서는 많은 개발자분들이 빠트리고 개발을 진행한다고 하시네요!! 저 또한 고려해보지 못한 부분입니다!</p>
<ol start="4">
<li>hypermedia as the engine of application state<blockquote>
<p>축약하여 헤티오스 <code>HATEOAS</code>라고 합니다!</p>
</blockquote>
</li>
</ol>
<p>헤티오스는 애플리케이션의 상태를 하이퍼링크를 통해 전이되어야 함을 의미합니다. </p>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/f870f228-c147-4578-bd45-d78d3a795924/image.png" alt="">
&lt;그런 Rest Api로 괜찮은가? 에서..&gt;</p>
<p>위의 사진은 DEVIEW 2017에서 이응준님께서 강의 해주신 ppt의 일부분을 발췌한 것입니다.</p>
<p>헤티오스는 api를 호출하고 응답하게 되면, 응답시에 다음 로직에서 필요한 애플리케이션의 api 호출을 담아서 제공하는 규칙을 의미합니다. </p>
<p>짧게 다음 상태에 대한 변이 내용을 담아서 보내도록 response를 구성해야 됨을 의미합니다.</p>
<p>글 목록 보기를 통해 제공된 데이터에 다음 단계의 api를 담아서 보내게 됩니다. 그렇게 진행하게 된다면, 프론트에서 하드코딩으로 상태전이를 진행할 필요 없이 server에서 내려주는 응답만으로도 상태를 변경할 수 있게 됩니다.</p>
<p>아래의 코드는 상태 전이를 헤더에서 진행하는 방법입니다.</p>
<pre><code>http://localhost:8080/api/member
Location: /api/member/login
Content-Type : application/donggeon+json

{
  &quot;status&quot;: 201,
  &quot;message&quot;: &quot;MEMBER_SIGN_SUCCESS&quot;,
  &quot;data&quot;: null
}</code></pre><p>아래의 코드는 상태 전이를 body에서 진행하는 방법입니다.</p>
<pre><code>http://localhost:8080/api/member
Content-Type : application/donggeon+json

{
  &quot;status&quot;: 201,
  &quot;message&quot;: &quot;MEMBER_SIGN_SUCCESS&quot;,
  &quot;data&quot;: null,
  &quot;link&quot; : {
          &quot;login&quot; : &quot;/api/member/login&quot;
  }
}</code></pre><p>server에서 모든 정보를 제공하기 때문에 어떤 Client가 오더라도 상호 운용이 가능하게 됩니다. </p>
<p>더불어 Server의 기능이 변경되거나 Client의 기능이 변경되더라도 상호 독립적으로 운영할 수 있기 때문에 보다 탄력적인 확장이 가능하게 됩니다!!</p>
<p>--&gt; 헤티오스를 적용하는 강의나 혹은 개발 준비생은 극히 드문것 같습니다.ㅜㅜㅜ 이번에 저도 처음 알게 되었습니다!!</p>
<h3 id="clientserver">Client–server</h3>
<p>해당 제약 조건은 클라이언트와 서버가 서로에 대한 종속성 없이 별도로 발전할 수 있어야 함을 의미합니다. 클라이언트는 리소스 URI만 알아야 합니다. 그 이상의 것은 추후의 확장 혹은 이전 버전에 부정적인 영향을 미칠 수 있기 때문에 최소 수준으로 간단함을 유지해야 하는 제약조건입니다.</p>
<p>결론적으로 어떤 클라이언트 프로그램이든, 어떤 서버 프로그램이든 동작해야 함을 의미합니다.</p>
<h3 id="stateless">Stateless</h3>
<p>클라이언트와 서버간에 상호 작용을 진행할 때 각각의 상태를 비저장으로 유지하는 것을 의미합니다. 서버는 클라이언트가 만든 최신 HTTP 요청에 대해 아무 것도 저장하지 않고 무조건 모든 요청을 새 것으로 처리합니다. </p>
<p>대신에 클라이언트는 사용자를 위한 상태 저장을 진행할 수 있는 응용 프로그램이어야 하며, 클라이언트는 애플리케이션의 상태를 관리할 책임을 갖게 됩니다.</p>
<p>그렇기에 서버는 요청에 대한 응답만 할 뿐, 응답 중 발생하는 상태에 대한 정보를 관리하지 않고, 클라이언트만이 관리하게 됩니다.</p>
<h3 id="cacheable">Cacheable</h3>
<p>캐싱은 부하가 감소했기 때문에 클라이언트 측의 성능 향상과 서버의 확장성 범위를 향상시킬 수 있습니다.</p>
<p>그렇기 때문에 REST에서는 캐싱이 적용 가능한 경우, 리소스에 대한 캐싱을 적용해야 하고, 리소스가 캐싱이 가능하다고 알려야 합니다.</p>
<p>캐싱을 통해 클라이언트와 서버간의 확장성과 성능을 증대시킬 수 있습니다.</p>
<p>--&gt; 해당 부분은 아직 학습이 미흡하여 진행하지 못했습니다.ㅜㅜ 추후에 서버에 캐싱을 하여 데이터를 제공하는 예제를 올리겠습니다!</p>
<h3 id="layered-system">Layered system</h3>
<p>Rest를 사용하게 되면 계층화 시스템 아키텍처를 도입할 수 있습니다!!</p>
<p>데이터를 어떤 서버에서 저장할지, API를 어떤 서버에서 제공할지, 인증과 인가를 어떤 서버에서 진행할지 클라이언트를 확인할 필요도, 알려고 할 필요도 없게 됩니다!</p>
<p>단순하게 제공된 리소스를 받기만 하면 되기 때문입니당!!</p>
<p>그렇기 때문에 REST를 사용하게 되면 서버를 계층화시키고 분산시킬 수 있는 장점이 있습니다!</p>
<h3 id="code-on-demand-optional">Code on demand (optional)</h3>
<p>클라이언트가 리소스에 대한 표현을 응답으로 받고 처리하는데, 어떻게 처리해야 하는지에 대해 서버가 코드를 제공하는 것을 의미합니다. </p>
<p>예를 들어 클라이언트가 특정 기능을 요청하면, 그 기능을 제공하는 자바스크립트를 클라이언트에게 응답할 수 있습니다.!!</p>
<h3 id="글을-마치며">글을 마치며</h3>
<p>REST를 만드신 분의 말씀은 아래와 같습니다..</p>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/612d39c5-12b5-4361-8af0-ce85d7547366/image.png" alt=""></p>
<p>한,두개의 제약조건을 어겨도 좋다.. 하지만, 그것은 진정한 RESTFUL이 아니다..라고 말씀하셨습니다.</p>
<p>REST를 REST답게 사용하기 위해서는 만드신 분이 설정하는 제약조건을 무조건적으로 따라야함을 알 수 있었습니다...</p>
<h3 id="동건동건동건-rest-회고">동건동건동건 REST 회고...</h3>
<p>이번에 REST를 학습하면서, 제가 얼마나 무지했는지 알게 되었습니다.
포스팅을 하면서 제가 짠 코드를 수정한다고 했지만, 결국에는 REST의 제약조건을 다 맞추지 못해 REST가 아닌 REST API를 짜게 되었습니다ㅜㅜ</p>
<p>위에서 설명한 REST 제약 조건말고도 다양한 REST 제약조건이 존재합니다! 아래의 블로그를 통해 확인하시면 될 것 같습니다!!</p>
<p>그 외에도 RESTFUL하게 짜기 위한 다양한 규칙들이 존재합니다!</p>
<ul>
<li><a href="https://sanghaklee.tistory.com/m/57">설계 가이드</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[세 번째 회고]]></title>
            <link>https://velog.io/@dong_geon_kim/%EC%84%B8-%EB%B2%88%EC%A7%B8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@dong_geon_kim/%EC%84%B8-%EB%B2%88%EC%A7%B8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Wed, 29 Sep 2021 02:11:40 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/dong_geon_kim/post/8109b0ca-5c3a-4f0f-a067-a1ab455bcf4e/image.png" alt=""></p>
<h3 id="변명-시작">변명 시작</h3>
<p>이번 달은 쉬는 날이 많았어요.. 그러다 보니,,, 공부를 많이 못했던 것 같아요.. 연휴가 끝나고 나서 일상이 불바다?가 된 것을 느끼게 된 것 같네요</p>
<p>역시 일은 그날그날 마무리해야 합니다..ㅜㅜㅜ</p>
<h3 id="1일-1커밋에-대해">1일 1커밋에 대해</h3>
<p>동료분들이 1일 1커밋을 하는 저를 보고 많이 놀라셨어요! 그렇게 열심히 깃허브를 관리한다고 생각하지 못했는데, 우연히 1일 1커밋을 하게 된 것 같네요!</p>
<p>저는 하루에 2시간은 무조건 프로그래밍을 하자! 라는 생각을 갖고 있어요. 그러다 보니 자동적으로 잔디밭을 채울 수 있게 된 것 같네요!!</p>
<h3 id="프로그래머스-교육과정을-진행하며">프로그래머스 교육과정을 진행하며</h3>
<p>프로그래머스 백엔드 데브코스를 진행하며 많은 것을 배우게 된 것 같아요. 기존에 알고 있던 내용이라도, 다시 한번 생각해 볼 수 있는 기회를 갖게 된 것 같습니다!</p>
<p>프로그래머스 감사해요!!!</p>
<h3 id="최근-근황">최근 근황?</h3>
<p>요즘은 알고리즘 문제를 최대한 자주 풀려고 노력해요. 꾸준히 준비하면 언제가는 어떤 문제도 풀 수 있지 않을까? 생각합니다.</p>
<p>그리고 인프런 강의와 개인적인 프로젝트를 꾸준하게 하고 있어요!! 2021년도에는 힘든 일도 많았고, 사람에 치이기도 했는데, 하반기가 되면 좋은 사람들을 많이 만나게 되어 정신적 회복을 진행하고 있습니다!</p>
<h3 id="앞으로">앞으로</h3>
<p>앞으로는 노는 시간을 더 줄이려고 해요!! 중간 중간 쉬는 시간을 두었다면, 이제는 조금 더 공부에 몰두할려고 해요!!</p>
<p>미래는 스스로 만들어야 하니까요!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[두 번째 회고]]></title>
            <link>https://velog.io/@dong_geon_kim/%EB%91%90-%EB%B2%88%EC%A7%B8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@dong_geon_kim/%EB%91%90-%EB%B2%88%EC%A7%B8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Thu, 16 Sep 2021 00:57:09 GMT</pubDate>
            <description><![CDATA[<h3 id="우주로-간-나의-velog">우주로 간 나의 velog</h3>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/4e564709-7ab3-4651-88e4-b0e08da0e91d/image.png" alt=""></p>
<p>처음 회고를 작성하고 거의 한달이 넘는 시간이 흐른 것 같습니다. <code>열심히 해야지! 나는 글도 잘 작성하는 개발자가 될거야!</code>라는 마음가짐은 어디로 갔는지 참.... 우주 저 멀리 떠나 버린 것 같아 오늘도 반성하게 되네요</p>
<p>아마 저 별 어딘가에 제 멘탈도 같이 있는 것 같네요</p>
<h3 id="번-아웃">번 아웃</h3>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/0beb5b2f-3668-4ac1-bd9f-596c819d0ce9/image.png" alt=""></p>
<p>열심히 공부한다고 생각했는데... 생각보다 실력이 엄청나게? 늘리지는 않고... 계속 같은 자리에 머무는 것 같다고 생각들었어요</p>
<p>아마도 이건, 제가 기본에 충실히 하지 않았기 때문에 발생한 문제라고 생각들어요</p>
<p>그래서 최근 한달?간 조금 쉬면서 공부했던 것 같습니다</p>
<p>하지만, 쉬면서도 쉬는게 아닌 일상이었어요 취업,,, 취업....취업.... 나도 개발자가 될 수 있을까? 라는 고민을 계속 했던 것 같습니다.ㅜㅜ</p>
<h3 id="앞으로의-도전">앞으로의 도전!</h3>
<p>코딩이 취업의 전부가 아니라고 어떤 분이 말씀 해주신게 생각났습니다. 저는 이제 개발자가 되기 위해 준비해야 될게 많은데 그것을 준비하지 못했던 것 같네요!</p>
<p>앞으로는 CS와 알고리즘도 꾸준히 공부할 예정입니다!ㅜㅜㅜ</p>
<h3 id="마치며">마치며</h3>
<p>기본기와 꾸준함이 중요하다고 다들 말하지만, 전 어느하나 제대로 한게 없네요</p>
<p>이번 기회에 다시 저를 재조립해야 함을 느끼게 된 것 같습니다!</p>
<p>모두 취업하는 그날까지 파이팅!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[SPRING-2] Spring AOP]]></title>
            <link>https://velog.io/@dong_geon_kim/CS-3-Spring-AOP</link>
            <guid>https://velog.io/@dong_geon_kim/CS-3-Spring-AOP</guid>
            <pubDate>Fri, 10 Sep 2021 11:09:27 GMT</pubDate>
            <description><![CDATA[<p>지금까지 스프링을 공부하면서 AOP에 대해 들어봤지만, 실제로 사용한 적은 없었던 것 같습니다.
그리고 이 기술이 어디서 사용되는지도 모른채 학습한 것 같습니다.</p>
<p>그래서 이번에는, AOP를 왜 쓰고, 어떻게 쓰는지에 대해 중점을 가지며 학습했습니다.</p>
<br>
<br>
<br>
<br>

<h3 id="aop란">AOP란?</h3>
<p>AOP는 Asepct Oriented Programming의 약자로서 관점 지향 프로그래밍을 의미합니다.
관심사의 분리를 통해 모듈성을 높이는 것을 목표로 하는 프로그래밍 패러다임입니다.</p>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/7b0b5217-e9e5-40cc-a805-6523a49c511e/image.png" alt=""></p>
<p>위의 사진을 보면, 치킨집과 쿠팡은 각기 다른 서비스를 제공하는 것을 알 수 있습니다. </p>
<p>치킨집은 주문을 받은 뒤, 치킨을 만들기 위한 재료를 통해 조리를 하고, 조리된 음식을 포장한 이후에 배달을 진행합니다.</p>
<p>쿠팡의 경우에는 주문을 받고, 요청된 물건을 정리한 뒤, 정리된 물건을 포장하고 배달을 진행합니다.</p>
<p>핵심기능 관점에서 치킨집과 쿠팡이 하는 업무는 다릅니다. 치킨집은 요식업과 관련된 기능을 제공하고, 쿠팡은 물류배송 서비스를 제공합니다.</p>
<p>하지만 부가기능 관점으로 바라본다면, 주문받기와 배달하기는 핵심적인 비즈니스로직이라기 보다는 부가적인 기능으로 생각할 수 있다. 정말 핵심적인 기능은 요청된 주문을 어떻게 처리할지에 대한 내용을 담은 2번과 3번이라고 할 수 있습니다.</p>
<br>
<br>
<br>
<br>

<p><img src="https://images.velog.io/images/dong_geon_kim/post/e32f83a7-8266-43cd-b2a6-bfe91bc748a9/image.png" alt=""></p>
<p>이렇게 핵심적인 비즈니스 로직은 아니지만, 반드시 진행해야 되는 반복적인 작업을 정리하는데 사용하는 기술이 AOP입니다.</p>
<br>
<br>

<p><img src="https://images.velog.io/images/dong_geon_kim/post/f5972c4e-4737-4d8b-82d2-d80d798fd37f/image.png" alt=""></p>
<p>AOP는 관점 지향 프로그래밍이라는 명칭을 갖고 있지만, 객체지향 프로그래밍을 대체하는 기술은 아닙니다. 
개발자가 실제 비즈니스 로직에 더 집중할 수 있도록 부가적인 로직을 분리시켜 한층 더 추상화를 진행할 수 있게 됨으로서 OOP를 더 OOP스럽게 만들 수 있는 보조자 역할을 맡습니다.</p>
<p>OOP는 중복된 다수의 기능이 존재하더라도 객체가 책임을 같고 로직을 수행하도록 구성되게 됩니다. 이렇게 진행될 경우, 불가피하게 중복된 다양한 코드가 발생하게 되고 수정과 확장시 복잡한 구조와 중복된 코드로 어려움을 겪을 수 있습니다.</p>
<p>하지만 AOP를 같이 적용하게 되면서 실제 중요하게 사용되는 비즈니스 도메인을 OOP를 통해 구체화시키고, AOP를 통해 부가적인 기능인 트랜잭션, 로깅, 모니터링과 같은 기능을 수행할 수 있게 됩니다.</p>
<br>
<br>
<br>
<br>

<h3 id="aop에서-쓰이는-용어">AOP에서 쓰이는 용어</h3>
<ul>
<li>Target</li>
</ul>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/623e5314-1458-40b4-95d7-6510b1de9535/image.png" alt=""></p>
<p>Target은 부가기능을 제공할 대상을 의미합니다. 주문받기, 배달하기 등의 부가기능을 제공받을 대상인 치킨집이 Target이 됩니다.</p>
<br>

<ul>
<li>Advice</li>
</ul>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/b562789a-de41-49a5-b89e-ab4b3b126e78/image.png" alt=""></p>
<p>Advice는 부가기능 자체를 의미합니다. 주문받기와 같이 부가기능을 담은 구현체 자체이며, 어떠한 기능이 언제 사용될지 정의합니다. 주문받기가 언제 사용될지 정의된 구현체를 의미합니다.</p>
<br>

<ul>
<li>JoinPoint</li>
</ul>
<p>JoinPoint는 Advice가 적용될 위치를 의미합니다. 해당 Advice가 어느 메서드에 실행되는지를 의미합니다.</p>
<br>

<ul>
<li>PointCut</li>
</ul>
<p>PointCut은 Advice를 적용할 JoinPoint를 선별하는 기능을 제공합니다. 결국 포인트컷은 부가기능이 적용될 대상을 선정하는 방법이라고 할 수 있습니다. 주문받기라는 기능이 치킨집 또는 쿠팡의 어떠한 특정 메서드에서 실행될지 설정할 수 있습니다.</p>
<br>

<ul>
<li>Aspect</li>
</ul>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/81647640-1939-43ed-8cd4-fccde8277e36/image.png" alt=""></p>
<p>Aspect는 핵심기능에 부가되어 의미를 갖도록하는 부가기능이 모여진 모듈을 의미합니다.
Advice와 PointCut 등 부가기능을 다루기 위한 모듈이 모인 집합입니다.</p>
<br>

<ul>
<li>Proxy</li>
</ul>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/59cd3254-6f06-49c3-b09f-4d4a27ba3883/image.png" alt=""></p>
<p>Proxy는 타겟을 랩핑한 오브젝트입니다. 어플리케이션에서 타켓을 호출하게 되면 Proxy가 호출되어 실행전, 후에 필요한 기능을 실핼시킬 수 있습니다.</p>
<br>
<br>
<br>
<br>

<h3 id="코드를-통해-이해하자">코드를 통해 이해하자!</h3>
<p>실제 코드로 AOP를 적용하면서 AOP에 대해 간략하게 학습을 진행했습니다.</p>
<pre><code class="language-java">@Component
public class ChickenHouse {

    public void open(){
        System.out.println(&quot;환영합니다! 치킨집입니당!&quot;);
    }

    public void makeChicken() {
        System.out.println(&quot;재료를 가공하고 튀김기를 통해 조리하기&quot;);
    }

    public void packChicken() {
        System.out.println(&quot;조리된 음식을 박스에 포장하기&quot;);
    }

    public void nonException() {
        System.out.println(&quot;제대로 실행되었습니다!&quot;);
    }

    public void exception() {
        throw new RuntimeException(&quot;예외 발생!&quot;);
    }
}</code></pre>
<p>ChickenHouse의 경우에는 간단한 메서드를 담고 있는 클래스입니다. 해당 클래스를 통해 Aop를 Test해봤습니다.</p>
<br>

<pre><code class="language-java">package com.example.springaop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Aspect 
@Component 
public class ChickenHouseAspect {
    ...
}
</code></pre>
<p>ChickenHouseAspect 클래스를 구성하였고 해당 클래스에 부가기능을 담았습니다.
Aspect 어노테이션을 통해 해당 클래스가 Aspect로서 기능한다는 것을 명시할 수 있습니다.</p>
<br>


<pre><code class="language-java">@Pointcut(&quot;execution(* com.example.springaop.ChickenHouse.*(..))&quot;)    
public void commonPointcut() {
}</code></pre>
<p>Pointcut 어노테이션을 통해 해당 Adivce가 어떤 로직이 수반된 이후에 동작할 것인지 명시할 수 있습니다.</p>
<br>

<pre><code class="language-java">@Before(&quot;execution(* com.example.springaop.ChickenHouse.makeChicken(..))&quot;)
public void before(JoinPoint joinPoint) {
     System.out.println(joinPoint.getSignature().getName() +
                &quot; : 실행전 먼저, 주문을 요청 받습니다!&quot;);
}</code></pre>
<p>Before 어노테이션의 경우에는 pointcut으로 지정한 로직이 수행되기 이전에 부가기능이 실행되도록 하는 기능을 제공합니다.
<img src="https://images.velog.io/images/dong_geon_kim/post/114db5b4-be7c-4f65-b12f-6a8ac2451520/image.png" alt=""></p>
<br>

<pre><code class="language-java">@After(&quot;execution(* com.example.springaop.ChickenHouse.packChicken(..))&quot;)
public void after(JoinPoint joinPoint) {
     System.out.println(joinPoint.getSignature().getName() + &quot; : 실행후, 배달을 시작합니다.&quot;);
}</code></pre>
<p>After 어노테이션은 pointcut으로 지정된 로직이 수행된 이후에 부가기능이 실행되도록 지원합니다.
<img src="https://images.velog.io/images/dong_geon_kim/post/e5998500-66cb-42ab-9123-920a8587e628/image.png" alt=""></p>
<br>

<pre><code class="language-java">@Pointcut(&quot;execution(* com.example.springaop.ChickenHouse.returnNumber())&quot;)
public void returnNumber() {
}

@AfterReturning(pointcut = &quot;returnNumber()&quot;, returning = &quot;value&quot;)
public void afterReturning(JoinPoint joinPoint, int value) {
      System.out.println(joinPoint.getSignature().getName() + &quot; : 반환된 값은 : &quot; + value);
}</code></pre>
<p>AfterReturning 어노테이션은 지정된 로직이 정상적으로 실행된 이후에 반환된 값을 받아서 추후 처리를 진행할 수 있는 기능을 제공합니다.</p>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/a287d810-34e6-4c68-a04b-0ab58e8228cc/image.png" alt=""></p>
<br>

<pre><code class="language-java">@AfterThrowing(value = &quot;execution(* com.example.springaop.ChickenHouse.exception(..))&quot;, throwing = &quot;e&quot;)
public void afterThrowing(JoinPoint joinPoint, Exception e) throws RuntimeException {
     System.out.println(joinPoint.getSignature().getName() + &quot; : exception이 터졌습니다!!&quot;);
    System.out.println(&quot;exception : &quot; + e.toString());
}</code></pre>
<p>AfterThrowing 어노테이션은 지정된 로직에서 Exception이 발생했을 경우 해당 Exception을 받아서 추후 로직을 처리할 수 있는 기능을 제공합니다.</p>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/1ba176a3-17cf-4714-918b-14d66611e85b/image.png" alt=""></p>
<br>

<pre><code class="language-java">@Around(&quot;execution(* com.example.springaop.ChickenHouse.open())&quot;)
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
     System.out.println(&quot;-----------------실행전---------------&quot;);
     joinPoint.proceed();
     System.out.println(&quot;-----------------실행후---------------&quot;);
}</code></pre>
<p>Around 어노테이션은 지정된 로직이 실행되기 전, 그리고 실행된 이후에 수행될 부가기능을 설정할 수 있습니다.
<img src="https://images.velog.io/images/dong_geon_kim/post/d0ed563c-defb-4b7a-a6c6-cbaf9b343913/image.png" alt=""></p>
<p>이번 스터디에서는 간단하게 AOP를 왜 사용하는지, 그리고 어떻게 사용해야 하는지에 대해 학습했습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CS-2] SSR과 CSR]]></title>
            <link>https://velog.io/@dong_geon_kim/CS-2-SSR%EA%B3%BC-CSR</link>
            <guid>https://velog.io/@dong_geon_kim/CS-2-SSR%EA%B3%BC-CSR</guid>
            <pubDate>Wed, 01 Sep 2021 04:23:46 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>이번에는 제가 스터디에서 배웠던 SSR과 CSR에 대해 정리해보는 시간을 가지려고 합니다!</p>
</blockquote>
<h3 id="ssr이란">SSR이란?</h3>
<blockquote>
<p>서버에서 사용자에게 보여줄 페이지를 모두 구성하여 사용자에게 페이지를 보여주는 방식을 의미합니다!</p>
</blockquote>
<p>Spring MVC에서 JSP 또는 Thymeleaf를 통해 서버렌더링으로 사용자에게 화면을 보여주게 합니다! 이러한 방식을 SSR이라고 합니다</p>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/c4452ae8-ef5a-4758-b2fc-e5a2bda53b3e/image.png" alt=""></p>
<p>SSR을 사용하게 되면, 서버에서 사용자에게 보여줄 화면을 미리 다 랜더링하여 제공하게 됩니다!</p>
<p>그렇기 때문에, client가 특정 UI에 대한 화면을 요청했을 경우 CSR보다 상대적으로 속도가 느리다는 단점이 존재합니다. 더불어 모든 요청과 랜더링을 서버에서 진행하다보니 서버가 가지는 역할과 책임이 너무 방대해질 수 있습니다</p>
<p>저희 학교 메인 홈페이지의 경우 SSR로 시스템이 운영되고 있습니다. 사용자의 요청이 들어왔을 경우, 전체 소스파일과 페이지를 랜더링하여 사용자에게 제공하게 되어있습니다. 그렇기 때문에 상대적으로 요청시 응답이 늦어지는 문제가 있습니다.</p>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/05eae58b-019f-4c0c-b9a0-684907479ea5/image.png" alt="">
<img src="https://images.velog.io/images/dong_geon_kim/post/e1403f1f-b81c-4ce8-98fb-1ce80f68bc45/image.png" alt="">
처음 이벤트가 발생한 이후에 추가적인 이벤트가 발생하지 않고 있습니다. 모든 데이터가 일시에 파싱되어 사용자에게 제공됨을 확인할 수 있습니다.</p>
<h3 id="csr이란">CSR이란?</h3>
<blockquote>
<p>브라우저에서 페이지를 직접 렌더링하는 것을 의미합니다. 모든 로직, 데이터, 템플릿 및 라우팅을 서버가 아닌 Client에서 처리합니다.</p>
</blockquote>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/4b6b5148-670c-4313-a2f7-503775dd63c5/image.png" alt=""></p>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/185a52a9-2240-4730-a3e0-bcc244f4894d/image.png" alt="">
<img src="https://images.velog.io/images/dong_geon_kim/post/564111f3-6aed-4a92-bd48-431adbacdc22/image.png" alt=""></p>
<p>Client가 특정 페이지를 요청했을 경우, 각각의 이벤트가 순서대로 동작하면서, 서버로부터 데이터를 할당하여 클라이언트 자체에서 html을 파싱합니다. </p>
<p>그렇기 때문에, 첫 로딩 이후 전체 페이지가 구성되기 까지 SSR보다 더 많은 시간이 들게 됩니다.</p>
<p>하지만 CSR의 경우에는 첫 로딩이 된 이후 부터, 요청된 부분만을 다시 읽어 랜더링하기 때문에 이후 웹 환경은 SSR보다 빠르게 이용할 수 있습니다.</p>
<h3 id="ssr을-대신하여-csr을-쓰는-이유">SSR을 대신하여 CSR을 쓰는 이유</h3>
<p>SSR은 CSR보다 초기 구동 속도가 빠릅니다. 이미 만들어진 view를 랜더링하기 때문에, 서버로부터 자원을 할당받고 랜더링하는 CSR보다는 화면이 빠르게 떠질 수 있습니다!</p>
<p>하지만, 동적인 웹, REACT를 활용한 DOM 관리등 CSR을 위한 프레임워크가 다수 등장하면서 SSR대신 CSR에 대한 인기가 커지고 있습니다</p>
<p>많은 요청이 발생했을 경우, 서버에 부담을 줄 수 있는 SSR 대신, CSR 방식을 통해 서버의 부담을 줄이고, 각각의 기능을 분리함으로서 조금 더 명확하게 아키텍쳐를 구분할 수 있는 장점도 존재합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[SPRING-1] IOC Inversion Of Control]]></title>
            <link>https://velog.io/@dong_geon_kim/SPRING-IOC</link>
            <guid>https://velog.io/@dong_geon_kim/SPRING-IOC</guid>
            <pubDate>Wed, 25 Aug 2021 04:54:21 GMT</pubDate>
            <description><![CDATA[<p>DI가 무엇인지 그리고 왜 사용해야 하는지 대략적으로 이전 포스팅을 통해 학습했습니다.
그렇다면 실제로 스프링에서 사용되는 IOC와 Bean이 무엇인지 학습하도록 하겠습니다!!</p>
<h3 id="ioc란">IOC란?</h3>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/2a7c1675-e973-4abf-b8bb-d87f57ecbf48/image.png" alt=""></p>
<blockquote>
<p>IOC <code>Inversion Of Control</code>의 약자로서 번역어로 <code>제어의 역전</code>이라고 합니다.</p>
<p>웹 어플리케이션 또는 기타 어플리케이션에서 개발자가 아닌, 프레임워크가 적절한 시점에 클래스의 오브젝트를 생성하고, 전달해주는 역할을 진행하는 것을 의미합니다.</p>
</blockquote>
<br>

<p><img src="https://images.velog.io/images/dong_geon_kim/post/9f2e39f9-0ef0-4c91-ac5f-0eb1678c9a5f/image.png" alt=""></p>
<ul>
<li>일반적인 프로그램<pre><code>public class Application {
  public static void main(String[] args){
      new Game(new Coin());
  }
}</code></pre></li>
</ul>
<p>일반적인 프로그램에서는 개발자가 원하는 시점에 객체를 전달하여 프로그램의 흐름을 변경하거나, 수정하고 관리할 수 있습니다. 그렇기 때문에 개발자는 객체에 대한 생성, 초기화, 실행, 소멸 등에 대한 모든 관리와 책임을 가지게 됩니다.</p>
<ul>
<li>스프링 프레임워크<pre><code>@SpringBootApplication
public class GameApplcation(){
  public static void main(String[] args){
      SpringApplication.run(GameApplication.class, args);
  }
}</code></pre></li>
</ul>
<p>반대로 프레임워크에서는 개발자가 원하는 객체에 대한 생성, 초기화, 실행, 소멸 등의 기능을 프레임워크의 컨테이너가 자동으로 처리해 줍니다. 이렇게 개발자가 아니라 프레임워크가 객체에 대한 관리를 대신해주는 것을 IOC라고 하며, 스프링에서는 이런 기능을 <code>Bean Factory와 ApplicationContext</code>를 통해 제공합니다. </p>
<h3 id="bean-등록하기">Bean 등록하기</h3>
<p>Bean Factory 또는 ApplicationContext를 통해 등록된 Bean을 가져오기 전, 먼저 Bean을 등록하는 작업이 필요합니다</p>
<ol>
<li><p>xml 기반 Bean 등록</p>
<pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
    xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    xsi:schemaLocation=&quot;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd&quot;&gt;

 &lt;bean id=&quot;game&quot;
       class=&quot;spring.ex.model.Game&quot; /&gt;
&lt;/beans&gt;</code></pre></li>
</ol>
<p>xml 설정 파일을 통해 Game이라는 클래스를 Bean으로 등록할 수 있습니다.
Bean의 id값과 해당 class의 위치 정보를 표기함으로써 Bean을 등록할 수 있습니다.</p>
<br>

<ol start="2">
<li><p>component-scan 기반 Bean 등록</p>
<pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
   xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
   xmlns:context=&quot;http://www.springframework.org/schema/context&quot;
   xsi:schemaLocation=&quot;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd&quot;&gt;

&lt;context:component-scan base-package=&quot;spring.ex.model&quot; /&gt;
</code></pre></li>
</ol>
</beans>
```

<p>Bean으로 등록할 객체에 <code>@Component</code> 어노테이션을 주기하면, 스프링은 해당 어노테이션을 확인하고, component-scan을 통해 해당 객체를 Bean으로 등록합니다!</p>
<p><code>@Service</code> 또는 <code>@Respository</code>와 같은 어노테이션을 들어가면, 최종적으로 <code>@Component</code>가 들어있음을 확인할 수 있습니다.</p>
<p>여기서 @Component는 @Bean과 유사하다고 느껴지지만, 조금의 차이점이 존재합니다.</p>
<p><code>@Bean</code>의 경우에는 개발자가 컨트롤이 불가능한 외부 라이브러리를 <code>Bean</code>으로 등록하고 싶은 경우에 사용됩니다. 컬렉션과 같이 제공되는 라이브러리를 Bean으로 등록할 때 사용됩니다. 메서드 기반으로 Bean을 등록하게 되어 있습니다.</p>
<pre><code class="language-java">@Bean
public ObjectMapper objectMapper(){
    return new ObjectMapper();
}</code></pre>
<p>반대로, <code>@Component</code>의 경우에는 개발자가 직접 컨트롤 가능한 클래스에 사용됩니다. 여기서 직접 컨트롤 가능하다는 것은, 개발자 직접 구현한 클래스를 의미합니다. 해당 방식의 경우에는 class 기반으로 Bean을 등록하게 됩니다.</p>
<pre><code class="language-java">@Component
public class Game {

}</code></pre>
<p>개발자가 임의로 @Bean 또는 @Component를 설정하는게 아니라, 각각의 type에 맞추어 어노테이션을 설정해야 합니다. 만약 type에 맞추어 설정하지 않는 경우에는 컴파일 에러가 발생할 수 있습니다.</p>
<pre><code class="language-java">@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {
}</code></pre>
<pre><code class="language-java">@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component {
}</code></pre>
<p>@Bean과 @Component를 들어가보면, 해당 어노테이션이 어떤 Type을 가져야 되는지 확인할 수 있습니다!</p>
<pre><code class="language-java">public class GameApplication {

    public static void main(String[] args) {

        ApplicationContext context = new ClassPathXmlApplicationContext(&quot;application.xml&quot;);
    }
}</code></pre>
<p><code>application.xml</code>에 등록한 Component들을 <code>ClassPathXmlApplicationContext</code>을 통해 읽어들여서 해당 Component 정보를 <code>ApplicationContext</code>로 가지고 있게 됩니다.</p>
<br>

<ol start="3">
<li>Config<pre><code class="language-java">import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
</code></pre>
</li>
</ol>
<p>@Configuration
public class ApplicationConfig {</p>
<pre><code>@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}</code></pre><p>}</p>
<pre><code>
config 파일을 통해 PasswordEncoder를 Bean으로 등록할 수 있습니다.

등록하고 싶은 객체를 메서드를 통해 Bean으로 등록하겠다고 표기를 진행합니다.
이후에 해당 ApplicationConfig.class에 @Configuration 어노테이션을 명시하여 해당 클래스에서 1개 이상의 Bean을 생성하고 있음을 명시해야 합니다!

`@Configuration` 어노테이션을 통해 해당 클래스가 스프링에서 Bean 등록을 위해 사용된 Config라는 것을 명시할 수 있게 됩니다! 더불어 해당 클래스의 싱글톤을 유지시킬 수 있습니다



&lt;br&gt;

4. component-scan 과 Config
```java
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackageClasses = GameApplication.class) 
public class ApplicationConfig {

}</code></pre><p><code>@ComponentScan(basePackageClasses = GameApplication.class)</code> 특정 위치의( 특정 패키지)에 대한 Component를 스캔하여 Bean으로 등록할 수 있는 기능을 제공합니다.</p>
<p>하나의 class가 될 수 있고, 또는 패키지 위치를 지정하여 패키지 안에 있는 모든 컴포넌트들을 Bean으로 등록할 수 있습니다.</p>
<br>

<ol start="5">
<li>SpringBootApplication<pre><code class="language-java">@SpringBootApplication
public class GameApplication {
 public static void main(String[] args) {
     SpringApplication.run(GameApplication.class, args);
 }
}</code></pre>
</li>
</ol>
<p>이전까지 개발자가 직접 Config 파일을 통해서 등록하거나, 혹은 Component-scan을 돌려서 해당 패키지 또는 id값을 통해 읽어들이는 과정을 SpringBoot에서는 <code>@SpringBootApplication</code>이라는 어노테이션을 통해 제공하게 됩니다.</p>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/f2d14621-9313-48bf-9969-e87982ed5a98/image.png" alt=""></p>
<p>결론적으로, 별다른 Config 파일 없이 <code>@Component</code>가 등록된 파일을 모두 스캔할 수 있는 기능을 제공합니다.</p>
<h3 id="spring-container">Spring Container</h3>
<p>Bean에 대한 관리를 수행하는 곳을 Spring Container라고 합니다. Bean의 생성, 연결, 설정 그리고 생명주기를 관리하는 역할을 맡습니다. </p>
<p>자세하게는 애플리케이션에 대해 정의한 메타데이터를 읽어 인스턴스화, 구성 및 관리할 개체에 대한 정보를 얻을 수 있습니다! 여기서 메타데이터는 스프링 컨테이너가 애플리케이션의 객체를 어떻게 인스턴스화하고, 설정하고, 조합해야 하는지 지시하기 위한 정보를 의미합니다. 위에서 자가성한 xml, annotation 그리고 java 파일 등이 메타데이터의 일환입니다!</p>
<p>스프링 컨테이너의 기능을 제공하는 인터페이스는 BeanFactory와 ApplicationContext가 존재합니다.</p>
<h3 id="bean-factory">Bean Factory</h3>
<blockquote>
<p>인스턴스를 생성하면서 설정하고 많은 수의 Bean을 관리하는 실질적인 컨테이너를 의미합니다. Bean들은 일반적으로 서로 의존성을 가진 협력관계이며, BeanFactory에 의해 사용된 설정 데이터가 반영되게 됩니다.</p>
</blockquote>
<p>여기서 컨테이너는 특정 클래스를 상속하거나 인터페이스를 구현하지 않는 POJO를 이용해 EJB의 기능을 유지하면서 복잡성을 제거하고, 라이프 사이클을 관리해주면서 개발자가 작성한 코드 또는 외부 라이브러리 등에 대한 처리과정을 위임받아 Bean을 관리합니다</p>
<p>주요 메서드는 아래와 같습니다!</p>
<pre><code class="language-java">// 애플리케이션 전체에서 공유되거나 독립적일 수 있는 지정된 bean의 인스턴스를 리턴
getBean() 

// 빈 팩토리에 주어진 이름의 빈이 포함되어 있는지 확인
containsBean()

// 해당 빈이 동일한 인스턴스를 반환하는지 확인
isSingleton()

// 해당 빈이 항상 독립된 인스턴스를 반환하는지 확인
isPrototype()

// 지정된 이름의 빈이 지정된 유형과 일치하는지 확인
isTypeMatch()

// 주어진 이름이 어떤 빈의 유형을 가졌는지 확인
getType()

// 주어진 이름이 어떤 별칭을 가졌는지 확인
getAliases()</code></pre>
<h3 id="applicationcontext">ApplicationContext</h3>
<p><code>EnvironmentCapable</code>, <code>ListableBeanFactory</code>, <code>HierarchicalBeanFactory</code>, <code>MessageSource</code>, <code>ApplicationEventPublisher</code>, <code>ResourcePatternResolver</code> 을 implement하여 <code>Bean Factory</code> 보다 더 많은 기능을 제공합니다.</p>
<p>ApplicationContext를 통해 Bean에 대한 관리를 더욱 용이하게 진행할 수 있습니다.</p>
<p>공통적으로 BeanFactory와 ApplicationContext가 비슷한 기능을 제공하게 됩니다. </p>
<h3 id="bean-factory와-applicationcontext-차이점">Bean Factory와 ApplicationContext 차이점</h3>
<ol>
<li><code>BeanFactory</code>는 요청 시 빈을 로드하는 반면 <code>ApplicationContext</code> 는 시작 시 모든 빈을 로드</li>
</ol>
<p>Game이라는 class를 생성하고 Bean 로드를 확인하기 위한 표기를 위해 isBeanInstantiated 필드를 선언합니다.</p>
<pre><code class="language-java">public class GameBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    private static boolean isBeanFactoryPostProcessorRegistered = false;

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory){
        setBeanFactoryPostProcessorRegistered(true);
    }

    public static boolean isBeanFactoryPostProcessorRegistered() {
        return isBeanFactoryPostProcessorRegistered;
    }

    public static void setBeanFactoryPostProcessorRegistered(boolean isBeanFactoryPostProcessorRegistered) {
        GameBeanFactoryPostProcessor.isBeanFactoryPostProcessorRegistered = isBeanFactoryPostProcessorRegistered;
    }
}</code></pre>
<p>Bean에 대한 등록을 위해 id와 class위치 그리고 init-method 방법을 기입합니다.</p>
<pre><code class="language-xml">&lt;bean id=&quot;game&quot; class=&quot;spring.ex.model.Game&quot; init-method=&quot;postConstruct&quot;/&gt;</code></pre>
<p>Game의 필드값이 true로 변경되었는지 test를 통해 확인을 진행합니다!</p>
<pre><code class="language-java">@Test
@Display(&quot;BeanFactory를 통한 초기화 확인 실패&quot;)
public void whenBFInitialized_thenGametNotInitialized_FAIL() {
    BeanFactory factory = new XmlBeanFactory(new ClassPathResource(&quot;bean-factory.xml&quot;));

    assertThat(Game.isBeanInstantiated(), is(false));
}</code></pre>
<p>실제로 Test를 돌린 결과, Game에 대한 초기화는 진행되지 않았습니다.
그 이유는 BeanFactory에 대한 초기화만 진행되었고, xml에 정의된 Game에 대해서는 진행되지 않았기 때문입니다. BeanFactory는 <code>getBean()</code>통해서 Bean에 대한 초기화가 가능하기 때문입니다.</p>
<pre><code class="language-java">@Test
@Display(&quot;BeanFactory를 통한 초기화 확인 성공&quot;)
public void whenBFInitialized_thenGameNotInitialized_SUCCESS() {
    BeanFactory factory = new XmlBeanFactory(new ClassPathResource(&quot;bean-factory.xml&quot;));

    Game game = (Game) factory.getBean(&quot;game&quot;);

    assertThat(Game.isBeanInstantiated(), is(true));
}</code></pre>
<p>BeanFactory에 경우에는 진짜 해당 Bean이 필요한 경우에 요청에 의해서 초기화가 진행됩니다. 이러한 초기화를 지연 로딩 <code>Lazy Loading</code>이라고 합니다.</p>
<p>반대로, ApplicationContext의 경우에는 즉시 로딩 <code>Eager Loading</code>을 통해 Bean을 관리합니다.</p>
<pre><code class="language-java">@Test
public void whenAppContInitialized_thenGameInitialized() {
    ApplicationContext context = new ClassPathXmlApplicationContext(&quot;bean-factory.xml&quot;);

    assertThat(Game.isBeanInstantiated(), is(true));
}</code></pre>
<p>ApplicationContext는 즉시로딩을 통해 runtime시 모든 bean을 확인합니다. </p>
<p>그렇기 때문에, ApplicationContext는 BeanFactory에 비해 개발자가 직접 관리해야 되는 부담은 적지만 한번에 전체 Bean을 로드하기 때문에 메모리를 많이 잡아 먹는 문제가 존재합니다.</p>
<p>반대로 BeanFactory의 경우에는 개발자가 원하는 타임에 Bean을 로드할 수 있는 장점이 존재하고 메모리에 대한 관리를 진행할 수 있게 됩니다. 하지만 <code>getBean()</code>을 통해서 로드를 해야 한다는 문제가 존재합니다.</p>
<p>하지만, Spring에서는 <code>ApplicationContext</code>를 사용하는 것을 지향합니다. 그 이유는 BeanFactory의 경우에는 Singleton과 Prototype에 해당하는 두 가지 Type만을 지원하지만, ApplicationContext는 웹 어플리케이션에서 사용되는 대다수의 type을 지원하기 때문입니다.</p>
<ol start="2">
<li>ApplicationContext는 시작시 <code>BeanFactoryPostProcessor</code>와<code>BeanPostProcessor</code>를 로드, Beanfactory는 요청시 로드</li>
</ol>
<p>postProcessBeanFactory와 BeanPostProcessor가 즉시 로딩이 되는지 확인하기 위해 해당 클래스를 정의합니다.</p>
<pre><code class="language-java">public class Game {
    private static boolean isBeanFactoryPostProcessorRegistered  = false;

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory){
        setBeanFactoryPostProcessorRegistered(true);
    }

    public static boolean isBeanFactoryPostProcessorRegistered() {
        return isBeanInstantiated;
    }

    public static void setBeanFactoryPostProcessorRegistered(boolean isBeanInstantiated) {
        Game.isBeanInstantiated = isBeanInstantiated;
    }
}</code></pre>
<pre><code class="language-java">public class GameBeanPostProcessor implements BeanPostProcessor {
    private static boolean isBeanPostProcessorRegistered = false;

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName){
        setBeanPostProcessorRegistered(true);
        return bean;
    }

    public static boolean isBeanPostProcessorRegistered() {
        return isBeanPostProcessorRegistered;
    }

    public static void setBeanPostProcessorRegistered(boolean isBeanPostProcessorRegistered) {
        GameBeanPostProcessor.isBeanPostProcessorRegistered = isBeanPostProcessorRegistered;
    }
}</code></pre>
<pre><code class="language-xml">&lt;bean id=&quot;gameBeanPostProcessor&quot; 
  class=&quot;spring.ex.model.GameBeanPostProcessor&quot; /&gt;
&lt;bean id=&quot;gameBeanFactoryPostProcessor&quot; 
  class=&quot;spring.ex.model.GameBeanFactoryPostProcessor&quot; /&gt;</code></pre>
<p>xml에 해당 bean에 대한 정보를 기입합니다.</p>
<pre><code class="language-java">@Test
public void whenBFInitialized_thenBFPProcessorAndBPProcessorNotRegAutomatically() {
    Resource res = new ClassPathResource(&quot;bean-factory.xml&quot;);
    ConfigurableListableBeanFactory factory = new XmlBeanFactory(res);

    assertThat(GameBeanFactoryPostProcessor.isBeanFactoryPostProcessorRegistered(), is(false));
    assertThat(GameBeanPostProcessor.isBeanPostProcessorRegistered(), is(false));
}</code></pre>
<p>test를 통해 bean을 xml에 정의했다고 하더라도, 즉시로딩이 되지 않음을 확인할 수 있었습니다. BeanFactory의 경우에는 <code>BeanFactoryPostProcessor</code>와 <code>BeanPostProcessor</code>를 요청시에 로드하기 때문에 test가 실패함을 알 수 있습니다.</p>
<p>반면에, ApplicationContex의 경우에는 run시 바로 즉시로딩이 되어 <code>BeanFactoryPostProcessor</code>와 <code>BeanPostProcessor</code>가 동작함을 확인할 수 있었습니다.</p>
<pre><code class="language-java">@Test
public void whenAppContInitialized_thenBFPostProcessorAndBPostProcessorRegisteredAutomatically() {
    ApplicationContext context 
      = new ClassPathXmlApplicationContext(&quot;bean-factory.xml&quot;);

    assertThat(GameBeanFactoryPostProcessor.isBeanFactoryPostProcessorRegistered(), is(true));
    assertThat(GameBeanPostProcessor.isBeanPostProcessorRegistered(), is(true));
}</code></pre>
<p>결과적으로 Spring IOC 컨테이너 기능을 제공하는 ApplicationContext와 BeanFactory에 대한 차이점은 Lazy와 Eager로 나눌 수 있다고 생각합니다. 해당 방식의 차이로 인해 메모리에 대한 영향도가 달라짐을 부수적으로 확인할 수 있었습니다.</p>
<h3 id="궁금한-점">궁금한 점</h3>
<ul>
<li><p>@Bean이 Type에 따라서 진행된다고 나와 있지만, 아래의 코드 처럼 사용자가 직접 구현한 코드를 등록할 때 @Bean을 붙여 등록할 수 있습니다... 그렇다면, Type에 따라 진행되는게 아니라, 형태에 따라 진행되는게 아닌지 궁금합니다!</p>
<pre><code class="language-java">@Configuration
public class ApplicationConfig {

  @Bean
  public Game game() {
      return new Game();
  }
</code></pre>
</li>
</ul>
<p>}</p>
<pre><code>
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL-2] 건강도 챙기면서...]]></title>
            <link>https://velog.io/@dong_geon_kim/TIL-2-%EA%B1%B4%EA%B0%95%EB%8F%84-%EC%B1%99%EA%B8%B0%EB%A9%B4%EC%84%9C</link>
            <guid>https://velog.io/@dong_geon_kim/TIL-2-%EA%B1%B4%EA%B0%95%EB%8F%84-%EC%B1%99%EA%B8%B0%EB%A9%B4%EC%84%9C</guid>
            <pubDate>Tue, 24 Aug 2021 08:23:12 GMT</pubDate>
            <description><![CDATA[<h4 id="반성-또-반성">반성 또 반성</h4>
<p>계속 Velog에 글을 작성하지 못한 것 같아 아쉬움이 남습니다..ㅜㅜㅜ</p>
<p>최근 프로그래머스 백엔드 교육과정을 수강 중이라,, 수업 듣고 과제하기가 힘들었습니다.. 
엄청 어렵거나, 힘들지는 않았지만 거북목과 일자목이라는 콜라보네이션이 저를 힘들게 하는 것 같습니다..ㅜㅜㅜ 공부하다가 어지러워 병원가서 주사 맞고,,, 계속 무한 반복,,,</p>
<p>그러다! 결국 헬스를 다시 시작하기로 했습니다!! 두둥!!! 운동을 하면 조금 좋아지지 않을까? 하는 생각에 2시간만 나를 위해? 써보자! 라는 결심이 들었습니다!!</p>
<p>너무 TMI가 많은 것 같아 저번주와 이번주에 어떤 것을 학습했는지 조금 정리해보려고 합니다.</p>
<p>저는 Spring 그리고 Java를 어떻게 사용해야 하고, 어떻게 써야하는지만 집중했던 것 같습니다..
<img src="https://images.velog.io/images/dong_geon_kim/post/200774a6-41c6-438d-bad0-f433c4a5ece8/image.png" alt="">
결국 저에게는 근본이 없었습니다.ㅜㅜㅜㅜ 그러다 보니 새로운 개념이 저에게 오면,, 계속 어려움을 느꼈던 것 같습니다!!</p>
<p>최근에는 지금까지 제가 공부했던 내용들을 다시 주서담는? 과정을 진행하고 있습니다!!</p>
<h4 id="가장-첫번째로-di와-dip에-대해-학습했습니다">가장 첫번째로 DI와 DIP에 대해 학습했습니다!</h4>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/97fc9d06-79ac-429f-82fa-4bd045d35bc5/image.png" alt=""></p>
<p>이전까지 단순하게 DI는 스프링이 만들어서 보관하는 Bean을 자동으로 주입받는다! 까지만 알고 있었습니다. 그 원리는 무엇이고, DI를 통해 우리가 얻을 수 있는 이점이 무엇인지 몰랐던 것 같습니다.</p>
<p>DI는 의존성 주입으로서, 객체를 외부로 부터 주입받아 사용하는 것을 의미합니다.</p>
<p>DI를 할 수 있는 방법은 다양한데, 그 중에서 Setter, Constructor, Field가 대표적으로 사용되는 방법입니다</p>
<p>Setter의 경우에는 SetMethod를 통해 bean을 주입 받을 수 있고, Constructor는 생성자를 통해 주입받을 수 있습니다. 마지막으로 Field의 경우에는 <code>@Autowired</code>를 통해 주입받을 수 있습니다.</p>
<p>다양한 DI 방식이 존재하지만, 그중에서도 현재 권고되는 DI 방식은 생성자 주입입니다. 생성자 호출 시점에 한번만 호출되는 것을 보장합니다! 더불어 final로 선언이 가능하여 불변객체로서 오류를 방지할 수 있는 역할을 수행할 수 있습니다!!</p>
<p>DIP는 의존 역전 원칙을 의미하며, 구상체에 의존하는 것이 아닌, 추상체에 의존하는 것을 의미합니다! 만약 어떠한 객체가 구상체에 의존하게 된다면, 불가피한 수정이 발생했을 때 추상체도 변경해야 하는 리스크가 존재합니다.!!!</p>
<p>하지만, 추상체에 의존하게 되면, 이런 불가피한 수정에도 확장성을 가지며 기능을 추가할 수 있다는 장점이 존재합니다!</p>
<h4 id="객체지향-공부하기">객체지향 공부하기!</h4>
<p>졸업생들과 함께 하는 스터디 모임이 존재합니다! 저번주 과제는 주차장 관리 시스템을 개발하는 것이었습니다!!</p>
<p>해당 과제를 진행하면서, 객체가 메세지를 전달하고, 스스로에 대한 유효성을 검사할 수 있도록 로직을 구현하는 연습을 진행했습니다!!!</p>
<p><a href="https://github.com/DongGeon0908/java-parking-system">주차 관리 시스템</a></p>
<p>요구사항을 어떻게 작성하느냐에 따라서 객체의 설계가 달라진다는 것을 알게 되었습니다!!</p>
<p>한가지 아쉬운 점은 너무 Enum을 남용하여 설계하다보니, 확장성이 줄어들고 하드코딩된 부분이 많았다는 점입니다.,,,,,ㅜㅜㅜㅜ</p>
<p>이번 리뷰를 통해 클래스를 설계할 때 조금 더 생각?하는 습관을 들여야 함을 알게 되었습니다...</p>
<h4 id="마치며">마치며</h4>
<p>현재 너무나 많은 일들이 저에게 다가온 것 같습니다..
하나씩 해결하면서, 스스로 성장하고 있다고 생각하지만 건강을 챙기지 못한 지나난 날의 동건에게 실망감을 갖기도 합니다.ㅜㅜㅜㅜㅜ</p>
<p>이제는 조금 더 건강을 지키며, 평생 가는 프로그래머가 되기 위해 노력해야 될 시기라고 생각합니다!</p>
<p>오늘도 동건동건동건</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA-4] DIP와 DI 이해하기]]></title>
            <link>https://velog.io/@dong_geon_kim/JAVA-4-DIP%EC%99%80-DI-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@dong_geon_kim/JAVA-4-DIP%EC%99%80-DI-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 18 Aug 2021 04:17:56 GMT</pubDate>
            <description><![CDATA[<p>고민, 고민 끝에 DI와 DIP에 대해 작성해보려고 합니다!!ㅜㅜㅜ 계속 주제를 바꾸는 것 같네요 흐엉.... 이번에는 확실하게 픽스하고 진행하겠습니다.</p>
<p>해당 주제는 제가 넥슨 웹개발자 면접때 받았던 질문입니다! 그럼 시작하겠습니다~</p>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/3e9280d4-e250-43b9-bcee-7df429a4ac11/image.png" alt=""></p>
<h3 id="di와-dip에-대해-설명하시오">DI와 DIP에 대해 설명하시오.</h3>
<ul>
<li>DI는 의존성 주입을 의미합니다. 객체가 다른 객체를 사용하기 위해서 본인의 내부 로직에서 외부 객체에 대한 인스턴스를 생성하는 것이 아닌, 외부로부터 인스턴스를 주입받아 사용하는 것을 의미합니다.</li>
<li>DI는 생성자 주입과 필드주입이 존재하며, 대체로 외부에서 변경이 가능한 생성자 주입을 사용하는 것을 권고합니다.</li>
<li>DIP는 의존성 역전 원칙을 의미합니다. 객체가 구현체에 의존하지 않고, 인터페이스를 통해 인스턴스를 할당받게 함으로서, 다형성을 증가시킬 수 있는 원칙을 의미합니다.</li>
<li>DIP를 다형성을 만족할 수 있고, 이를 통해 확장에 열려있을 수 있으며, 인터페이스를 통해 변경과 변화 그리고 코드의 일관성을 지킬 수 있습니다.</li>
</ul>
<h3 id="di와-dip가-뭐지">DI와 DIP가 뭐지?</h3>
<p>우리가 Spring Project를 구현하다보면, 필드 주입 또는 생성자 주입을 통해 객체를 받아서 사용할 것입니다.</p>
<p>보통은 아래의 코드처럼 생성자 주입을 통해 필요한 객체를 주입받아서 사용합니다</p>
<pre><code>private final Book book;

public Study(Book book){
    this.book = book;
}</code></pre><p>or</p>
<pre><code>@Autowired
private Book book;</code></pre><p>여기 매개변수로 받는 Book이 IOC 컨테이너를 통해 생성되고 주입되는 객체를 의미합니다! IOC 컨테이너에서 객체는 생성되고 사망하고...</p>
<p>이 부분은 너무나 방대하여 다음에 다시 정리하도록 하겠습니다!</p>
<p>위의 코드에서 외부에서 객체의 주입이 발생하는데.,..이런 주입을 DI <code>Dependency Injection</code>이라고 합니다</p>
<p>위의 코드처럼 외부의 주입을 통해 Study라는 Class에서 Book을 사용할 수 있습니다. 물론, Study에서 Book에 대한 인스턴스를 생성해서 사용할 수도 있습니다.</p>
<pre><code>class Study {
    Book book = new Book();
}</code></pre><p>or</p>
<pre><code>class Study {
    private Book book;

    public Study(){
        book = new Book();
  }
}</code></pre><p>위의 코드처럼 Study가 Book을 생성해서 사용할 경우 Study와 Book의 의존관계에서 결합도는 매우매우 커지게 됩니다!</p>
<p>의존관계에서 결합도가 높아지게 될 경우, Book이 변경되었을 때 Study는 Book과 연관된 코드를 전부 변경해야 하는 수고스러움이 발생합니다!</p>
<pre><code>class Study {
    private Book book;

    public Study(){
        book = new Book(10, &quot;3만원&quot;);
  }
}</code></pre><p>위의 코드처럼 Book의 생성자가 바뀐다고 가정하면, new로 생성할 경우에는 Study의 생성자에서도 코드 변경의 귀찮음이 발생하게 됩니다..ㅜ</p>
<p>이렇게 Study라는 클래스 내부에서 객체를 생성하고 관리하게 되면, 추후 발생하는 변화에 유동적으로 대응할 수 없는 문제가 발생합니다!</p>
<p>그렇기 때문에 DI <code>Dependency Injection</code>이라는 기능을 통해 외부로 부터 주입받아서 결합도를 낮추고 변화에 능동적으로 대처하도록 구현해야 합니다. </p>
<h3 id="필드주입과-생성자-주입-그리고-setter-주입">필드주입과 생성자 주입 그리고 Setter 주입</h3>
<p>필드주입보다 생성자 주입이 좋다고 다들 말하지만, 실제로 왜 좋은지에 대해 고민해본적이 없던것 같습니다. 더불어 지금은 사용하지 않는 Setter 주입에 대해서 살펴보겠습니다!</p>
<pre><code>public class Study {

    @Autowired
    private Book book;
}</code></pre><p>아마 많은 교재에서 필드 주입을 통해 인스턴스를 할당할 것입니다,,, 인텔리제이를 사용하신다면, 필드주입 부분에서 에러를 확인하실 수 있는데 필드주입은 현재 스프링 또는 자바 어플리케이션에서 권고하지 않는 방식입니다.</p>
<p>필드를 선언하고 필드 위에 <code>@Autowired</code>를 선언하면, 외부 의존성 주입을 받지 않고 인스턴스를 생성하여 Bean에 등록할 수 있습니다. 이방식은 코드가 간결한 장점이 있지만! Test를 작성할때 외부주입이 불가능함으로 어려움을 겪을 수 있습니다. 더불어 추상체가 아닌 구현체를 직접 생성하기 때문에 변화에 민감해집니다.</p>
<p>생성자 주입은 아래와 같이 외부의 주입을 통해 의존관계를 형성하는 방법입니다!</p>
<pre><code>public class Study {

    private final Book book;

  public Study(Book book){
        this.book = book;
  }
}</code></pre><p>외부로 부터 주입 받기 때문에 변화에 능동적으로 대처할 수 있고, 구현체에 의존하지 않고 사용할 수 있는 장점이 있습니다!</p>
<p>더불어 final로 생성된 불변객체를 사용함으로서, 인스턴스의 복제, 비교가 쉬워지며, 한번 생성한 인스턴스에 대한 변경을 금지시킴으로서 안전한 객체사용이 가능해집니다!</p>
<p>Setter 주입은 set() 메서드를 통해 생성자를 주입하는 방법입니다</p>
<pre><code>public class Study{
    private Book book;

    @Autowired
    public void setBook(Book book){
        this.book = book;
  }
}</code></pre><p>선택적으로 book에 대한 인스턴스를 주입받아 생성할 수 있도록 구현하는 방식입니다!</p>
<p>물론, 해당 방식을 사용하면, 원하는 인스턴스를 개발자가 원하는 시기에 생성할 수 있고 관리할 수 있다는 장점이 존재합니다!</p>
<p>하지만! 이 방식의 경우 Study객체의 인스턴스가 생성되었을 때 set()을 돌려주지 않으면 book이 null값을 가져 exception이 터질 수 있습니다!</p>
<p>런타임시에 문제를 해결할 수 없기 때문에 해당 주입 방법은 지양하는 것을 추천드립니다!</p>
<p>다음으로 interface를 통해 확장성을 가지는 예를 살펴보겠습니다!</p>
<pre><code>class Study {
    private final Book book;

    public Study(Book book){
        this.book = smallBook;
  }
}</code></pre><p>SmallBook이라는 Book을 implements한 클래스가 있다고 가정합시다!</p>
<p>Study에서는 Book이라는 존재만 알고 있어도 smallBook이라는 구현체를 받아서 사용할 수 있게 됩니다!</p>
<pre><code>Book smallBook = new SmallBook();
new Study(smallBook);</code></pre><p>반대로 직접 인스턴스를 생성할 경우!</p>
<pre><code>class Study {
    private final Book book;

    public Study(){
        this.book = new SmallBook();
  }
}</code></pre><p>Study는 book을 implements한 모든 구현체를 직접 Study안에서 수정해야 하는 불편함을 겪게 됩니다..</p>
<p>이처럼 Study가 구현체에 의존하게 된다면, Book이라는 인터페이스를 implements한 모든 class에 대한 생성자 혹은 변환 메서드를 구현해야 하는 불편함이 발생합니다!</p>
<p>그렇기 때문에 우리가 자주 외웠던 SOLID의 마지막 원칙 DIP <code>Dependency Inversion principle</code> 의존성 역전 원칙를 통해 구현체 직접 의존하지 않고, 추상화된 클래스를 의존함으로서 변경에 유용하고 다형성을 통한 확장을 유용하게 할 수 있는 코드를 작성해야 합니다!</p>
<p>DIP의 개념이 쓰이는 곳은 정말 방대합니다. 예를 들어 Spring에서 OAuth2.0을 통해 로그인을 진행한다고 하면</p>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/84ed139d-092e-4cb2-8a6c-42110e24358e/image.png" alt=""></p>
<p>이렇게 다양한 소셜네트워크 서비스가 존재할 것입니다. 만약 해당 객체들을 서로 다른 클래스로 구현한다면</p>
<pre><code>public class KaKao{

}

public class Facebook{

}

public class Naver{

}</code></pre><p>이렇게 무지막지한 class 생성 폭발이 발생할 겁니다! 그리고 이를 service에서 사용하게 된다면</p>
<pre><code>public void loginkakao(){
    kakao.login();
}

public void loginNaver(){
    naver.login();
}

public void loginFacebook(){
    facebook.login();
}</code></pre><p>다형성이라는 개념은 어디에도 없게 되고, 코드의 길이는 점점 길어지며, login을 진행하기 위해서 필요한 서비스 로직은 방대해지게 됩니다..</p>
<p>그렇기 때문에 카카오, 페이스북, 네이버 모두 로그인이라는 인터페이스를 상속받아서 사용하게 된다면 추후 로그인 로직에서 다형성을 지킬 수 있으며, 구현체에 의존하지 않는 코드를 작성할 수 있게 됩니다.</p>
<p>결국, 인터페이스를 통해 선언된 로직을 통해 카카오, 페이스북, 네이버에 의존하지 않고도 로그인 서비스를 이용할 수 있게 되는 것입니다.</p>
<pre><code>public interface Login(){
    void login();
}

public class KaKao implements Login{

}

public class Facebook implements Login{

}

public class Naver implements Login{

}

public void login(){
    login.login();
}</code></pre><p>지금까지 간단한 예제를 살펴보며, DI와 DIP에 대해 간략하게 살펴봤습니다!</p>
<h3 id="di에-대해-다시-정리하자면">DI에 대해 다시 정리하자면..</h3>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/b6f2ca3c-0330-4a17-a75c-70bcf8d9f3e8/image.png" alt=""></p>
<p>아마도 위의 예제 코드를 보더라도 많이 어려움을 느낄 것 같습니다.. 그래서 탕수육으로 비교하며 DI에 대한 정리를 마칠려고 합니다!</p>
<p>부먹 탕수육은 소스가 이미 부어져 있어서 새로운 소스가 나타났을때, 기존의 소스를 제거하기 위해 많은 어려움이 존재할 것입니다..ㅜㅜ</p>
<p>하지만 찍먹 탕수육의 경우에는 새로운 소스가 나타난다면, 언제든지 새로운 소스를 찍어먹으며 다채로운 맛을 느낄 수 있을 겁니다!!</p>
<p>마찬가지로 DI도 외부로부터 주입받음으로써, 내부의 로직 변경없이, 변경된 클래스에 대한 설정만으로도 문제를 해결할 수 있는 장점을 제공합니다!</p>
<h3 id="그렇다면-dip는">그렇다면 DIP는?</h3>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/7ec6b17c-8d40-4eba-84a8-38e00f26d3bb/image.png" alt=""></p>
<p>DIP는 치킨집에서 제일 잘나가는 치킨을 무엇이냐고 물어보는 것과 같다고 생각합니다.</p>
<p>우리가 치킨집에 가서 제일 잘팔리는 치킨을 달라고 하면, 종업원은 다양한 치킨메뉴 중 어떤 것을 시킬거냐고 물어볼 것입니다.</p>
<p>만약 우리가, 후라이드 치킨을 시켰다면, 그 가게에서 제일 잘팔리는 양념치킨을 못먹었을 겁니다...</p>
<p>마찬가지로 DIP는 치킨처럼 큰 범주를 가진 인터페이스를 통해서 양념치킨과 후라이드치킨과 같은 구상체를 받을 수 있는 원칙입니다.</p>
<p>이를 통해 우리는 치킨이 양념치킨 또는 후라이드치킨처럼 종류가 다양해지는 다형성이라는 기능을 살릴 수 있게 됩니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CS-1] URI와 URL 그리고 URN]]></title>
            <link>https://velog.io/@dong_geon_kim/CS-1-URI%EC%99%80-URL-%EA%B7%B8%EB%A6%AC%EA%B3%A0-URN-uh2jaxd6</link>
            <guid>https://velog.io/@dong_geon_kim/CS-1-URI%EC%99%80-URL-%EA%B7%B8%EB%A6%AC%EA%B3%A0-URN-uh2jaxd6</guid>
            <pubDate>Fri, 13 Aug 2021 07:26:20 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>URI, URL, URN에 대해서 고민해 본적이 없던 것 같습니다.. 이번 기회에 세가지의 차이점에 대해 정리해보겠습니다!</p>
</blockquote>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/5965d605-f696-41e2-b4a3-eab1f7d5f0cf/image.png" alt=""></p>
<h3 id="uri">URI</h3>
<blockquote>
<p><code>uniform resource identifier</code>의 약자로서 정보 리소스를 고유하게 식별하고 위치를 지정할 수 있는 시통합 자원 식별자를 의미합니다!</p>
<p>이런 고유한 주소를 가진 식별자를 URI라고 합니다!</p>
</blockquote>
<ul>
<li>클라이언트가 서버의 특정 리소스를 요청한다고 하면!
<code>http://www.donggeon.com/donggeon/home.jpg</code> 이것이 URI 입니당!</li>
<li>URI는 URL과 URN을 포괄하는 큰 범주의 식별자를 의미합니다!<ul>
<li>결론적으로 고유한 식별자를 나타내주는 기술로 URL과 URN이 존재합니다!</li>
</ul>
</li>
</ul>
<hr/>

<h3 id="url">URL</h3>
<blockquote>
<p><code>uniform resource locator</code>의 약자로서 특정 서버의 한 리소스에 대한 구체적인 위치를 제공합니다!
리소스가 어디에 있고, 어떻게 접근해야 되는지 알려주며 리소스를 식별하는 역할을 합니다!</p>
</blockquote>
<ul>
<li><p>URL의 구조</p>
<ul>
<li><code>스킴://서버위치/경로</code></li>
</ul>
</li>
<li><p>리소스</p>
<ul>
<li>웹에서 식별할 수 있는 모든 자원을 의미</li>
</ul>
</li>
<li><p>스킴 <code>scheme</code></p>
<ul>
<li>리소스에 접근하기 위해 사용되는 프로토콜을 서술!</li>
<li><code>http</code></li>
</ul>
</li>
<li><p>서버위치 <code>서버의 인터넷 주소</code></p>
<ul>
<li>서버의 위치, 웹 클라이언트가 리소스가 어디에 호스팅 되어 있는지 알려줍니다!</li>
<li><code>www.donggeon.com</code></li>
</ul>
</li>
<li><p>경로 <code>웹 서버의 리소스</code></p>
<ul>
<li>서버에 존재하는 로컬 리소스들 중에서 요청받은 리소스가 무엇인지 알려줍니다!</li>
<li><code>/donggeon/home.jpg</code></li>
</ul>
</li>
<li><p>URL이 가져온 평화</p>
</li>
</ul>
<blockquote>
<p>URL을 사용하기 전에는 각각의 애플리케이션이 가지고 있는 분류방식에 맞추어 접속해야 했고, 원하는 정보를 얻기 위해서 해당 애플리케이션의 접근 방법을 알아야 하는 불편함이 존재했습니다.!!
하지만, URL을 통해서 획일화된 접근 방법으로 이전과 다르게 쉽고 빠른 접근이 가능해졌습니다!</p>
</blockquote>
<ul>
<li>URL 문법<ul>
<li>URL을 구성하는데 쓰이는 체계
<code>스킴://사용자이름:비밀번호@호스트:포트/경로;파라미터?질의#프래그먼트</code></li>
</ul>
</li>
</ul>
<table>
<thead>
<tr>
<th>컴포넌트</th>
<th>설명</th>
<th>사용</th>
</tr>
</thead>
<tbody><tr>
<td>스킴</td>
<td>어떤 프로토콜을 사용해야 하는지</td>
<td>알파벳으로 시작<br><code>url</code>의 나머지 부분과 첫 번째 <code>:</code>로 구분 <br>대소문자를 가리지 않음</td>
</tr>
<tr>
<td>사용자 이름</td>
<td>특정 스킴은 리소스에 접근하기 위해 사용자 이름이 필요</td>
<td>defauat는 <code>anonymous</code><br>사용자 이름과 비밀번호를 <code>@</code>로 구분<br>사용자 이름과 비밀번호를 <code>:</code>로 구분</td>
</tr>
<tr>
<td>비밀번호</td>
<td>사용자의 비밀번호, 사용자 이름에 <code>;</code>을 붙여 표가</td>
<td>사용자 이름과 비밀번호를 <code>@</code>로 구분<br>사용자 이름과 비밀번호를 <code>:</code>로 구분</td>
</tr>
<tr>
<td>호스트</td>
<td>리소스를 호스팅하는 서버의 호스트명 또는 IP주소<br>리소스를 호스팅하고 있는 장비와 리소스스에 접근할 수 있는 서버가 어디에 있는지 확인!</td>
<td><code>www.donggeon.com</code></td>
</tr>
<tr>
<td>포트</td>
<td>리소스를 호스팅하는 서버가 열어놓은 포트</td>
<td><code>www.donggeon.com:80</code></td>
</tr>
<tr>
<td>경로</td>
<td>서버 내 리소스가 서버 어디에 있는지 가리킴</td>
<td>HTTP 스킴을 사용하는 경우 <code>/</code>를 통해 경로 조각을 나눔</td>
</tr>
<tr>
<td>파라미터</td>
<td>특정 스킴에서 입력 파라미터를 기술하는 용도<br>애플리케이션이 서버에 정확한 요청을 하기 위해 필요한 입력 파라미터를 받는데 사용</td>
<td><code>이름/값</code> 쌍의 리스트로 <code>;</code>로 구분되어 받음, 애플리케이션이 리소스에 접근하는데 필요한 어떤 추가 정보든 전달 가능</td>
</tr>
<tr>
<td>질의</td>
<td>스킴에서 애플리케이션에 파라미터를 전달하는 용도</td>
<td><code>?</code>우측에 나오는 값의 질의문!<br>질의문은 <code>이름=값</code> 쌍 형으로 <code>&amp;</code>으로 구분되어 표기!</td>
</tr>
<tr>
<td>프래그먼트</td>
<td>리소스의 조각 또는 일부분</td>
<td>리소스 내부의 특정 조각을 지칭할 수 있음<br><code>www.donggeon.com/index.html#age</code></td>
</tr>
</tbody></table>
<ul>
<li>단축 URL == 상대 URL<ul>
<li>리소스 안에 있는 리소스를 간결하게 기술하는데 사용하며, URL 일부를 입력하면 자동으로 완성!</li>
</ul>
</li>
</ul>
<hr/>

<h3 id="상대-url과-절대-url">상대 URL과 절대 URL</h3>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/8606f870-39b3-44b3-b591-6e0657109586/image.png" alt=""></p>
<ul>
<li>상대 URL<ul>
<li>URL을 짧게 표기하는 방식</li>
<li>모든 정보를 갖고 있지 않음!</li>
<li>필요한 정보를 얻기 위해 기저<code>base</code>라고 하는 다른 URL을 사용해야 함!<ul>
<li>기저 URL은 리소스에 명시적으로 제공되며 포함되고 있는 URL을 의미합니다!</li>
<li>기저 URL이 없다면, 보통 절대 URL로 구성되어 있는다는 것을 의미하지만, 불완전하거나 깨진 URL일 수 도 있습니다!</li>
</ul>
</li>
</ul>
</li>
<li>절대 URL<ul>
<li>리스소에 접근하는데 필요한 모든 정보를 가짐</li>
</ul>
</li>
</ul>
<hr/>

<h3 id="url-확장">URL 확장</h3>
<blockquote>
<p>사용자가 URL을 빠르게 입력하도록 도와주는 기능!</p>
</blockquote>
<ul>
<li><p>호스트 명 확장</p>
<ul>
<li>단순한 휴리스틱만을 사용해서 입력한 호스트 명을 전체 호스트명으로 확장</li>
<li>naver을 입력하면 -&gt; <a href="http://www.naver.com%EC%9C%BC%EB%A1%9C">www.naver.com으로</a> 확장!</li>
</ul>
</li>
<li><p>히스토리 확장</p>
<ul>
<li>과거에 사용자가 방문했던 URL의 기록을 저장해 놓기!</li>
<li><a href="http://www.na%EB%A7%8C">www.na만</a> 입력해도 이전 기록을 찾아서 <a href="http://www.naver.com%EC%9D%84">www.naver.com을</a> 만들어줌!</li>
</ul>
<hr/>

</li>
</ul>
<h3 id="안전하지-않은-문자">안전하지 않은 문자</h3>
<blockquote>
<p>정보의 유실을 방지하기 위해서 특정 문자를 제외시키고 알파벳을 통해 URL을 구성하도록 한것!</p>
<p>그러다 보니, 특정 문자를 사용해야 할때 어떻게 진행해야 될지 문제가 발생하였고!</p>
<p>이것을 해결하기 위해 이스케이프라는 기능이 추가되었음!!</p>
</blockquote>
<ul>
<li><p>이스케이프</p>
<ul>
<li>안전하지 않은 문자 <code>알파벳을 제외한 문자들</code>를 알파벳 유형으로 인코딩해서 URL을 구성!</li>
<li>이스케이프를 통해 특정 문자나 데이터를 인코딩할 수 있게 되어 이동성과 완성도가 UP!</li>
</ul>
</li>
<li><p>인코딩 체계</p>
<ul>
<li>안전하지 않은 문자를 <code>%</code> 기호를 통해 아스키 코드로 표현!</li>
</ul>
</li>
</ul>
<blockquote>
<p>안전하지 않은 문자 자체를 URL에 기입하여 사용할 수 있다.. 하지만 어플리케이션을 구성할 때 제일 중요한 것은 약속된 정해진 내용을 기반으로 구현해야 된다는 것이다!</p>
<p>기존에 약속된 내용을 부시고, 독자적인 구성을 진행한다면 어플리케이션의 오류 또는 오작동을 일으킬 수 있기 때문이다!</p>
</blockquote>
<hr/>

<h3 id="urn">URN</h3>
<blockquote>
<p><code>uniform resource name</code>의 약자로서, 콘텐츠를 이루는 리소스의 위치에 영향 받지 않는 유일무이한 이름 역할을 합니다!</p>
</blockquote>
<ul>
<li>위치 독립성</li>
</ul>
<blockquote>
<p>리소스를 옳기더라도 독립적인 유일무이한 위치를 제공합니다!, 단 리소스가 해당 URN을 변경하지 않는다는 가정하에요!
현재 그 리소스가 어디에 존재하든 상관없이 이름만으로 리소스를 식별할 수 있습니다!</p>
</blockquote>
<ul>
<li>URL -&gt; URN으로</li>
</ul>
<blockquote>
<p>URL의 가장 큰 문제점은 가르키고 있는 리소스가 옮겨지면 기존에 사용하던 URL은 더 이상 사용 불가하다는 것이다! 객체의 위치와 상관없이 절대적으로 사용가능한 기술이 URN이다!
URN으로 바꾸려고 변화를 꾀하지만, 방대한 웹 생태계에서 URL 기술을 대체하기까지 아직 많은 시간이 걸린다!</p>
</blockquote>
<hr/>

<h3 id="마치며">마치며</h3>
<p>지금까지 단순하게 URL이라고 칭했던 정보 제공 데이터에 대해 학습할 수 있는 기회가 되었습니다.
URI가 URL과 URN을 감싸안는 집합이며, URL과 URN이 리소스의 상대적 혹은 절대적 주소에 따라 차이점이 존재함을 알게 되었고, 더불어 현재 우리가 쓰고 있는 주소체계는 대부분 URL임을 확인하게 되었습니다!</p>
<p>URL이 가지고 있는 규칙과 스킴, 서버위치, 경로 등의 기본적인 쳬계와 더불어 기타 다양한 구조를 학습할 수 있었습니다! 생각보다 많은 정보와 기능을 가질 수 있는 것을 알게 되었고, 이를 활용하여 다양한 어플리케이션에서 유용하게 쓰일 수 있음을 배웠습니다!</p>
<p>마지막으로 URL이 리소스에 의존적이어서 리소스의 위치가 변경되면 기존 URL로 데이터를 찾을 수 없는 단점을 알게 되었고, 이를 해결하기 위해 나온 URN이라는 절대적 주소 기술 체계에 대해 알게 되었습니당!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Gof-1] 추상 팩토리 패턴 Abstract Factory Pattern]]></title>
            <link>https://velog.io/@dong_geon_kim/Gof-1-%EC%B6%94%EC%83%81-%ED%8C%A9%ED%86%A0%EB%A6%AC-%ED%8C%A8%ED%84%B4-Abstract-Factory-Pattern</link>
            <guid>https://velog.io/@dong_geon_kim/Gof-1-%EC%B6%94%EC%83%81-%ED%8C%A9%ED%86%A0%EB%A6%AC-%ED%8C%A8%ED%84%B4-Abstract-Factory-Pattern</guid>
            <pubDate>Fri, 06 Aug 2021 23:02:04 GMT</pubDate>
            <description><![CDATA[<hr/>

<br>

<h3 id="추상-팩토리-패턴이란">추상 팩토리 패턴이란?</h3>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/d3c5701d-c780-4a8f-bb8f-6a74d2e8fba1/image.png" alt=""></p>
<blockquote>
<p><code>Abstract Factory Pattern</code>은 구체적인 클래스에 의존하지 않고 서로 연관된 객체들의 조합을 만드는 인터페이스를 제공하는 패턴입니다! 다양한 구성 요소 별로 <code>객체의 집합</code>을 생성해야 할 때 유용</p>
</blockquote>
<ul>
<li><p>추상 팩토리 팩토리 패턴은 관련 있는 객체를 묶어서 만들고, 조건에 맞추어 각각의 객체를 생성할 수 있는 패턴입니다! 팩토리 메서드와 유사하지만, 한층 더 추상화화여 사용하는 방법입니다!!</p>
</li>
<li><p>팩토리 패턴과 다르게 추상 클래스에 의존하는 구상 클래스를 생성하지 않아도 인스턴스를 생성할 수 있는 장점이 있습니다! 서로 다른 객체들을 하나의 공장에서 관리함으로써 생성할 수 있는 장점이 있습니다!!</p>
</li>
</ul>
<h3 id="추상-팩토리-다이어그램입니다">추상 팩토리 다이어그램입니다!</h3>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/b583cc59-4164-41d0-830e-5e0813a12802/image.png" alt=""></p>
<h4 id="charger">charger</h4>
<pre><code>public interface Charger {
    String message = &quot;충전기 생성&quot;;
}

public class LgCharger implements Charger {
    public LgCharger() {
        System.out.println(Brand.LG + message);
    }
}

public class AppleCharger implements Charger {
    public AppleCharger() {
        System.out.println(Brand.APPLE + message);
    }
}</code></pre><ul>
<li>charger interfact를 통해 lg와 apple charger를 하나로 묶었습니다!!</li>
<li>공통된 부분이 많은 것 같아서 이점은 다시 수정해보려고 합니다!</li>
</ul>
<h4 id="laptop">laptop</h4>
<pre><code>public interface Laptop {
    String message = &quot;노트북 생성&quot;;
}

public class LgLaptop implements Laptop {

    public LgLaptop() {
        System.out.println(Brand.LG + message);
    }
}

public class AppleLaptop implements Laptop {

    public AppleLaptop() {
        System.out.println(Brand.APPLE + message);
    }
}
</code></pre><ul>
<li>laptop도 charger와 마찬가지로 묶어서 만들었습니다!!</li>
<li>학습을 진행하기 위한 예제로 사용하려다 보니 부족한게 많은 것 같습니다....ㅜㅜ</li>
</ul>
<h3 id="productfactory">ProductFactory</h3>
<pre><code>public interface ProductFactory {
    Laptop createLaptop();

    Charger createCharger();
}</code></pre><h3 id="lgproductfactory">lgProductFactory</h3>
<pre><code>public class LgProductFactory implements ProductFactory {
    @Override
    public Laptop createLaptop() {
        return new LgLaptop();
    }

    @Override
    public Charger createCharger() {
        return new LgCharger();
    }
}</code></pre><ul>
<li>Factory를 통해서 LG 상품을 하나로 묶어 생성할 수 있도록 구현했습니다!</li>
</ul>
<h3 id="appleproductfactory">appleProductFactory</h3>
<pre><code>public class AppleProductFactory implements ProductFactory {
    @Override
    public AppleLaptop createLaptop() {
        return new AppleLaptop();
    }

    @Override
    public AppleCharger createCharger() {
        return new AppleCharger();
    }
}</code></pre><ul>
<li>lg Factory와 마찬가지로 묶어서 만들었습니다!!</li>
<li>추상 팩토리 패턴을 활용하니 더 쉽고 알아볼 수 있는 코드를 구현할 수 있게 된 것 같습니다</li>
<li>다만 아직 초보자라 구현하는데 많은 시간이 걸린 것 같습니다...ㅜㅜㅜ</li>
</ul>
<h3 id="brandfacotry">BrandFacotry</h3>
<pre><code>public class BrandFactory {
    public void createProduct(String brandName) {
        Brand brand = Brand.findByBrand(brandName);
        ProductFactory productFactory = choiceFactory(brand);
        createParts(productFactory);
    }

    private ProductFactory choiceFactory(Brand brand) {
        if (brand == Brand.LG) {
            return new LgProductFactory();
        }
        return new AppleProductFactory();
    }

    private void createParts(ProductFactory productFactory) {
        productFactory.createLaptop();
        productFactory.createCharger();
    }
}</code></pre><ul>
<li>BrandFactory를 통해 알맞은 brand를 찾고, 그 브랜드의 하위 메서드를 생성할 수 있도록 구현했습니다!!</li>
</ul>
<h3 id="brand">Brand</h3>
<pre><code>public enum Brand {

    LG(&quot;엘지&quot;),
    APPLE(&quot;애플&quot;);

    private final String brand;

    Brand(final String brand) {
        this.brand = brand;
    }

    private static final String BRAND_SEARCH_ERROR_MESSAGE = &quot;브랜드명이 잘못된 입력입니다.&quot;;

    public static Brand findByBrand(String inputBrand) {
        return Arrays.stream(Brand.values())
                .filter(b -&gt; b.brand.equals(inputBrand))
                .findAny()
                .orElseThrow(() -&gt; new IllegalArgumentException(BRAND_SEARCH_ERROR_MESSAGE));
    }

}</code></pre><ul>
<li>Enum class는 예제에서 딱히 사용을 안하시는 것 같은데,,, 저는 이게 편리해서 사용해봤습니다!</li>
</ul>
<h3 id="마치며">마치며</h3>
<ul>
<li>위키피디아에서 본 클래스 다이어그램과 구글링을 통해 여러 예제를 본 것 같습니다. 실제로 추상 팩토리 패턴을 사용해서 예제를 학습하다보니, interface로 묶어주고 또 묶어준 것을 한번 더 묶어줌으로서 이후 로직이 간단하고 가시성이 높아짐을 확인하게 되었습니다!!</li>
<li>아직 예제 코드에서 수정할 부분이 많아서 추후 조금씩 수정하고 업로드하겠습니다!</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[GoF-0] Design Pattern을 학습하며]]></title>
            <link>https://velog.io/@dong_geon_kim/GoF-0-Design-Pattern%EC%9D%84-%ED%95%99%EC%8A%B5%ED%95%98%EB%A9%B0</link>
            <guid>https://velog.io/@dong_geon_kim/GoF-0-Design-Pattern%EC%9D%84-%ED%95%99%EC%8A%B5%ED%95%98%EB%A9%B0</guid>
            <pubDate>Fri, 06 Aug 2021 12:38:15 GMT</pubDate>
            <description><![CDATA[<hr />

<br>

<h3 id="gof---design-pattern">GoF - Design Pattern</h3>
<blockquote>
<p><code>Gang of Four</code> 4명의 개발자가 합심하여 모두가 쉽고 빠른 개발을 위해 만든 소프트웨어 디자인 패턴이다!</p>
<p>디자인 패턴을 통해 더 쉽고 빠른 개발을 진행할 수 있습니다!</p>
<p>하지만,,, 실제로 어떻게 동작하는지 자세히 모르기 때문에 이번 기회에 하나씩 알아보도록 하겠습니다!</p>
</blockquote>
<h4 id="생성-패턴">생성 패턴</h4>
<ol>
<li>Abstract Factory</li>
<li>Builder</li>
<li>Factory Method</li>
<li>Prototype</li>
<li>Singleton</li>
</ol>
<h4 id="구조-패턴">구조 패턴</h4>
<ol start="6">
<li>Adapter</li>
<li>Bridge</li>
<li>Composite</li>
<li>Decorator</li>
<li>Facade</li>
<li>Flyweight</li>
<li>Proxy</li>
</ol>
<h4 id="행위-패턴">행위 패턴</h4>
<ol start="13">
<li>Chain of Responsibility</li>
<li>Command</li>
<li>Interpreter</li>
<li>Iterator</li>
<li>Mediator</li>
<li>Memento</li>
<li>Observer</li>
<li>State</li>
<li>Strategy</li>
<li>Template Method</li>
<li>Visitor</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA-3] Object 탐구하기]]></title>
            <link>https://velog.io/@dong_geon_kim/JAVA-3-Object-%EC%B0%B8%EA%B5%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@dong_geon_kim/JAVA-3-Object-%EC%B0%B8%EA%B5%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 06 Aug 2021 10:54:21 GMT</pubDate>
            <description><![CDATA[<h1 id="object객체-탐구하기---tostring-equals-hashcode">Object(객체) 탐구하기 - toString(), equals(), hashCode()</h1>
<hr />

<h3 id="😱-이번에는">😱 이번에는?</h3>
<ul>
<li>Object(객체) 탐구하기 - toString(), equals(), hashCode() 언제 쓰이는지!!</li>
</ul>
<br>

<h3 id="🛒-들어가면서">🛒 들어가면서</h3>
<ul>
<li>프로젝트를 진행하다보면, 항상 toString(), equals(), hashCode()를 어떻게 재정의할지 고민합니다.. </li>
<li>그러다 보니까 Lombok에서 지원하는 @EqualsAndHashCode @ToString을 사용하는 것 같습니다..ㅜㅜ</li>
<li>이펙티브 자바와 클린코드 책을 읽으면서, 어노테이션을 최소화하고, 개발자가 직접 작성하는 방향이 좋다고 배우게 된 것 같습니다.<ul>
<li><code>필요없는 코드가 자동 생성되는 것을 방지</code>하기 위해서 라고 학습했습니다!</li>
</ul>
</li>
<li>무엇이 좋은지, 그리고 <code>@Override</code>를 어떻게 해야될지 고민했던 것 같습니다,,</li>
<li>이번 기회에 Object Class에 있는 method를 어떻게 사용할지에 대해 작성하도록 하겠습니당!!!~~</li>
</ul>
<br>

<h3 id="😆-object-class란">😆 Object Class란?</h3>
<ul>
<li>자바 클래스의 최최최고 조상 클래스입니다!!!<blockquote>
<p>모든 클래스는 Object 클래스를 상속받고 있습니다!
우리가 따로 <code>extends</code>하지 않더라도 기본으로 상속을 제공합니다!!</p>
</blockquote>
</li>
<li><code>java.lang</code> pakage에 속하며, 자바의 가장 기본적인 동작들을 수행합니다!<blockquote>
<p>그렇기 때문에 별다른 import 없이 사용 가능해요~~</p>
</blockquote>
</li>
</ul>
<h3 id="🖊-tostring">🖊 toString()</h3>
<ul>
<li>toString은 기본적으로 해당 인스턴스의 대한 정보를 문자열로 반환합니다!<blockquote>
<p>기본적으로 toString을 쓰게 되면! 아래와 같이 참조된 정보를 출력하게 됩니다!!
사용자가 원하는 값을 출력하기 위해서는 재정의가 필요합니다!</p>
</blockquote>
</li>
</ul>
<pre><code>DongGeon dongGeon = new DongGeon();
System.out.println(dongGeon);

&gt;&gt; DongGeon@1233123C</code></pre><ul>
<li><p>Lombok을 이용하게 되면서 toString을 조금 더 편하게 사용할 수 있습니다!</p>
<blockquote>
<p>Lombok을 사용하면, 정말 편리하게 toString을 이용할 수 있지만! 모든 데이터가 같이 출력되기 때문에 필요 없는 데이터도 같이 출력되게 됩니다 ㅜㅜ</p>
</blockquote>
<pre><code>@ToString
public Class DongGeon {
  private int age;
  private String name;

  public DongGeon(int age, String name){
      this.age = age;
      this.name = name;
  }
}
</code></pre></li>
</ul>
<p>DongGeon dongGeon = new DongGeon(25, &quot;김동건&quot;);
System.out.println(dongGeon);</p>
<blockquote>
<blockquote>
<p>DongGeon(age=25, name=김동건)</p>
</blockquote>
</blockquote>
<pre><code>
- toString을 재정의 하는 이유!
1. 객체가 가진 정보를 조금 더 가독성 있게 보이기 위하여!
2. 개발자가 원하는 정보를 출력하도록 변경할 필요가 있다!!</code></pre><p>public Class DongGeon {
    private int age;
    private String name;</p>
<pre><code>public DongGeon(int age, String name){
    this.age = age;
    this.name = name;
}

@Override
public String toString() {
    return &quot;나는 &quot; + name + &quot;이고, 나이는 &quot; + age + &quot;이다&quot;;
}</code></pre><p>}</p>
<p>DongGeon dongGeon = new DongGeon(25, &quot;김동건&quot;);
System.out.println(dongGeon);</p>
<blockquote>
<blockquote>
<p>나는 동건이고, 나이는 25이다</p>
</blockquote>
</blockquote>
<pre><code>

&lt;br&gt;

### 🥳 equals()
&gt; 각 인스턴스가 동일한 인스턴스인지 비교합니다! 내용이 같은지, 주소가 같은지 확인할 수 있지만, `==` 대신 equals를 쓰는 이유는 재정의가 가능하기 때문입니다! 그리고 참조형 필드를 비교하기 위해서도요!


- 동일성과 동등성
&gt; 비슷하겠지만, 동일성은 오브젝트가 완전히 같은지를 의미합니다
&gt; 동등성은 같은 정보를 내포가 있는지를 의미합니다!!
</code></pre><p>DongGeon donggeon1 = new DongGeon(25, &quot;김동건&quot;);
DongGeon donggeon2 = new DongGeon(25, &quot;김동건&quot;);</p>
<p>boolean checkOne = donggeon1 == donggeon2;
boolean checkTwo = donggeon1.equals(donggeon2);</p>
<pre><code>
- `==` 연산을 사용할 경우 원시타입의 경우에는 값을 비교합니다! 정황상 donggeon1과 donggeon2는 같은 값을 가지고 있지만!!서로 다른 주소이기 때문에 `false`가 리턴되게 됩니다 ㅜㅠㅜ

- 반대로 `equals`연산을 사용하게 되면 재정의하여 equals가 가진 기본 성능을 바꿀 수 있다!
    + Object Class를 까보면, equals는 기본적으로 `==` 연산을 하고 있다!</code></pre><pre><code>public boolean equals(Object obj) {
    return (this == obj);
}</code></pre><pre><code>
- 기본으로 제공되는 equals 연산자는 결국 `==`와 같은 기능을 제공한댜.... 그렇기 때문에 @Override를 통해 우리의 코드에 맞는 equals를 재정의해야 합니당!</code></pre><p> @Override
    public boolean equals(Object object) {
        if (!(object instanceof this)) {
            return false;
        }
        return this.equals(object);
    }</p>
<pre><code>- 위의 코드처럼 `instanceof` 연산자를 통해 재정의하면 더욱  equals의 기능을 극대화시킬 수 있다!




### 😩 hashCode()
&gt; hashCode는 객체를 식별할 수 있는 정수 값을 의미합니다! hashCode를 통해 저장된 데이터를 더 빠르게 조회할 수 있습니다!

- `hashCode()`는 원래 사용자가 직접 재정의해줘서 구해줘야 합니다!! ㅜㅜ
     하지만 각 IDE가 재정의해주는 hashCode가 정말 좋게 구현되어 있기 때문에 이점은 PASS~

- `hashCode`를 재정의함으로써 HashTable에 HashCode가 최적화되어 삽입될 수 있는 장점이 있습니다!
    + 하지만, ,.,, hashCode를 재정의하면서 나오는 불편함...크름...
</code></pre><pre><code>@Override
public int hashCode() {
    if (this == null) {
        return 0;
    }
    return this.hashCode();
}</code></pre><p>```</p>
<ul>
<li>저의 경우에도 hashCode를 직접 재정의해서 구하기 보다는 IDE 또는 LOMBOK에서 만들어주는 hashCode를 사용하고 있습니다!</li>
</ul>
<h3 id="🎲-결론">🎲 결론</h3>
<blockquote>
<p>toString(), hashCode(), toString() 모두 재정의하여 개발자가 원하는 값을 반환하도록, 혹은 내부 로직을 변경함으로써 원하는 기능을 제공하도록 수정하는 것이 좋다고 생각합니다!</p>
<p>다만!! 우리에게는 LOMBOK이 있고 편리한 TOOL이 너무나 많습니다 ㅜㅜ</p>
<p>모든 것을 재정의하고 모든 부분에서 어노테이션 없이 사용하기에는 아직 초보(예비)개발자가 하기에 너무나 &gt; 큰 부담이 되는 것 같습니다..ㅜㅜㅜ</p>
<p>그렇기 때문에, 일단 어노테이션을 작성해서 개발을 하다가, 리펙토링을 하며, 하나씩 어노테이션을 지우고 직접 구현해 나가는 방향도 저는 좋다고 생각합니다... 물론 지극히 개인적인 의견입니다!!</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA-2] StringBuilder와 StringBuffer의 차이]]></title>
            <link>https://velog.io/@dong_geon_kim/JAVA-2-StringBuilder%EC%99%80-StringBuffer%EC%9D%98-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@dong_geon_kim/JAVA-2-StringBuilder%EC%99%80-StringBuffer%EC%9D%98-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Thu, 05 Aug 2021 09:29:50 GMT</pubDate>
            <description><![CDATA[<h1 id="stringbuilder와-stringbuffer의-차이">StringBuilder와 StringBuffer의 차이</h1>
<p align="center">
<img src="https://images.velog.io/images/dong_geon_kim/post/46e042c8-df6d-4b52-a346-f1ebf3f1df2a/KakaoTalk_20210520_210902458.jpg"  width="300" height="400"/>
</p>

<hr />

<h3 id="😱-이번에는">😱 이번에는?</h3>
<ul>
<li><code>StringBuilder와 StringBuffer는 무슨 차이</code> 입니다!</li>
</ul>
<br>

<h3 id="🛒-들어가면서">🛒 들어가면서</h3>
<ul>
<li>JAVA에서 문자를 다룰 수 있는 기술을 다양하게 존재합니다! 그중에서 String, StringBuffer, StringBuilder가 가장 많이 사용되는 방법이라고 생각합니당.</li>
<li>각각의 기능들은 비슷한 기능을 제공하지만, 실제로 안을 보면 사뭇 다름을 알 수 있어요!</li>
<li><code>String, StringBuffer, StringBuilder</code>를 하나씩 풀어나가며  이번 과제를 진행하겠습니당당당!!</li>
</ul>
<br>


<h3 id="😆-불변-객체와-가변-객체">😆 불변 객체와 가변 객체</h3>
<ol>
<li>불변 객체    <ul>
<li>불변 객체 <code>immutable object</code>는 생성 후 그 상태를 바꿀 수 없는 객체</li>
<li>불변 객체는 <code>String, Integer, Boolean</code>과 같은 <code>Class</code>도 있지만, 사용자가 직접 final로 원시타입을 생성하여 불변 객체를 만들 수 있습니다!</li>
</ul>
</li>
</ol>
<pre><code>    public class Person {
        private final String name;
        private final int age;

        public Person(String name, int age){
            this.name = name;
            this.age = age;
        }
    }</code></pre><ol start="2">
<li>가변 객체<ul>
<li>가변 객체 <code>mutable object</code>는 생성 후에도 상태를 변경할 수 있는 개체</li>
<li><code>int, char, boolean</code> 등 원시타입 필드를 가진 클래스는 가변 객체입니다!</li>
<li>하지만, 원시타입 필드에 <code>final</code>을 붙여서 불변 객체로 만들 수도 있습니다.</li>
</ul>
</li>
</ol>
<pre><code>    public class Person {
        private String name;
        private int age;

        public Person(String name, int age){
            this.name = name;
            this.age = age;
        }
    }</code></pre><h3 id="🖊string">🖊String</h3>
<blockquote>
<p>처음 알고리즘 문제를 풀었을 때, 항상 String을 사용했던 것 같습니다! 그런데 어느 순간부터 String을 사용한 연산을 하면, 메모리를 너무 많이 잡아먹어 문제를 해결하지 못했던 것 같아요..ㅜㅜㅜ</p>
</blockquote>
<ol>
<li><code>String</code>은 무엇인가?</li>
</ol>
<ul>
<li><code>String</code>은 원시 타입이 아닙니다!</li>
<li>문자열을 가진 객체입니다!</li>
</ul>
<ol start="2">
<li><code>String</code>은 불변 객체입니다!</li>
</ol>
<ul>
<li>가변 객체와 다르게 한번 생성하면 그 값을 바꿀 수 없습니다!<ul>
<li>하지만, 재할당은 가능합니다!</li>
</ul>
</li>
</ul>
<ol start="3">
<li><code>String</code>을 생성하는 방법!<pre><code>String index = new String(&quot;예시&quot;);
String index = &quot;예시&quot;;</code></pre></li>
<li><code>String</code>이 제공하는 Method<pre><code>equals
indexOf
replaceAll
substring
toUpperCase</code></pre></li>
</ol>
<p>결국, 불변객체를 사용해야 하는 경우 String을 사용하는 것은 좋지만, 값이 계속 바뀌는 상황일 경우에는 지양하는 것이 좋다!</p>
<h3 id="🥳-stringbuffer">🥳 StringBuffer</h3>
<blockquote>
<p>처음 무작정 코딩테스트를 위해 <code>StringBuffer</code>를 사용했던 경험이 있습니다. 면접때 면접관님이 <code>StringBuffer</code>를 사용한 이유와 <code>StringBuilder</code>와의 차이점을 물으셨지만.. 결국 완벽한 답을 하지 못한 경험이 있습니다.</p>
</blockquote>
<ul>
<li><code>String</code>과 다르게 <code>StringBuffer</code>는 가변 객체입니다!</li>
<li>기존에 할방받은 공간에 새로운 데이터가 쌓이고, 추가 데이터가 공간보다 커지게 되면, 기존의 버퍼 크기를 늘립니다!!</li>
<li><code>StringBuffer</code>는 동기화 <code>Synchronized</code>를 지원합니다!<ul>
<li>여러 스레드가 하나의 자원을 사용하려고 할때 다른 스레드의 접근을 막는 것이 동기화 입니다!!</li>
<li>동기화를 지원하기 때문에 <code>StringBuffer</code>는 멀티스레드 환경에 쓰입니다!<ul>
<li>물론 멀티스레드 환경이 아니더라도 사용할 수 있지만, 그럴 경우에는 <code>StringBuilder</code>가 더 효율적입니다.</li>
</ul>
</li>
<li>동기화를 지원하는 `StringBuffer&quot;는 멀티스레드 환경에서 안전하게 자원을 사용할 수 있음을 보장합니다!!</li>
</ul>
</li>
</ul>
<h3 id="😩-stringbuilder">😩 StringBuilder</h3>
<blockquote>
<p>알고리즘 문제를 풀때, <code>StringBuffer</code>보다 <code>StringBuilder</code>가 더 빠르다는 말을 들었습니다. 혹해서 아직까지 StringBuilder를 가끔 사용하고 있는 것 같습니다. 이번 기회에 <code>StringBuilder</code>를 탐구하겠습니당!!</p>
</blockquote>
<ul>
<li><code>StringBuilder</code>도 <code>StringBuffer</code>와 마찬가지로 가변 객체입니다!</li>
<li>하지만 동기화를 지원하지 않는 다는 가장 큰 차이점이 존재합니다!</li>
<li>동기화를 지원하지 않는 StringBuilder를 사용하는 가장 큰 이유는<ul>
<li><code>StringBuffer</code>보다 단일 스레드 환경에서 빠른 속도를 보여주기 때문입니다!</li>
</ul>
</li>
</ul>
<h3 id="🎲-결론">🎲 결론</h3>
<blockquote>
<p>String은 불변 객체이고, StringBuffer와 StringBuilder는 가변 객체이다</p>
</blockquote>
<blockquote>
<p>단일 스레드 환경에서 StringBuilder는 제일 좋은 성능을 발휘한다.</p>
</blockquote>
<blockquote>
<p>StringBuffer는 Synchronized를 지원하지만, StringBuilder는 지원하지 않는다.</p>
</blockquote>
<blockquote>
<p>StringBuffer는 멀티 스레드 환경에서 안정성 보장한다.</p>
</blockquote>
<blockquote>
<p>상황에 맞추어 StringBuffer와 StringBuilder를 사용해야 하며, 무엇이 좋은지는 그 상환이 판단한다.</p>
</blockquote>
<blockquote>
<p>간혹, String이 StringBuffer와 StringBuilder보다 좋은 성능을 보일 떄 도 있다!</p>
</blockquote>
<br>

<h3 id="📚-reference">📚 Reference</h3>
<ul>
<li><a href="https://wikidocs.net/205">점프 투 자바</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA-1] Coding Convention]]></title>
            <link>https://velog.io/@dong_geon_kim/JAVA-1-Coding-Convention</link>
            <guid>https://velog.io/@dong_geon_kim/JAVA-1-Coding-Convention</guid>
            <pubDate>Thu, 05 Aug 2021 07:12:26 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/dong_geon_kim/post/5792bebb-82fc-418b-b34b-b836c30d53ed/image.png" alt=""></p>
<hr />
<br>

<h3 id="😣-coding-convention">😣 Coding Convention!</h3>
<p>프로그래밍을 하다보면, 협업을 위해 팀 또는 회사가 규칙을 정해서 Coding Rule를 만듭니다!</p>
<p>일종의 규칙이자, 관례 그리고 법이라고 생각합니다! 이번에는 Coding Convention에 대해 다뤄보려고 합니다!!</p>
<h3 id="🕓naming-rule">🕓Naming Rule</h3>
<p>Class의 경우에는! 각 단어의 앞글자를 대문자로 사용합니다!</p>
<pre><code>class MyClass // o
class myclass // x</code></pre><p>그리고, 클래스는 대게 특정한 오브젝트를 이름으로 가집니다!</p>
<p>method의 경우에는! 첫 단어의 앞글자는 소문자이고, 다음 글자의 앞글자는 대문자입니다!</p>
<pre><code>void helloDongGeon // o
void HelloDongGeon // x</code></pre><p>method는 메세지를 던져주는 역할을 합니다! 
그러다 보니 class와 다르게 동사형을 사용합니다! ~~하다 라는 의미를 갖는 이름을 가지도록 명칭을 지어주어야 합니당당</p>
<p>field명은 method와 비슷합니다! 하지만! class와 마찬가지로 특정한 오브젝트를 이름으로 가집니다!</p>
<pre><code>int human = 3; // o
int run = 4; // x</code></pre><h3 id="🕒-reference">🕒 Reference</h3>
<p>java에서는 모든 것이 레펀스 값입니다!! &lt;-- 곰튀김님께서 해주신 말씀!</p>
<p>자바의 타입에서는 원시값과 박싱된 값이 있는데,,,</p>
<p>원시값은</p>
<p><code>boolean, byte, int, short, long, float, double, char이 있습니다!!</code></p>
<p>우리가 자주쓰는 String은 원시값이 아닙니다!! 이것에 대해서는 다음 Chapter에서 작성하겠습니당!</p>
<p>Call By Value : 값에 의한 호출</p>
<blockquote>
<p>원래의 데이터를 복사해서 처리하기 때문에 원본 값을 보존할 수 있다!</p>
</blockquote>
<p>Call By Refernece : 참조에 의한 호출</p>
<blockquote>
<p>원래 데이터를 직접 참조하여 사용하기 때문에 공유해서 쓰는 방법이다!, 원본 값을 사용하기 때문에 원래 값에 영향을 미칠 수 있다! </p>
</blockquote>
<h3 id="🕒-constant-pool">🕒 Constant Pool</h3>
<pre><code>public void talk() {
    String convention = &quot;&quot;;
    for(int i=0; i &lt; 10; i++){
        convention += &quot;a&quot;;
    }
}</code></pre><p>위의 코드처럼 String 객체에 <code>+=</code> 연산을 진행할 경우 이미 메모리에 상주한 값을 바꾸는게 아니라, 새로운 데이터를 메모리에 생성하게 됩니다!!
결국!! 이와 같은 로직이 있다면 메모리가 폭발!!</p>
<h3 id="🕑-object">🕑 Object</h3>
<p>모든 객체의 최상위 객체는 <code>Object</code> 입니다!!</p>
<pre><code>public class People extends Object</code></pre><p>모든 클래스에서 <code>Object</code> 최상위 클래스는 자동적으로 extends되어 집니다~~</p>
<p>그렇기 때문에 <code>Object</code> class에서 사용되는 메서드를 <code>@Override</code>해서 쓸 수 있어요~</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL-1] 시작입니다!!]]></title>
            <link>https://velog.io/@dong_geon_kim/TIL-1-%EC%8B%9C%EC%9E%91%EC%9E%85%EB%8B%88%EB%8B%A4</link>
            <guid>https://velog.io/@dong_geon_kim/TIL-1-%EC%8B%9C%EC%9E%91%EC%9E%85%EB%8B%88%EB%8B%A4</guid>
            <pubDate>Thu, 05 Aug 2021 06:56:28 GMT</pubDate>
            <description><![CDATA[<h1 id="💻-동건동건동건의-신나는-하루">💻 동건동건동건의 신나는 하루</h1>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/d1d4e387-c01d-46d9-ab81-0024351afba5/image.png" alt=""></p>
<hr />

<h3 id="😱-첫-기록인-만큼-왜-시작했는지">😱 첫 기록인 만큼 왜 시작했는지</h3>
<p>TIL이라는 것을 알긴 했지만, 스스로?가 납득할 정도로만 작성했던 것 같습니다.</p>
<p>단순하게 체크리스트?처럼 작성해서 기록하고 공부했던 것 같아요
물론 TIL이 남들에게 보여지기 위해서 작성하는 것은 아니지만, 어느 정도 나를 정리할 수 있는 공간은 아니었습니다.
그렇기 때문에! 이제부터 TIL을 통해 조금씩 정리해보려고 합니다!!!!🥰🥰</p>
<br>



<h3 id="😝-처음이라-아직-어려워요">😝 처음이라 아직 어려워요</h3>
<p>정말 정말 정말 좋은 기회로 프로그래머스 백엔드 데브코스 백엔드 과정을 수강하게 되었습니다!!🙏🙏🙏
자바 언어와 스프링 프레임워크를 어느정도 학습한 시점에서 스스로 기본기가 부족하다고 느꼈고 지원하게 했습니다.
아직 어려운 내용을 학습하지는 않아서 그래도 무난하게 따라가고 있습니다!! 하지만.,,,</p>
<br>

<h3 id="😜-조금-어려웠던거">😜 조금 어려웠던거?</h3>
<p>수업 내용을 따라가기에 어렵다고 느낀 적은 없습니다.. 그런데 가장 어려웠던 것은 프로그램의 전반적인 시스템?을 이해하는 부분인 것 같습니다.
워낙 방대하고, 큰 규모를 자랑하다 보니... 어느 정도 시스템을 이해하는데 시간이 걸렸던 것 같습니다!
아직 완벽하게 이해하지 않았지만, 차근차근 프로그래머스 교육 시스템에 녹아들도록 노력하려고 합니다~~🌱🌱</p>
<br>

<h3 id="📚-그래서-오늘-공부를-뭐했지">📚 그래서 오늘 공부를 뭐했지?</h3>
<p>오늘 주된 학습은 크게 4가지인 것 같습니다</p>
<ol>
<li><p>프로그래머스 교육 시스템 파악하기</p>
</li>
<li><p>인터페이스 학습하기!</p>
</li>
<li><p>Spring-Security</p>
</li>
<li><p>TIL 작성하기!!!</p>
<br>
### 📣📣 차근차근 하나씩 정리하겠습니다! 📣📣

</li>
</ol>
<h4 id="🕐-프로그래머스-교육-시스템-파악하기">🕐 프로그래머스 교육 시스템 파악하기</h4>
<p>저번 주 금요일 프로그래머스 백엔드 과정의 전반적인 기둥이신 스펜서 님께서 시스템에 대해 자세히 설명해주셨습니다.</p>
<p>그런데... 막상 스스로 해보려고 하니 이게 뭐지?라고 계속 갸우뚱한 것 같습니다.</p>
<p>직접 부딪혀보지 않으면 모른다는 말이 이것을 말하는구나 생각 들었습니다.</p>
<p>그래도 스펜서 님께서 정리해주신 노션 정보와 공지사항을 통해 드디어 대략적인 시스템 구조를 90% 정도 알게 된 것 같습니다!!!! 🙌🙌🙌</p>
<p>감사합니당 감사합니당~</p>
<br>

<h4 id="🕑-인터페이스-학습하기">🕑 인터페이스 학습하기</h4>
<p>아마도 자바 개발자에게 있어 인터페이스는 핵심 요소라고 생각합니다</p>
<p>인터페이스를 통해 기능을 확장시킬 수도 있고, 반대로 규제할 수 있어 없어서는 아니될 최고의 아이템입니다!!</p>
<p>그렇기 때문에 인터페이스를 학습했던 내용은 조금 더 다듬어서 TIL 남기겠습니다!!</p>
<p>ps. 강의를 들으면서, 객체지향을 대입해서 인터페이스에 대해 쉽고 빠르게 알려주는 강의는 처음입니다. 처음부터 이 방식으로 배웠다면, 아마 지금 저는 자바 왕이 되었을 것 같습니다...😹😹</p>
<br>

<h4 id="🕒-spring-security">🕒 Spring-Security</h4>
<p>Okky를 통해 만난 동갑내기 삼인방이 있습니다!! 다들 객체지향과 웹에 대해 관심이 있었고, 현재 물물교환을 주제로 하는 토이 프로젝트를 진행하고 있습니다!</p>
<p>저는 해당 토이 프로젝트에서 Member Domain을 맡아서 구현하고 있습니다! </p>
<p>사실 지난 화요일에 노트북이 과도한 업무로 사망해서 포맷하느라,,, 기존 데이터를 날리느라 애써 구현했던 소스를.,,, 잃어버리게 되었습니다..ㅜㅜㅜ 깃에 커밋을 한다는 것을 push를 하지 못해서 날리게 되었습니다..</p>
<p>한번 날리게 되니까 커밋 후 바로 push 하는 습관이 든 것 같습니다 📢📢📢📢</p>
<p>유림님이 선물해주신 인프런 강의를 들으며 깃에 대한 완벽한 학습을 진행해야 될 것 같습니다!</p>
<p>오늘 가장 오래 고민 했던 내용은 Security가 보관하고 있을 객체를 어떻게 관리할까 였습니다,.,</p>
<p><img src="https://images.velog.io/images/dong_geon_kim/post/45186267-725e-42e0-824c-157f34ce58c5/image.png" alt="">
레포지터리에서 뺴온 데이터를 DTO로 가공할 것인지, 아니면 레 포지터에서 조회할 때부터 다른 DTO를 사용할 것인지 고민했던 것 같습니다.. 이 부분에 대해서 4시간 넘게 고민했지만, 어떤 코드가 좋을지 모르겠어서.,,, 팀원들과 한번 상의하기로 했습니다!!</p>
<p>또또또
<img src="https://images.velog.io/images/dong_geon_kim/post/e3291ffa-6d09-49f0-b9ed-0a790b36f63f/image.png" alt=""></p>
<p>아직 회원가입과 로그인만 구현했는데.... 겁나기 시작합니다.. 두렵기 시작합니다.. 무섭기 시작합니다...ㅜㅜㅜㅜ</p>
<p>아직 끝이 보이지는 않지만, 열심히 공부하다 보면 언제가 끝이 보이지 않을까 소망합니다</p>
<br>

<h4 id="🕓-til-작성하기">🕓 TIL 작성하기!!!</h4>
<p>저는 TIL을 작성하는 게 처음이라 많이 어색하고 어려운 것 같습니다..</p>
<p>죽여,,줘...
지금도 이 글을 작성하기까지 지우고, 쓰고, 지우고, 쓰고를 무한 반복하고 있습니다..ㅜㅜㅜㅜ🤒🤒🤒</p>
<p>아직 어떻게 작성해야 하는지, 그리고 무엇을 중점으로 두어야 하는지 감이 잡히지 않지만! 계속 계속 도전하겠습니당당</p>
<br>


<h3 id="📫-마치며">📫 마치며</h3>
<p>TIL을 쓰려고 했는데.. 다시 읽어보니 회고가 된 것 같습니다.ㅜㅜㅜㅜ 반성 반성</p>
<p>스펜서 님께서 예쁘게 작성해주신 공지를 읽으며, 인터페이스 부분을 다시 작성해야겠습니다!!</p>
<p>벌써 이 글을 작성하고 있는 시간은 오전 2시 50분!!</p>
<p>쓰다 보니 두서가 없고, 괜스레 핵심이 없는 것 같아 아쉬움이 남습니다ㅜㅜ</p>
<p>반성은 다음 TIL에서 하는 걸로 마무리하며, 오늘은 여기서 뿅!🤘🤘🤘🤘</p>
<p>ps. 앞으로 프로그래스를 통해 좋은 습관을 들이도록 노력 노력!!!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[첫 회고 입니다!]]></title>
            <link>https://velog.io/@dong_geon_kim/retrospect1</link>
            <guid>https://velog.io/@dong_geon_kim/retrospect1</guid>
            <pubDate>Sun, 01 Aug 2021 05:55:50 GMT</pubDate>
            <description><![CDATA[<img src="https://images.velog.io/images/dong_geon_kim/post/d47ec909-fe1e-40d0-a9ef-35be30a436e0/KakaoTalk_20210730_161220267.jpg" width="30%" height="30">

<h3 id="2년만에-글을-쓰며">2년만에 글을 쓰며</h3>
<p>2019년도에는 블로그를 통해 회고와 인사이트에 대한 내용을 적은 것 같아요..
그런데 어느 순간부터 글을 쓰는 행위를 멀리하게 된 것 같아요
아마도 공부가 먼저다? 라는 생각을 했던 것 같습니다.. 돌아간다면, 일주일에 한 번 이상은 회고록을 작성할 것 같아요!</p>
<h3 id="저는">저는..</h3>
<p>지금은 직장인이 아니에요.. 저는 아직 학생으로서 객체지향과 스프링을 학습하고 있습니다! 예전에는 무작정 구글링을 통해 코드복사?만을 한 것 같아 반성하고 있어요
지금이라도 멋진 개발자가 되기 위해 학습하고 있습니다!!</p>
<h3 id="이번주에-내가-했던거">이번주에 내가 했던거</h3>
<p>이번주는 정말 바빴던 것 같아요!
프로그래머스에서 진행하는 데브코스 백엔드 과정에 붙어서, 해당 과정에 대한 준비도 필요했고, 개인적으로 하고 있던 스터디와 프로젝트를 진행하느라~~ 잠도 제대로 못 잤어요,,</p>
<h3 id="반성하고-있는거">반성하고 있는거?</h3>
<p>열심히 공부한다고 생각하는데, 항상 정말 중요한 내용에 대해 잊어버리는 것 같아서 아쉬움을 느껴요.. 그리고 가장 큰 것은 스스로를 믿고 의지하는 부분이 약한 것 같아요</p>
<p>나를 믿고, 내 주관을 믿어야 하는데 반성 또 반성</p>
<h3 id="앞으로">앞으로</h3>
<p>저는 매주 1회 이상은 회고를 작성하려고 합니다!! 회고를 통해 이후의 나에게 좋은 인사이트를 줄거라 기대해요!!</p>
]]></description>
        </item>
    </channel>
</rss>