<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>dk_ovo.log</title>
        <link>https://velog.io/</link>
        <description>안녕하세요~</description>
        <lastBuildDate>Sun, 15 Sep 2024 06:17:53 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. dk_ovo.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/dk_ovo" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[JavaScript 학습 정리 (3) - 공 튀기기 게임]]></title>
            <link>https://velog.io/@dk_ovo/JavaScript-%ED%95%99%EC%8A%B5-%EC%A0%95%EB%A6%AC-3-%EA%B3%B5-%ED%8A%80%EA%B8%B0%EA%B8%B0-%EA%B2%8C%EC%9E%84</link>
            <guid>https://velog.io/@dk_ovo/JavaScript-%ED%95%99%EC%8A%B5-%EC%A0%95%EB%A6%AC-3-%EA%B3%B5-%ED%8A%80%EA%B8%B0%EA%B8%B0-%EA%B2%8C%EC%9E%84</guid>
            <pubDate>Sun, 15 Sep 2024 06:17:53 GMT</pubDate>
            <description><![CDATA[<h1 id="공-튀기기-게임-실습하기">공 튀기기 게임 실습하기</h1>
<p><a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_building_practice">https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_building_practice</a></p>
<p>해당 글에 나와있는 기본 소스를 가지고 실습을 하며 만드는 과정이다.</p>
<h2 id="클래스-생성-shape--슈퍼클래스-ball--자식-evlilball--자식">클래스 생성 (Shape = 슈퍼클래스, Ball = 자식, EvlilBall = 자식)</h2>
<p>자바스크립트의 클래스는 자바의 클래스와 만드는 방법이 조금 다르다. Java의 경우 클래스 파일을 만들어서 클래스를 분리하면서 생성하는 반면, 자바스크립트는 클래스는 JS는 프로토타입 기반 객체 지향 프로그래밍 언어이며, 초기 자바스크립트에 클래스란 개념은 없었으나, ES6 자바스크립트에서 클래스가 도입되었다. 하지만 클래스도 JS에서는 프로토타입 기반으로 구현된 것이다. 정확히 말하면 function과 new를 통해 클래스처럼 쓸 수 있는 것이다.</p>
<p>javascript와 java의 클래스 차이를 조금 정리하면 다음과 같다</p>
<p><strong>1. Class</strong></p>
<ul>
<li>JavaScript : Class가 존재 하지 않음 -&gt; 이 역할을 Function과 Prototype이 함</li>
<li>Java : Class가 존재, Class = 속성 + 기능</li>
</ul>
<p><strong>2. Object</strong></p>
<ul>
<li>JavaScript : Object는 하나의 타입이며 속성(변수) + 기능(함수)으로 구성</li>
<li>Java : Object는 Class의 인스턴스</li>
</ul>
<p><strong>3. Function</strong></p>
<ul>
<li>JavaScript : 함수 역할을 하면 함수, 객체 안에 있으면 메서드, Java의 Class역할을 하면 생성자 등으로 기능함
 -&gt; Function이 Class 역할을 할때는 변수+메서드로 구성되기에 Object처럼 봐도 무방.</li>
<li>Java : 메서드 only</li>
</ul>
<p><strong>4. 생성자</strong></p>
<ul>
<li>JavaScript : Function이 수행함</li>
<li>Java : 클래스의 이름</li>
</ul>
<p><strong>5. 상속</strong></p>
<ul>
<li><p>JavaScript : Class가 존재하지 않아 Prototype을 이용하여 상위 Function을 복제하여 상속받음</p>
</li>
<li><p>Java : extends를 사용하여 상위 Class를 상속받음</p>
<p>추가적으로 주의할 점은 1개의 클래스에 constructor 는 1개만 올 수 있다. 따라서 Java와 달리 생성자 오버로딩이 불가능하다, 그렇지만 마찬 가지로 다른 방법을 통해 오버로딩과 비슷한 기능을 만들어낼  수 있다.</p>
</li>
</ul>
<h3 id="shape-클래스--ball-클래스">Shape 클래스 &amp; Ball 클래스</h3>
<p>다음은 부모클래스를 인 Shape와 자식 클래스인 Ball 클래스를 만드는 예제이다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/0916bd1c-0bad-468d-83e3-4f1530293815/image.png" alt=""></p>
<h3 id="evil-클래스">Evil 클래스</h3>
<p>마찬가지로 shpae 클래스의  자식 클래스인 evil 클래스이다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/629b5ad9-f18d-48d1-91ca-be133c8c9ad9/image.png" alt=""></p>
<h2 id="ball-객체를-loop를-통해-찍어내기">Ball 객체를 loop를 통해 찍어내기</h2>
<p>ball 객체를 담는 배열 balls[] 를 만든 후 무한정 찍어낼 수 없기 때문에 갯수에 제한을 건다.
이후 각기 다른 크기와 색상을 만들기 위해 객체를 생성할 때 무작위의 크기와 색상을 입혀준다. </p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/6d775fdb-71de-46ef-aa34-e5359f2994ac/image.png" alt=""></p>
<p>객체를 생성할 때
함수단위스코프(var,let,const) + 변수명 = new + Class명 방식으로 생성하면 된다.</p>
<h2 id="evilball-공-잡아먹는-공">EvilBall (공 잡아먹는 공)</h2>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/0a7e6e6b-398e-4683-bff4-bdc140ad9010/image.png" alt=""></p>
<p>생성 방식은 동일하며 매서드 쪽 부분의 차이가 있다.</p>
<h2 id="loop">loop</h2>
<p>loop를 통해 기능을 반복적으로 수행하며, 게임을 정상적으로 작동하게끔 만드는 핵심 영역이다. 여기에서 사용되는 ball과 evilball의 반복되는 부분은 매서드로 따로 빼주었다.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/7f284b63-c5e7-4245-be8a-5d3f7f1535b4/image.png" alt=""></p>
<h2 id="완성-화면">완성 화면</h2>
<p>w,a,s,d 키로 저 흰 원을 움직여서 공과 닿으면 닿은 공이 사라지면 우측 위의 count가 한개씩 줄어든다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/707e3fe4-35a7-4ee5-b9fb-6cd4bfcd5ba0/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JavaScript 학습 정리 (2)]]></title>
            <link>https://velog.io/@dk_ovo/JavsScript-%ED%95%99%EC%8A%B5-%EC%A0%95%EB%A6%AC-2</link>
            <guid>https://velog.io/@dk_ovo/JavsScript-%ED%95%99%EC%8A%B5-%EC%A0%95%EB%A6%AC-2</guid>
            <pubDate>Thu, 29 Aug 2024 16:20:34 GMT</pubDate>
            <description><![CDATA[<h1 id="스터디-내용">스터디 내용</h1>
<p><a href="https://developer.mozilla.org/ko/docs/Learn/JavaScript/Building_blocks/Image_gallery#%ED%8F%89%EA%B0%80_%ED%98%B9%EC%9D%80_%EC%B6%94%EA%B0%80%EC%A0%81%EC%9D%B8_%EB%8F%84%EC%9B%80">https://developer.mozilla.org/ko/docs/Learn/JavaScript/Building_blocks/Image_gallery#%ED%8F%89%EA%B0%80_%ED%98%B9%EC%9D%80_%EC%B6%94%EA%B0%80%EC%A0%81%EC%9D%B8_%EB%8F%84%EC%9B%80</a></p>
<p>해당 링크로 들어가서 주어진 내용 대로 구현하면 된다.
HTML, CSS 는 수정할 필요 없이 Script 부분만 수정하면 된다.</p>
<h2 id="정리">정리</h2>
<p>for문 (반복문)으로 thumb-bar div안에 img들 추가
<img src="https://velog.velcdn.com/images/dk_ovo/post/aaf4197b-f18b-4036-a7f6-06104f692203/image.png" alt="">const newImage = document.createElement(&#39;img&#39;); 가 주어졌고 반복문을 통해 이미지들을 삽입한다.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/969190d0-2020-46fe-897c-6a73c0f87710/image.png" alt="">
images 폴더 경로에 있는 이미지 파일 명들을 images 배열에 넣고, 해당 사진들을 나중에 onclick 이벤트로 클릭했을 때 나올 사진들의 설명도 description 배열에 넣는다.</p>
<p>setAttribute() 함수는 지정된 HTML 요소의 속성 “값”을 설정할 수 있는 함수이다.
만약 setAttribute(&#39;name&#39;, &quot;김동규&quot;) 로 했다면 HTML요소에 name=&quot;김동규&quot; 와 같은 값이 들어가게 되는 것이다. 아래는 결과이다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/014e68e7-c5f3-4174-bc0e-311cd2b41dcb/image.png" alt=""></p>
<p>그나마 가장 고민이 됐던 onclick eventListener를 설정한 부분이다. click을 할 경우 displayImage.src의 속성이 e 즉 현재 마우스로 클릭한 이미지의 속성값으로 바뀐다. 이번 문제에서는 src(이미지 파일 경로)와 alt(이미지 설명) 이 필요하므로  두개를 각각 바꾸게 한다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/e2fa9ec0-42a9-478d-9293-89cfdeac1d9f/image.png" alt=""></p>
<p>밝기조절 버튼의 경우도 마찬가지로 click이벤트를 생성해서 setAttribute로 Class의 값을 Light일때와 Dark일 때 이미지의 밝기를 각각 설정해주면 된다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/753dab17-6511-4c1f-8ffc-87b611765317/image.png" alt=""></p>
<h2 id="script단-최종-코드">Script단 최종 코드</h2>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/9d580275-65ea-4f60-8650-944bf01bb361/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Java Script 학습 및 정리 (1)]]></title>
            <link>https://velog.io/@dk_ovo/Java-Script-%ED%95%99%EC%8A%B5-%EB%B0%8F-%EC%A0%95%EB%A6%AC-1</link>
            <guid>https://velog.io/@dk_ovo/Java-Script-%ED%95%99%EC%8A%B5-%EB%B0%8F-%EC%A0%95%EB%A6%AC-1</guid>
            <pubDate>Sat, 17 Aug 2024 19:05:40 GMT</pubDate>
            <description><![CDATA[<h2 id="undefined와-null의-차이">Undefined와 Null의 차이</h2>
<p>JavaScript에는 &#39;없음&#39;을 나타내는게 2가지가 있는데 null과 undefined이다. 의미는 비슷할지라도 사용되는 목적은 다르다..</p>
<p>JavaScript에서는 값이 대입되지 않은 변수 혹은 속성을 사용하려고 하면 undefined 를 반환한다.</p>
<p>추가적으로 undefined: 값이 정의되지 않았다. null: 값이 비어있다. NaN: 값이 아니다. === 계산불가능</p>
<h3 id="정수와-실수">정수와 실수</h3>
<p>Java와 다르게 정수와 실수 둘 다 Number 타입이다.</p>
<h3 id="typeof-연산자">typeof 연산자</h3>
<p>JavaScript에서는  typeof를 사용해서 데이터의 타입을 확인할 수 있다.</p>
<pre><code>var a = 0
typeof a
</code></pre><p>출력값: &quot;Number&quot;</p>
<h3 id="와--연산자">==와 === 연산자</h3>
<p>==는 Equal Operator이고,  ===는 Strict Equal Operator이다. </p>
<p>==는 a == b 라고 할때, a와 b의 값이 같은지를 비교해서, 같으면 true, 다르면 false라고 한다.(값만 같으면 true이다.)</p>
<p>즉
var a = 1
var b = &quot;1&quot;</p>
<p>console.log(a == b); // true 
console.log(a === b); // false </p>
<p>다음과 같은 결과가 나온다.</p>
<h3 id="prompt-함수">prompt 함수</h3>
<p>JavaScript에서 prompt() 함수는 사용자에게 입력을 요청하는 프롬프트 상자를 화면에 표시하기 위해 사용됩니다. 프롬프트 상자에서 계속 진행하려면 보통은ㄴ &quot;확인&quot; 또는 &quot;취소&quot; 버튼을 클릭하도록 구성된다.</p>
<h3 id="while-반복문-사용">While 반복문 사용</h3>
<p>var a = 10;
while (a &lt; 50) {
    console.log(a);
    a++
}</p>
<h3 id="break와-continue">break와 continue</h3>
<p>break는 반복문을 빠져나가기 위해 사용, continue의 경우 반복문의 처음으로 돌아간다.</p>
<p><strong>continue 정리</strong>
while: 조건식( i &lt; 10 )으로 이동
for: 증감식 ( i++) 으로 이동</p>
<h2 id="배열">배열</h2>
<h3 id="push와-pop">push()와 pop()</h3>
<p>push(value) : 배열의 뒤 쪽에 새로운 원소를 삽입
pop(): 배열의 마지막 원소를 빼서 변수에 넣어 주며 이때 변수의 길이는 1 감소합니다.</p>
<h3 id="shift와-unshift">shift()와 unshift()</h3>
<p>push, pop과 반대로 동작</p>
<p>unshift(v): 배열의 맨 앞에 새로운 값을 추가합니다.
shift(): 배열의 앞에서 값을 빼서 변수에 넣어 줍니다.</p>
<h2 id="객체">객체</h2>
<h3 id="객체-생성">객체 생성</h3>
<p>var a = {};</p>
<p>입력값
typeof a;</p>
<p>출력값
&quot;object&quot;</p>
<p>a.name = &quot;DongGyu&quot;</p>
<p>입력값
a;</p>
<p>출력값
{name: &quot;DongGyu&quot;}</p>
<h3 id="json-표기법을-이용한-객체-생성">JSON 표기법을 이용한 객체 생성</h3>
<p>var person = {
  &quot;name&quot;: &quot;DongGyu&quot;,
  &quot;height&quot;: 184,
  &quot;weight&quot;: 83,
  &quot;introduce&quot;: function() {
       console.log(&quot;My name is&quot; + this.name) 
  }
};</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Observer(옵저버 패턴), Strategy(전략 패턴), Composite(복합체 패턴) ]]></title>
            <link>https://velog.io/@dk_ovo/Observer%EC%98%B5%EC%A0%80%EB%B2%84-%ED%8C%A8%ED%84%B4-Strategy%EC%A0%84%EB%9E%B5-%ED%8C%A8%ED%84%B4-Composite%EB%B3%B5%ED%95%A9%EC%B2%B4-%ED%8C%A8%ED%84%B4</link>
            <guid>https://velog.io/@dk_ovo/Observer%EC%98%B5%EC%A0%80%EB%B2%84-%ED%8C%A8%ED%84%B4-Strategy%EC%A0%84%EB%9E%B5-%ED%8C%A8%ED%84%B4-Composite%EB%B3%B5%ED%95%A9%EC%B2%B4-%ED%8C%A8%ED%84%B4</guid>
            <pubDate>Sat, 20 Jul 2024 23:57:01 GMT</pubDate>
            <description><![CDATA[<h1 id="observer-옵저버-패턴">Observer (옵저버 패턴)</h1>
<p>주제(Subject)가 변경될 때 마다 옵저버들에게 변화를 알려주는 디자인 패턴
<strong>한 객체의 상태가 바뀌면 객체에 의존하는 다른 객체에게 자동으로 내용이 갱신되는 방법으로 일대다(one-to-many) 의존성을 정의</strong>한다.</p>
<p>주제(subjet)는 옵저버들이 인터페이스를 구현하는 것을 제외하면 옵저버에 대해 아는게 없다. 따라서 이들의 결합은 느슨한 결합(Loose Coupling) 형태이다.</p>
<h2 id="subject-인터페이스">Subject 인터페이스</h2>
<ol>
<li>옵저버의 등록, 제거, 변화를 알려주는 매서드가 있으며, 주제는 여러개의 옵저버가 있을 수 있다.</li>
<li>주제는 상태가 바뀔 때마다 매서드를 통해 옵저버들에게 알려줘야한다.</li>
</ol>
<h2 id="producer-클래스">Producer 클래스</h2>
<ol>
<li>Subject 인터페이스를 구현한 클래스</li>
<li>고유한 상태 값을 가질 수 있음</li>
<li>전체 상태 값을 변경하는 setData와 같은 매서드를 사용시, notifyObservers()와 같이 옵저버들에게 변화를 알려준다.</li>
<li>상태값 각 필드는 getter 매서드로 구현되어있어, 옵저버들이 풀 방식으로 상태값을 직접 가져올 수 있다.</li>
</ol>
<h2 id="특징">특징</h2>
<ol>
<li>옵저버는 언젵튼 새로 추가 및 제거가 가능하다.</li>
<li>새로운 형식의 옵저버를 추가할 때 주제는 변경이 필요 없다.</li>
<li>주제와 오버저는 서로 독립적으로 재사용이 가능하다.</li>
<li>주제나 옵저버가 달라져도 서로 영향받지 않는다.</li>
</ol>
<h2 id="장점-및-단점">장점 및 단점</h2>
<p>장점</p>
<ol>
<li>주제와 옵저버 모두 인터페이스를 통해 느슨한 결합을 유지한다.</li>
<li>옵저버 패턴에서는 구성을 활용해 관리하므로 확장성이 좋다.</li>
<li>옵저버들은 서로 독립적이기 때문에 특정 옵저버가 문제가 생겨도 다른 옵저버에 영향이 없다.</li>
</ol>
<p>단점</p>
<ol>
<li>옵저버 객체가 많아질수록 모든 옵저버 객체에 대한 처리를 하므로 성능 저하가 일어날 수 있다.</li>
</ol>
<h1 id="startegy-전략-패턴">Startegy (전략 패턴)</h1>
<p>정책 패턴(Policy Pattern)이라고도 불림
알고리즘을 정의하고 캡슐화 하여 각 알고리즘군을 수정해 사용할 수 있게 해준다.
객체의 행위를 변경하고 싶은 경우 <strong>직접 수정하는 것이. 아닌, 전략이라고 불리는 캡슐화한 알고리즘을 변경함으로 유연하게 확장하는 디자인 패턴</strong>이다.</p>
<h2 id="구성">구성</h2>
<ol>
<li>ConcreteStartegy(전략 알고리즘 객체들): 알고리즘 행위, 동작을 객체로 정의한 구혀네</li>
<li>Strategy Interface (전략 인터페이스): 모든 전략 구현체에 대한 공용 인터페이스</li>
<li>Context (컨텍스트): 알고리즘을 실행할 때 마다 해당 알고리즘과 연결된 전략 객체의 매서드를 호출</li>
<li>Client (클라이언트): 특정 전략 객체를 컨텍스트에 전달 함으로써 전략을 등록 및 변경하여 전략 알고리즘을 실행한 결과를 누린다.</li>
</ol>
<h2 id="전략-패턴-사용-시기">전략 패턴 사용 시기</h2>
<ol>
<li>전략 알고리즘의 여러 버젼 또는 변형이 필요할 때 클래스화를 통해 관리</li>
<li>알고리즘 코드가 노출되면 안되는 데이터에 접근하거나 활용하고자 할 때</li>
<li>알고리즘의 동작이 런타임에 실시간으로 교체가 필요할 때</li>
</ol>
<h2 id="장점-및-단점-1">장점 및 단점</h2>
<p>장점</p>
<ol>
<li>알고리즘을 정의하고 캡슐화하여 런타임 시에 알고리즘을 선택하는 데 사용됨</li>
<li>알고리즘을 쉽게 변경 및 대체할 수 있으므로 유연함</li>
<li>알고리즘 추가 및 수정을 할 때 코드 수정이 최소화되므로 확장성이 높아짐</li>
<li>알고리즘을 캡슐화했기에 코드 재사용성이 좋음</li>
<li>각각 알고리즘을 독립적으로 테스트할 수 있으므로 용이함</li>
</ol>
<p>단점</p>
<ol>
<li>추가적인 클래스 및 인터페이스가 필요하기에 <strong>코드 복잡성이 증가</strong>될 수 있음</li>
<li>런타임 시에 알고리즘을 선택하는 데 추가적인 오버헤드 발생 가능</li>
<li>전략패턴을 구현하는 것이 어려울 수 있으므로, 적절한 분석과 설계가 필요하다.</li>
</ol>
<h1 id="composite-pattern-복합체-패턴">Composite Pattern (복합체 패턴)</h1>
<p>객체들의 관계를 트리 구조로 구성해 전체-부분 계층을 표현하는 패턴으로, 사용자가 단일 객체와 복합 객체 모두 동일하게 다루게 하는 것을 컴포짙트 패턴 (복합체 패턴) 이라 한다.</p>
<p>즉 클라이언트가 단일 객체나 복합 객체를 동일하게 취급하는 것을 목적으로 한다.</p>
<h2 id="특징-1">특징</h2>
<ol>
<li><p>일종의 구조 패턴이라고 불리며, 작은 클래스들을 상속과 합성을 이용해 더 큰 클래스를 생성하는 방법을 제공하는 패턴이다.</p>
</li>
<li><p>독립적으로 개발한 클래스 라이브러리를 하나로 사용할 수 있으며, 여러 인터페이스를 합성해 서로 다른 인터페이스들의 통일된 추상을 제공한다.</p>
</li>
<li><p>구조 패턴은 인터페이스나 구현을 복합하는 것이 아닌, 객체를 합성하는 방법을 제공한다. 따라서 <strong>런타임에서 복합 방법이나 대상을 변경할 수 있어 유연성</strong>을 가진다.</p>
</li>
</ol>
<h2 id="구성-1">구성</h2>
<ol>
<li><p>Component
클라이언트가 composition 내의 오브젝트들을 다루기 위한 인터페이스
인터페이스 또는 추상 클래스로 정의되며, 모든 오브젝트들에게 공통되는 매서드를 정의한다.</p>
</li>
<li><p>Leaf Object
컴포넌트를 구현하며, composition 내 오브젝트들의 행동을 정의한다. 이때 다른 컴포넌트에 대해 참조를 가지면 안된다.</p>
</li>
<li><p>Composite Object
Leaf 객체들로 이뤄져 있으며, 컴포넌트 내 명령들을 구현한다.
클라이언트가 composite 객체와 leaf 객체를 동일 취급할 수 있도록 composite object도 컴포넌트를 구현해야 한다.</p>
</li>
</ol>
<p>leaf 그룹에 대한 동작 (add, remove 등..) 을 할 수 있는 매서드들을 클라이언트에 제공한다.</p>
<h2 id="장점-및-단점-2">장점 및 단점</h2>
<p>장점</p>
<ol>
<li><p>유연성
객체의 구조를 변경하는데 유용하다. 새로운 개별 객체나 복합 객체를 추가하더라도 클라이언트가 코드를 수정할 필요가 없으며, 객체 간 결합도를 낮춰 유연성을 높인다</p>
</li>
<li><p>단순성
개별 객체와 복합 객체를 동일한 방식으로 다룰 수 있어 클라이언트의 코드가 단순해진다.</p>
</li>
<li><p>재사용성
객체를 구성하는 방식이 일관성 있고, 재사용성이 높은 구조를 만들 수 있다.</p>
</li>
<li><p>구조적 안정성
복합 객체 내부의 구조를 안정적으로 유지할 수 있다. 복합 객체에서 개별 객체를 제거하더라도 객체 간의 관계가 깨지지 않는다.</p>
</li>
</ol>
<p>단점</p>
<ol>
<li><p>처리 비용
복합 객체 내부의 모든 개별 객체를 처리해야 하기 때문에 처리 비용이 증가할 수 있다.</p>
</li>
<li><p>설계 복잡성
객체의 구조가 복잡한 경우에는 효과적이지만, 반대로 객체의 구조가 단순한 경우에는 오히려 설계의 복잡성을 증가시킬 수 있다.</p>
</li>
<li><p>특정 상황에서의 한계
개별 객체와 복합 객체가 서로 다른 인터페이스를 가지는 경우나, 복합 객체 내부 구조가 동적으로 변하는 경우에는 컴포지트 패턴을 사용하기 힘들다.</p>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[CS Study - Singleton Pattern (싱글톤 패턴]]></title>
            <link>https://velog.io/@dk_ovo/CS-Study-Singleton-Pattern-%EC%8B%B1%EA%B8%80%ED%86%A4-%ED%8C%A8%ED%84%B4</link>
            <guid>https://velog.io/@dk_ovo/CS-Study-Singleton-Pattern-%EC%8B%B1%EA%B8%80%ED%86%A4-%ED%8C%A8%ED%84%B4</guid>
            <pubDate>Fri, 05 Jul 2024 06:43:11 GMT</pubDate>
            <description><![CDATA[<h1 id="싱글톤-패턴singleton-pattern-이란">싱글톤 패턴(Singleton Pattern) 이란?</h1>
<p>단 하나의 유일한 객체를 만들어서 사용하는 패턴이며 새로운 인스턴스를 만들지 않기 때문에 메모리 절약적인 측면에서 강점이 있다.싱글톤 패턴을 적용하는 경우로는 <strong>객체가 리소스를 많이 차지하는 무거운 역할을 가진 클래스일 때 주로 이용</strong>한다.</p>
<p>생성자를 private 하게 만들어 클래스 외부에서 클래스의 인스턴스를 생성하지 못하게 차단하고, 내부적으로는 단 한개의 인스턴스에 대한 접근을 제공한다.</p>
<p><strong>싱글톤 패턴 사용 목적</strong></p>
<p>커넥션 풀, 스레드 풀, 디바이스 설정 객체 등과 같은 경우 인스턴스를 여러 개 만들게 되면 불필요한 자원을 사용하게 되고, 프로그램이 예상치 못한 결과를 낳을 수 있다. 따라서 객체를 필요할 때마다 생성하는 것이 아닌 <strong>단 한 번만 생성하여 전역에서 이를 공유하고 사용</strong>할 수 있게 하기 위해 싱글톤 패턴을 사용한다.</p>
<h2 id="싱글톤-패턴-장--단점">싱글톤 패턴 장 &amp; 단점</h2>
<h4 id="장점">장점</h4>
<ol>
<li><p>유일한 인스턴스: 싱글톤 패턴이 적용된 인스턴스는 애플리케이션 전역에 단 하나만 존재한도록 보장하고, 이는 객체이 일관된 상태의 유지 및 전역에서의 접근을 가능하게 한다.</p>
</li>
<li><p>메모리 절약: 인스턴스가 하나 뿐이므로 메모리 절약이 된다. 생성자를 여러번 호출해도 새로운 인스턴스를 생성하지 않으므로 메모리 점유 및 해제에 대한 오버헤드를 줄인다.</p>
</li>
<li><p>지연 초기화: 인스턴스가 실제로 사용되는 시점에 생성해 초기 비용을 줄인다.</p>
</li>
</ol>
<h4 id="단점">단점</h4>
<ol>
<li><p>결합도 증가: 전역에서 접근을 허용하기 때문에 해당 인스턴스에 의존하는 경우 결합도가 증가한다.</p>
</li>
<li><p>테스트 복잡성: 단 하나의 인스턴스만을 생성하고 자원을 공유하므로 클래스 결합도가 높아질 경우 테스트가 어려워질 수 있다. </p>
</li>
<li><p>상태 관리의 어려움: 싱글톤 클래스가 상태를 갖고 있는 경우 전역에 사용되어 변경될 수 있으며, 이는 예기치 못한 일을 발생시킬 수 있다.</p>
</li>
<li><p>전역에서 접근: 애플리케이션 내 어디서든 접근이 가능할 경우, 무분별한 사용을 막기 힘들며 이로 인에 변경에 대한 복잡성이 증가한다.</p>
</li>
</ol>
<p> </p>
<h2 id="싱글톤-구현-방법">싱글톤 구현 방법</h2>
<p>싱글톤의 패턴 구현은 다양하게 존재한다. 그 중 공통되는 특징들은 다음과 같다.</p>
<ol>
<li>private 생성자만을 정의하여 외부 클래스로부터 인스턴스 생성을 차단한다.</li>
<li>싱글톤을 구현하고자 하는 클래스 내부에 멤버 변수로 private static 객체 변수를 만든다.</li>
<li>public static 매서드를 통해 외부에서 싱글톤 인스턴스에 접근하도록 접점을 제공한다.</li>
</ol>
<h2 id="대표적인-싱글톤-구현-6가지">대표적인 싱글톤 구현 6가지</h2>
<ol>
<li><p>Eager Initialization</p>
</li>
<li><p>Static Block Initialization</p>
</li>
<li><p>Lazy Initialization</p>
</li>
<li><p>Thread Safe singleton</p>
</li>
</ol>
<p><strong>5. Bill Pugh Singleton Implementation (정적 내부 클래스)</strong></p>
<p><strong>6. Enum Singleton</strong></p>
<h3 id="eager-initialization">Eager Initialization</h3>
<p>가장 간단한 구현 방법, 싱글톤 클래스의 인스턴스를 로딩 단계에서 생성한다. 단점으로는 해당 어플리케이션에서 해당 인스턴스를 사용하지 않아도 생성하기 때문에 메모리 낭비가 발생한다.</p>
<p>해당 방법은 클래스가 다소 적은 리소스를 다룰때 적합하다. File System, DB connectio등 큰 리소스는 해당 방법보다 getInstance() 매서드가 호출되기 전까지 인스턴스를 생성하지 않는게 좋다. 또한 Exception Handling도 제공하지 않는다.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/4d04e2fa-81ba-4965-b536-0857183a9a81/image.png" alt=""></p>
<h3 id="static-block-initialization">Static block initialization</h3>
<p>Eager Initialization과 유사하지만 static {} 을 통해서 Exception Handling이 가능하다.
인스턴스 생성 과정에 발생하는 예외 처리는 가능해졌지만, 여전히 클래스 로딩 단계에서 인스턴스를 생성하고 있어서 단점이 있다.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/a3423302-d1e7-4a6e-8e0f-6f790cbe500c/image.png" alt=""></p>
<h3 id="lazy-initialization">Lazy Initialization</h3>
<p>앞선 두개의 방법과 달리 호출될 때 초기화를 하는 방법이다. global access인 getInstance() 매서드를 호출할 때 인스턴스가 생성되지 않았다면 생성한다.</p>
<p>사용하지 않음으로 인한 인스턴스 낭비는 해결했으나, 아직 <strong>Multi-Thread 환경에서 동기화 문제</strong>를 해결하진 못했다. 만약 인스턴스가 생성되지 않았음에도, 여러 쓰레드가 동시의 getInstance()를 호출하면 하나가 아닌, 여러개의 인스턴스가 생성되어 싱글톤 패턴의 의미가 없어지는 경우가 생길 수 있다. 따라서 이 방법은 Single-Thread 환경이 보장됐을 때 쓰기 적합하다.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/404430bd-af9d-46e0-9e40-729cc7aaee46/image.png" alt=""></p>
<h3 id="thread-safe-singleton">Thread Safe Singleton</h3>
<p>Lazy Initialization 문제를 해결하기 위한 방법으로, getInstance() 매서드에 synchronized를 걸어두는 방식이다. synchronized 키워드는 임계 영역(Critical Section)을 형성하여 해당 영역에 <strong>오직 하나의 쓰레드만 접근 가능</strong>하게 해 줍니다.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/906375b0-b4b3-427c-b966-8a192a6d7711/image.png" alt=""></p>
<p>위의 방식은 getInstance() 메서드 내에 진입하는 쓰레드가 한개로 보장받기 때문에 멀티쓰레드 환경일지라도 정상적으로 동작한다. 하지만 synchronized 키워드 자체에 대한 리소스가 크기 때문에 <strong>호출이 잦은 어플리케이션에서는 성능이 저하</strong>되는 단점이 있다.</p>
<p>이를 또다시 보완하기 위해 duble checked locking 방법이 있다. getInstance() 메서드 수준에 lock을 걸지 않고 instance가 null일 경우만 synchronized가 동작하게 한다.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/bf2d3ccc-7e8e-4e6f-b80b-b4d37193c5b7/image.png" alt=""></p>
<h3 id="bill-pugh-singleton-implementation-정적-내부-클래스">Bill Pugh Singleton Implementation (정적 내부 클래스)</h3>
<p>Bill Pugh가 고안한 방식으로, inner static helper class(정적 내부 클래스) 방식을 사용하는 것이다. 앞선 방식들이 안고 있는 문제점들을 대부분 해결한 방식이며, <strong>현재 가장 널리 쓰이는 싱글톤 구현 방법</strong> 이다.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/21252e1e-94c4-49a8-9113-6ca9042e1883/image.png" alt=""></p>
<p>private inner static class를 둬서 싱글톤 인스턴스를 갖고 있게 한다.
SingletonHelper 클래스는 1번 방식과 2번 방식과 달리 클래스가 Load 될 때에도 Load되지 않고 있다가 getInstance()가 호출됐을 때 비로소 JVM 메모리에 로드되며, 인스턴스를 생성한다.
또한 synchronized를 사용하지 않기 때문에 4번의 문제였던 성능 저하 또한 해결했다.</p>
<p>초기화 지연 측면: singletonHelper 클래스가 로드될 때 JVM은 이 클래스의 정적 초기화 과정에서 단 한 번 INSTANCE를 초기화 한다. 이 과정에서 스레드는 안전하다.</p>
<p>스레드 안전성 측면: 클래스 로딩 과정에서 JVM은 클래스 초기화가 스레드 안전하게 이뤄지도록 보장하기 때문에 별도의 동기화 처리가 필요없다.</p>
<p>결론적으로 지연 초기화(Lazy Initialization)과 스레드 안전성을 자연스럽게 보장하면서 코드가 간결해졌다. 또한 메모리 소비적 측면에서 실제 인스턴스가 필요할때 까지 생성하지 않기 때문에 메모리 효율성도 갖췄다.</p>
<h3 id="enum-singleton">Enum Singleton</h3>
<p>Enum은 싱글톤을 구현하는 가장 간단하면서도 안전한 방법이다. 이는 직렬화와 리플렉션을 통한 공격에서도 안전함을 가져온다. Java의 거장이라 불리는 Joshua Bloch는 Enum으로 싱글톤을 구현하는 방법을 제안했다.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/1a54a537-89ea-4861-8988-c4a5d3c1f68b/image.png" alt=""></p>
<p>단점은 1,2 번과 마찬가지로 사용하지 않았을 경우 메모리 문제를 해결하지 못한 것과 유연성이 떨어지는 점을 가지고 있다.</p>
<h3 id="결론">결론</h3>
<p>모든 Singleton 구현 방법은 각기의 장 &amp; 단점을 가지고 있다. 가장 쉽고 간단하게 singleton 을 구현하자 한다면 Enum방법이겠지만, 완성도 높고 단점이 적은 구현을 하고자 한다면 정적 내부 클래스 방법을 사용하면 좋겠다는 생각이다. 상황에 맞춰서 어떤 방식이 효율적이면서 좋을지 고민해보면 좋을 것 같다.</p>
<h3 id="향후-계획">향후 계획</h3>
<p>공부를 하면서 간단한 예시 코드를 작성했지만 실전에 적용한 것과는 많이 다르다는 생각이다. 언젠간?!? 실전 코드로 적용해서 구현하는 과정과 특히 Thread Safe 하지 않는 과정을 직접 테스트 해보면서 볼 계획이다. 당장은 해야할 급한 것들이 많다..</p>
<p>-참조-
<a href="https://readystory.tistory.com/116">https://readystory.tistory.com/116</a>
<a href="https://ittrue.tistory.com/563">https://ittrue.tistory.com/563</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CS Study - Template Method Pattern (템플릿 매서드 패턴) & Factory Method Pattern (팩토리 매서드 패턴)]]></title>
            <link>https://velog.io/@dk_ovo/CS-Study-Template-Method-Pattern-%ED%85%9C%ED%94%8C%EB%A6%BF-%EB%A7%A4%EC%84%9C%EB%93%9C-%ED%8C%A8%ED%84%B4-Factory-Method-Pattern-%ED%8C%A9%ED%86%A0%EB%A6%AC-%EB%A7%A4%EC%84%9C%EB%93%9C-%ED%8C%A8%ED%84%B4</link>
            <guid>https://velog.io/@dk_ovo/CS-Study-Template-Method-Pattern-%ED%85%9C%ED%94%8C%EB%A6%BF-%EB%A7%A4%EC%84%9C%EB%93%9C-%ED%8C%A8%ED%84%B4-Factory-Method-Pattern-%ED%8C%A9%ED%86%A0%EB%A6%AC-%EB%A7%A4%EC%84%9C%EB%93%9C-%ED%8C%A8%ED%84%B4</guid>
            <pubDate>Wed, 19 Jun 2024 00:36:50 GMT</pubDate>
            <description><![CDATA[<h1 id="템플릿-매서드-패턴">템플릿 매서드 패턴</h1>
<p>특정 작업을 처리하는 일부분을 서브 클래스로 캡슐화하여 <strong>전체적인 구조는 바꾸지 않으면서 특정 단계에 수행하는 내용을 바꾸는 패턴</strong>이다.</p>
<p>예를들어 HTTP와 SMTP Client 프로그램의 경우, 주고받는 메세지의 내용이 다르지만 둘 다 인터넷 프로토콜을 이용해 서버에 요청을 전달하고 결과를 수신하는 점에서 동일하다.</p>
<p>이와 같이 <strong>두개 이상의 프로그램이 같은 골격 하에 동작한다고 가정</strong>할 때 기본 골격에 해당하는 알고리즘은 일괄적으로 처리하면서 각 프로그램에 다른 부분은 따로 만들고 싶을때 템플릿 매서드 패턴을 사용한다.</p>
<p>※ 디자인 패턴에서의 템플릿: <strong>변하지 않는 것</strong>을 의미한다.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/c2222330-0551-4f01-9ad1-ecb76ae49143/image.png" alt=""></p>
<p>알고리즘의 구조를 매서드에 정의하고, 하위 클래스에서 알고리즘 구조의 변경없이 알고리즘을 재정의한다. 변하지 않는 기능은 슈퍼클래스 (상위 클래스)에 만들어 두고 자주 변경하며 확장할 기능은 서브 클래스에서 만들도록 한다.</p>
<h2 id="템플릿-매서드의-패턴-구조">템플릿 매서드의 패턴 구조</h2>
<h3 id="추상-클래스-구현-부분">추상 클래스 구현 부분</h3>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/70684abc-4495-424d-a597-50d9e8b32520/image.png" alt=""></p>
<h3 id="구현-클래스-구현-부분">구현 클래스 구현 부분</h3>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/f3d6fef3-3a3b-405a-aafd-0d2e2025ab5e/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/d410ee99-36d6-412f-8001-5fffb8be7ed4/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/16be7716-f13c-438d-bfd9-5a7e26f317ac/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/3b2ba57f-b03b-4c0a-953a-a66de294d998/image.png" alt=""></p>
<h3 id="hook-매서드-적용과-최종-클라이언트-값">hook 매서드 적용과 최종 클라이언트 값</h3>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/a98b8b80-4a03-4579-9c3c-d32c544b3ebc/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/de02241b-3796-4d41-b826-7b81099ead4e/image.png" alt=""></p>
<h3 id="1-abstractclass추상-클래스">1. AbstractClass(추상 클래스)</h3>
<p>템플릿 매서드를 구현하고, 템플릿 매서드에 돌아가는 추상 메서드를 선언한다. 이 추상 메서드는 하위 클래스 (구현된 클래스)인 ConcreteClass 역할에 의해 구현된다.</p>
<h3 id="2-concreteclass구현-클래스">2. ConcreteClass(구현 클래스)</h3>
<p>AbstractClass를 상속하고 추상 매서드를 구체적으로 구현한다. 이곳 ConcreteClass에서 구현한 메서드가 AbstractClass의 템플릿 메서드에서 호출된다.</p>
<h3 id="3-hook-method훅-메서드">3. Hook method(훅 메서드)</h3>
<p>hook 메서드는 <strong>부모 템플릿 매서드의 영향이나 순서를 제어</strong>하려고 할 때 사용되는 매서드의 형태이다. 이를 통해 자식 클래스에서 더 유연하게 템플릿 매서드의 알고리즘 로직을 다양화 할 수 있다.</p>
<p>훅 매서드는 추상 매서드가 아닌, <strong>일반 메서드로 구현</strong>한다. 이는 선택적으로 자식 클래스에서 오버라이드 해서 제어하거나 혹은 그냥 놔두기 위해서이다.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/23bb8f09-dd48-4d35-96e1-7754263319e9/image.png" alt=""></p>
<h2 id="탬플릿-매서드-패턴-장단점">탬플릿 매서드 패턴 장&amp;단점</h2>
<h3 id="장점">장점</h3>
<ol>
<li>상위 추상클래스로 로직을 공통화 하여코드의 중복을 줄일 수 있다.</li>
<li>자식 클래스의 역할을 줄여 핵심 로직 관리가 용이하다.</li>
<li>객체지향적인 프로그래밍을 가능하게 해준다.</li>
<li>클라이언트가 대규모 알고리즘의 특정 부분만 재정의하도록 하여, 알고리즘의 다른 부분에 발생하는 변경 사항의 영향을 덜 받도록 한다.</li>
<li>서브 클래스의 역할을 줄이고, 핵심 로직을 상위 클래스에서 관리하므로서 관리가 용이해진다.</li>
</ol>
<h3 id="단점">단점</h3>
<ol>
<li>추상 매서드가 많아지면 클래스 관리가 복잡해진다.</li>
<li>클래스간 관계와 코드가 꼬일 우려가 있다.</li>
<li>알고리즘의 제공된 골격에 의해 유연성이 제한될 수 있다.</li>
<li>알고리즘 구조가 복잡해질 수록 템플릿 로직 형태를 유지하기가 어렵다.</li>
<li>상위 클래스에서 선언된 추상 메서드를 하위 클래스에서 구현할 때, 어느 타이밍에 호출되는지 클래스 로직을 이해해야 한다.</li>
<li>상위 클래스의 로직을 수정해야 하는 상황이 생기면, <strong>모든 서브 클래스의 수정이 필요할 수 있다.</strong></li>
<li>하위 클래스를 통해 기본 단계 구현을 억제해 리스코프 치환 원칙을 위반할 여지가 있다.</li>
</ol>
<h2 id="탬플릿-매서드-패턴-사용-예시-직접-구현">탬플릿 매서드 패턴 사용 예시 (직접 구현)</h2>
<p>출처</p>
<ol>
<li><a href="https://coding-factory.tistory.com/712">https://coding-factory.tistory.com/712</a></li>
<li><a href="https://inpa.tistory.com/entry/GOF-%F0%9F%92%A0-%ED%85%9C%ED%94%8C%EB%A6%BF-%EB%A9%94%EC%86%8C%EB%93%9CTemplate-Method-%ED%8C%A8%ED%84%B4-%EC%A0%9C%EB%8C%80%EB%A1%9C-%EB%B0%B0%EC%9B%8C%EB%B3%B4%EC%9E%90">https://inpa.tistory.com/entry/GOF-%F0%9F%92%A0-%ED%85%9C%ED%94%8C%EB%A6%BF-%EB%A9%94%EC%86%8C%EB%93%9CTemplate-Method-%ED%8C%A8%ED%84%B4-%EC%A0%9C%EB%8C%80%EB%A1%9C-%EB%B0%B0%EC%9B%8C%EB%B3%B4%EC%9E%90</a></li>
<li><a href="https://velog.io/@letskuku/%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4-%ED%85%9C%ED%94%8C%EB%A6%BF-%EB%A9%94%EC%84%9C%EB%93%9C-%ED%8C%A8%ED%84%B4Template-Method-Pattern">https://velog.io/@letskuku/%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4-%ED%85%9C%ED%94%8C%EB%A6%BF-%EB%A9%94%EC%84%9C%EB%93%9C-%ED%8C%A8%ED%84%B4Template-Method-Pattern</a></li>
<li><a href="https://engineering.linecorp.com/ko/blog/templete-method-pattern">https://engineering.linecorp.com/ko/blog/templete-method-pattern</a></li>
</ol>
<h1 id="팩토리-매서드-패턴-factory-method-pattern">팩토리 매서드 패턴 (Factory Method Pattern)</h1>
<p>팩토리 매서드 패턴은 <strong>객체를 생성하는 클래스를 따로 두는 것</strong> 이다. <strong>실질적인 클래스의 구현은 하위 클래스에서 완성</strong>되며 이 경우 상위 클래스는 하위 클래스의 구현 내용을 모르더라도 사용이 가능하다.</p>
<p>다시말해 다양한 구현체(Product)가 있고, 그 중 특정한 구현체를 만드는 다양한 팩토리 (Creator)를 제공할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/ca25ee83-364d-41a3-890d-0dc95d86e4c7/image.png" alt=""></p>
<h2 id="팩토리-메서드-사용-목적">팩토리 메서드 사용 목적</h2>
<ol>
<li>생성할 객체의 타입을 예측하기 어려울 때</li>
<li>생성할 객체를 기술하는 책임을 서브클래스에 정의하고자 할 때</li>
<li>객체 생성의 책임을 서브클래스에 위임하고 서브클래스의 정보를 은닉하고자 할 때</li>
</ol>
<p>팩토리 매서드의 사용 목적은 <strong>클래스 간의 결합도(Coupling)를 낮추기 위해서다.</strong> 결합도라는 것은 <strong>클래스의 변경할 부분이 생겼을 때 얼마나 다른 클래스에 영향을 주는 것인가</strong> 를 생각하면 된다. 팩토리 매서드를 통해 직접 객체를 생성후 사용하는 것을 서브 클래스에 위임함으로써 의존성을 제거하며 결합도 또한 낮출 수 있게 된다.</p>
<p>※ 결합도(Coupling)는 낮을 수록 좋고, 응집도(Cohesion)는 높을수록 좋다.</p>
<h2 id="팩토리-매서드-핵심-개념">팩토리 매서드 핵심 개념</h2>
<ol>
<li>Product: 제품의 인터페이스를 정의</li>
<li>Concrete Product: Product 인터페이스를 구현한 구체적인 클래스</li>
<li>Creator: 제품을 생성하는 팩토리 메서드를 선언하는 추상 클래스 또는 인터페이스</li>
<li>Concrete Creator: Creator 클래스를 상속하여 실제 제품을 생성하는 구체적인 클래스</li>
</ol>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/5343c099-0470-4162-8fab-c91d2bfab206/image.png" alt=""></p>
<p>정리
Product 인터페이스: Icecream
Concrete Product 클래스: Babbambar, Pigbar
Creator 추상 클래스: IcecreamFactory
Concrete Creator 클래스: BabbambarFactory, PigbarFactory</p>
<h2 id="팩토리-매서드-장--단점">팩토리 매서드 장 &amp; 단점</h2>
<h3 id="장점-1">장점</h3>
<ol>
<li>기존 코드를 수정하지 않고 새로운 인스턴스를 다른 방법으로 생성하도록 확장이 가능하다.</li>
<li>SOLID 원칙중 개방 폐쇄 원칙을 지키는 방법이다.(확장: 새로운 인스턴스 추가, 변경: 기존 코드를 수정)</li>
<li>재사용성이 높아져 코드가 간결해진다.</li>
</ol>
<h3 id="단점-1">단점</h3>
<ol>
<li>클래스가 많아진다. (클래스의 계층이 커질 수 있다.)</li>
<li>제품 클래스가 바뀔 때마다 새로운 서브 클래스를 생성해야 한다.</li>
<li>클라이언트가 creator 클래스를 반드시 상속하여 Product를 생성해야 한다.</li>
</ol>
<h2 id="실제-코드-구현-예제">실제 코드 구현 예제</h2>
<p>아이스크림 공장이 있고 아이스크림을 만들어 낸다고 가정하여 팩토리 매서드를 구현하였다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/ef35069c-9046-4859-ade2-167ac67bb5fa/image.png" alt=""></p>
<p>아이스크림 제품에 대한 인터페이스를 만들어주고 여기서 나오는 아이스크림(바밤바 &amp; 돼지바) 그리고 향후 만들어질 아이스크림들은 이 인터페이스를 구현해야 한다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/6a67be5d-1bfb-4002-9238-6f9394d4ed48/image.png" alt="">
Icecream 인터페이스를 구현한 Babbambar 클래스와
<img src="https://velog.velcdn.com/images/dk_ovo/post/b40ad68c-9dbf-4a63-8f0d-d2cff932d21c/image.png" alt="">
마찬가지로 Icecream 인터페이스를 구현한 Pigbar 클래스를 만들어 준다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/20d0ce54-55d5-47e9-8e1e-aa9e4b08355f/image.png" alt=""></p>
<p>이제 추상 클래스인 IcecreamFactory 클래스를 상속받은 팩토리 클래스들을 구현해준다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/882f7e42-41b0-46a4-99f7-3cdf989fec8a/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/f5b31f38-b357-4f81-9887-f51ed40a61c7/image.png" alt=""></p>
<p>마지막 클라이언트 코드
<img src="https://velog.velcdn.com/images/dk_ovo/post/734f04cb-9aeb-4d90-9144-dc263f6cd6e5/image.png" alt=""></p>
<p><strong>[다이어그램]</strong>!<img src="https://velog.velcdn.com/images/dk_ovo/post/f1ec2528-748d-403e-96ae-1ed70a0f0a52/image.png" alt=""></p>
<p>여기서 만약에 끌레도르 아이스크림이 추가된다 한다면 <strong>Icecream 인터페이스를 구현한 Cledore.java</strong>와 <strong>IcecreamFactory 추상클래스를 상속받은 CledoreFactory.java</strong>를 구현한 후 클라이언트단에 똑같이 구현해주면 된다.
<img src="blob:https://velog.io/41a02c7a-0f38-469f-bd69-a1970d0e2ed0" alt="업로드중.."></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CS Study - Adapter Pattern(어댑터 패턴)
]]></title>
            <link>https://velog.io/@dk_ovo/CS-Study-Adapter-Pattern%EC%96%B4%EB%8C%91%ED%84%B0-%ED%8C%A8%ED%84%B4</link>
            <guid>https://velog.io/@dk_ovo/CS-Study-Adapter-Pattern%EC%96%B4%EB%8C%91%ED%84%B0-%ED%8C%A8%ED%84%B4</guid>
            <pubDate>Sun, 09 Jun 2024 01:07:33 GMT</pubDate>
            <description><![CDATA[<h1 id="어댑터-패턴adapter-pattern">어댑터 패턴(Adapter Pattern)</h1>
<p>호환되지 않는 인터페이스를 가진 객체들이 호환될 수 있도록 하는 구조적 디자인 패턴이다.
레거시 코드들을 재사용 할 수 있게 해준다.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/dd3b936c-5c2a-4348-b050-6750a0322579/image.png" alt=""></p>
<h2 id="어탭터-패턴들의-요소">어탭터 패턴들의 요소</h2>
<p>Target: 변화에 대한 요구사항
Adaptee: 기존 코드
Adapter: 변화에 대한 요구사항을 반영해 구현한 새로운 코드
Operation: Adaptee가 가지고 있는 기능을 Adapter가 주입받아서 구현한 것
Client: 인터페이스인 Target을 통해 사용할 수 있게 된다.</p>
<h2 id="어댑터-패턴-사용-예시">어댑터 패턴 사용 예시</h2>
<p>지메일과 네이버 메일을 통합으로 사용할 수 있게 해주는 코드 예시</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/9cc169f6-cbab-40e8-a029-26ee31f2f00d/image.png" alt=""></p>
<p>이메일 어댑터 Interface 구현
<img src="https://velog.velcdn.com/images/dk_ovo/post/1b0cb347-639b-4d14-aed4-d06b9b8d88f9/image.png" alt=""></p>
<p>SendingService로 지메일과 네이버 메일 공통 서비스 인터페이스 구현</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/dd17f000-9c77-40cf-a78c-78e12e239375/image.png" alt=""></p>
<p>최종 클라이언트
<img src="https://velog.velcdn.com/images/dk_ovo/post/8066e02c-711e-446c-aec2-452435775dc3/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CS 스터디 - 스트림(Stream)
]]></title>
            <link>https://velog.io/@dk_ovo/CS-%EC%8A%A4%ED%84%B0%EB%94%94-%EC%8A%A4%ED%8A%B8%EB%A6%BCStram</link>
            <guid>https://velog.io/@dk_ovo/CS-%EC%8A%A4%ED%84%B0%EB%94%94-%EC%8A%A4%ED%8A%B8%EB%A6%BCStram</guid>
            <pubDate>Sat, 25 May 2024 16:44:34 GMT</pubDate>
            <description><![CDATA[<h1 id="스트림stream이란">스트림(Stream)이란?</h1>
<p>스트림은 Java8 버젼에 추가 됐으며 람다(Lambda)를 활용할 수 있는 기술 중 하나이다. Java 8 이전에는 배열 또는 컬렉션의 인스터스를 다루는 방법은 for또는 foreach문을 통해 요소를 하나씩 꺼내는 방법이였다. 이는 복잡해질수록 코드 양이 많아져 로직이 섞이게 되거나 메서드를 나눌경우 루프를 여러번 도는 문제가 발생했다.</p>
<h2 id="스트림의-특징">스트림의 특징</h2>
<ol>
<li>데이터 소스를 변경하지 않는다</li>
</ol>
<ul>
<li>데이터 소스로부터 데이터를 읽기만 할 뿐, 소스를 변경하지 않는다.</li>
<li>필요할 경우 정렬된 결과를 컬렉션이나 배열에 담아서 변환이 가능하다.</li>
</ul>
<ol start="2">
<li>스트림은 일화용이다.</li>
</ol>
<ul>
<li>Iterator처럼 일회용이다. Iterator로 컬렉션을 요소를 모두 읽고 나면 사용할 수 없는 것 처럼, 스트림도 재사용이 불가능하여 다시 사용하고자 하면 다시 생성해야 한다.</li>
</ul>
<ol start="3">
<li>작업을 내부 반복으로 처리한다.</li>
</ol>
<ul>
<li>내부 반복은 반복문을 매서드 내부에 숨길 수 있는 것을 의미한다.</li>
<li>forEach()는 스트림에 정의된 메서드 중 하나로 매개변수에 대입된 람다식 데이터 소스의 모든 요소에 적용한다.<pre><code class="language-java">for (String str : strList) {
  System.out.println(str)
}
</code></pre>
</li>
</ul>
<p>stream.forEach(System.out::println);</p>
<pre><code>위의 두 코드는 같은 내용이다. 즉, forEach()는 매서드 안으로 for 문을 넣은 것과 같다.

## 스트림의 연산과 매서드
스트림이 제공하는 다양한 연산을 이용해 복잡한 작업을 간단한 처리가 가능하다. 연산은 크게 두가지로 **&quot;중간 연산&quot;** 과 **&quot;최종 연산&quot;** 으로 분류할 수 있다.

**※ 최종 연산: 연산 결과가 스트림이 아닌 연산. 스트림의 요소를 소모하므로 단 한번만 가능하다.**

### 중간 연산 매서드
![](https://velog.velcdn.com/images/dk_ovo/post/5ebb90d6-2fbb-4b31-8992-0628276d4f3c/image.png)


### 최종 연산 매서드
![](https://velog.velcdn.com/images/dk_ovo/post/f649daf6-9f53-4dfb-b11c-792d54d7891c/image.png)


## 스트림의 장점
스트림은 &#39;데이터의 흐름&#39;이다. **배열 또는 컬렉션 인스턴스에 함수 여러개를 조합해 원하는 결과를 필터링하고 가공된 결과를 얻을 수 있다.** 또한 람다를 이용해 코드의 양을 줄이고 간결한 표현이 가능하다. 배열과 컬렉션을 함수형으로 처리가 가능한 것이다.

다른 장점으론 간단한 병렬처리(multi-threading)이 가능한 점이다. 하나의 작업을 둘 이상으로 작업으로 나눠 동시에 진행하여 많은 요소들을 빠르게 처리가 가능하다.

## 스트림 만들기
Collection에 stream()이 정의 되어 있다. 그렇기에 Collection의 자손인 List와 Set을 구현한 컬렉션 클래스는 모두 ```java Stream&lt;T&gt; Collection.stream) ``` 으로 스트림을 생성할 수 있다.

### List를 스트림으로 생성하기
``` java
List&lt;Integer&gt; list  = Arrays.asList(1,2,3,4,5);
Stream&lt;Integer&gt; intStream = list.stream();

intStream.forEach(system.out::println); // 스트림의 모든 요소 출력</code></pre><h3 id="배열을-스트림">배열을 스트림</h3>
<pre><code class="language-java">/* Stream과 Arrays에 정의된 static 매서드 */
Stream&lt;T&gt; Stream.of(T values)
Stream&lt;T&gt; Stream.of(T[])
Stream&lt;T&gt; Arrays.stream(T[])
Stream&lt;T&gt; Arrays.stream(T[] array, int sstratInclusive, it end Exclusive)

/* 문자열 Stream 생성 */
Stream&lt;String&gt; strStream = Stream.of(&quot;a&quot;, &quot;b&quot;, &quot;c&quot;);
Stream&lt;String&gt; strStream = Stream.of(new String[] {&quot;a&quot;, &quot;b&quot;, &quot;C&quot;});
Stream&lt;String&gt; strStream = Arrays.stream(new String[]{&quot;a&quot;, &quot;b&quot;, &quot;c&quot;});
Stream&lt;String&gt; strStream = Arrays.stream(new String[]{&quot;a&quot;, &quot;b&quot;, &quot;c&quot;}, 0, 3);


/* int, long, double 과 같은 기본형 배열 스트림 생성 매서드 */
IntStream IntStream.of(int... values)
IntStream IntStream.of(int[])
IntStream Arrays.stream(int[])
IntStream Arrays.stream(int[] array, int stractInclusive, int endExclusive)</code></pre>
<h3 id="특정-범위의-정수">특정 범위의 정수</h3>
<p>IntStream과 LongStream은 <strong>지정된 범위의 연속된 정수를 스트림으로 생성해서 변환</strong>할 수 있다.</p>
<pre><code class="language-java">IntStream    IntStream.rangeClosed(int being, int end)

/* range는 end를 포함하지 않고, rangeClosed는 **end를 포함하여 반환** */
IntStream intStream = IntStream.range(1, 5); // 1,2,3,4
IntStream intStream = IntStream.rangeClosed(1, 5) // 1,2,3,4,5</code></pre>
<h3 id="임의의-수">임의의 수</h3>
<p>아래는 난수로 만들어진 스트림들을 반환하며 다음과 같은 범위를 갖는다.</p>
<pre><code class="language-java">IntStream ints () // Integer.MIN_VALUE &lt;= ints() &lt;= Integer.MAX_VALUE
LongStream longs() // Long.MIN_VALUE &lt;= longs() &lt;= Long.MAX_VALUE
DoubleStream doubles() // 0.0 &lt;= doubles() &lt; 1.0</code></pre>
<p>위의 매서드들은 크기가 정해지지 않은 &quot;무한 스트림&quot; 이기에 limit()로 스트림의 크기에 제한을 해줘야 한다. 결론은 limit()은 스트림 개수를 지정하는데 사용되며, 무한 스트림을 유한스트림으로 만들어준다.</p>
<h3 id="람다식-iteeratorgenerater">람다식 iteerator(),generater()</h3>
<p>Stream 클래스의 iterator(), generater()는 람다식을 매개변수로 받아서 <strong>람다식에 의해 계산되는 값들을 요소로 하는 무한 스트림을 생성</strong></p>
<pre><code class="language-java">static &lt;T&gt; Stream &lt;T&gt; iterate(T seed, UnaryOperator&lt;T&gt; f)
static &lt;T&gt; Stream &lt;T&gt; generate(Supplier&lt;T&gt; s)</code></pre>
<p>iterate()는 seed로 지정된 값부터 시작해, 람다식 f에 의해 계산된 결과를 다시 seed값으로 해서 계산을 반복한다.</p>
<pre><code class="language-java">// 0,3,6,9
Stream&lt;Integer&gt; evenStream = Stream.iterate(0, n-&gt;n+3)</code></pre>
<p>generater()는 iterate()처럼 람다식에 의해 계산되는 값을 요소로 무한스트림을 생성 반환하지만, iterate()와 다른 점은, <strong>이전 결과를 이용해 다음 요소를 계산하지 않는다</strong>.</p>
<p><strong>iterator()와 generater()모두 IntStream, DoubleStream과 같은 기본형 스트림 타입의 참조변수를 다룰 수 없다.</strong> 만약 다루고자 하면 mapToInt()와 같은 매서드로 변환을 해야 한다.</p>
<pre><code class="language-java">IntStream = evenStream = Stream.iterate(0, n-&gt; n+3).mapToInt(Integer::valueOf)l</code></pre>
<h3 id="빈-스트림">빈 스트림</h3>
<p>요소가 없는 빈 스트림을 생성할 수 있다. <strong>스트림에서 연산을 수행한 결과가 하나도 없으면, null보다 빈 스트림을 리턴해주는게 낫다.</strong></p>
<pre><code class="language-java">Stream emptyStream = Stream.empty(); // 빈 스트림 생성
long count = emptyStream.count();</code></pre>
<h3 id="두-스트림-연결">두 스트림 연결</h3>
<p>concat() 매서드를 통해 두 스트림을 한개로 연결도 가능하다. 단, 이 때 <strong>연결하려는 두 스트림의 요소는 같은 타입</strong>이여야 한다.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/51a30266-b565-4be2-ae53-faf89aba4cce/image.png" alt=""></p>
<h3 id="스트림-자르기---skiplimit-매서드">스트림 자르기 - skip(),limit() 매서드</h3>
<p>skip()과 limit() 매서드는 스트림으 일부를 잘라내고자 할 때 사용할 수 있다.</p>
<pre><code class="language-java">Stream&lt;T&gt; skip(long n) // n개의 요소 건너뛰기
Stream&lt;T&gt; limit(long maxSize) // 스트림의 요소를 maxSize개로 제한</code></pre>
<h3 id="스트림-요소-걸러내기---filter-distinct">스트림 요소 걸러내기 - filter(), distinct()</h3>
<p>filter의 경우 주어진 조건(Predicate)이 맞지 않는 요소들을 걸러내며
distinct()는 스트림에서 중복된 요소를 제거한다.</p>
<pre><code class="language-java">Stream&lt;T&gt; filter(Predicate&lt;? super T? predicate)
Stream&lt;T&gt; distinct()</code></pre>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/c7a6738e-49e4-4dc4-9ace-3b00cb3c6b87/image.png" alt=""></p>
<h3 id="정렬---sorted">정렬 - sorted()</h3>
<p>스트림을 정렬할때는 sorted 매서드를 사용한다.</p>
<pre><code class="language-java">Stream&lt;T&gt; sorted()
Stream&lt;T&gt; sorted(Comparator&lt;? super T&gt; comparator)</code></pre>
<p><strong>sorted() 매서드는 지정된 Comparator로 정렬하지만, 지정된 것이 없다면 디폴트 값인 오름차순으로 정렬</strong>한다.</p>
<h3 id="변환---map">변환 - map()</h3>
<p>스트림의 요소에 저장된 값 중 원하는 필드만 뽑아내거나 특정 형태로 변환해야 할 경우 map() 매서드를 사용한다.</p>
<pre><code class="language-java">/* &lt;T&gt;타입을 &lt;R&gt;타입으로 변환해서 반환하는 함수를 지정해야 한다.
Stream&lt;R&gt; map(Function&lt;? super T&gt;, ? extends R&gt; mapper)</code></pre>
<h3 id="조회---peek">조회 - peek()</h3>
<p>peek()는 forEach()와 달리 <strong>스트림의 요소를 소모하지 않기 때문에 연산 사이에 여러번 끼워도 문제가 안된다.</strong></p>
<h3 id="maptoint-maptolong-maptodouble">MapToInt(), MapToLong(), MapToDouble()</h3>
<p>map()은 연산의 결과로 Stream&lt;타입&gt; 스트림을 반환하는데, 스트림의 요소를 숫자로 반환할 경우 IntStream과 같은 기본형 스트림으로 반환하는게 유용하다</p>
<p>Stream&lt;타입&gt; 스트림을 기본형 스트림으로 변환할 때 아래와 같은 매서드를 써야 변환이 가능하다</p>
<pre><code class="language-java">IntStream mapToInt(ToIntFunction&lt;? super T&gt; mapper)
LongStream mapToLong(ToLongFunction&lt;? super T&gt; mapper)
DoubleStream mapToDouble(ToDoubleFunction&lt;? super T&gt; mapper)</code></pre>
<p>mapToInt()와 자주 함께 사용되는 매서드는 Integer의 parseInt()나 valueOf()가 있다.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/817d3c2e-a2cc-4972-9e00-20520476ec36/image.png" alt=""></p>
<p>Stream&lt;타입&gt;의 경우 count()만 지원하는 것과 달리 IntStream과 같은 기본형 스트림은 다음과 같은 편리한 메서드를 제공한다. <strong>단, 이 매서드들은 &quot;최종연산&quot;이므로 호출 후 스트림이 닫힌다는 점에 주의가 필요</strong>하다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/df68ad3c-b73d-4664-a739-aa19c2dc1df6/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/502b387f-6dc6-429b-b4ed-a24b923a5cb8/image.png" alt="">
다음과 같이 한번 호출한 경우 Stream이 닫히기 때문에 변수에 대입을 하는 것을 포함하는 것 등 재호출이 불가능하다.</p>
<h2 id="optional타입-와-optionalint">Optional&lt;타입&gt; 와 optionalInt</h2>
<p>Stream의 최종 연산 매서드 중에 반환 타입이 Optional이 있다.
Optional&lt;타입&gt;은 제네릭스 클래스로 &quot;T 타입의 객체&quot;를 감싸는 래퍼런스 클래스다. 따라서 Optional 타입의 객체엔 모든 타입의 참조변수를 담을 수 있다.</p>
<pre><code class="language-java">public final class Optional&lt;T&gt; {
    private final T value;
}</code></pre>
<p>최종 연산 결과를 반환하는게 아닌 Optional 객체에 담아서 반환한다.
때문에 반환값이 null인지 체크할 필요 없<strong>이 Optional의 매서드를 통해 간단히 구현</strong>할 수 있다.</p>
<h3 id="optional-객체-생성">Optional 객체 생성</h3>
<p>Optional의 객체를 생성하기 위해서는 of() 또는 ofNullable()을 사용한다.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/efc22a21-e6b5-4d5a-82bc-11b7a2c5abe7/image.png" alt=""></p>
<p>Optional.of(null) 의 경우 NullPointerException이 발생하지만 Optional.ofNullable(null)의 경우 정상적으로 실행된다.</p>
<h3 id="optional-객체-값-가져오기">Optional 객체 값 가져오기</h3>
<p>Optional의 객체의 값을 가져올 땐 get() 매서드를 사용한다. 이때 만약 값이 null일 경우 NoSuchElementException이 발생하며, 이를 방지하기 위해 orElse() 매서드로 대체할 값을 지정할 수 있다.</p>
<pre><code class="language-java">Optional&lt;String&gt; optionalTest = Optional.of(&quot;test&quot;);
String optionalString = optionalTest.get(); // 
String optionalString = optionalTest.orElse(&quot;Null값이 들어오거나 잘못된 값이 들어왔습니다.&quot;);</code></pre>
<p>정상적으로 문자열이 들어가면 해당 값을 반환, 그렇지 않을 경우 &quot;Null값이 들어오거나 잘못된 값이 들어왔습니다.&quot; 반환</p>
<h3 id="optional객체는-stream처럼-filtermapflatmap사용이-가능하다">Optional객체는 Stream처럼 filter(),map(),flatMap()사용이 가능하다.</h3>
<pre><code class="language-java">int result = Optional.of(&quot;123&quot;)
    .filter(x-&gt;x.length() &gt;0)
        .map(Integer::parseInt).orElse(-1); // result = 123


int result2 = Optional.of(&quot;&quot;)
    .filter(x-&gt;x.length() &gt;0)
    .map(Integer::parseInt).orElse(-1); // result = -1</code></pre>
<h2 id="stream---collect">Stream - Collect()</h2>
<p>스트림의 최종 연산 중 가장 복잡하면서 유용하게 활용되는 매서드이다.
collect()는 Collector 인터페이스를 구현한 것으로, 직접 구현도 가능하며, 미리 작성된 것을 사용할 수도 있다.
Collectors클래스는 미리 작성된 다양한 종류의 컬렉터를 반환하는 static 매서드를 가지고 있다.</p>
<h3 id="스트림을-컬렉션과-배열로-변환---tolist-toset-tomap-tocollection-toarray">스트림을 컬렉션과 배열로 변환 - toList(), toSet(), toMap(), toCollection(), toArray()</h3>
<p><strong>스트림의 모든 요소를 컬렉션에 수집</strong>하려면, toList()와 같은 매서드를 사용하면 된다.
List나 Set이 아닌 특정 컬렉션을 지정하려면, toCollection()에 해당 컬렉션의 생성자 참조를 매개변수로 넣는다.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/33df6406-1e05-44b7-a589-75952166db7e/image.png" alt=""></p>
<h3 id="streambuilder">Stream.builder()</h3>
<p>빌더(Builder)를 사용하면 스트림에 직접 원하는 값을 넣을 수 있다. 마지막에 build 메서드로 스트림을 리턴한다.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/3b54be63-2e3e-4633-8658-8c0d057dfa64/image.png" alt=""></p>
<h3 id="stream---matching">Stream - Matching()</h3>
<p>조건식 람다 Predicate를 받아서 해당 조건을 만족하는 요소가 있는 체크 후 리턴한다. 총 3가지의 매서드가 있다.</p>
<ol>
<li>한개라도 조건을 만족하는 요소가 있는지 (anyMatch)</li>
<li>모두 조건을 만족하는지 (allMatch)</li>
<li>모두 조건을 만족하지 않는지(noneMatch)</li>
</ol>
<pre><code class="language-java">boolean anyMatch(Predicate&lt;? super T&gt; predicate);
boolean allMatch(Predicate&lt;? super T&gt; predicate);
boolean noneMatch(Prediate&lt;? super T&gt; predicate);</code></pre>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/12bd6375-3981-4425-8a3c-cbccc092ef78/image.png" alt=""></p>
<p>다음과 같이 구현이 가능하다.</p>
<p>참조: <a href="https://hstory0208.tistory.com/entry/Java%EC%9E%90%EB%B0%94-Stream%EC%8A%A4%ED%8A%B8%EB%A6%BC%EC%9D%B4%EB%9E%80">https://hstory0208.tistory.com/entry/Java%EC%9E%90%EB%B0%94-Stream%EC%8A%A4%ED%8A%B8%EB%A6%BC%EC%9D%B4%EB%9E%80</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Java CS 정리 (1)]]></title>
            <link>https://velog.io/@dk_ovo/Java-CS-%EC%A0%95%EB%A6%AC-1</link>
            <guid>https://velog.io/@dk_ovo/Java-CS-%EC%A0%95%EB%A6%AC-1</guid>
            <pubDate>Thu, 09 May 2024 07:27:12 GMT</pubDate>
            <description><![CDATA[<h3 id="자바의-바이트-코드란">자바의 바이트 코드란?</h3>
<p>자바 바이트코드 (Java bytecode)란 자바 가상 머신(JVM)이 이해할 수 있는 언어로 변환된 자바 소스 코드를 의미한다. 즉 .java 파일을 javac이 .class 파일로 변환해준다. javac(자바 컴파일러)에 의해 변<strong>환되는 코드의 명령어 크기가 1바이트라서 자바 바이트 코드</strong>라고 불린다. 이런 자바 바이트 코드는 JVM만 설치되어 있으면 어떤 OS에서도 실행이 가능하다.</p>
<h2 id="매서드-오버로딩과-매서드-재정의">매서드 오버로딩과 매서드 재정의</h2>
<h3 id="오버로딩">오버로딩</h3>
<p>같은 클래스 내에서 메서드를 확장하는 것, 메서드 명은 같지만 매개변수, 반환 형 등을 다르게 하여 코드의 재사용성을 높여준다. 아래는 오버로딩이 되기 위한 조건이다.</p>
<ol>
<li>메서드의 이름이 같아야함</li>
<li>매개 변수, 반환형(return)은 달라도 된다.</li>
<li>같은 클래스 내에 선언되어야 한다.</li>
<li>만약 <strong>매개 변수의 갯수가 같다면 자료형이 달라야 하며, 자료형이 모두 같다면 매개 변수의 갯수가 달라야</strong> 한다.</li>
</ol>
<h3 id="오버라이딩">오버라이딩</h3>
<p>부모 클래스의 매서드를 자식 클래스에서 매서드를 &#39;재정의&#39; 하는 것이다.
즉 상속 받은 부모 클래스의 매서드를 재정의 하는 것이며, 다른 클래스의 매서드를 재정의 하는 것이 아니다.</p>
<ol>
<li>매서드의 이름이 같아야함</li>
<li>매개변수, 반환형(return), 접근제어자가 같아야 한다.</li>
</ol>
<h3 id="정리">정리</h3>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/db531459-06f4-42f7-b4b8-fe0c2fe3ca48/image.png" alt=""></p>
<h2 id="자바-플랫폼의-독립성">자바 플랫폼의 독립성</h2>
<p>기존의 언어들로 짜여진 프로그램 (ex. .java파일)을 실행시키기 위해서는 소스 코드 컴파일러(javac)를 통해서 어셈블리어로 변환하고(.class), 변환된 어셈블리어를 다시 어셈블러를 통해 기계가 해석할 수 있는 기계어로 변환해야 한다.</p>
<p>하지만, 문제는 여기서 생긴다. 하드웨어 마다 그리고 제조사마다 기계어의 설계가 다른 것이다.</p>
<p>예로 Intel 64bit, CPU와 AMD 64bit CPU의 기계어의 설계는 다르다. 기존의 언어들은 OS에 종속 되어서 프로그램을 다른 OS에 적용하기 위해 많은 시간과 노력이 들지만, 자바는 JVM을 통해 OS나 HW가 아닌, JVM과 통신을 하고 JVM이 자바 응용프로그램으로 전달받은 명령을 변환하여 OS와 통신한다.</p>
<p>이 때문에 자바는 OS를 신경쓸 필요가 없으며, JVM만 각 OS에 호환되는 버젼으로 설치만 해주면 된다. 즉 플랫폼의 독립성이란 하드웨어 또는 운영체제 와 같은 플랫폼에 종속되지 않으며, 독립적으로 실행이 가능한 것을 말한다.</p>
<h2 id="java의-가장-중요한-기능이란">Java의 가장 중요한 기능이란?</h2>
<p>자바의 경우 플랫폼에 독립적으로 프로그래밍 할 수 있도록 설계되었다. &#39;Write Onece, Run Anywhere(WORA)&#39; 원칙에 따라 어떤 플랫폼에도 실행이 될 수 있다.</p>
<p>또한 자바는 객체지향 프로그래밍 언어(OOP)로서, 4가지의 큰 특징으로 상속, 다형성, 캡슐화, 추상화를 가지고 있으며 이는 코드의 재사용성과 유지 보수성을 높이며, 대규모 개발에 적합하다는 장점을 가지고 있다. 또한 강력한 메모리 관리와 예외처리 기능을 제공하여, 안정적인 애플리케이션 개발이 가능하다.</p>
<h2 id="jdk와-jre-jvm에-대한-설명과-차이가-무엇인가요">JDK와 JRE, JVM에 대한 설명과 차이가 무엇인가요?</h2>
<h3 id="jdkjava-development-kit">JDK(Java Development Kit)</h3>
<p>JDK는 자바 개발 도구로서 소프트웨어 개발 키트이다. JDK는 플랫폼에 따라 다르며, Java코드를 개발하기 위한 디버깅과 모니터링을 하기 위한 도구가 포함되어 있으며 JRE의 상위 집합체이다. .java 파일을 바이트 코드로 변환하는 javac가 여기에 포함되어 있다.</p>
<h3 id="jrejava-runtime-environment">JRE(Java Runtime Environment)</h3>
<p>Java 코드를 실행하는데 필요한 구성 요소를 Java 클래스 라이브러리에 제공하는 소프트웨어 번들이다. JRE는 플랫폼에 따라 다르며 JVM이 실행하는데 필요한 클래스와 라이브러리 그리고 기타 지원파일이 포함되어 있다.JRE는 JVM을 생성하는 Java의 일부이다. JRE는 소스코드를 실행하는 환경만 포함되어 있다.</p>
<h3 id="jvmjava-virtual-machine">JVM(Java Virtual Machine)</h3>
<p>JVM은 바이트 코드로 이루어진 .class 파일을 실행하고 실행하기 위한 환경을 제공한다. JVM은 플랫폼 의존도가 높다. .class 바이트 코드는 JIT(Just-In-Time) 컴파일러에 의해 바이너리 코드로 변환된다.</p>
<p>.java(소스코드) -&gt; JDK의 javac를 통해 .class(바이너리 코드) 변환 -&gt; JVM을 통해 .class 코드를 JIT와 같은 컴파일러를 통해 바이너리 코드로 변환</p>
<h2 id="java는-다중상속이-되는가">Java는 다중상속이 되는가?</h2>
<p>결론부터 말하자면 다중상속은 불가능하다. 다중 상속을 할 수 있게 되면, 하나의 클래스가 어러개의 상위 클래스를 상속받을 수 있다. 이 경우 <strong>&#39;다이아몬드 문제&#39;</strong>가 발생하게 된다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/91c0400a-345d-4955-94c2-1b258fab1d73/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/53eb6a81-170a-4c8b-bcf3-76e71916f703/image.png" alt="">
이처럼 최상위 클래스의 GrandFather가 있고</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/7ab36288-aa9d-486d-bd9e-7702cf142e6d/image.png" alt="">
그 아래 FatherA</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/c93ddd2a-b76d-4eb8-8163-38a04d0c4072/image.png" alt="">
FatherB가 있으며</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/1fbd7159-8713-4df1-9e2f-3ded6fe61378/image.png" alt="">
Son은 FatherA와 FatherB를 상속받고 있다. 하지만 벌써부터 Intellij에 다중 상속이 안되는 것을 볼수 있다. 또한, super.method()를 확인해보면 다음과 같이 어떤 메서드를 정의 할 것인지 정해지지 않았다. 애초에 Java는 다중 상속을 받으면 컴파일 자체를 하지 못하게 하고 있다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/6c2a75a8-f2fa-4bf1-ba61-b4386e0aa6e6/image.png" alt=""></p>
<p>하지만 이럼에도 인터페이스는 다중 상속이 가능하다. <strong>인터페이스는 다중상속이 되는 것이고, 클래스의 경우 다중상속이 불가능</strong> 하다.</p>
<p>그 이유는 인터페이스는 <strong>&quot;매서드가 정의되지 않았기 때문&quot;</strong> 이다. 즉 선언된 형태의 매서드만 가지는 인터페이스는, 동일 시그니처의 매서드를 얼마든지 상속 받아도 아무 문제가 발생하지 않는다. 아직 구현되지 않았기 때문에 자손 클래스에서 새롭게 정의되어야 하기 때문이다.</p>
<p>결론적으로 인터페이스는 구현된 매서드가 없기 때문에, 다중 상속이 가능하다. 하지만, 클래스나 추상클래스는 이미 구현된 매서드가 존재하기 때문에 다중 상속이 불가능하다.</p>
<h2 id=""></h2>
]]></description>
        </item>
        <item>
            <title><![CDATA[추상클래스와 인터페이스 정리]]></title>
            <link>https://velog.io/@dk_ovo/%EC%B6%94%EC%83%81%ED%81%B4%EB%9E%98%EC%8A%A4%EC%99%80-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@dk_ovo/%EC%B6%94%EC%83%81%ED%81%B4%EB%9E%98%EC%8A%A4%EC%99%80-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Thu, 09 May 2024 03:54:04 GMT</pubDate>
            <description><![CDATA[<h1 id="추상클래스와-인터페이스">추상클래스와 인터페이스</h1>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/3a8c0c05-84d2-4096-a258-a12ccd596b92/image.png" alt=""></p>
<h2 id="인터페이스-interface">인터페이스 (Interface)</h2>
<ol>
<li>내부의 모든 메서드는 public abstract로 정의 (default 메서드 제외)</li>
<li>내부의 모든 필트는 public static final = 상수</li>
<li><strong>클래스에 다중 구현</strong> 지원.</li>
<li><strong>인터페이스끼리는 다중 상속</strong>을 지원</li>
<li>인터페이스에도 static, default, private <strong>접근 제어자를 붙여서 클래스 가이 구체적인 메서드를 가질 수</strong> 있다. 하위멤버의 중복 메서드를 일부분 통합할 순 있지만, 필드는 상수이기 때문에 중복 필드 통합은 불가능하다.</li>
<li>부모 자식 관계인 상속에 얽메이지 않고, 공통 기능이 필요할 때 마다 추상 메서드를 정의 한 후 구현(implement)하는 방식으로 <strong>추상 클래스보다 자유롭게 사용</strong>할 수 있다.</li>
<li><strong>클래스와 별도로 구현 객체가 같은 동작을 한다는 것을 보장</strong>하기 위해 사용하는 것에 초점이 맞춰져있음</li>
<li>다중 구현을 통해, 내부 멤버가 없는 빈 인터페이스를 선언하여 마커 인터페이스로서 이용이 가능</li>
<li>OOOable 형식으로 네이밍 규칙을 따른다.</li>
</ol>
<h2 id="추상-클래스-abstract">추상 클래스 (abstract)</h2>
<ol>
<li>하위 클래스들의 공통점을 모아 추상화 하여 만든 클래스</li>
<li>다중 상속이 불가능하며, <strong>단일 상속만 허용</strong>한다.</li>
<li>추상 메서드 외에 일반 클래스와 같이 <strong>일반적인 필드, 메서드, 생성자를 가질 수</strong> 있다.</li>
<li>추상화(추상 메서드)를 하면서 <strong>중복되는 클래스 멤버들을 통합하고 확장</strong>을 할 수 있다.</li>
<li>추상클래스는 <strong>클래스 간의 연관 관계를 구축</strong>하는 것에 촛점을 둔다.</li>
</ol>
<h4 id="추상-메서드abstract-method">추상 메서드(abstract method)</h4>
<p>추상 메서드(abstract method)란 <strong>자식 클래스에서 반드시 오버라이딩 해야만 사용할 수 있는 메서드</strong>를 의미한다.</p>
<p>추상 메서드를 선언하여 사용하는 목적은 추상 메서드가 포함된 클래스를 상속받는 자식 클래스가 반드시 추상 메서드를 구현하도록 하기 위함이다.</p>
<p>예로 모듈처럼 중복되는 부분이나, 공통적인 부분은 미리 다 만들어진 것을 사용하고 이를 받아 사용하는 쪽에서 자신에게 필요한 부분만 재정의하여 사용함으로써 생산성이 향상되고 배포등이 수위지기 때문이다.</p>
<p><strong>추상메서드는 선언부만 존재하며, 구현부는 작성되어 있지 않다.</strong>
추상 메서드는 작성되지 않은 <strong>구현부를 자식클래스에서 오버라이딩 해서 사용</strong>하는 것이다.</p>
<p>추상 메서드는 다음과 같은 문법으로 선언한다
<strong><em>abstract 반환타입 메서드명 ();</em></strong></p>
<p>선언부만 있고 구현부가 없다는 의미로 선언부 끝에 세미콜론(;)을 추가한다. 중괄호 {} 또한 필요없다.</p>
<h3 id="인터페이스와-추상클래스의-각-사용처">인터페이스와 추상클래스의 각 사용처</h3>
<p>인터페이스와 추상클래스 둘 다 똑 같이 추상 메서드를 통해 상속&amp;구현을 통한 메서드 강제 구현 규칙을 가지는 추상화 클래스다.</p>
<p>하지만 둘의 분명한 고유 특징들을 가지고 있으며, 이로 인해서 사용처가 갈리게 된다. 대표적으로 &#39;다중 상속&#39; 기능 여부의 차이가 있지만, 이에 따른 사용 목적이 다르다는 것이 포인트이다.</p>
<p>인터페이스(Interface): implements 라는 키워드처럼 인터페이스에 정의된 메서드를 각 클래스의 목적에 맞게 기능을 구현하는 느낌</p>
<p>추상 클래스(Abstract): extends 키워드를 사용해서 자신의 기능들을 하위 클래스로 확장 시키는 느낌</p>
<h3 id="추상-클래스를-사용하는-경우">추상 클래스를 사용하는 경우</h3>
<ol>
<li><p>상속 받을 클래스들이 <strong>공통으로 가지는 메서드와 필드가 많아 중복 멤버 통합</strong>을 할 때</p>
</li>
<li><p>멤버에 public 이외의 접근자(protected, private) 선언이 필요한 경우</p>
</li>
<li><p>non-static, non-final 필드 선언이 필요한 경우 (각 인스턴스에서 상태 변경을 위한 메서드가 필요한 경우)</p>
</li>
<li><p>요구 사항과 함께 구현 세부 정보의 일부 기능만 지정했을 때 </p>
</li>
<li><p>하위 클래스가 오버라이드하여 재정의하는 기능들을 공유하기 위한 상속 개념을 사용할 때</p>
</li>
<li><p>추상클래스는 이를 상속할 각 객체들의 공통점을 찾아서 추상시켜 놓은 것으로, 상속 관계를 타고 올라 갔을 때 같은 부모 클래스를 상속하며 부모 클래스가 가진 기능들을 구현해야 할 경우에 사용한다.</p>
</li>
</ol>
<h4 id="추상클래스의-다형성-이용-설계">추상클래스의 다형성 이용 설계</h4>
<p>추상클래스의 다형성이나 인터페이스의 다형성 둘 다 클래스 타입을 통합하는 취지의 기능은 같다.</p>
<p>다만, 추상클래스는 미리 논리적인 클래스 상속 구조를 만들어 놓고 사용이 결정되는 느낌이 강하다.</p>
<p>결론적으로 추상클래스를 통한 다형성을 이용할땐, 부모 추상 클래스와 논리적으로 관련이 있는 확장된 자식 클래스를 다루는 점에서 의미적으로 관계가 묶여있다고 볼 수 있다.</p>
<h4 id="명확한-계층-구조-추상화">명확한 계층 구조 추상화</h4>
<p>중복된 멤버를 제거하는 것을 떠나서, 클래스끼리의 명확한 계층 구조가 필요한 경우에도 추상 클래스를 사용한다.</p>
<p>추상클래스나 인터페이스나 추상 매서드를 이용한 구현 원칙을 강제하는 것은 같지만, 추상클래스는 결국 &#39;클래스&#39;이며 클래스와 의미있는 연관관계를 구축할때 사영된다 볼 수 있다.</p>
<p>의미있는 연관 관계란, 부모와 자식 간의 논리적으로 묶인 관계라 볼 수 있다. 개, 고양이, 사자 를 동물이라고 관계로 묶는 것 과 같이, 단어 그 자체의 논리성과 의미성이 있는 연관 관계로 연결지으면 된다.</p>
<h3 id="추상-클래스-직접-사용-예시">추상 클래스 직접 사용 예시</h3>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/96a0a11d-d405-4b7c-a7d9-4f310521b0d3/image.png" alt=""></p>
<p>가게를 운영한다고 가정하고 MarketStaff 추상 클래스는 Manager와 PartTimer의 하위 클래스를 가지고 있다.</p>
<p>매니저와 아르바이트생은 각각 이름과, 직함이 있으므로 상위클래스인 추상 클래스의 필드로 공통적으로 선언해준다.</p>
<p>일반 메서드인 greeting()의 경우 추상클래스에서 <strong>추상 매서드와 다르게 구현 내용이 포함</strong>되어 있어야 한다. 매니저든, 알바생이든 &quot;안녕하세요&quot;라고 인사하는 것은 공통의 동작이므로 추상메서드가 아닌 일반 메서드로 구현한다. 또한 하위 클래스에서 이를 Overriding하여 재정의 할 수 있고, 그대로 쓸 수도 있다.</p>
<p>추상 메서드인 working(); 과 cleaning();의 경우 매니저와 알바생 모두 하는 일들이지만, 직함이 다르므로 다른 업무를 할 것이라고 여겨지기 때문에 <strong>구현체가 없는 추상 메서드로 구현</strong>을 한다. 하위 클래스의 경우 상위클래스의 추상 메서드들을 반드시 Override 하여 구현체를 정의해야한다. 
<img src="https://velog.velcdn.com/images/dk_ovo/post/1a9e655b-f92f-449a-acc3-fe286737b619/image.png" alt=""></p>
<h4 id="추상-클래스에서-일반-메서드를-구현하는-이유">추상 클래스에서 일반 메서드를 구현하는 이유</h4>
<ol>
<li><p>공통된 동작의 구현: 추상 클래스는 하위 클래스들이 공통으로 사용하는 동작을 구현할 수 있다. <strong>이는 반복되는 코드를 피하여 코드의 재사용성을 높이며</strong>, 공통된 동작을 중복해서 하위의 클래스에서 구현하지 않기 때문에 코드를 간결하게 유지가 가능하다.</p>
</li>
<li><p>확장성과 유연성 제공: 추상클래스의 일반 메서드는 하위 클래스에서 필요에 따라 재정의(Override)할 수 있다. 이는 하위클래스의 기본 동작을 변경하거나 확장의 유연성을 제공한다. 또한, 추상 클래스의 일반 메서드를 상속 받을 때 구현체가 똑같으므로 공통되어 코드의 일관성을 유지할 수 있게 한다.</p>
</li>
<li><p>구현 세부 사항 은닉: 추상 클래스의 일반 메서드는 하위 클래스에서 구현되지 않는 경우도 있다. 이는 상위 클래스에서 필요한 기능을 추상화하여 하위 클래스에 구현 세부 사항을 숨기는 데 도움을 준다. 이러한 추상화는 클래스 간의 결합도를 낮추고 코드를 더 관리하기 쉽게 만듭니다.</p>
</li>
</ol>
<p>결론적으로 추상 클래스에 일반 메서드를 정의함으로써 코드의 재사용성, 유연성, 유지보수성을 높일 수 있습니다. 이는 객체 지향 프로그래밍의 원칙 중 하나인 코드 재사용성과 모듈화를 따르게 되는 방향이다.</p>
<h3 id="인터페이스를-사용하는-경우">인터페이스를 사용하는 경우</h3>
<ol>
<li><p>어플리케이션의 기능을 정의해야 하지만, 그 구현 방식이나 대상에 대해 추상화를 할 때</p>
</li>
<li><p>서로 관련성이 없는 클래스들을 묶어주고 싶을 때 (형제관계)</p>
</li>
<li><p>다중 상속(구현)을 통한 추상화 설계를 해야할 때</p>
</li>
<li><p>특정 데이터 타입의 행동을 명시하고 싶지만, 어디서 그 행동이 구현되는지는 신경쓰지 않는 경우</p>
</li>
<li><p>클래스와 별도로 구현 객체가 같은 동작을 한다는 것을 보장하기 위해 사용한다.</p>
</li>
</ol>
<h4 id="자유로운-타입-묶음">자유로운 타입 묶음</h4>
<p>인터페이스의 가장 큰 특징은 <strong>상속에 구애 받지 않은 상속(구현)이 가능</strong>하다는 것이다.</p>
<p>상속(extends)는 클래스끼리 논리적인 타입의 묶음의 의 의미가 있다면, <strong>구현(implements)의 경우 자유로운 타입의 묶음</strong>이다. 따라서 서로 논리적이지 않고, 관련이 적은 클래스끼리 필요에 의해 형제 타입처럼 묶을 수 있다.</p>
<p>예시로 다음과 같이 Creature라는 최상위 추상 클래스와 하위 추상클래스인 Animal과 Fish가 있고, 각 클래스들을 구체적으로 의미를 부여해 구현한 Parrot, Tiger, People 클래스와 Whale 클래스가 있다고 가정한다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/247580a0-9427-4ec1-b675-ccfbfa023da9/image.png" alt=""></p>
<p>이를 코드로 표현하면 다음과 같다.</p>
<pre><code class="language-//">abstract class Creature { }

// 추상 클래스 (부모 클래스)
abstract class Animal extends Creature { }
abstract class Fish extends Creature { }

// 자식 클래스
class Parrot extends Animal { }
class Tiger extends Animal { }
class People extends Animal { }

class Whale extends Fish { }</code></pre>
<p>이렇듯 상속 관계를 설정 후 동작을 하는 메서드를 추가해야 한다고 할 경우 만약 수영을 하는 swimming() 메서드를 각 자식 클래스에 추가하려 할 경우 나중에 확장을 위한 <strong>추상화 원칙</strong> 을 따라야 한다고 한다. 그러면 부모 클래스인 Animal이나 조상 클래스인 Creature에 추상 메서드를 추가해야 하는데, swimming은 고래와 사람만 할 수 있기 때문에 이둘을 포함하는 조상 클래스인 Creature에 추상 메서드를 추가해야 한다.</p>
<p>하지만 조상 클래스인 Creature에 추상 메서드를 추가하게 될 경우, 모든 자손/ 자식 클래스에서 반드시 추상 메서드를 구현해야 하는 규칙 때문에 수영이 불가능한 앵무새나 호랑이도 swimming 메서드를 구체화 해야하는 일이 생겨버린다. 당연히 일반 메서드로 넣기에도 swimming 자체를 할 수 없는 종들이기에 문제가 생긴다.</p>
<p>메서드를 선언하기만 하고 빈칸으로 둘 수 있으나, 이는 객체 지향적 설계에 위반될 뿐 아니라 유지보수 측면에서도 좋지 않다.</p>
<p>이를 해결하기 위해 인터페이스에 추상 메서드를 선언하고 이를 구현(implements)하면 자유로운 타입 묶음을 통해 추상화를 이룰 수 있다. </p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/e433a238-8ecd-4f61-b90d-e133468d5ef1/image.png" alt=""></p>
<pre><code class="language-abstract">
abstract class Animal extends Creature { }
abstract class Fish extends Creature { }

// 
interface Swimmable {
    void swimming();
}

class Tiger extends Animal { }
class Parrot extends Animal { }
class People extends Animal implements Swimmable{
    @Override
    public void swimming() {}
}

class Whale extends Fish implements Swimmable{
    @Override
    public void swimming() {}
}</code></pre>
<p>이렇듯 사람과 고래의 공통된 매서드를 인터페이스를 통해 자유롭게 자식 클래스에 상속을 시킴으로써 구조화된 객체 지향 설계를 추구할 수 있다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/bc77d582-6480-4347-895b-6bf3f45f0ac8/image.png" alt=""></p>
<h3 id="인터페이스-다형성-이용-설계">인터페이스 다형성 이용 설계</h3>
<p>추상클래스의 경우 클라이언트에서 자료형을 사용하기 전 미리 논리적으로 클래스의 상속 구조를 만들어 놓은 후 사용을 결정하는 느낌이면, 인터페이스의 경우 반대로 <strong>미리 만들든 나중에 만들든 그때 필요에 따라 구현해서 자유롭게 붙이거나 떼어낼 수 있는 느낌</strong>으로 볼 수 있다.</p>
<p>정리하면, 인터페이스의 다형성은 부모 자식 클래스와 달리 논리적으로 관련이 없는 별개의 클래스들을 다루며, 상속관계에 얽히지 않고 구현(implements)만 하면 자유롭게 다형성을 이용할 수 있다.</p>
<h3 id="마커-인터페이스">마커 인터페이스</h3>
<p>일반적인 인터페이스와 같지만, 사실상 아무 메서드도 선언하지 않은 빈 껍데이 인터페이스를 말한다.</p>
<pre><code class="language-interfaace">}</code></pre>
<p>아무 내용도 없어서 쓰임이 없어 보이지만, 마커 인터페이스의 역할은 <strong>오로지 객체의 타입과 관련된 정보만을 제공</strong>해주는 것이다.</p>
<h4 id="마커-인터페이스-예시">마커 인터페이스 예시</h4>
<p>상위 클래스 Animal을 만들고 하위로 Lion, Chicken 등 여러가지 동물 클래스들을 만들어 상속을 시켰다. 이때 born() 매서드의 경우 Animal 타입의 매개변수를 받고 새끼를 낳는지, 알을 낳는지, instanceof 연산자로 클래스 타입을 구분했다.</p>
<pre><code>class Animal {
    public static void born(Animal a) {
        if(a instanceof Lion) {
            System.out.println(&quot;새끼를 낳았습니다.&quot;);
        } else if(a instanceof Chicken) {
            System.out.println(&quot;알을 낳았습니다.&quot;);
        } else if(a instanceof Snake) {
            System.out.println(&quot;알을 낳았습니다.&quot;);
        }
        // ...
    }
}

class Lion extends Animal { }
class Chicken extends Animal { }
class Snake extends Animal { }</code></pre><p>하지만 이 경우 자식의 클래스 갯수가 많아질수록 코드가 난잡하고 길어지는 단점이 있다.</p>
<p>따라서 아무 내용이 없는 빈껍데기 인터페이스를 선언 후 적절한 클래스에 implements 시킴으로써, 단순한 타입 체크용으로 사용하는 것이다. 이럴 경우 다음과 같이 코드가 심플해질 수 있다.</p>
<pre><code>// 새끼를 낳을 수 있다는 표식 역할을 해주는 마커 인터페이스
interface Breedable {}

class Animal {
    public static void born(Animal a) {
        if(a instanceof Breedable) {
            System.out.println(&quot;새끼를 낳았습니다.&quot;);
        } else {
            System.out.println(&quot;알을 낳았습니다.&quot;);
        }
    }
}

class Lion extends Animal implements Breedable { }
class Chicken extends Animal { }
class Snake extends Animal { }</code></pre><h3 id="인터페이스--추상클래스-조합하여-사용">인터페이스 + 추상클래스 조합하여 사용</h3>
<p>추상클래스와 인터페이스는 같이 조합되어 많이 사용되기도 한다. 가장 큰 특징이라고 볼 수 있는 <strong>추상 클래스의 중복 멤버 통합 + 인터페이스의 다중 상속 기능</strong> 을 동시에 사용하기 위함이다. 이 둘을 같이 사용하는 여러 코드 패턴들이 나왔고, 이것이 디자인 패턴의 근간이 되었다 볼 수 있다.</p>
<h3 id="추상클래스에-인터페이스-일부-구현-방법">추상클래스에 인터페이스 일부 구현 방법</h3>
<p>추상클래스에 인터페이스를 implements 하고, 인터페이스의 추상 메서드를 아예 구현하지 않거나, 일부만 구현하는 방식으로 통합된 추상 클래스를 만들 수 있다.</p>
<pre><code>interface Animal {
    void walk();
    void run();
    void breed();
}

// Animal 인터페이스를 일부만 구현하는 포유류 추상 클래스
abstract class Mammalia implements Animal {
    public void walk() { ... }
    public void run() { ... }
    // breed() 메서드는 자식 클래스에서 구체적으로 구현하도록 일부로 구현하지 않음 (추상 메서드로 처리)
}

// 인터페이스 + 추상 클래스를 상속하여 사용
class Lion extends Mammalia {
    @Override
    public void breed() { ... }
}</code></pre><h3 id="interface---abstract--concrete-class-디자인-패턴">Interface - Abstract -Concrete Class 디자인 패턴</h3>
<p>인터페이스와 추상클래스를 이용한 클래스 설계 패턴이다.
인터페이스는 강력하지만, <strong>필드는 상수만 가능하여 중복된 필드가 있을 경우 인터페이스로 해결할 수 없는 단점</strong>이 있다. 이땐 어쩔 수 없이 추상 클래스를 사용해야 하며, 그렇다고 추상클래스를 남용하면 단일 상속의 제한 때문에 클래스의 의존성이 커지게 된다.</p>
<p>이러한 서로간의 단점들을 극복할 여러 조합 방법이 <strong>인터페이스 - 추상클래스 - 클래스 구현 디자인 패턴</strong>이다.</p>
<h4 id="인터페이스---추상클래스---클래스-구현-디자인-패턴-예시">인터페이스 - 추상클래스 - 클래스 구현 디자인 패턴 예시</h4>
<pre><code>interface IShape {
    void setOpacity(double opacity); // 도형 투명도 지정
    void setColor(String color); // 도형 색깔 지정
    void draw(); // 도형 그리기
}</code></pre><p>이 Shape의 인터페이스에 적힌 스펙대로 도형 클래스를 설계해야 해서 설계에 맞게 다음과 같이 Rectangle과 Square클래스를 만들고 인터페이스를 구현하여 추상 메서드를 구체화 했다.</p>
<pre><code>interface IShape {
    void setOpacity(double opacity);
    void setColor(String color);
    void draw();
}

// 인터페이스 설계서에 따라 클래스를 구현
class Rectangle implements IShape {
    double opacity; // ! 중복
    String color; // ! 중복

    public void setOpacity(double opacity) { // ! 중복
        this.opacity = opacity;
    }
    public void setColor(String color) { // ! 중복
        this.color = color;
    }

    public void draw() {
        System.out.println(&quot;draw Rectangle with&quot;);
        System.out.println(opacity);
        System.out.println(color);
    }
}

// 인터페이스 설계서에 따라 클래스를 구현
class Square implements IShape {
    double opacity; // ! 중복
    String color; // ! 중복

    public void setOpacity(double opacity) { // ! 중복
        this.opacity = opacity;
    }
    public void setColor(String color) { // ! 중복
        this.color = color;
    }

    public void draw() {
        System.out.println(&quot;draw Rectangle with&quot;);
        System.out.println(opacity);
        System.out.println(color);
    }
}

public class Pattern {
    public static void main(String[] args) {
        IShape[] rec = { new Rectangle(), new Square() };

        rec[0].setOpacity(0.7);
        rec[0].setColor(&quot;red&quot;);
        rec[0].draw();

        rec[1].setOpacity(0.3);
        rec[1].setColor(&quot;yellow&quot;);
        rec[1].draw();
    }
}</code></pre><p>이 과정에서 중복된 코드들이 보인다. 인터페이스는 기본적으로 중복되는 멤버에 대해 클래스와 같이 묶는 역할을 하지 못한다. 인터페이스에 선언할 수 있는 필드는 오로지 상수이며, 디폴트 메서드가 있어도 한계가 있다.</p>
<p>이를 해결하는 방법으로 인터페이스(interface)와 구체 클래스(concrete class) 중간에 추상 클래스(abstract class) 하나를 두고 공통되는 부분을 모아 두는 것이다.</p>
<p>아래의 예제에서 공통 부분을 추상 클래스로 따로 뽑으면 다음과 같아진다.</p>
<pre><code>abstract class Shape implements IShape { // 인터페이스를 상속하는 추상클래스
    // 중복되는 멤버들을 모아놓고
    protected double opacity;
    protected String color;

    public void setOpacity(double opacity) {
        this.opacity = opacity;
    }
    public void setColor(String color) {
        this.color = color;
    }

    // void draw(); 는 구체화 안함
}</code></pre><p>실제 구현 클래스인 Rectangle 과 Square 클래스에서는 추상 클래스 Shape를 extends 하고 인터페이스의 draw() 메소드 부분만 구체화 해주면 된다.</p>
<pre><code>class Rectangle extends Shape {
    public void draw() {
        System.out.println(&quot;draw Rectangle with&quot;);
        System.out.println(opacity);
        System.out.println(color);
    }
}

class Square extends Shape {
    public void draw() {
        System.out.println(&quot;draw Rectangle with&quot;);
        System.out.println(opacity);
        System.out.println(color);
    }</code></pre><p>이런 방식으로 자바에서 제공하는 재료를 각자의 위치에 맞게 조합적인 코드를 짜는 것이 디자인 패턴이라고 한다.</p>
<p>위의 패턴은 중복제거에는 효과적이지만, 클래스 상속을 기반으로 하고 있으므로 다른 클래스를 상속 받아야 하는 경우 이 패턴을 못쓴다는 단점이 있다.</p>
<p>참조 출처: <a href="https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-vs-%EC%B6%94%EC%83%81%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%B0%A8%EC%9D%B4%EC%A0%90-%EC%99%84%EB%B2%BD-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0">https://inpa.tistory.com/entry/JAVA-☕-인터페이스-vs-추상클래스-차이점-완벽-이해하기</a> [Inpa Dev 👨‍💻:티스토리]</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CS 스터디 - 에러(Error)와 예외처리(Exception)]]></title>
            <link>https://velog.io/@dk_ovo/CS-%EC%8A%A4%ED%84%B0%EB%94%94-%EC%97%90%EB%9F%ACError%EC%99%80-%EC%98%88%EC%99%B8%EC%B2%98%EB%A6%ACException</link>
            <guid>https://velog.io/@dk_ovo/CS-%EC%8A%A4%ED%84%B0%EB%94%94-%EC%97%90%EB%9F%ACError%EC%99%80-%EC%98%88%EC%99%B8%EC%B2%98%EB%A6%ACException</guid>
            <pubDate>Wed, 08 May 2024 08:51:31 GMT</pubDate>
            <description><![CDATA[<h1 id="프로그래밍의-오류error-종류">프로그래밍의 오류(Error) 종류</h1>
<p>프로그램에서 오류가 발생할 경우 시스템 레벨에서 프로그램에 문제를 야기하여, 원치않는 버그를 일으키거나, 심할경우 실행 중인 프로그램을 강제로 종료하기도 한다.</p>
<p>내부적 요인으로는 프로그램 설계 로직에 문제가 생겨서 그럴 수 있고, 외부적인 요인으로는 프로그램 자체 문제가 아닌 하드웨어에서 문제가 생겨 오류가 발생할 수 있다.</p>
<p>프로그래밍 언어에서는 <strong>오류를 발생 시점에 따라 크게 3가지</strong>로 나눈다.</p>
<ol>
<li>컴파일 에러(Compile-Time Error)</li>
</ol>
<ul>
<li>컴파일할 때 발생하는 에러</li>
</ul>
<ol start="2">
<li>런타임 에러(Runtime Error)</li>
</ol>
<ul>
<li>실행시에 발생하는 에러</li>
</ul>
<ol start="3">
<li>논리적 에러(Logical Error)</li>
</ol>
<ul>
<li>실행은 되지만 의도와 다르게 동작을 하는 것</li>
</ul>
<h3 id="컴파일-에러compiliation-error">컴파일 에러(Compiliation Error)</h3>
<p>컴파일 단계에서 오류를 발견하면 컴파일러가 에러 메세지를 출력해주는 것을 말한다. 컴파일 에러 발생의 대표 원인으로 <strong>문법 구문 오류(syntax error)</strong>를 들 수 있다.</p>
<p>예를들어 코딩을 할 때 맞춤법, 또는 문장부호(;), 선언되지 않은 변수와 같은 것들을 사용하면 컴파일 단계에서 에러를 일으킨다.</p>
<p>컴파일 에러는 심각하게 볼 오류는 아니다. 컴파일 단계에서 오류가 났다는 것은 프로그램 실행 자체가 안됐기 때문에 개발자가 찾아서 수정을 하면 되며, IDE에서는 일정 주기로 계속 자동으로 컴파일을 해주기 때문에 문제르 바로바로 알 수 있다.</p>
<h3 id="런타임-에러runtime-error--실행-오류">런타임 에러(Runtime Error) = 실행 오류</h3>
<p>컴파일 에러가 발생하지 않았더라도, 프로그램 실행 중 에러가 발생하여 잘못된 결과를 얻거나, 외부적인 요인으로 기계적 결함으로 프로그램이 비정상적으로 종료가 될 수 있다.</p>
<p>대체로 개발 단계에서 설계 미숙(논리적)으로 발생하는 경우가 많으며, 런타임 에러(실행 오류)가 발생하게 되면 개발자가 역추적하여 원인을 찾아야 한다. 이러한 잠재적인 런타임 에러를 방지하기 위해 프로그램 실행도중 발생할 수 있는 경우의 수를 고려하여 이에 대한 대비를 한다.</p>
<h3 id="논리-에러logic-error">논리 에러(Logic Error)</h3>
<p>논리적 에러로 이른바 &#39;버그&#39;라고 불린다고 볼 수 있다.</p>
<p>프로그램이 실행하고 진행하는데 아무런 문제가 없는 오류이지만, 결과가 예쌍과 달라서 사용자가 의도한 작업을 수행하지 못하게 되어 서비스 이용에 지장이 생길 수 있다.</p>
<p>예를 들어서 음수가 나오면 안되는 상황에서 음수의 결과값이 나오는 경우 같은 것들을 들 수 있다.</p>
<p>논리적 오류의 경우 프로그램 자체는 문제없이 돌아가기 때문에 별다른 에러 메세지를 알리지 않는다. 따라서 개발자는 프로그램 전반의 코드와 알고리즘을 체크해야 한다.</p>
<h2 id="error와-exception의-차이">Error와 Exception의 차이</h2>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/bcf0aebf-9eaa-4d25-9da6-4be3ca1bde13/image.png" alt="">
자바 프로그래밍에는 실행시(Runtime)발생할 수 있는 오류를 <strong>&#39;에러(Error)&#39;와 &#39;예외(Exception)&#39;</strong> 두가지로 구분한다.</p>
<h3 id="error-에러">Error (에러)</h3>
<p><strong>프로그램 코드에 의해서 수습될 수 없는 심각한 오류</strong></p>
<p>에러는 컴파일시 문법적인 오류와 런타임시 Null Point 참조와 같은 오류로 프로세스에 심각한 문제를 야기시켜 프로세스를 종료시킬 수 있다.</p>
<p>Error는 메모리 부족(Out of Memory Error) 이나 스택 오버플로우 (Stack Over flow Error)와 같이 발생하면 복구할 수 없는 심각한 오류이며, 예측 불가능하다. 즉, 에러는 JVM 실행에 문제가 생긴 것으로 개발자가 대처할 방법이 없다.</p>
<h4 id="-out-of-memory-error란">※ Out of Memory Error란?</h4>
<p>JVM에 설정된 메모리의 한계를 벗어난 상황일 때 발생. Heap 사이즈가 부족하거나, 너무 많은 class를 로드할때, 가용 가능한 swap이 없을때, 큰 메모리의 native메소드가 호출될 때 등이 있다. 이를 해결하기위해 dump 파일분석, jvm 옵션 수정 등이 있습니다.</p>
<h4 id="-stack-overflow란">※ Stack Overflow란?</h4>
<p>Stack 영역의 메모리가 지정된 범위를 넘어갈 때 발생한다. <strong>Stack 메모리는 보통 지역 변수가 저장되는 영역</strong>이다. 함수에서 지역 변수를 선언하면 지역 변수는 Stack 메모리에 할당되고, 함수를 빠져나오면 Stack에서 메모리가 해제된다.</p>
<p>만약 한 함수에서 너무 큰 지역 변수를 선언하거나 함수를 재귀적으로 무한정 호출하게 되면 stack overflow가 발생할 수 있다.</p>
<p>Stack Overflow가 발생하면 컴파일러 옵션에서 <strong>stack 영역의 크기를 늘리거나</strong> 또는 <strong>함수에서 사용하는 지역 변수의 크기를 줄이거나 아니면 지역 변수를 전역 변수로 바꾸어 해결</strong>할 수 있다.</p>
<h3 id="exception-예외">Exception (예외)</h3>
<p><strong>프로그램 코드에 의해서 수습될 수 있는 다소 미약한 오류</strong></p>
<p>알고리즘 오류로 Exception 예외가 계속 발생한다 해도 Error처럼 프로그램이 죽거나 그럴 경우는 적다.</p>
<p>대부분의 예외(Exception)는 개발자가 구현한 로직에서 발생한 실수나 사용자의 영향에 의해 발생한다. 그래서 예외는 에러와 달리 문제가 발생해도 이에 대한 대응 코드를 미리 작성해놓으면 어느정도 프로그램의 비정상적인 종료 또는 동작을 방지할 수 있다.</p>
<p>Java의 경우 예외처리 문법 (Try-Catch)이 있다.</p>
<p>따라서 개발자는 예외처리(Exception Handling)을 통해 예외 상황을 처리하여 프로그램이 종료되지 않도록 할 필요가 있다.</p>
<h4 id="예외처리exception-handling">예외처리(Exception Handling)</h4>
<p>프로그램 실행 시 발생할 수 있는 예외의 발생에 대한 코드를 작성하는 행위를 말한다. 프로그램 실행 중 발생하는 에러는 어쩔 수 없지만, 예외의 경우 개발자의 실력에 따라 충분히 포괄적으로 방지가 가능하다. 예외처리의 목적은 예외의 발생으로 인한 실행중인 프로그램의 비정상적인 종료를 막고, 정상적인 실행상태를 유지하는데 의미가 있다.</p>
<h4 id="예외가-주로-발생하는-원인">예외가 주로 발생하는 원인</h4>
<ol>
<li>사용자의 잘못된 데이터 입력</li>
<li>잘못된 연산</li>
<li>개발자가 로직을 잘못 작성</li>
<li>하드웨어, 네트워크 오작동</li>
<li>시스템 과부하</li>
</ol>
<h2 id="자바의-예외exception클래스">자바의 예외(Exception)클래스</h2>
<h2 id="error와-exception-클래스의-계층-구조">Error와 Exception 클래스의 계층 구조</h2>
<p>자바에서는 오류를 Error와 Exception으로 나눴고, 이들을 클래스로 구현하여 처리한다.</p>
<p>IllegalArgumentException을 비롯해 NullPointerException과 IOException도 모두 클래스이다.</p>
<p>JVM은 프로그램을 실행하는 도중 예외가 발생하면, <strong>해당 예외 클래스로 객체를 생성하고 예외 처리 코드에서 예외 객체를 이용할 수 있도록</strong> 한다.</p>
<h4 id="자바의-오류-클래스-계층-구조">자바의 오류 클래스 계층 구조</h4>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/d81ac1e7-0e38-4833-a2e7-b5c56af6d50e/image.png" alt=""></p>
<h4 id="throwable-클래스">Throwable 클래스</h4>
<p>Error와 Exception 모두 자바의 최상위 클래스인 Object 클래스를 상속받는다. 그리고 그 사이에 Throwable 클래스와 상속 관계가 있으며, <strong>Throwable 클래스의 역할은 오류나 예외에 대한 메세지를 담는 것</strong>이다.</p>
<p>대표적으로 getMessage()와 printStackTrace()메서드가 이 클래스에 속해있다. Error와 Exception 클래스에서도 위 두 메서드를 마찬가지로 사용 가능하다.</p>
<p>Error 클래스의 경우 외부적인 요인으로 인해 발생하는 오류이기 때문에 대처가 불가능하다. 따라서 <strong>눈여겨 볼 클래스는 Exception 클래스</strong>이다.</p>
<h2 id="exception예외-클래스-계층-구조">Exception(예외 클래스) 계층 구조</h2>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/848867c4-ce10-406f-99e9-9adf963e469d/image.png" alt=""></p>
<p>자바에서 다루는 모든 예외 오류는 Exception 클래스에서 처리한다. 그리고 아래의 Exception 클래스 트리 구조를 보았을 때 파란색은 컴파일 에러, 붉은색은 런타임에러를 보여준다.</p>
<h3 id="exception-및-하위-클래스파란색">Exception 및 하위 클래스(파란색)</h3>
<p>사용자의 실수와 같은 외적인 요인에 의해 발생되는 컴파일할 때 발생하는 예외</p>
<p>Checked Exception으로 예외처리가 필수며, 처리하지 않을 경우 컴파일이 실행되지 않는다. JVM 외부와 통신(네트워크, 파일 시스템 등)할 때 주로 쓰인다. <strong>RuntimeException 이외의 모든 예외가 이곳에 해당</strong>한다.</p>
<h4 id="존재하지-않은-파일의-이름을-입력filenotfoundexception">존재하지 않은 파일의 이름을 입력(FileNotFoundException)</h4>
<h4 id="실수로-클래스-이름을-잘못-기재classnotfoundexception">실수로 클래스 이름을 잘못 기재(ClassNotFoundException)</h4>
<h4 id="입력한-데이터-형식이-잘못된-경우dataformatexception">입력한 데이터 형식이 잘못된 경우(DataFormatException)</h4>
<h3 id="runtimeexception-클래스붉은색">RuntimeException 클래스(붉은색)</h3>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/25f960d8-d326-4802-93e4-4d37cb92bd7d/image.png" alt=""></p>
<h3 id="checked-exception과-unchecked-exception-정리">Checked Exception과 Unchecked Exception 정리</h3>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/51bfec0b-78a4-4c9d-a279-fbb43b10c7b0/image.png" alt="">
푸른 색인 Checked Exception은 컴파일 예외 클래스들을 카리키는 것이며, 붉은 색인 Unchecked Exception은 런타임 예외 클래스들을 가리킨다.</p>
<p>Checked / Unchecked Exception으로 재분류한 이유는 <strong>코드적 관점에서 예외 처리 동작을 필수 지정 유무에 따라 나뉘기 때문</strong></p>
<h4 id="명시적-예외-처리와-그렇지-않은-처리의-차이">명시적 예외 처리와 그렇지 않은 처리의 차이</h4>
<ul>
<li><p>명시적 예외 처리가 필요한 경우(Checked Exception)의 경우 체크하는 시점이 컴파일 하는 단계이기 때문에,별도로 예외처리를 하지 않으면 컴파일 자체가 안된다.</p>
</li>
<li><p>따라서 <strong>Checked Exception이 발생 가능한 메서드면 반드시 로직을 Try-Catch 구문으로 감싸거나 throws로 던져서 처리</strong>해야 한다.</p>
</li>
<li><p>반면 명시적 예외 처리가 불필요한 경우(Unchecked Exception)의 경우 예외 처리를 하지 않아도 된다. 개발자의 충분한 주의로 미리 피할 수 있는 경우가 대부분이여서 <strong>자바 컴파일러는 별도의 예외처리를 하지 않도록 설계</strong>되어 있기 때문이다. 따라서 Try-catch 구문으로 감싸지 않아도 컴파일도 되고 실행이 가능하다.</p>
</li>
</ul>
<h3 id="주요-method">주요 Method</h3>
<h4 id="printstacktrace">PrintStackTrace()</h4>
<ul>
<li>발생한 Exception의 출처를 메모리 상에서 추적하면서 결과를 알려준다. 발생한 위치를 정확히 출력해줘서 가장 많이 쓰이며 void를 반환한다.</li>
</ul>
<h4 id="getmessage">getMessage()</h4>
<ul>
<li>한줄로 요약된 메세지를 String으로 반환한다.</li>
</ul>
<h4 id="getstacktrace">getStackTrace()</h4>
<ul>
<li>JDK1.4 부터 지원한다. printStackTrace()를 보완하며, StackTraceElement[] 이라는 문자열 배열로 변경해서 출력하고 저장한다.</li>
</ul>
<h4 id="checked를-unchecked-예외로-변환">Checked를 Unchecked 예외로 변환</h4>
<ul>
<li>checked exception은 반드시 try-catch 문으로 감싸야 한다. 하지만, 예외처리가 귀찮고 가독성이 해친다는 판단이 있을 경우, unchecked exception으로 변환시켜 컴파일에게 예외처리를 강제하지 않게 할 수 있다.</li>
</ul>
<p><strong>예시</strong>
public static void install () {
    throw new RuntimeException(new IOException(&quot;설치 불가능&quot;));
}
이처럼 try-catch 구문이 필수인 Checked 예외인 IOException을 Unchecked 예외인 RuntimeException으로 감싸 컴파일 단계에서 예외처리를 강제하는 것을 피할 수 있다.</p>
<h2 id="exception-handling-3가지-기법">Exception Handling 3가지 기법</h2>
<h3 id="1-예외-복구">(1) 예외 복구</h3>
<ol>
<li>예외 상황을 파악하고 문제를 해결하여 정상 상태로 돌려놓는 방법</li>
<li>Exception이 발생하더라도 어플리케이션은 정상 동작</li>
<li>반복문을 이용하여 예외가 발생하더라도 일정 수만큼 재시도하여 예외 복구를 시도</li>
<li>만일 최대 재시도 횟수를 넘기는 경우 예외를 발생시키거나 플랜B로 문제를 해결 시도</li>
<li>네트워크에 연결하거나 하는 등의 로직에서 유용함</li>
</ol>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/16bef326-e044-485e-a0fa-5c38b5fd7bb8/image.png" alt=""></p>
<h3 id="2-예외-처리-회피---추천하는-방식은-x">(2) 예외 처리 회피 -&gt; 추천하는 방식은 X</h3>
<ol>
<li>예외 처리를 직접 담당하지 않고 호출한 쪽으로 던져서 회피하는 방법(throws)</li>
<li>호출한 쪽에서 예외를 처리하는 것이 바람직할 때 사용한다.</li>
<li>해당 로직에서 예외가 발생했을 때 처리하지 않고, <strong>회피하는 것이 최선의 방법일 때만 사용</strong>한다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/099cd817-a898-4204-a2d7-d639fcb17004/image.png" alt=""></p>
<h3 id="3-예외-전환">(3) 예외 전환</h3>
<ol>
<li><p>예외 처리 회피와 비슷하게 메서드 밖으로 예외를 던지지만, 무작정 던지는 것이 아니라 <strong>적절한 예외로 필터링 해서 던지는 방법</strong></p>
</li>
<li><p>조금 더 명확한 의미로 전달되기 위해 적합한 의미를 가진 예외로 변경하여 throws하는 것이라 볼 수 있다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/77f4a096-fded-48d8-b520-3f7aa8280323/image.png" alt=""></p>
</li>
<li><p>예외처리를 상위 클래스로 단순하게 포장(wrap)하는 방법도 일컫는다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/9038730f-4405-4bc0-8202-5f2394d8a919/image.png" alt=""></p>
</li>
</ol>
<h3 id="exception-handling-주의-사항">Exception Handling 주의 사항</h3>
<h4 id="catch에는-로깅-복구-등의-로직을-추가할-것">catch에는 로깅, 복구 등의 로직을 추가할 것</h4>
<ol>
<li><p>예외를 아무 로직 없이 catch만 하는 것은 바람직하지 x
<img src="https://velog.velcdn.com/images/dk_ovo/post/298f41f2-7916-4e8d-acce-11cc6c470f77/image.png" alt=""></p>
</li>
<li><p>catch에 단순히 throw만 하는 것도 바람직하지 x
<img src="https://velog.velcdn.com/images/dk_ovo/post/5f9983ea-e3b0-49cd-b98c-f0c2bb48a021/image.png" alt=""></p>
</li>
</ol>
<ol start="3">
<li>로그를 출력하거나, 문제를 원상 복구 시키는 로직을 첨가하는 등 catch만 수행하지 않고 해당 예외에 대한 처리를 해줘야 한다.</li>
</ol>
<h4 id="예외-stack을-남겨서-추적-유지보수성을-높이기">예외 Stack을 남겨서 추적, 유지보수성을 높이기</h4>
<ol>
<li><p>Exception의 추적성과 유지보수성을 높이기 위햐 e.toString() 또는 e.getMessage()로 마지막 예외 메세지만 남기는 것 보다, 전체 Exception Stack을 다 넘기는 편이 좋다.</p>
</li>
<li><p>대표적인 slf4j 라이브러리의 log.error() 역시 e.printStackTrace() 처럼 Exception의 stack도 남긴다.</p>
</li>
</ol>
<h4 id="logging-framewokrk-사용하기">Logging Framewokrk 사용하기</h4>
<ol>
<li><p>e.printStackTrace() 대신 LoggingFramework(slf4j, commons logging, log4j, logback)를 활용할 것</p>
</li>
<li><p>Logging Framework를 이용하면 로그 파일을 쪼갤 수 있으며, 여러 서버의 log를 한곳에 모아서 보는 System도 활용이 가능하다.</p>
</li>
</ol>
<h3 id="try-catch-구문-예외-잡기">Try-Catch 구문 (예외 잡기)</h3>
<p>로직 중에 예외가 발생할지 모르는 부분에 try-catch 구문으로 감싼다.</p>
<ul>
<li><p>try에는 위험한 로직이 포함되며, catch에는 예외가 발생할 경우 수행될 로직이 들어간다.</p>
</li>
<li><p>try중이라도 예외가 발생할 경우 다음의 코드들은 실행되지 않으며, catch 구문으로 넘어간다.</p>
</li>
<li><p>catch 구문은 else-if 처럼 여러개 쓸 수 있다.</p>
</li>
<li><p>finally는 가장 마지막에 실행하고 싶은 로직이 들어가며, 대표적으로 .close()와 같은 것이 있다.</p>
</li>
</ul>
<h3 id="throws-구문예외-던지기">Throws 구문(예외 던지기)</h3>
<p>예외 처리를 현재의 메서드가 직접 처리하지 않고, 호출한 곳에다 예외의 발생 여부를 통보한다. 호출한 메서드는 이걸 또 Throw 할 것인지 직접 처리할 건지 정해야 한다. (return보다 강력함)</p>
<h3 id="throw와-throws-차이">※throw와 throws 차이</h3>
<p>예외는 개발자가 작성한 로직에 의해 발생된다. 추가적으로 예외에 대한 책임을 전가할 수도 있으며, throw와 throws이다.</p>
<h4 id="throw">throw</h4>
<p>throw는 <strong>예외를 강제로 발생시킨 후, 상위 블럭이나 catch문으로 예외를 던진다.</strong> 
<img src="https://velog.velcdn.com/images/dk_ovo/post/6b7c4797-ba72-4259-826e-6bdf23a055d2/image.png" alt=""></p>
<p>main에서 exceptionTest 메서드를 호출하고, 여기서 throw를 통해 Exception을 강제로 발생하고 있다.
이 때문에 catch 블럭으로 처리가 위임되며, 여기서 예외를 처리하고 있다.</p>
<h4 id="throws">throws</h4>
<p>throws는 <strong>예외가 발생하면 상위 메서드로 예외를 던진다.</strong>
<img src="https://velog.velcdn.com/images/dk_ovo/post/db57956e-a0dd-42ce-aecb-a16739cf0ea6/image.png" alt="">
일반적으로 throws를 사용하면 try, catch 구문이 생성되지 않는데, 이는 throws 구문에 의해 예외 처리를 호출부로 위임하기 때문이다.
즉 throw를 통해 예외를 발생시키고 throws는 이 예외를 밖으로 던지고 있다.</p>
<h4 id="throw--throws">throw + throws</h4>
<p>둘을 함께 사용하면 예외처리를 catch문에서도 하고, 호출부로 예외를 던진다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/5eee8a24-f3f9-4b60-ab69-38bc269de1ea/image.png" alt="">
throw e를 통해 예외를 발생시키면 throws에 의해 상위 메서드로 예외를 던진다. 예외처리를 예외 발생지와 호출부에서 하고 싶으면 이 방법을 쓸 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ OSI 7 계층 정리 ]]]></title>
            <link>https://velog.io/@dk_ovo/OSI-7-%EA%B3%84%EC%B8%B5-TCPIP-4%EA%B3%84%EC%B8%B5</link>
            <guid>https://velog.io/@dk_ovo/OSI-7-%EA%B3%84%EC%B8%B5-TCPIP-4%EA%B3%84%EC%B8%B5</guid>
            <pubDate>Wed, 08 May 2024 04:43:25 GMT</pubDate>
            <description><![CDATA[<h1 id="osi-7계층이란">OSI 7계층이란?</h1>
<p>네트워크 통신이 일어나는 과정을 7단계로 나눈 국제 표준화 기구(ISO)에서 정의한 네트워크 표준 모델 1계층 ~ 7계층 까지 구성되어 있으며, 각 계층을 지날 때 마다. 각 계층에서 Header가 붙고 <strong>수신측은 역순으로 헤더를 분석</strong>하게 된다.</p>
<ol>
<li>물리계층</li>
<li>데이터 링크 계층</li>
<li>네트워크 계층</li>
<li>전송 계층</li>
<li>세션 계층</li>
<li>표현 계층</li>
<li>응용 계층</li>
</ol>
<h2 id="1계층-물리-계층physical-layer">1계층-물리 계층(Physical Layer)</h2>
<p>OSI 7 계층 모델 상의 최하위 계층
단말기기와 전송매체 사이의 인터페이스를 정의하고, 데이터 링크 계층(2계층) 엔티티 간의 비트 전송을 위해 물리적(기계적, 전기적, 기능적, 절차적) 수단을 제공하는 계층</p>
<p>전기적, 기계적 기능적인 특성을 이용해 통신 케이블로 데이터를 전송하는 물리적인 장비 (통신 케이블, 리피터 허브 등...)
사용되는 통신 단위: 비트(Bit)이며 1과 0으로만 나타내지는, 전기적으로 on, off 상태이다.
장비: 통신 케이블, 리피터, 허브</p>
<h3 id="주요-기능">주요 기능</h3>
<ol>
<li>전기적 신호 규격을 정의함 (전송속도, 신호의 레벨 등)</li>
<li>신호의 인코딩/ 디코딩 (선로 부호화)</li>
<li>비트 동기 (프리엠블 처리 등)</li>
<li>전송매체 규격 (매체 종류, 케이블링 커넥터 등.. / 토폴로지 구격도 포함 가능)</li>
<li>물리적 회선 관리 (DTE와 DCE간에 성립되는 물리적 회선에 대한 작동유지,작동 중지 등을 규정)</li>
</ol>
<h2 id="2계층-데이터-링크계층datalink-layer">2계층-데이터 링크계층(DataLink Layer)</h2>
<p>OSI 계층 모델 상에서 2계층
잡음이 있는 인접 노드간의 물리적인 회선을 상위 망계층(Layer 3)이 신뢰적으로 사용할 수 있도록 <strong>전송에러가 없는 통신 채널로 변환시키는 계층</strong>
<img src="https://velog.velcdn.com/images/dk_ovo/post/a4b13859-e3fd-4ec8-8562-8094ad5c005a/image.png" alt=""></p>
<p>물리계층을 통해 송수신되는 정보의 오류와 흐름을 관리하여 안전한 통신의 흐름을 관리
프레임에 물리적 주소(MAC address)를 부여하고 에러검출, 재전송, 흐름제어를 수행
사용되는 전송 단위: 프레임(Frame)
장비: 브릿지, 스위치, 이더넷 등 (여기서 MAC주소를 사용한다.)
-&gt; 브릿지나 스위치를 통해 MAC address를 가지고 물리계층에서 받은 정보를 전달</p>
<h3 id="오류-검출-과정">오류 검출 과정</h3>
<p>오류 검출의 예시: 기존 AA 주소 컴퓨터에서 스위치를 통해 DD로 데이터를 보낼 떄 AA|DD|0100011로 보낸다. 이번엔 그 뒤에 추가로 오류를 검출할 수 있는 코드를 추가한다. (캡쳐에는 0x1A4D)
<img src="https://velog.velcdn.com/images/dk_ovo/post/0296beca-775b-4377-a4f3-3d55eca2a5b2/image.png" alt=""></p>
<p>AA|DD|0100011|<strong>0x1A4D</strong>(추가) 해당 데이터가 잘 보내졌는지 확인할 수 있는 코드가 추가 되었고, 아래 과정을 거치며 오류 확인을 할 수 있게된다.</p>
<ol>
<li>송신 측(AA)에서 계산을 수행하여 오류 확인 코드 생성.</li>
<li>이 코드를 데이터 뒷부분에 추가되어 함께 전송</li>
<li>수신측(DD)에서 도착한 오류코드에 대해 동일한 계싼을 수행</li>
<li>수신 측에서 계산한 값과 프레임에 포함된 원래의 값을 비교</li>
<li>두 값이 일치하면, 데이터 전송이 정상적으로 이뤄진 것으로 판단.</li>
<li>일치하지 않을 경우 -&gt; <strong>오류가 발생한 것으로 간주하고 재전송을 요청</strong></li>
</ol>
<h3 id="주요-기능-1">주요 기능</h3>
<ol>
<li>물리 계층 비트열을, 전송/운반/전달하는 역할</li>
</ol>
<ul>
<li>데이터를 링크화시켜 정확하고 안정적, 신뢰적으로 전송시킴
※ 2계층 관련 구현이 매우 다양함</li>
<li>HDLC, PPP, FDDI, PDH/SDH, ATM, Frame Relay, 이더넷, 무선LAN, 이동통신 등 </li>
</ul>
<ol start="2">
<li>프레이밍(Framing)</li>
</ol>
<ul>
<li>데이터를 프레임(frame)으로 그룹화, 데이터의 프레임화를 물리계층에 의해서 제공되는 비트 파이프(Pipe)를 패킷(또는 프레임)화된 링크(Link)로 변환</li>
<li>전송할 데이터를 전송단위로서의 패킷(또는 프레임)으로 나눠 그룹화시키는 역활</li>
</ul>
<ol start="3">
<li>흐름제어</li>
</ol>
<ul>
<li>보내는 측과 받는 측간의 속도차를 보상</li>
</ul>
<ol start="4">
<li>에러제어</li>
</ol>
<ul>
<li>에러 보정을 위한 에러제어 등의 기능들을 제공</li>
<li>물리 전송매체의 특징상 오류와 잡음이 랜덤하게 발생활 확률이 높으므로 전송 오류를 검출하고 이것을 수정</li>
<li>정확하게 수신되지 않은 패킷들을 재전송 (송신 측에서 타이머와 ACK신호에 의해 전송에러를 알 수 있음)</li>
</ul>
<p>ACK란?: 확인응답(Acknowlegment)로 송신메세지가 정상 수신되었음을, 수신측에서 송신측으로 확인 응답하는 것
용도: 오류제어 및 흐름제어를 위해 사용
방법: 통상, 데이터프레임 안에 포함시켜 응답함</p>
<ol start="5">
<li>순서화 (Sequencing)</li>
</ol>
<ul>
<li>패킷이나 ACK 신호를 잘못 혼동하는 것을 피하기 위해서는 패킷과 ACK 신호에는 Sequence number(일련번호)가 부여되어야만 함 -&gt; 위의 예시에서는 &#39;0100011&#39;가 해당</li>
</ul>
<ol start="6">
<li>데이터 링크 연결 관리 (Data Link Connection Management)</li>
</ol>
<ul>
<li>두 노드 간에 데이터 링크의 설정, 유지, 단락 및 데이터 전송들을 제어</li>
</ul>
<ol start="7">
<li>매체접근제어 (Media Access Control)</li>
</ol>
<ul>
<li>다양한 매체 및 회선형태의 수용 및 다중 사용자 접근 등</li>
</ul>
<ol start="8">
<li>데이터 링크 내 노드간 식별성 제공</li>
</ol>
<p>※ 궁극적으로 데이터링크 프로토콜은 인접한 기기 사이의 통신을 관리하고, 신뢰도가 낮은 전송로를 신뢰도가 높은 전송로로 전환시키는데 주로 사용</p>
<h3 id="물리-계층과-데이터링크-계층간의-비교">물리 계층과 데이터링크 계층간의 비교</h3>
<p>항상 물리 계층(1계층) 상에서는 &#39;잡음&#39;,&#39;간섭&#39;,&#39;왜곡&#39;,&#39;지연&#39; 등의 영향을 받게 됨 따라서 잡음 있는 인접 노드 간을 전송에러 없는 통신 채널로 변환 필요 (2계층-데이터 링크 계층)</p>
<h2 id="3계층-네트워크-계층network-layer">3계층-네트워크 계층(Network Layer)</h2>
<p>OSI 7계층모델에서 3계층에 해당되는 계층
인터넷에서 서브네트워크 간의 연결(패킷 전달)하는 역할을 담당하는 계층</p>
<ul>
<li>인터넷: 라우터들에 의해 분할 연결된 서브네트워크들의 모음
이 계층의 대표적인 프로토콜로는 IP및 X.25가 있음
<img src="https://velog.velcdn.com/images/dk_ovo/post/d2137d48-58b6-4ed1-aa6d-43aca9c4b0d8/image.png" alt=""></li>
</ul>
<p>데이터를 목적지까지 가장 안전하게 빠르게 전달
라우터(Router)를 통해 경로를 선택하고 주소를 정하고(IP) 경로(Route)에 따라 패킷을 전달 &gt; IP 헤더가 붙음
전송되는 단위: 패킷(Packet)
장비: 라우터(Router)</p>
<h3 id="주요-기능-2">주요 기능</h3>
<ol>
<li>경로제어(라우팅)</li>
</ol>
<ul>
<li>단말기 혹은 커퓨터가 어떤 망에 접속되어 있을 때 송신하고자 하는 정보가 망을 통해서 어떻게 상대방의 수신측까지 전달되는지 제어하는 일을 담당 (발신에서 착신까지의 패킷 경로를 제어)</li>
<li>하나 이상의 복수 통신망을 통한 중계를 하며, 개방시스템 간의 데이터를 전송</li>
</ul>
<p>※라우팅: IP주소를 기반으로 통신 데이터를 보낼 최적의 경로를 선택하는 과정으로 라우터에서 담당.</p>
<ol start="2">
<li>투명성</li>
</ol>
<ul>
<li>상위 계층인 전송계층 (4계층)의 경로선택과 중계 등, 망계층 고유의 기능에 대하여 의식하지 않도록 투명하게 하는 역할</li>
</ul>
<ol start="3">
<li>논리적 주소체계 부여 (IP 주소)</li>
</ol>
<ul>
<li>라우팅과 관련된 주소의 지정 등 주소체계 정립</li>
</ul>
<ol start="4">
<li>연결지향성 및 비연결성 서비스 제공</li>
</ol>
<ul>
<li>망계층은 상위의 트랜스포트 계층에게 연결지향성 및 비연결성 서비스 모두를 제공, 연결지향 서비스는 연결의 설정, 사용, 해제를 위한 가장 기초를 가짐</li>
</ul>
<h2 id="4계층-전송-계층transport-layer-host-to-host-layer">4계층-전송 계층(Transport Layer, Host-to-host Layer)</h2>
<p>OSI 7계층의 4계층에 해당
양단간에 어떤 종류의 망이 사용되었는지를 의식하지 않고, 쌍방 응용프로세스간에 투명하고 신뢰성 있게 양단 간의 논리적인 통신을 이루는 계층</p>
<p>종단간 양 호스트 내의 응용 프로세스 상호 간의 통신을 지원</p>
<ul>
<li>Port 번호, 전송방식(TCP/UDP) 결정 -&gt; TCP 헤더 붙음</li>
<li>두 지점간의 신뢰성 있는 데이터를 주고 받게 해주는 역할</li>
<li>신호를 분산하고 다시 합치는 과정을 통해 에러와 경로를 제어</li>
</ul>
<h3 id="주요-기능-및-특징">주요 기능 및 특징</h3>
<ul>
<li>가장 핵심적인 계층이며 또한 가장 복잡한 계층</li>
<li>소프트웨어적인 상위 3개의 계층과 하드웨어적인 하위 3개의 계층 사이에서 중간적인 성격을 띔</li>
</ul>
<ol>
<li>네트워크가 아닌, 호스트 내에서 구동된 프로세스 사이의 연결 확립(End-to-End)</li>
</ol>
<ul>
<li>트랜스포트 계층은 정보전달을 두 호스트(host-to-host)간 보다는, 주로 프로세스 간 (process-to-process)의 통신으로 바꿔줌</li>
<li>양 호스트의 종단간 응용 프로세스 상호 간의 통신을 지원</li>
</ul>
<ol start="2">
<li>투명한 전송</li>
</ol>
<ul>
<li>바로 상위 또는 하위의 계층에서 사용하는 제어방법 및 그 내용에 관계없이 정보가 세션계층 - 전송계층 - 망계층 간에 내용이 바뀜없이 투명(Transparent)하게 전송</li>
<li>즉 경로 선택이나 중계기능에 관여하지 않으며, 양단간(end-to-end)데이터의 투명한 양방향 전송 기능을 제공</li>
</ul>
<ol start="3">
<li>두 종단 프로세스 간에 성립된 세션 제어</li>
</ol>
<ul>
<li>세션(Session)을 갖고 있는 두 이용자 사이의 전송을 위한 종단 간 제어</li>
</ul>
<ol start="4">
<li>신뢰적 전송 지원</li>
</ol>
<ul>
<li>동일 또는 이기종 시스템간에 어떤 망(공중망: PSTN, 패킷공중데이터망: PSDN 등)이 어떻게 연결되었든 간에 관계없이 정보를 틀림없이 상대 단말기에 전달</li>
<li>논리회선(세션, 가상회선 등) 가능</li>
</ul>
<ol start="5">
<li>다중화 &amp; 역다중화 지원</li>
</ol>
<ul>
<li>동시에 여러 개의 논리적 연결을 가능하게 하는 다중화(Multiplexting)</li>
</ul>
<ol start="6">
<li>지연(Delay)에 따른 왜곡 및 대역폭 부족에 대한 일부 보상</li>
</ol>
<h3 id="전송-계층-프로토콜의-복잡성">전송 계층 프로토콜의 복잡성</h3>
<ul>
<li><p>네트워크 계층(3 layer)로 부터 얻은 서비스의 형태(연결지향성 및 비연결성)에 따라, 전송 계층 프로토콜의 크기와 복잡성이 결정</p>
</li>
<li><p>만일 망계층에서 가상회선 능력이 있고, 신뢰할 수 있는 통신 지원이 있으면 전송 계층의 기능이 최소로 축소될 수 있지만, 그 반대의 경우 전송계층이 에러감지와 회복을 위해 많은 노력을 해야 함 (TCP의 경우)</p>
</li>
</ul>
<h3 id="전송-계층-프로토콜transport-protocol들의-예시">전송 계층 프로토콜(Transport Protocol)들의 예시</h3>
<p>TCP/IP 에서는 다음과 같은 프로토콜들이 트랜스포트 계층에 존재: TCP, UDP, SCTP 등..  이러한 프로토콜들이 상위 계층 응용 프로세스를 식별하는 수단 -&gt; <strong>포트번호</strong></p>
<h4 id="tcp-특징">TCP 특징</h4>
<ul>
<li>양단 프로세스 간에 다중 연결 식별이 가능함</li>
<li>식별은 소켓주소에 의함 : 소켓주소 = (송신,수신 IP 주소 + 포트번호)</li>
<li>각 TCP 연결마다 독립적으로 관리됨</li>
<li>신뢰성, 연결지향적</li>
</ul>
<h4 id="udp-특징">UDP 특징</h4>
<ul>
<li>연결성이 없으므로, 단지 1개의 소켓 구조만 있으면 가능하다.</li>
<li>비신뢰성, 비연결성, 실시간</li>
</ul>
<h4 id="sctp-특징">SCTP 특징</h4>
<ul>
<li>UDP, TCP 장점들 만을 취하였으나, NAT,방화벽 통과시에 문제가 있어 대용량 및 낮은 지연을 요하는 전송에만 주로 사용한다.</li>
</ul>
<p>이러한 프로토콜들을, 하위 IP 계층에서 구분하는 수단 : IP 헤더 내 프로토콜 필드(Protocol ID)</p>
<h2 id="5계층-세션-계층session-layer">5계층-세션 계층(Session Layer)</h2>
<ul>
<li><p><strong>통신계층</strong> 네트워크 상에서, 양 종단간 일회용 논리적 연결 SVC(가상회선), TCP 세션 등..</p>
</li>
<li><p><strong>다중처리시스템</strong> 다중사용자 컴퓨터에서, 한 사용자가 로그인 후 ~ 로그아웃 까지의 경과 -&gt; 이 경우 사용 이력 기록을 세션 로그(Log)라고 함</p>
</li>
<li><p>주 지점간의 프로세스 및 통신하는 호스트 간의 연결을 유지</p>
</li>
<li><p>TCP/IP 세션 체결, 포트 번호를 기반으로 <strong>통신세션 구성</strong></p>
</li>
<li><p>API,Socket</p>
</li>
</ul>
<p>※ 통상, 서버 등 다중 세션 가능 장비들은 수없이 많이 연결된 동시 세션의 처리 능력을 갖춰야 한다.</p>
<h3 id="세션-계층-세션-프로토콜-세션-키">세션 계층, 세션 프로토콜, 세션 키</h3>
<h4 id="세션-계층session-layer">세션 계층(Session Layer)</h4>
<ul>
<li>OSI 7 계층 모델의 5계층에 해당하며, 종단 호스트 프로세스 간에 세션을 생성, 유지, 종료하는데 필요한 여러 기능을 제공한다.</li>
</ul>
<h4 id="세션-설정-프로토콜">세션 설정 프로토콜</h4>
<ul>
<li>세션의 설정, 변경 해제와 관련된 프로토콜 (SIP, SDP 등..)</li>
</ul>
<h4 id="세션-키session-key">세션 키(Session Key)</h4>
<ul>
<li>하나의 논리적 세연결 세션 동안만 유효한 암호키</li>
</ul>
<h3 id="주요-기능-3">주요 기능</h3>
<ol>
<li>세션의 설정, 관리 해제 (Session manage)</li>
</ol>
<ul>
<li>세션을 설정 및 해제하는 기능</li>
</ul>
<ol start="2">
<li>대화 관리 (Dialogue manage)</li>
</ol>
<ul>
<li>통상, 토큰을 사용함으로써 대화를 관리</li>
<li>성립된 세션을 통한 상호 대화 관리를 하는 양단간 응용 개체를 위해 토큰 개념이 정의됨</li>
<li>누가 언제 통신하였는지를 결정하며, 토큰을 교환함으로써 구현</li>
<li>프로세스는 토큰을 가졌을 때 전송할 수 있음</li>
</ul>
<p>여기서 토큰은, 어떤 서비스의 실행을 기동하는 권리를 표현하는 것</p>
<ol start="3">
<li>다중화(Multiplexing)</li>
</ol>
<ul>
<li>효율을 높이기 위해, 여러 세션들을 묶어서 1개의 같은 전송계층 접속을 사용할 수 있음 이와 반대로 1개 세션이 속도 등을 위해 다수의 전송계층 접속들을 사용할 수도 있다.</li>
<li>따라서 전송 계층에서와 같이 세션 계층에서도 상향, 하향 다중화가 가능</li>
</ul>
<ol start="4">
<li>대화 단위별 그룹화(check point, synchronization)</li>
</ol>
<ul>
<li>세션 계층은 전송시 점검점, 동기점 등을 삽입함으로써 메세지를 대화 단위로 그룹화 함</li>
<li>만일, 중간에 에러가 발생하면 중단된 대화 단위부터 전송을 다시 시작함</li>
</ul>
<ol start="5">
<li>데이터의 범주화 교환</li>
</ol>
<ul>
<li>OSI는 데이터를 4가지 범주로 구분한 바 있다. (정보 데이터, 급송 데이터, 제어 데이터, 세션 파라미터 협상에 사용되는 데이터)</li>
</ul>
<h3 id="세션-계층-예시">세션 계층 예시</h3>
<h4 id="통신-중-세션-형태-tcp-세션-등">통신 중 세션 형태: TCP 세션 등</h4>
<h4 id="네트워크-지원용-api--socket-rpc-nfs-smb-netbios-등">네트워크 지원용 API : Socket, RPC, NFS, SMB, NetBIOS 등</h4>
<h3 id="데이터베이스-쿼리용-sql">데이터베이스 쿼리용: SQL</h3>
<h2 id="6계층-표현-계층presentation-layer">6계층-표현 계층(Presentation Layer)</h2>
<p>OSI 7계층 중 6 계층에 해당
네트워크 상의 여러 이기종 시스템들이 저마다 다른 데이터 표현 방식을 사용하는데, <strong>이를 하나로 통일된 구문 형식으로 변환시키는 기능을 수행</strong>하는 계층</p>
<ul>
<li>전송하는 <strong>데이터 표현방식을 결정</strong>(ex. 데이터 변환, 압축, 암호화 등)</li>
<li>파일 인코딩, 명령어를 포장, 압축, 암호화</li>
<li>JPEG, MPEG, GIF, ASCII 등</li>
</ul>
<h3 id="표현-계층의-역할">표현 계층의 역할</h3>
<h4 id="데이터-값이-여러-다양한-시스템에서-다른-방법으로-표현-및-저장됨">데이터 값이 여러 다양한 시스템에서 다른 방법으로 표현 및 저장됨</h4>
<ul>
<li><p>정수형 값은 시스템에 따라 16비트, 24비트, 36비트 등으로 표현되므로, 두 응용 계층 프로토콜 개체가 서로 통신할 때 양쪽 개체 간의 메세지가 같은 뜻 (공통의 어휘)로 교환되어야 함</p>
</li>
<li><p>따라서 두 응용계층 간의 메세지 교환은 동일한 가상의 문법이 상호 합의되어 있어야 함 (이러한 번역기/변환기 역할을 수행하는 계층이 표현계층)</p>
</li>
</ul>
<h3 id="주요-기능-4">주요 기능</h3>
<ol>
<li><p>응용 계층(7 layer)의 다양한 표현양식(Syntax)을 공통의 형식으로 변환</p>
</li>
<li><p>암호화 (Encryption)</p>
</li>
<li><p>암축(Compression)</p>
</li>
<li><p>코드 변환</p>
</li>
</ol>
<ul>
<li>서로 다른 상이한 형태의 코드변환 (ASCII, EBCDIC, binary 등), 파일 변환, 문장 축소화 등의 기능 수행</li>
</ul>
<ol start="5">
<li>가상 터미널 규약</li>
</ol>
<ul>
<li>라인과 스크린의 길이, 라인의 종료 약속, 페이지 모드, 커서의 특성 등이 상호간에 다르므로 가상적인 터미널을 만든다.</li>
</ul>
<h2 id="7계층-응용-계층application-layer">7계층-응용 계층(Application Layer)</h2>
<p>OSI 7 계층의 최종 목적지로, 응용 프로세스와 직접 관계하여 일반적인 응용 서비스를 수행(ex. explore, chrome 등..)</p>
<h3 id="응용어플리케이션-응용-프로그램-응용-계층">응용(어플리케이션), 응용 프로그램, 응용 계층</h3>
<p>응용(Application)</p>
<ul>
<li>다양한 범주의 정보처리 기능들을 총칭 (컴퓨팅 작업)</li>
</ul>
<p>응용 프로그램(App)</p>
<ul>
<li>컴퓨터 사용자와의 상호작용을 통해, 특정 작업을 처리하는 특정 소프트웨어를 칭함</li>
</ul>
<p>응용 계층(Application Layer)</p>
<ul>
<li>여러 하위 통신 프로토콜 개체들에 대해, 사용자 관점의 인터페이스를 제공하는 통신 계층</li>
</ul>
<h3 id="응용계층-내-프로세스-간의-통신">응용계층 내 프로세스 간의 통신</h3>
<ul>
<li>응용계층 프로세스들 사이의 통신은, 하위 표현계층이 제공하는 서비스를 이용한다. 즉 데이터의 형식을 정하고(format), 부호화하고(code), 암호화하고(encrypt), 압축하는 서비스를 통하여 이뤄진다.</li>
</ul>
<h4 id="응용-프로세스-예시">응용 프로세스 예시</h4>
<ul>
<li>전자메일, 가상단말, 파일 송&amp;수신, 웹 응용 등</li>
</ul>
<h4 id="응용계층-관련-프로토콜">응용계층 관련 프로토콜</h4>
<ul>
<li>OSI 프로토콜: FTAM, CMIP 등</li>
<li>TCP/IP 프로토코리 FTP(파일 전송), SMTP(메일전송), HTTP(웹문서 전송), TELNET(문자단말) 등</li>
</ul>
<p>[참조]
<a href="https://lxxyeon.tistory.com/155">https://lxxyeon.tistory.com/155</a>
<a href="https://rf-yeolmu.tistory.com/138">https://rf-yeolmu.tistory.com/138</a>
<a href="http://www.ktword.co.kr/test/view/view.php?no=424">http://www.ktword.co.kr/test/view/view.php?no=424</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JDK 및 Java 실행 원리]]></title>
            <link>https://velog.io/@dk_ovo/JDK-%EB%B0%8F-Java-%EC%8B%A4%ED%96%89-%EC%9B%90%EB%A6%AC</link>
            <guid>https://velog.io/@dk_ovo/JDK-%EB%B0%8F-Java-%EC%8B%A4%ED%96%89-%EC%9B%90%EB%A6%AC</guid>
            <pubDate>Wed, 08 May 2024 02:20:40 GMT</pubDate>
            <description><![CDATA[<h1 id="jvm-java-virtual-machine">JVM (Java Virtual Machine)</h1>
<p>&#39;자바를 실행하기 위한 가상 기계(컴퓨터)&#39; 라고 볼 수 있다.
<strong>Java는 OS 에 종속적이지 않다는 특징</strong>이 있으며, OS에 종속받지 않고 실행이 되기 위해선 OS 위에서 Java를 실행시킬 무언가가 필요하며 그게 JVM이다.</p>
<p>정리하면 <strong>OS에 종속받지 않고 CPU 가 Java를 인식, 실행할 수 있게 하는 가상 컴퓨터</strong>이다.</p>
<h2 id="컴파일-과정">컴파일 과정</h2>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/2ff84b61-a498-469a-b0b0-619e88eb52e4/image.png" alt=""></p>
<ol>
<li><p>개발자가 <strong>자바 소스코드 (.java)</strong> 파일을 작성</p>
</li>
<li><p>자바 컴파일러(Java Compiler = javac)가 자바 소스 파일을 컴파일 진행, 이때 나오는 파일은 자바 <strong>바이트 코드(.class)</strong> 파일로 아직 OS가 읽을 수 없지만, JVM은 이해할 수 있는 코드로 변환한다. 이때 바이트 코드의 각 명령어는 1바이트 크기의 Opcode와 추가 피연산자로 이뤄져 있다.</p>
</li>
<li><p>컴파일된 바이트 코드 (.class)를 JVM의 클래스 로더(Class Loader)에 전달한다.</p>
</li>
<li><p>클래스 로더는 동적로딩(Dynamic Loading)을 통해 필요한 클래스들을 로딩 및 링크하여 런타임 데이터 영역 (Runtime Data Area) 즉 JVM의 메모리에 올린다.</p>
</li>
</ol>
<ul>
<li><p>[클래스 로더 세부 동작]</p>
<ol>
<li>로드</li>
</ol>
<ul>
<li>class 파일을 가져와서 JVM의 메모리에 로드한다.</li>
</ul>
<ol start="2">
<li>검증</li>
</ol>
<ul>
<li>자바 언어 명세(Java Language Specification) 및 JVM 명세에 명시된 대로 구성되어 있는지 검사한다.</li>
</ul>
<ol start="3">
<li>준비</li>
</ol>
<ul>
<li>클래스가 필요로 하는 메모리를 할당(필드, 메서드, 인터페이스 등..)</li>
</ul>
<ol start="4">
<li>분석</li>
</ol>
<ul>
<li>클래스의 상수 풀 내 모든 심볼릭 레퍼런스를 다이렉트 레퍼런스로 변경한다.</li>
</ul>
<ol start="5">
<li>초기화</li>
</ol>
<ul>
<li>클래스 변수들을 적절한 값으로 초기화한다. (Static 필드)</li>
</ul>
</li>
</ul>
<ol start="5">
<li>실행엔진(Executin Engine)은 <strong>JVM 메모리에 올라온 바이트 코드들을 명령어 단위로 하나씩 가져와서 실행</strong>한다. 이때 실행 엔진은 두가지의 방식으로 변경한다.</li>
</ol>
<p>a. 인터프리터</p>
<ul>
<li>바이트 코드 명령어를 하나씩 읽어서 해석하고 실행한다. 하나 하나의 실행은 빠르나, 전체적인 실행 속도가 느린 단점을 가지고 있다.</li>
</ul>
<p>b. JIT 컴파일러(Just-In-Time Compiler)</p>
<ul>
<li>인터프리터의 단점을 보완하기 위해 도입된 방식이다.</li>
<li>바이트 코드 전체를 컴파일하여 바이너리 코드로 변경하고, 이후에는 해당 메서드를 더이상 인터프리팅 하지 않고, 바이너리 코드로 직접 실행하는 방식이다. 하나씩 인터프리팅 하여 실행하는 것이 아니라 바이트 코드 전체가 컴파일 된 바이너리 코드를 실행하는 것이기 때문에 전체적인 실행 속도는 인터프리팅에 비해 훨씬 빠르다.</li>
</ul>
<h4 id="간단-요약">간단 요약</h4>
<ol>
<li><p>java 소드코드, 즉 원시코드 .java 는 CPU가 인식하지 못하여 컴파일이 필요하다.</p>
</li>
<li><p>OS에 도달하기 전(이때 OS는 .java가 기계어가 아니기 때문에 인식 못함) JDK안에 있는 javac를 통해 JVM이 인식할 수 있는 Java bytecode인 .class 로 변환된다. (java compiler가 .java 파일을 .class 라는 java bytecode로 변환)</p>
</li>
</ol>
<p>※ Java Compiler는 JDK를 설치하면 bin에 존재하는 javac.exe를 말한다. (JDK 안에 java compiler가 포함되어 있음), javac 명령어를 통해 .java 파일을 .class로 컴파일 할 수 있다.</p>
<ol start="3">
<li>변환된 bytecode (.class)는 기계어가 아니기 때문에 OS에서 실행할 수 없다. 이때, JVM이 OS가 bytecode를 이해할 수 있도록 해석해준다. 이 때문에 ByteCode는 JVM위에서 OS와 상관없이 실행될 수 있는 것이다.</li>
</ol>
<h3 id="바이트코드">바이트코드</h3>
<p>바이트코드란? : 가상 컴퓨터(VM)에서 돌아가는 실행 프로그램을 위한 이진 표현법. (0과1)</p>
<p>자바 바이트 코드(Java bytecode)는 JVM이 이해할 수 있는 언어로 변환된 자바 소스코드를 의미한다.</p>
<p>자바 컴파일러에 의해 변환된 코드의 명령어 크기가 1바이트라서 자바 바이트 코드로 불리고 있다.</p>
<p>바이트코드는 다시 실시간 번역기 또는 JIT 컴파일러에 의해 바이너리 코드로 변환된다.</p>
<h3 id="jit-compiler">JIT compiler</h3>
<p>JIT 컴파일(just-in-time compiliation) 또는 동적 번역(dynamic translation)이라고 한다.</p>
<p>JIT 컴파일러는 <strong>프로그램을 실제 실행하는 시점에 기계어로 번역하는 컴파일러</strong>다.</p>
<p>JIT Compiler 도입 배경
인터프리터 방식의 단점을 보완하기 위해 도입 되었다. 인터프리터 방식으로 실행하다가 적절한 시점에 바이트 코드 전체를 컴파일하여 기계어로 변경하고, 이후에는 더이상 인터프리팅 하지 않고 기계어로 직접 실행하는 방식이다.</p>
<p>기계어(컴파일된 코드)는 캐시에 보관하기 때문에 한번 컴파일된 코드는 빠르게 수행하게 된다.</p>
<p>자바에서는 자바 컴파일러가 자바 프로그램 코드를 바이트 코드로 변환한 다음, 실제 바이트 코드를 실행하는 시점에서 JVM 정확히는 JRE이 바이트코드를 JIT 컴파일을 통해 기계어로 변환한다.</p>
<h2 id="jvm-구성-요소">JVM 구성 요소</h2>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/3ebc0e47-1208-414a-bfbf-c8fdbcc0004c/image.png" alt=""></p>
<p>JVM은 다음과 같이 구성되어 있다.</p>
<ul>
<li>클래스 로더 (Class loader)</li>
<li>실행 엔진 (Execution Engine)<ul>
<li>인터프리터(Interpreter</li>
<li>JIT 컴파일러(Just-in-Time)</li>
<li>가비지 컬렉터(Garbage Collector)</li>
</ul>
</li>
<li>런타임 데이터 영역(Runtime Data Area)</li>
</ul>
<h3 id="클래스-로더">클래스 로더</h3>
<p>JVM 내로 클래스 파일 .class 을 로드하고, 링크를 통해 배치하는 작업을 수행하는 모듈이다.</p>
<p>런타임시 동적으로 클래스를 로드하고 jar 파일 내 저장된 클래스들을 JVM위에 탑재한다.</p>
<p>클래스를 처음으로 참조할 때, 해당 클래스를 로드하고 링크하는 역할을 한다.</p>
<h3 id="실행-엔진">실행 엔진</h3>
<p>클래스를 실행시키는 역할이다.
클래스로더가 JVM 내의 런타임 데이터 영역에 바이트 코드를 배치시키고, 이것은 실행엔진에 의해 실행된다.</p>
<p>자바 바이트 코드 (.class)는 기계가 바로 수행할 수 있는 언어보다는 인간이 보기 편한 형태로 기술된 것이다. 따라서 실행 엔진은 이와 같은 바이트 코드를 실제로 JVM 내부에서 기계가 실행할 수 있는 형태로 변경한다.</p>
<h4 id="인터프리터">인터프리터</h4>
<p>자바 바이트 코드를 명령어 단위로 읽어서 실행한다. 하지만 한줄씩 수행하기 때문에 느리다는 단점이 있다.</p>
<h4 id="jit-compiler-just-in-time-compiler">JIT compiler (Just-In-Time compiler)</h4>
<p>인터프리터 방식으로 실행하다가 적절한 시점에 바이트 코드 전체를 컼파일하여 기계어로 변경 후, 이후에는 더이상 인터프리팅 하지않고 기계어로 직접 실행하는 방식</p>
<h4 id="가비지-컬렉터-garbage-collector">가비지 컬렉터 (Garbage Collector)</h4>
<p>더 이상 사용되지 않는 인스턴스를 찾아서 메모리에서 삭제함</p>
<h3 id="runtime-data-area">Runtime Data Area</h3>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/702886db-3b76-4bd4-8211-a0eb48c7391f/image.png" alt="">
프로그램을 수행하기 위해서 OS에서 할당받은 메모리 공간</p>
<h4 id="pc-register">PC Register</h4>
<p>Thread가 시작될 때 생성되며, 생성될 때 마다 생성되는 공간으로, 스레드마다 하나씩 존재한다.</p>
<p>Thread가 어떤 부분을 어떤 명령으로 실행해야 하는지에 대한 기록을 하는 부분으로 현재 수행중인 JVM 명령의 주소를 갖는다.</p>
<p>※ 프로세스란?
단순히 실행중인 프로그램(Program)을 말하며, 사용자가 작성한 프로그램이 운영체제에 의해 메모리 공간을 할당받아 실행중인 것을 말한다.</p>
<p>프로세스는 프로그램에 사용되는 데이터와 메모리 등의 자원 그리고 스레드로 구성된다.</p>
<p>※ 스레드란?
프로세스 내에서 실제로 작업을 수행하는 주체를 의미
모든 프로세스에는 한개 이상의 스레드가 존재하여 작업을 수행한다.</p>
<p>또한, 두개 이상의 스레드를 가지는 프로세스를 멀티스레드 프로세스(multi-threaded process)라고 한다.</p>
<h4 id="jvm-stack">JVM Stack</h4>
<p>프로그램 실행과정에서 임시로 할당되었다가 <strong>메소드를 빠져나가면 바로 소멸되는 특성의 데이터를 저장하기 위한 영역</strong>이다.</p>
<p>각종 형태의 변수나 임시 데이터, 스레드나 메소드의 정보를 저장한다.</p>
<p>메소드 호출 시마다 각각의 스택 프레임(해당 메서드만을 위한 공간)이 생성된다, 메서드 수행이 끝나면 프레임 별로 삭제를 한다.</p>
<p>메소드 안에서 사용되는 값들을 저장한다. 또 호출된 메소드의 매개변수, 지역변수, 리턴 값 및 연산시 일어나는 값들을 임시로 저장한다.</p>
<h4 id="native-method-stack">Native method stack</h4>
<p>자바 프로그램이 컴파일되어 생성되는 바이트 코드가 아닌 <strong>실제 실행할 수 있는 기계어로 작성된 프로그램을 실행시키는 영역</strong>.</p>
<p>Java가 아닌 다른 언어로 작성된 코드를 위한 공간
Java Native Interface를 통해 바이트 코드로 전환하여 저장하게 된다.</p>
<p>일반 프로그램처럼 커널이 스택을 잡아 독자적으로 프로그램을 실행시키는 영역</p>
<h4 id="method-area--텍스트class-area--static-area">Method Area (= <strong>텍스트</strong>Class Area = Static Area)</h4>
<p><strong>클래스 정보를 처음 메모리 공간에 올릴 때 초기화되는 대상을 저장하기 위한 메모리 공간</strong></p>
<h4 id="runtime-constant-pool">Runtime Constant Pool</h4>
<p>스태틱 영역에 존재하는 별도 관리 영역
상수 자료형(final)을 저장하여 참조하고 중복을 막는 역할을 수행한다.</p>
<h4 id="heap-영역">Heap 영역</h4>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/b1e58e59-2198-49a1-8e19-928572e01fe7/image.png" alt=""></p>
<p>객체를 저장하는 가상 메모리 공간. new 연산자로 생성되는 객체와 배열들을 저장한다.</p>
<p>Class Area(Static Area)에 올라온 클래스들만 객체로 생성할 수 있다.</p>
<p>Prermanent Generation
영구적인 세대이다. 생성된 객체들의 정보의 주소값이 저장된 공간이다. 클래스 로더에 의해서 load되는 Class, Method등에 대한 Meta 정보가 저장되는 영역이고 JVM에 의해 사용된다.
Reflection을 사용하여 동적으로 클래스가 로딩되는 경우에 사용된다.</p>
<p>※ Reflection이란?
객체를 통해 클래스의 정보를 분석해 내는 프로그래밍 기법
구체적인 클래스 타입을 알지 못해도, 컴파일된 바이트 코드를 통해 역으로 클래스의 저보를 알아내어 사용할 수 있다.</p>
<h2 id="jdk와-jre의-차이">JDK와 JRE의 차이</h2>
<h3 id="jdk-java-development-kit">JDK (Java Development Kit)</h3>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/c4114765-27ce-4d60-a834-dc30157a74d0/image.png" alt="">
Java를 사용하기 위해 모든 필요한 기능을 갖춘 Java용 SDK(Software Development Kit)이다.</p>
<p>※ SDK(Software Develop Kit) 란?
하드웨어 플랫폼, 운영체제 또는 프로그래밍 언어 제작사가 제공하는 툴이며 키트의 요소는 제작사마다 다르다.
SDK의 대표적인 예로 JDK 등이 있으며, SDK를 활용하여 애플리케이션을 개발할 수 있다.</p>
<p><strong>JDK는 JRE를 포함</strong>하고 있다. 
JRE에 있는 모든 것 뿐만 아니라 컴파일러(javac)와 jdb, javadoc와 같은 도구도 있다.</p>
<p><strong>JDK는 프로그램을 생성, 실행 컴파일</strong> 할 수 있다.</p>
<h3 id="jre-java-runtime-environment">JRE (Java Runtime Environment)</h3>
<p><strong>JVM + 자바 클래스 라이브러리 (Java Class Library)등으로 구성</strong>되어 있다.
컴파일 된 Java 프로그램을 실행하는데 필요한 패키지이다.</p>
<p>JDK: 자바 프로그램을 실행, 컴파일, 개발용 도구이며 JRE,JVM을 모두 포함하는 포괄적인 키트이다.
JRE: 자바 프로그램을 실행할 수 있게 하는 도구이며 JVM을 포함하고 있다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/2efe84d6-be6e-441d-b78e-4abd558eaf0c/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CS Study - GC(Garbage Collection)]]></title>
            <link>https://velog.io/@dk_ovo/CS-Study-GCGarbage-Collection</link>
            <guid>https://velog.io/@dk_ovo/CS-Study-GCGarbage-Collection</guid>
            <pubDate>Sun, 05 May 2024 00:10:18 GMT</pubDate>
            <description><![CDATA[<h1 id="gcgarbage-collection이란">GC(Garbage Collection)이란?</h1>
<p>가비지컬렉션은 Java의 메모리 관리 방법 중 하나로 JVM의 <strong>Heap 영역에서 동적으로 할당됐던 메모리 중 필요없게 된 메모리 객체를 모아서 주기적으로 제거하는 프로세스</strong>를 말한다.</p>
<p>C 또는 C++ 언어에서는 가비지 컬렉션이 없어서 프로그래머가 직접 수동으로 메모리 할당과 해제를 해줘야하는 번거로움이 있지만, Java에서는 가비지컬렉터가 메모리 관리를 대신 해주기 때문에 효율적으로 메모리를 사용할 수 있게 해주며, 개발자는 개발에만 집중 할 수 있게 해준다.</p>
<h1 id="gc의-대상">GC의 대상</h1>
<p>가비지 컬렉션은 특정 객체가 garbage인지 아닌지를 도달성, 도달능력(Reachability)이라는 개념을 적용한다.</p>
<p>객체에 레퍼런스가 있으면 Reachable로 구분되며, 객체에 유효한 레퍼런스가 없으면 Unreachable로 구분 후 수거한다.</p>
<p>Reachable: 객체가 참조되고 있는 상태
Unreachable: 객체가 참조되고 있지 않은 상태</p>
<h1 id="gc의-동작-과정">GC의 동작 과정</h1>
<p>간단한 원리는 가비지 컬렉션이 될 대상 객체를 <strong>식별(Mark)</strong> 하고 <strong>제거(Sweep)</strong> 하며 객체가 제거되어 파편화된 메모리 영역을 앞에서 부터 채워나가는 <strong>작업(Compaction)</strong>을 수행한다.</p>
<h3 id="mark-과정">Mark 과정</h3>
<p>먼저 Root Space로부터 그래프 순회를 통해 연결된 객체들을 찾아내어 각각 어떤 객체를 참조하고 있는지 찾은 후 마킹하는 과정</p>
<p><strong>※Root Space란?</strong>: 힙 영역에 있는 객체들을 참조하고 있는 메모리 영역의 집합 (ex. Stack의 로컬변수, Method Area의 Static 변수)</p>
<h3 id="sweep-과정">Sweep 과정</h3>
<p>참조하고 있지 않은 객체 즉 Unreachable 객체들을 Heap에서 제거한다.</p>
<h3 id="compact-과정">Compact 과정</h3>
<p>Sweep 후에 분산된 객체들을 Heap의 시작 주소로 모아 메모리가 할당된 부분과 그렇지 않은 부분으로 압축한다.</p>
<h1 id="heap의-메모리-구조">Heap의 메모리 구조</h1>
<p>JVM의 힙(Heap) 영역은 동적 레퍼런스 데이터가 저장되는 공간으로서, <strong>가비지 컬렉션에 대상이 되는 공간</strong>이다.</p>
<p>Heap영역은 처음 설계될 때 다음의 2가지를 전제 (Weak Generational Hypothesis)로 설계되었다.</p>
<ol>
<li>대부분의 객체는 금방 접근 불가능한 상태(Unreachable)가 된다.</li>
<li>오래된 객체에서 새로운 객체로의 참조는 아주 적게 존재한다.</li>
</ol>
<p>즉, 객체는 대부분 일회성되며, 메모리에 오랫동안 남아있는 경우는 드물다는 것이다. 
이러한 특성을 이용해 JVM 개발자들은 보다 효율적인 메모리 관리를 위해, 객체의 생존 기간에 따라 물리적인 Heap 영역을 나누게 되었고 <strong>Young 과 Old 총 2가지 영역으로 설계</strong>하였다.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/93ffa486-6738-4a7d-aa24-628f30cb97c3/image.png" alt=""></p>
<h3 id="young-영역young-generation">Young 영역(Young Generation)</h3>
<p>새롭게 객체가 할당 (Allocation)되는 영역
대부분의 객체가 금방 Unreachable 상태가 되기 때문에, 많은 객체가 Young 영역에 생성되었다가 사라진다.
Young 영역에 대한 가비지 컬렉션 (Garbabe Collectio)을 Minor GC라고 부른다.</p>
<h3 id="old-영역-old-generation">Old 영역 (Old Generation)</h3>
<p>Young 영역에서 Reachable 상태를 유지하여 살아남은 객체가 복사되는 영역
Young 영역보다 크게 할당되며, 영역의 크기가 큰 만큼 가비지는 적게 발생한다.
Old 영역에 대한 GC를 Major GC 또는 Full GC라고 부른다.</p>
<p>여기서 그치지 않고 또 다시 힙 영역은 더욱 효율적인 GC를 위해 <strong>Young 영역을 3가지 영역(Eden, survivor0, survivor 1)으로 나눈다.</strong></p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/cff5cd29-fb9a-4955-827d-8b3678ced6d0/image.png" alt=""></p>
<h3 id="eden">Eden</h3>
<p>new 를 통해 새로 생성된 객체가 위치.
정기적인 쓰레기 수집 후 살아남은 객체들을 Survivor 영역으로 보냄</p>
<h3 id="survivor-0--survivor-1">Survivor 0 / Survivor 1</h3>
<p>최소 1번 이상 GC에서 살아남은 객체가 존재하는 영역
Survivor영역엔 특별한 규칙이 있는데, Survivor 0 또는 Survivor 1 둘 중 하나에는 꼭 비어 있어야 한다.</p>
<p>이렇게 하나의 힙 영역을 세부적으로 쪼갬으로서 객체의 생존 기간을 면밀하게 제어하여 가비지 컬렉터(GC)를 보다 정확하게 불필요한 객체를 제거하는 프로세스를 실행하도록 한다.</p>
<h1 id="minor-gc">Minor GC</h1>
<p>Minor GC란 <strong>Young Generation 영역에서 발생되는 GC</strong>를 일컫는다.
Young Generation 영역은 짧게 살아남는 메모리들이 존재하는 공간이며, 모든 객체는 처음에는 Young Generation에 생성되게 된다.</p>
<p>Young Generation의 공간은 Old Generation에 비해 상대적으로 작기 때문에 <strong>메모리 상의 객체를 찾아 제거하는데 적은 시간이 걸린다.</strong> (공간의 크기가 작은 곳에서 찾기 때문)</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/b5375bea-b561-4708-b0d5-db7ed3d7772b/image.png" alt=""></p>
<h3 id="minor-gc-동작-과정">Minor GC 동작 과정</h3>
<ol>
<li>처음 객체가 생성되면 Young Generation 영역의 Eden 영역에 위치한다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/9ed22693-71d6-47a2-98f7-83449319efd2/image.png" alt=""></li>
</ol>
<ol start="2">
<li><p>객체가 계속 생성되어 Eden 영역이 꽉차게 되면 Minor GC가 실행
<img src="https://velog.velcdn.com/images/dk_ovo/post/688fc485-94ca-4d16-bcaf-94477023e6b9/image.png" alt=""></p>
</li>
<li><p>Mark 동작을 통해 Reachable 객체를 탐색
<img src="https://velog.velcdn.com/images/dk_ovo/post/88682206-6784-49be-b5dd-70d1b7c70052/image.png" alt=""></p>
</li>
<li><p>Eden 영역에서 살아남은 객체는 1개의 Survivor 영역으로 이동
<img src="https://velog.velcdn.com/images/dk_ovo/post/2819b2f8-2e3a-4c10-9bee-82ec1e9378c4/image.png" alt=""></p>
</li>
<li><p>Eden 영역에서 사용되지 않은 객체 (Unreachable)의 메모리를 해제 (Sweep)
<img src="https://velog.velcdn.com/images/dk_ovo/post/30152716-4372-42a8-917d-8bae9cec56cc/image.png" alt=""></p>
</li>
<li><p>살아남은 모든 객체들은 age의 값이 1씩 증가
<img src="https://velog.velcdn.com/images/dk_ovo/post/3db7d8bb-439b-4f7b-945a-4a8dc1d5fb49/image.png" alt=""></p>
</li>
</ol>
<h4 id="age-값이란">age 값이란?</h4>
<p>Survivor 영역에서 객체의 객체가 살아남은 횟수를 의미하는 값이며, Object Header에 기록된다.
만일 age 값이 임계값에 다다르면 Promotion(Old 영역으로 이동) 여부를 결정한다.
JVM 중 가장 일반적인 HotSpot JVM의 경우 이 age의 기본 임계값은 31이다.
객체 헤더에 age를 기록하는 부분이 6bit 로 되어 있기 때문이다.</p>
<ol start="7">
<li>다시 Eden 영역에 신규 객ㄱ체들이 가득 차게 되면 다시한번 Minor GC를 발생하고 Mark한다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/c34b667d-5828-4212-9e95-4d7d621c7c61/image.png" alt=""></li>
</ol>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/9e6a7abc-241b-4fa4-bbc5-84e1d629192c/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/51c487fd-5ed7-4216-86b5-7cdf17690c1f/image.png" alt=""></p>
<ol start="8">
<li><p>Marking 한 객체들을 비어있는 Survival1으로 이동하고 Sweep한다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/84fbdff0-2059-4d8b-9dd3-e2f1837d7743/image.png" alt=""></p>
</li>
<li><p>살아남은 모든 객체들은 age값이 1씩 증가 
<img src="https://velog.velcdn.com/images/dk_ovo/post/5bc4e5c5-2890-43ca-bf30-1de5ba18df5e/image.png" alt=""></p>
</li>
</ol>
<p>1 ~ 9 까지의 과정들을 계속해서 반복하게 된다.</p>
<h1 id="major-gc-full-gc">Major GC (Full GC)</h1>
<p>Old Generation은 길게 살아남는 메모리들이 존재하는 공간이다.</p>
<p>Old Generation의 객체들은 거슬러 올라가면 처음에는 Young Generation에 의해 시작되었으나, GC 과정 중에 제거되지 않은 경우 age 임계값이 차게되어 이동된 경우이다.</p>
<p>Major GC는 Minor GC의 객체들이 계속 Promotion되어 Old 영역의 메모리가 부족해지면 발생하게 된다.</p>
<ol>
<li><p>Young Generation 영역의 객체의 임계값에 (해당 자료는 8로 가정) 도달하게 될 경우
<img src="https://velog.velcdn.com/images/dk_ovo/post/045f17fc-3291-4c8a-9ca5-31027965ee7f/image.png" alt=""></p>
</li>
<li><p>해당 객체들은 Old Generation으로 이동되며, <strong>이를 Promotion</strong> 이라 부른다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/d5aa7cfc-2e2a-42b2-aa36-a292980a6813/image.png" alt=""></p>
</li>
<li><p>이 과정이 반복되며 Old Generation 영역의 공간(메모리)가 부족하게 되면 Major GC가 발생하게 된다.</p>
</li>
</ol>
<p>Major GC는 Old Generation 영역의 데이터가 가득 차면 GC를 실행하는 단순한 방식이다.</p>
<p>Old 영역에 할당된 메모리가 허용치를 넘게 되면, Old 영역에 있는 모든 객체들을 검사하여 참조되지 않는 객체들을 한꺼번에 삭제하는 Major GC가 실행되게 된다.</p>
<p>하지만 <strong>Old Generation은</strong> Young Generation에 비해 <strong>상대적으로 큰 공간을 가지고 있어, 이 공간에서 메모리 상의 객체 제거에 많은 시간이 걸리게 된다.</strong></p>
<p>Young Generation 영역은 Old 보다 크기가 작기 때문에 GC가 보통 0.5 ~ 1초 사이에 끝난다. 따라서 Minor GC는 애플리케이션에 크게 영향을 주지 않는다.</p>
<p>하지만 Old 영역의 Major GC는 일반적으로 Minor GC보다 오래 걸리며, <strong>10배 이상의 시간</strong>을 사용한다.</p>
<p>Major GC가 일어나면 Thread가 멈추고 Mark and Sweep 작업을 해야 해서 CPU에 부하를 주기 때문에 멈추거나 버벅이는 현상이 일어나기 때문에 <strong>Stop-The-World</strong> 같은 문제가 발생하게 된다.</p>
<h3 id="stop-the-world">Stop The World</h3>
<p>GC를 실행하기 위해 JVM이 모든 애플리케이션 실행을 멈추는 것
stop-the-world가 발생하면 GC를 실행하는 쓰레드를 제외한 나머지 쓰레드는 모두 작업을 멈춘다.
GC작업을 완료한 이후에 작업을 다시 시작한다.
<strong>어떤 가비지 컬렉터 알고리즘을 사용하더라도 stop-the-world는 발생</strong>한다.</p>
<h3 id="minor-gc-와-major-gc-차이점-간단-정리">Minor GC 와 Major GC 차이점 간단 정리</h3>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/b3a75c39-7be3-4c6a-a4a3-8530ba6fd2df/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[8월 14일 KPT 회고]]]></title>
            <link>https://velog.io/@dk_ovo/8%EC%9B%94-14%EC%9D%BC-KPT-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@dk_ovo/8%EC%9B%94-14%EC%9D%BC-KPT-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Mon, 14 Aug 2023 11:12:43 GMT</pubDate>
            <description><![CDATA[<h2 id="진행">진행</h2>
<p>Trello 서비스를 구현하는 프로젝트
필수 작업: 백엔드 로그인 기능, Board CRUD 기능, ColumnList CRUD 기능, Card CRUD기능, CardComment CRUD 기능
추가 작업: 프론트엔드 구현</p>
<h2 id="느낀점">느낀점</h2>
<ol>
<li><p>백엔드 기능을 구현함에 있어서 엔티티 연관관계에 대해 고민하고 배울 수 있었다. 특히 ManㅛManyToMany 관계에 대해 중간 테이블을 설정하여 풀어보면서 새로운 경험을 할 수 있었다.</p>
</li>
<li><p>프론트엔드와 백엔드 간의 연결 어려움 -&gt; 프론트엔드를 배우지 않다 보니 GPT를 사용한다 한들 이를 이해해야 수정을 할 수 있는데 할 수 없는 점이 어려웠음.</p>
</li>
<li><p>깃 활용을 하면서 각자 다른 브랜치에 작업 후 메인으로 머지하는 과정에서 commit 히스토리가 꼬여서  이전 버젼으로 돌아가게 되어 작업 내용이 사라지는 경험을 하여 깃에 대해 좀 더 알아갈 수 있었다. -&gt; 모두가 각자 브랜치를 만들어서 작업을 하는게 맞는지 혹은 다른 방법이 있는지 고민 필요</p>
</li>
</ol>
<h3 id="kpt">KPT</h3>
<p>Keep</p>
<ol>
<li>서로 막히는 부분이 있으면, 맡은 파트가 아니여도 적극적으로 도와줬음</li>
<li>엔티티 연관관계에 대해서 초기에 설정을 잘 잡고 시작하였음</li>
<li>하루 2번의 회의를 통해 소통을 원활이 하였음</li>
</ol>
<p>Problem</p>
<ol>
<li>깃 허브를 병합하는 과정에서 커밋 히스토리가 꼬여 하루정도 해결하느라 시간이 많이 빼앗김</li>
<li>프론트엔드를 완벽하게 구현하진 못했음 -&gt; 보드 수정, 컬럼 이동, 카드 삭제, 카드이동, 댓글 CRUD</li>
<li>프론트엔드를 구현함에 있어서 계속해서 백엔드가 추가 또는 수정하는 일이 발생 -&gt; 프론트엔드에 대한 이해가 부족했기 때문에 더 많이 발생한 것 같음</li>
</ol>
<p>Try</p>
<ol>
<li>깃 허브가 꼬인 이유에 대해 공부</li>
<li>프론트엔드와 연결하는 부분에 대해 공부하기 -&gt; 최종프로젝트 준비</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL - 8월4일]]]></title>
            <link>https://velog.io/@dk_ovo/TIL-8%EC%9B%944%EC%9D%BC</link>
            <guid>https://velog.io/@dk_ovo/TIL-8%EC%9B%944%EC%9D%BC</guid>
            <pubDate>Fri, 04 Aug 2023 08:13:18 GMT</pubDate>
            <description><![CDATA[<h2 id="지연로딩과-즉시로딩">지연로딩과 즉시로딩</h2>
<p>FetchType은 2가지 &quot;LAZY&quot;와 &quot;EAGER&quot;가 있고 각각 즉시로딩과 지연 로딩에 해당된다. 기본 값 즉 디폴트 값으로 @ManyToOne의 경우 EAGER가 설정되어있고, @OneToMany의 경우 LAZY로 설정이 되어 있다.</p>
<h3 id="lazy지연로딩의-사용">LAZY(지연로딩)의 사용</h3>
<p>@OneToMany의 경우 List형태로 해당 엔티티가 여러개가 있을 수 있으므로 효율적으로 정보를 조회하기 위해서 LAZY로 지연로딩을 하게 되어있다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/e49cd6f7-966c-4467-8132-36d5c6d72cc7/image.png" alt=""></p>
<p>지연로딩의 경우 필요한 시점에 정보를 불러온다.</p>
<h3 id="eager즉시로딩의-사용">EAGER(즉시로딩)의 사용</h3>
<p>@ManyToOne의 경우 일반 객체 타입으로 즉시 정보를 가져와도 무리가 없으므로 EAGER로 즉시 로딩을 하게 디폴트 값이 설정되어 있다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/fbfd82fd-b0ba-49d4-a9b9-a158e64144f9/image.png" alt=""></p>
<p>즉시 로딩의 경우 조회할 때 연관된 모든 Entity의 정보를 즉시 가져온다. 만약 @OneToMany에 EAGER로 설정할 경우 조회를 할 때마다 엔티티 여러개가 있을 때 모든 정보를 가져오려고 하기 때문에 좋지 않다. -&gt; 사실상 이렇게는 사용하지 않는다고 한다.</p>
<h3 id="영속성-컨텍스트와-지연로딩의-관계">영속성 컨텍스트와 지연로딩의 관계</h3>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/7c390f65-44e2-41c4-b646-7145a299b677/image.png" alt="">
따라서 @ManyToOne 쪽의 기본은 EAGER 이지만 LAZY로 바꿀 경우 에러가 발생한다.
지연로딩(LAZY)이 된 Entity의 정보를 조회하려고 할 때 반드시 영속성 컨텍스트가 존재해야 한다.
&#39;영속성 컨텍스트가 존재해야 한다&#39; 라는 의미는 결국 &#39;트랜잭션&#39;이 적용되어있어야 한다라는 의미이다.</p>
<h4 id="transactional">Transactional</h4>
<p>보통 @Transactional의 경우 Insert, Update, Delete 할때 사용하고 단순히 조회할 때에는 사용하지 않는다. 다만, <strong>※ 지연로딩(LAZY)된 엔티티 정보를 조회하려 할때는 마찬가지로 사용을 해줘야 한다.</strong></p>
<h2 id="영속성-전이">영속성 전이</h2>
<h3 id="cascade-persist">Cascade: PERSIST</h3>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/d462fd08-a29d-4809-839b-01fba75d04ef/image.png" alt="">
<img src="https://velog.velcdn.com/images/dk_ovo/post/f4eb5e19-92d5-445b-80bf-036ee025fbae/image.png" alt="">
기존의 경우 addFoodList 매서드를 만든 다음에 food와, food2 객체를 foodRepository에 직접 save를 해줬어야 했다.</p>
<p><strong>JPA에서는 이를 간편하게 처리하는 방법으로 영속성전이(Cascade)의 PERSIST 옵션을 제공한다.</strong></p>
<p>영속성 전이란?
-&gt; 영속 상태의 Entity에서 수행되는 작업들이 연관된 Entity까지 전파되는 상황을 뜻한다.</p>
<p>영속성 전이를 사용하여 해당 Entity를 저장할 때 연관된 Entity까지 자동으로 저장하기 위해서는 자동으로 저장하려 하는 연관된 Entity에 추가한 연관관계 어노테이션에 cascade = CascadeType.PERSIST 를 설정하면 된다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/bab9478a-3150-47df-8845-8274e7bc39be/image.png" alt=""></p>
<p>이렇게 PERSIST 설정을 할 경우 다음과 같이 음식 Entity객체 food, food2를 영속 상태로 만들지 않아도 자동으로 잘 저장된다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/d7bdaae0-7674-47dc-9c5c-9c870f5ed6a1/image.png" alt=""></p>
<h3 id="cascade--remove">Cascade : REMOVE</h3>
<p>Robbie User가 탈퇴하면서 주문한 Order 객체들을 모두 삭제하려고 할 때 다음과 같이 진행할 수 있다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/4760972b-86b4-4f74-9e9c-8d1986194fa6/image.png" alt="">
이렇듯 먼저 User 객체에서</p>
<ol>
<li>지연로딩(LAZY)된 foodList를 deleteAll 매서드를 통해 모두 삭제한 후 </li>
<li>userRepository.delte 매서드로 User 엔티티를 지워야 한다.</li>
</ol>
<p>**JPA에서는 이를 간편하게 처리하는 방법으로 영속성전이(Cascade)의 REMOVE 옵션을 제공한다.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/819bccec-44c4-4393-a296-efa6dcbbeb2a/image.png" alt="">
cascade = {CascadeType.PERSIST, CascadeType.REMOVE} 이렇게 중복으로 옵션을 설정할 수도 있다.</p>
<p>고객 Entity의 @OneToMany 애너테이션에 연관된 음식 Entity도 자동으로 삭제될 수 있도록 REMOVE 옵션을 추가한다.</p>
<h4 id="cascade-remove-적용한-테스트-코드">Cascade Remove 적용한 테스트 코드</h4>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/93ae5b32-9eaa-465a-a52f-7d60121508aa/image.png" alt=""></p>
<p>해당 코드를 실행해보면 User 엔티티만 삭제했지만, foodList들도 모두 삭제됐음을 DB를 통해 확인할 수 있다.</p>
<p>정확히 연관되어있는 foodList들을 먼저 delete한 후 User를 delete하였다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/54210c1e-341c-4fcc-91b0-76f07667685c/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL - 8월3일]]]></title>
            <link>https://velog.io/@dk_ovo/TIL-7%EC%9B%9431%EC%9D%BC</link>
            <guid>https://velog.io/@dk_ovo/TIL-7%EC%9B%9431%EC%9D%BC</guid>
            <pubDate>Thu, 03 Aug 2023 09:43:27 GMT</pubDate>
            <description><![CDATA[<h2 id="1n-onetomany">1:N (OneToMany)</h2>
<h3 id="단방향-관계">단방향 관계</h3>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/8140d340-f15e-4dbc-8925-5058c1da3c3d/image.png" alt=""></p>
<p>외래키의 주인은 음식 Entity이지만 실제 외래키는 고객 Entity가 가지고 있다.</p>
<p>1 : N에서 N 관계의 테이블이 외래 키를 가질 수 있기 때문에 외래 키는 N 관계인 users 테이블에 외래 키 컬럼을 만들어 추가하지만 외래 키의 주인인 음식 Entity를 통해 관리한다.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/fe78bb91-f891-4ec7-9e7b-953fd50befb9/image.png" alt=""></p>
<h3 id="양방향-관계">양방향 관계</h3>
<p>1 대 N 관계에서는 <strong>일반적으로 양방향 관계가 존재하지 않는다.</strong></p>
<p>1 대 N 관계에서 양방향 관계를 맺으려면 음식 Entity를 외래 키의 주인으로 정해주기 위해 고객 Entity에서 mappedBy 옵션을 사용해야 하지만 <strong>@ManyToOne 애너테이션은 mappedBy 속성을 제공하지 않기 때문이다</strong>.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/a5800d81-6d79-46ac-b484-40bc84031a67/image.png" alt=""></p>
<h2 id="n대-m-관계-manytomany">N대 M 관계 (ManyToMany)</h2>
<h3 id="단방향-관계-1">단방향 관계</h3>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/34a9b4ea-bb15-41a6-96d7-d912d7f36e56/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/ea33975d-a6e7-4ae9-a507-0ed8285b3033/image.png" alt=""></p>
<p>여기서 주의할 점은 Order를 중간 테이블로 생성하기 때문에 @JoinTable 어노테이션으로 추가를 한다.</p>
<p>다른 특징으로는 주문  테이블은 PK가 없고 FK만 존재한다.</p>
<p>음식 Entity가 ManyToMany에서 주인 엔티이이기 때문에 설정을 음식 Entity에서 진행한다. </p>
<h3 id="양방향-관계-1">양방향 관계</h3>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/4209841f-960a-42bb-b3ef-2ed8d552008c/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/941a480c-d764-4403-bc3d-7c3b7f496b87/image.png" alt=""></p>
<h4 id="n대m-양방향-테스트--외래-키-저장-실패">N대M 양방향 테스트 : 외래 키 저장 실패</h4>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/953fd178-1d73-47d0-a782-360fb6070d35/image.png" alt="">
외래키의 주인이 아닌 user 엔티티쪽에서 food 엔티티를 저장하려고 하면 user 테이블과 food 테이블에는 정상적으로 저장이 되지만, order테이블을 확인해보면 food_id와 user_id 값이 들어가지 않는다.</p>
<h4 id="n대m-양방향-테스트-외래키-저장-실패---성공">N대M 양방향 테스트: 외래키 저장 실패 -&gt; 성공</h4>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/830d0d24-03ba-412e-87da-f1739d090517/image.png" alt="">
외래키의 주인이 아닌 user엔티티에서 food를 저장하기 위해서는 addFoodList()라는 매서드를 만들고 사용한한다. </p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/fac0d36e-2ebd-412a-8df4-c6d06169c226/image.png" alt="">
이때 외래키(연관관계) 설정을 위해 Food에서 userList를 호출하고 user 객체 자신을 add한다.</p>
<h4 id="n대m-양방향-테스트">N대M 양방향 테스트</h4>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/c92f423e-a381-44ae-97f4-3585a3f52208/image.png" alt=""></p>
<p>해당 결과는 DB 저장에는 문제가 되지 않으나, User를 사용하여 food의 정보를 조회할 수 없다.</p>
<h4 id="n대m-양방향-테스트-객체와-양방향-장점-활용">N대M 양방향 테스트: 객체와 양방향 장점 활용</h4>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/2d3436fc-1bd9-463f-a4dc-ecd3359e658e/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/dca78e97-6e98-419d-8634-f26a723e8ffe/image.png" alt="">
food 엔티티에 addUserList() 매서드를 생성하여 user 정보를 추가하고, 해당 매서드에 객체 활용을 위해 user 객체에 food 정보를 추가하는 코드를 추가한다. -&gt; user.getFoodList().add(this);</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/57c8e4d5-d11c-45cb-a5f0-d22e72dddd21/image.png" alt=""></p>
<h4 id="n대m-조회--food-기준-user-정보-조회">N대M 조회 : Food 기준 user 정보 조회</h4>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/ae2b7279-1201-4f9c-a34a-6b12415f97cb/image.png" alt=""></p>
<p>foodRepostiroy에서 Id 1번 값인 &quot;아보카도 피자&quot;가 출력된다.</p>
<p>List<User> userList = 아보카도 피자를 시킨 유저 리스트 이다.
따라서 orders 테이블에 food_id 1인 아보카도 피자 를 시킨 user_id 1 그리고 user_id 2에 해당되는 Robbie와 Robert가 출력된다.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/2752dc05-1928-4cf8-9f84-0e67af279bef/image.png" alt=""></p>
<h4 id="n대m-조회--user-기준-food-정보-조회">N대M 조회 : User 기준 food 정보 조회</h4>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/31a872c8-a1f4-44ff-af1f-4e9e4ca4e47a/image.png" alt=""></p>
<p> userRepository에서 Id 1번 값인 &quot;Robbie&quot;가 출력된다.</p>
<p> List<Food>foodList = Robbie가 가진 foodList 이다.
  <img src="https://velog.velcdn.com/images/dk_ovo/post/9d635d59-f3d3-4a13-9797-40cbfaad28df/image.png" alt=""></p>
<p> 따라서 food 테이블에 있는 id 1번값과 2번 값에 해당하는 내용이 출력된다.
  <img src="https://velog.velcdn.com/images/dk_ovo/post/c54384ce-8404-4293-a68e-55f2494b3ce4/image.png" alt=""></p>
<p><strong>출력</strong>
아보카도 피자
50000.0
고구마 피자
30000.0</p>
<h3 id="중간-테이블">중간 테이블</h3>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/b2c30aa9-13b5-479f-ab43-6c983ab83207/image.png" alt=""></p>
<p>중간 테이블 orders를 직접 생성하여 관리하면 변경이 발생할 경우 컨트롤하기가 쉬워 확장성에 좋다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/cfc4f1c9-cb8f-4607-984e-aac14963e0e6/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/4673b266-7914-41c3-9a5b-a81e6de7673a/image.png" alt=""></p>
<p> 이전까지는 User 엔티티와 Food 엔티티만 있었고 자동 생성된 중간 테이블을 사용했으나, 이제 직접 Order라는 엔티티를 만들었기 때문에 새롭게 관계를 설정해야 한다.</p>
<h4 id="테이블-설정">테이블 설정</h4>
<p><strong>Food 엔티티</strong>
  <img src="https://velog.velcdn.com/images/dk_ovo/post/cbc998c6-5911-4c71-879b-5ad9f0a5e993/image.png" alt=""></p>
<p><strong>User 엔티티</strong>
  <img src="https://velog.velcdn.com/images/dk_ovo/post/3de02e95-f1dc-40bd-8a7e-a071086524b9/image.png" alt=""></p>
<p><strong>Order 엔티티</strong>
  <img src="blob:https://velog.io/d1c93044-43c9-4ec4-b1df-ae9401d69d0a" alt="업로드중.."></p>
<p>이제 Order 엔티티가 Food와 User엔티티와 @ManyToOne 관계에서 외래키의 주인이므로 @JoinColumn으로 각각 Food와 User 엔티티를 불러온다.</p>
<p>반대로 Food와 User 엔티티는 외래키의 주인이 아닌 쪽으로 @OneToMany 어노테이션과 mappedby로 Order엔티티를 설정한다. </p>
<p>결과적으로 Food와 User가 중간 테이블인 Order테이블을 통해 조회가 가능하다.Order엔티티는 테이블에 Food와 User 엔티티의 외래키를 가지고 있고, 반대로 Food와 User는 Order엔티티를 가지고 있으나 테이블에는 반영이 되지 않는다.</p>
<h4 id="중간-테이블-테스트">중간 테이블 테스트</h4>
<p>  <img src="blob:https://velog.io/7348ad33-0d65-48dd-a30f-4e4fa8c1d346" alt="업로드중.."></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL - 7월27일]]]></title>
            <link>https://velog.io/@dk_ovo/TIL-7%EC%9B%9427%EC%9D%BC</link>
            <guid>https://velog.io/@dk_ovo/TIL-7%EC%9B%9427%EC%9D%BC</guid>
            <pubDate>Thu, 27 Jul 2023 13:26:19 GMT</pubDate>
            <description><![CDATA[<h2 id="entity-연관관계">Entity 연관관계</h2>
<p>DB에서는 어떤 테이블을 기준으로 하든 원하는 정보를 JOIN을 사용하여 조회할 수 있다.
이처럼 DB 테이블간의 관계에서는 방향의 개념이 없지만, <strong>Entity에서는 단방향 또는 양방향 연관관계를 설정</strong>하여 조회를 할 수 있거나 하지 못하게 될 수 있다.</p>
<h3 id="db테이블간-연관관계">DB테이블간 연관관계</h3>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/a1fec9fe-af7d-4cb6-901e-c5251cd4b237/image.png" alt=""></p>
<h3 id="jpa-entity에서의-연관관계">JPA Entity에서의 연관관계</h3>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/9c904790-2d21-421c-bc5d-277b3d7ac5d3/image.png" alt=""></p>
<p>JPA Entity에서는 조회를 하기 위해서는 단방향 또는 양방향으로 관계를 맺어야 한다. 이때 고객 Entity에서는 음식에 대한 정보가 Collumn으로 나올 필요가 없기 때문에 @Collumn으로 열 추가를 하지 않는다, 음식 Entity의 경우 고객의 id 정보가 나와야 하기 때문에 @JoinCollumn으로 열을 추가한다. (이래야만 고객 Entity에서  음식 Entity를 조회하는게 가능하기 때문)</p>
<p><strong>&lt;정리&gt;</strong>
DB 테이블에서는 테이블 사이의 연관관계를 FK(외래 키)로 맺을 수 있고 방향 상관없이 조회가 가능
Entity에서는 상대 Entity를 참조하여 Entity 사이의 연관관계를 맺을 수 있다.
하지만 <strong>상대 Entity를 참조하지 않고 있다면 상대 Entity를 조회할 수 있는 방법이 없다.</strong>
따라서 <strong>Entity에서는</strong> DB 테이블에는 없는 <strong>방향의 개념이 존재</strong>합니다.
이때 양방향 관계의 경우 외래키의 주인이 아닌 곳에서 (mappedBy = &quot;&quot;) 으로 지정을 한다.
Ex. 음식 Entity가 주인일 경우 고객 Entity에서 mappedBy로 지정을 해야한다.</p>
<h3 id="1대1-관계-onetoone-어노테이션">1대1 관계 (@OneToOne 어노테이션)</h3>
<p>1:1 관계를 맺어주는 역할을 함</p>
<h4 id="단방향-관계">단방향 관계</h4>
<p><strong>Entity에서 외래 키의 주인은 일반적으로 N(다)의 관계인 Entity</strong> 이지만, <strong>1 대 1 관계에서는 외래 키의 주인을 직접 지정</strong>해야합니다.</p>
<p><strong>외래 키 주인만</strong>이 외래 키 를 <strong>등록, 수정, 삭제</strong>할 수 있으며, 주인이 아닌 쪽은 오직 외래 키를 읽기만 가능합니다.</p>
<p>@JoinColumn()은 외래 키의 주인이 활용하는 애너테이션 -&gt; 컬럼명, null 여부, unique 여부 등을 지정할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/0aa3f686-bb1f-4372-b8c9-34934619fd86/image.png" alt=""></p>
<h4 id="양방향-관계">양방향 관계</h4>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/7e934cec-b917-449d-ae41-5fd620943ef1/image.png" alt=""></p>
<p><strong>양방향 설정</strong>
양방향 관계에서 외래 키의 주인을 지정해 줄 때 mappedBy 옵션을 사용합니다.
mappedBy의 속성값은 외래 키의 주인인 상대 Entity의 필드명을 의미한다.</p>
<h4 id="관계-설정-방법에-대한-정리"><strong>관계 설정 방법에 대한 정리.</strong></h4>
<p><strong>단방향</strong>이라면 외래 키의 주인만 상대 Entity 타입의 필드를 가지면서 @JoinColumn()을 활용하여 외래 키의 속성을 설정.</p>
<p><strong>양방향</strong>이라면 외래 키의 주인은 상대 Entity 타입의 필드를 가지면서 @JoinColumn()을 활용하여 외래 키의 속성을 설정.</p>
<p>그리고 상대 Entity는 외래 키의 주인 Entity 타입의 필드를 가지면서 mappedBy 옵션을 사용하여 속성 값으로 외래 키의 주인 Entity에 선언된 @JoinColumn()으로 설정되고 있는 필드명을 넣어주면 된다.</p>
<h4 id="mappedby의-속성-값은-외래키의-주인인-상대-entity에-있는-필드joincolumn으로-설정명을-의미한다">※mappedBy의 속성 값은 외래키의 주인인 상대 Entity에 있는 필드(JoinColumn으로 설정)명을 의미한다.</h4>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/bd04a596-967e-423f-928e-868936972dbe/image.png" alt=""></p>
<p>1:1 관계에서는
@JoinColumn을 생략해도 default값으로 설정이 되고, DB에 칼럼명도 &quot;필드명_id&quot; 로 설정이 된다. </p>
<p>하지만 이후 1대 다 관계에서 외래키의 주인 Entity가 @JoinColumn을 생략하면 JPA가 외래키를 저장할 칼럼을 파악할 수 없어서 의도치 않은 중간 테이블을 생성하게 된다.</p>
<p>따라서 @JoinColimn을 생략할 수 있지만, 왠만해서는 직접 선언하여 활용하는 것이 좋다.</p>
<p>마찬가지로 양방향 관계에서 mappedBy를 생략할 경우 JPA가 외래키의 주인 Entity를 파악할 수 없어서 의도치 않는 중간테이블이 생성될 수 있다.</p>
<h4 id="entity에서-주인이-아닌-쪽에서-주인인-entity를-저장하는-방법">Entity에서 주인이 아닌 쪽에서 주인인 Entity를 저장하는 방법</h4>
<p>외래 키 저장 실패 -&gt; 성공
<img src="https://velog.velcdn.com/images/dk_ovo/post/96bcc313-9203-416e-a5eb-9165ed2646ae/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/ee86d40f-2e64-4814-8906-72fde93b88a7/image.png" alt=""></p>
<p>엔티티 주인인 쪽 Food에서 처음엔 User에 대한 객체가 생성되지 않았으므로 user_id를 가질 수 없었다. 이후 DB에 저장하기 전 User 객체가 생성되었고 이후 addfood 매서드를 통해서 food 객체에 생성된 User를 set해서 주입을 진행</p>
<p>이제 Food 쪽에서 User 엔티티에 대한 객체를 담고 있으므로 userRepository와 foodRepository에 각 객체들을 save 매서드를 통해 저장한다.</p>
<p>DB를 확인하면 정상적으로 Food 테이블의 user_id 컬럼에 User 엔티티의 id 값이 반영된 것을 확인할 수 있다.</p>
<h4 id="주인-entity에서-아닌쪽의-entity의-저장하는-방법">주인 Entity에서 아닌쪽의 Entity의 저장하는 방법</h4>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/352a414b-efc8-4f22-8a0a-77b7a8f36df2/image.png" alt=""></p>
<p>Food가 연관관계의 주인이므로 먼저 User 엔티티의 객체를 생성하고 값을 set매서드를 통해 정한다. Food 엔티티의 객체를 생성하고 User엔티티를 set매서드를 통해서 엔티티의 값을 받아온다.</p>
<p>UserRepository와 FoodRepostory에 각각 엔티티의 객체들을 save매서드로 저장한다. </p>
<h3 id="n대-1관계">N대 1관계</h3>
<h4 id="단방향-관계-1">단방향 관계</h4>
<p>외래키의 주인쪽에 @ManyToOne의 어노테이션을 설정하여 단방향 N:1 관계를 설정하면 된다.
일반적으로는 N:1 관계에서는 N쪽이 외래키의 주인이다.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/0e11eda2-e301-4df1-9280-f0ce3dada05e/image.png" alt="">
<img src="https://velog.velcdn.com/images/dk_ovo/post/2b6e365c-e9ae-4908-8dce-2704c51968f4/image.png" alt=""></p>
<h4 id="양방향-관계-1">양방향 관계</h4>
<p>마찬가지로 음식 Entity가 N의 관계로 외래 키의 주인이다.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/bf353fee-9dd1-4857-aab7-ee6a32f99268/image.png" alt="">
여기서 고객 엔티티의 (Only Entity)표현은 고객 엔티티에 Java의 컬렉션이 있어도 <strong>실제 DB에는 표현이 되지 않음을 의미</strong>한다.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/7a4268bd-dc65-4f9f-bf08-349ab0a2af06/image.png" alt=""></p>
<p>음식 Entity는 외래키의 주인이므로 @ManyToOne 어노테이션을 사용한다. 반대로 외래키의 주인이 아닌 고객 Entity는 N의 관계를 가지는 음식 Entity를 표현하기 위해 List 컬렉션을 사용하고, mappedBy (외래키 주인 설정) 을 해야한다.</p>
<h4 id="외래키-저장-실패-예시">외래키 저장 실패 예시</h4>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/d2a05ac3-1703-4bb7-8514-4fb16a27487d/image.png" alt="">
DB의 Food 엔티티에 user_id 값이 null인 것으로 확인할 수 있다.</p>
<h4 id="외래키-저장-성공-예시">외래키 저장 성공 예시</h4>
<ol>
<li>외래키의 주인이 아닌 Entity에서 해당 메서드에 외래키(연관 관계) 설정 -&gt; 외래키의 주인이 아닌 곳에서 설정하기 위해서는 추가 매서드를 만들어서 설정을 해줘야 한다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/94aeb8b4-1abd-4deb-8f1a-cf1be7080ec7/image.png" alt=""></p>
<ol start="2">
<li>외래키의 주인인 Entity에서 외래 키 (관계 설정) 설정 -&gt; 외래키의 주인 쪽에서 주인이 아닌 쪽의 Entity를 주입한다.
<img src="https://velog.velcdn.com/images/dk_ovo/post/334c453c-d3a4-4477-8225-437625294f77/image.png" alt=""></li>
</ol>
<h4 id="외래키-조회">외래키 조회</h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL - 7월19일]]]></title>
            <link>https://velog.io/@dk_ovo/TIL-7%EC%9B%9419%EC%9D%BC</link>
            <guid>https://velog.io/@dk_ovo/TIL-7%EC%9B%9419%EC%9D%BC</guid>
            <pubDate>Wed, 19 Jul 2023 13:05:32 GMT</pubDate>
            <description><![CDATA[<h2 id="backofficeprojcet">BackOfficeProjcet</h2>
<h3 id="git">Git</h3>
<h4 id="git을-merge-하면서-생긴-병목">Git을 Merge 하면서 생긴 병목</h4>
<ol>
<li>Api 명세서와 ERD를 작성하긴 했지만, 각자 작성하다 보니 Entity와 필드명이 각기 다른 </li>
<li>Git Pull Request를 요청하고 병합하는 과정에서 매 사람마다 시간 소요 다수 발생 -&gt; 이거에 대한 해결을 추후에 튜터님께 한번 여쭤볼 예정.</li>
<li>Git commit 하지 않고 checkout을 할 경우 내용이 모두 날라가게 된다. 팀원중 한명이 겪었던 큰 일이다.</li>
</ol>
<h2 id="새로-알게-된-내용-정리">새로 알게 된 내용 정리</h2>
<h3 id="httpservletresponse-와-httpservletrequest-차이">HttpServletResponse 와 HttpServletRequest 차이</h3>
<p><strong>HttpServlet 이란?</strong></p>
<p>HTTP 프로토콜을 사용하는 웹 브라우저에서 서블릿 기능을 수행
따라서 개발자는 HttpServlet을 상속받아 많은 기능을 사용할 수 있다.
WAS가 웹브라우저로부터 Servlet 요청을 받으면
요청 받을 때 전달 받은 정보를 HttpServletRequest 객체를 생성해서 저장한다.
웹브라우저에 응답을 반환할 HttpServletResponse 객체를 생성한다. (응답을 담기 전 빈 객체)
생성된 HttpServletRequest, HttpServletResponse 객체를 Servlet에 전달한다.</p>
<p><strong>Servlet이란?</strong>
WAS에서 동적 웹페이지 구현을 할 수 있도록 도와주는 자바 클래스의 일종 (프로그래밍 기술)
서블릿 관련 추상 메서드를 제공하는 인터페이스이다.
Servlet 덕분에 개발자는 의미있는 <strong>비즈니스 로직에 집중</strong>할 수 있다.
EX. init(), service() 등</p>
<p><strong>HttpServletRequest</strong>
HTTP 요청 정보(클라이언트 요청, 쿠키, 세션 등)를 제공하는 인터페이스
HTTP 프로토콜의 request 정보를 서블릿에게 전달하기 위한 목적으로 사용한다.
Message Body의 Stream을 읽어들이는 메서드를 가지고 있다.</p>
<p>&lt;메서드 예시&gt;
a. getParameterNames() : 현재 요청에 포함된 매개변수 이름을 열거 형태로 넘겨준다.
b. getParameter(name) : 문자열 name과 같은 이름의 매개변수를 가져온다.</p>
<p><strong>HttpServletResponse</strong>
HTTP 응답 정보(요청 처리 결과)를 제공하는 인터페이스
Servlet은 HttpServletResponse객체에 content-type, 응답 코드, 응답 메세지 등을 담아서 전송한다.
Servlet으로 들어온 요청은 텍스트(HTML)로 응답을 보내기 때문에 출력 스트림을 받기 위해 주로 response로부터 writer 객체를 얻어서 내보낸다.</p>
<p>PrintWriter w = response.getWriter();
&lt;메서드 예시&gt;
a. setContentType() : 요청에 대해 클라이언트에게 돌려줄 content-type 결정
b. setCharacterEncoding()</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL - 7월17일]]]></title>
            <link>https://velog.io/@dk_ovo/TIL-7%EC%9B%9417%EC%9D%BC</link>
            <guid>https://velog.io/@dk_ovo/TIL-7%EC%9B%9417%EC%9D%BC</guid>
            <pubDate>Mon, 17 Jul 2023 13:18:54 GMT</pubDate>
            <description><![CDATA[<h2 id="스파르타-팀-프로젝트-발제">스파르타 팀 프로젝트 발제</h2>
<p>심화주차 팀 프로젝트가 발제되었고, 난이도 (상) 의 쓰레드를 참고한 백엔드 서버를 만들기로 하였다. 필수구현과 추가 구현 리스트는 아래와 같다.</p>
<p><strong>필수 구현 기능</strong></p>
<ol>
<li>사용자 인증 기능 (희석님)<ul>
<li>회원가입</li>
<li>로그인</li>
<li>로그아웃</li>
</ul>
</li>
<li>프로필 관리<ul>
<li>프로필 수정 (나)</li>
</ul>
</li>
<li>게시물 CRUD (인수님)</li>
<li>댓글 CRUD (휘수님)<ul>
<li>댓글작성</li>
<li>댓글수정</li>
<li>댓글삭제</li>
</ul>
</li>
</ol>
<p>추가 구현 기능</p>
<ol>
<li>소셜 로그인 기능 구현 (상인님)</li>
<li>좋아요 기능</li>
<li>팔로우 기능</li>
<li>관리자 기능(백오피스)</li>
<li>프론트엔드</li>
</ol>
<p>추추가 기능</p>
<ol>
<li>프로필에 사진 업로드</li>
<li>게시물에 멀티미디어 지원 기능</li>
<li>AWS 배포</li>
<li>HTTP -&gt; HTTPS 업그레이드</li>
</ol>
<h3 id="erd-entity-relationship-diagram-작성">ERD (Entity Relationship Diagram) 작성</h3>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/543a86ec-5609-41fb-8155-2046a92280bb/image.png" alt=""></p>
<ol>
<li>User의 id(PK값)은 모든 엔티티의 FK로 들어간다.</li>
<li>ERD 관계도에 대해서 팀원들의 도움으로 더 알 수 있었다. 
<img src="https://velog.velcdn.com/images/dk_ovo/post/162fb219-fd8b-4ff5-856d-f2a90ef85548/image.png" alt=""></li>
</ol>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/b85cae68-dae2-4566-93fe-a3e847fcb82f/image.png" alt=""></p>
<h4 id="추가-정리">추가 정리</h4>
<p>(1 : 1) 관계 : 부모는 하나의 자식이 있다.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/82b4c2be-d4cb-44b5-a5d4-f698f54c5077/image.png" alt=""></p>
<p>(1 : N) 관계 : 부모는 하나 이상의 자식이 있다.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/8903e1ea-22e6-4054-a61d-edd825c8bf6b/image.png" alt=""></p>
<p>(N : N) 관계 : 하나 이상의 부모와 하나 이상의 자식이 있다.</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/37114aa2-2bcc-45ad-9376-829045515533/image.png" alt=""></p>
<p>(1 : 1(o)) 관계 : 부모는 하나의 자식이 있을 수도 있다.(없을수도있다)</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/4c5cd2bb-5d75-4228-893a-bdc05680ea58/image.png" alt=""></p>
<p>(1 : N(o)) 관계 : 부모는 여러개의 자식이 있을 수도 있다.(없을수도있다)</p>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/c770887f-02f6-4f5d-a1ce-15f018879f9e/image.png" alt=""></p>
<h3 id="와이어프레임">와이어프레임</h3>
<p><img src="https://velog.velcdn.com/images/dk_ovo/post/1931e6b8-740a-4841-b3fd-6b34ab838c80/image.png" alt=""></p>
<p>와이어프레임은 조금 아쉬웠던 부분이 Front를 구현하면 매우 중요하다고 느꼈는데 (지난번 팀 프로젝트) 만일 백엔드만 구현한다 했을 때 와이어프레임은 크게 와닿는 느낌을 못느끼는 것 같았다.</p>
<p>하지만, 와이어프레임을 이해하고 설계하는것도 중요하기에 나름 최선을 다해서 작성하였다.</p>
<h3 id="api명세서">API명세서</h3>
<p>API명세서의 중요성은 지난 팀프로젝트 때 많이 느꼈다. 확실하게 ERD와 API명세가 갖춰지지 않으면, 계속 프론트와 백엔드 모두 수정해야해서 리소스 낭비가 심하게 된다는 것을 알게 되었다.</p>
<p>지난번 부족했던 경험을 바탕으로 이번에 팀원들과 비교적 수월하게 API 명세를 작성할 수 있었다.
<a href="https://teamsparta.notion.site/062f404a03bf4ab69ab3383e10e4389b?v=92ee429d92e34410af885f8e42c72cf8">https://teamsparta.notion.site/062f404a03bf4ab69ab3383e10e4389b?v=92ee429d92e34410af885f8e42c72cf8</a></p>
<h2 id="부족한점">부족한점</h2>
<ol>
<li><p>git Repository를 만들고 처음 init 까지 하는데 아직도 어렵다. git에대한 공부가 더 필요하다고 느꼈다.</p>
</li>
<li><p>ERD 관계도에 대해 개념이 많이 부족했다. 표기법과 더불어 N:N관계에 대해 아직 강의를 듣지 않아서 강의 수강의 필요성을 느꼈다.</p>
</li>
<li><p>API명세서에 대해 아직은 스스로 짤 수 있을까? 라는 의문이 들었다. 과제를 하면서 조금은 익숙해졌지만, 스스로 새로운 API명세 테이블을 구성하라고 하면 어려울 것 같다 생각이 들어서 좀 더 꼼꼼하게 보고 배워나가려 한다.</p>
</li>
</ol>
]]></description>
        </item>
    </channel>
</rss>