<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>winsome_joo.log</title>
        <link>https://velog.io/</link>
        <description>반복되는 실수를 기록을 통해 줄여가보자!</description>
        <lastBuildDate>Thu, 12 Sep 2024 00:58:28 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. winsome_joo.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/winsome_joo" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[그리디 알고리즘]]></title>
            <link>https://velog.io/@winsome_joo/%EA%B7%B8%EB%A6%AC%EB%94%94-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</link>
            <guid>https://velog.io/@winsome_joo/%EA%B7%B8%EB%A6%AC%EB%94%94-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</guid>
            <pubDate>Thu, 12 Sep 2024 00:58:28 GMT</pubDate>
            <description><![CDATA[<h1 id="그리디-알고리즘이란">그리디 알고리즘이란?</h1>
<p>그리디 알고리즘은 현재 상태에서 보는 선택지 중 최선의 선택지가 전체 선택지 중 최선의 선택지라고 가정하는 알고리즘이다.</p>
<p>쉽게 말해 <strong>매 선택에서 지금 이 순간 당장 최적인 답을 선택하여 적합한 결과를 도출하자 하여 전체적인 최적 해를 찾는 알고리즘이다.</strong></p>
<hr>
<h1 id="그리디-알고리즘-단점">그리디 알고리즘 단점</h1>
<p>그리디 알고리즘은 지금 당장 좋은 것만 고르는 방법으로, <strong>현재의 선택이 나중에 미칠 영향은 고려하지 않는다.</strong></p>
<p>💡 [문제] 노드에서 가장 합이 높은 방법을 선택하는 방법을 생각해 봅니다.</p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/68622d8e-c7c6-4dd3-8ecb-459a937af784/image.png" alt=""></p>
<p><strong>최적의 선택</strong>: 3+100=103
<strong>그리디한 선택</strong>: 10+8=18 </p>
<p>첫번 째 단계에서 최적이지만 미래 선택까지 포함한다면 최적의 알고리즘이 아닐 수 있다.</p>
<hr>
<h1 id="그리디-알고리즘을-통해-문제를-해결하는-방법">그리디 알고리즘을 통해 문제를 해결하는 방법</h1>
<h3 id="👉-탐욕-알고리즘-문제를-해결하는-방법">👉 탐욕 알고리즘 문제를 해결하는 방법</h3>
<ol>
<li>선택 절차(Selection Procedure): 현재 상태에서의 최적의 해답을 선택한다.</li>
<li>적절성 검사(Feasibility Check): 선택된 해가 문제의 조건을 만족하는지 검사한다.</li>
<li>해답 검사(Solution Check): 원래의 문제가 해결되었는지 검사하고, 해결되지 않았다면 선택 절차로 돌아가 위의 과정을 반복한다.</li>
</ol>
<h1 id="탐욕-알고리즘-예시">탐욕 알고리즘 예시</h1>
<h3 id="❗️탐욕-알고리즘을-일상-예시-1--매트로이드">❗️탐욕 알고리즘을 일상 예시 1 – 매트로이드</h3>
<p><strong>하나몬은 오늘도 편의점에서 열심히 아르바이트하고 있다.
손님으로 온 박해커는 과자와 음료를 하나씩 집어 들었고, 물건 가격은 총 4,040원이 나왔다.
박해커는 계산을 하기 위해 5,000원을 내밀며, 거스름돈은 동전의 개수를 최소한으로 하여 거슬러 달라고 하였다.</strong></p>
<h3 id="👉-이때-하나몬은-어떻게-거슬러-주어야-할까">👉 이때 하나몬은 어떻게 거슬러 주어야 할까?</h3>
<ul>
<li><p>탐욕 알고리즘으로 동전의 개수를 헤아리는 일은 일반적으로 거스름돈으로 동전을 선택하는 방법과 동일하다.</p>
</li>
<li><p>거스름돈 960원을 채우기 위해서 먼저 500원짜리 동전을 한 개를 선택한다.</p>
</li>
<li><p>그다음은 100원짜리 동전을 네 개 선택하고, 그다음엔 50원짜리 동전과 10원짜리 동전을 각각 하나씩 선택할 것이다.</p>
<h3 id="👉-탐욕-알고리즘의-문제-해결-과정을-적용">👉 탐욕 알고리즘의 문제 해결 과정을 적용</h3>
</li>
</ul>
<ol>
<li>선택 절차</li>
</ol>
<ul>
<li>거스름돈의 동전 개수를 줄이기 위해 현재 가장 가치가 높은 동전을 우선 선택한다.</li>
</ul>
<ol start="2">
<li>적절성 검사</li>
</ol>
<ul>
<li>1번 과정을 통해 선택된 동전들의 합이 거슬러 줄 금액을 초과하는지 검사한다.</li>
<li>초과하면 가장 마지막에 선택한 동전을 삭제하고, 1번으로 돌아가 한 단계 작은 동전을 선택한다.</li>
</ul>
<ol start="3">
<li>해답 검사</li>
</ol>
<ul>
<li>선택된 동전들의 합이 거슬러 줄 금액과 일치하는지 검사한다.</li>
<li>액수가 부족하면 1번 과정부터 다시 반복한다.</li>
</ul>
<h3 id="👉-이-과정을-통해-얻은-문제에-대한-해답">👉 이 과정을 통해 얻은 문제에 대한 해답</h3>
<p>가장 가치가 높은 동전인 500원 1개를 먼저 거슬러 주고 잔액을 확인한 뒤, 이후 100원 4개, 50원 1개, 10원 1개의 순서대로 거슬러 준다.</p>
<h1 id="참고-자료">참고 자료</h1>
<p><a href="https://velog.io/@falling_star3/%EA%B7%B8%EB%A6%AC%EB%94%94-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98Greedy-Algorithm">https://velog.io/@falling_star3/%EA%B7%B8%EB%A6%AC%EB%94%94-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98Greedy-Algorithm</a></p>
<p><a href="https://hanamon.kr/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%ED%83%90%EC%9A%95%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-greedy-algorithm/">https://hanamon.kr/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%ED%83%90%EC%9A%95%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-greedy-algorithm/</a></p>
<p><a href="https://www.youtube.com/watch?v=_IZuE7NIeW4&amp;t=373s">https://www.youtube.com/watch?v=_IZuE7NIeW4&amp;t=373s</a></p>
<p><a href="https://hanamon.kr/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%ED%83%90%EC%9A%95%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-greedy-algorithm/">https://hanamon.kr/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%ED%83%90%EC%9A%95%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-greedy-algorithm/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[@Transactional에 대한 이해]]></title>
            <link>https://velog.io/@winsome_joo/Transactional%EC%97%90-%EB%8C%80%ED%95%9C-%EC%9D%B4%ED%95%B4</link>
            <guid>https://velog.io/@winsome_joo/Transactional%EC%97%90-%EB%8C%80%ED%95%9C-%EC%9D%B4%ED%95%B4</guid>
            <pubDate>Wed, 31 Jul 2024 16:23:27 GMT</pubDate>
            <description><![CDATA[<h1 id="개요">개요</h1>
<p>Spring에서 코드를 작성할 때 @Transaction을 자주 사용하곤했는데 DB에 무결성, 안전성을 보장해준다기에 사용하곤 했다. 하지만 어떤식으로 보장해주는지 잘 알지 못하는 것은 재대로 Spring을 사용하는 것이 아니기에 이번 기회에 정리해보려고한다. </p>
<hr>
<h1 id="선언적-트랜잭션-vs-프로그래밍적-트랜잭션">선언적 트랜잭션 VS 프로그래밍적 트랜잭션</h1>
<p>Spring에서는 Transaction 처리를 지원하는데 프로그래밍적 트랜잭션 처리와 선언적 트랜잭션을 지원해준다.</p>
<ol>
<li>프로그래밍적 트랜잭션</li>
</ol>
<ul>
<li>Spring에서 제공하는 프로그래밍적 트랜잭션은 두 가지가 있다.</li>
<li>TransactionTemplate(프로그래밍적 트랜잭션 사용 시 Spring에서 권장 함)</li>
<li>PlatformTransactionManager</li>
</ul>
<ol start="2">
<li>선언적 트랜잭션</li>
</ol>
<ul>
<li>클래스, 메서드 위에 @Transactional을 추가해서 관리한다.</li>
</ul>
<hr>
<h2 id="프로그래밍적-트랜잭션--transactional">프로그래밍적 트랜잭션 =/= @Transactional</h2>
<pre><code>public class PointTransaction {

    private PointDao pointDao;
    private TransactionTemplate transactionTemplate;

    public void setPointDao(PointDao pointDao) {
        this.pointDao = pointDao;
    }

    public void setTransactionManager(PlatformTransactionManager transactionManager) {
        this.transactionTemplate = new TransactionTemplate(transactionManager);
        this.transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
    }

    public void invoke() {
        dolnternalTransaction();
    }

    public void dolnternalTransaction() throws Exception {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() { 
            protected void doInTransactionWithoutResult(TransactionStatus status) { 
                try { 
                    pointDao.plusPoint() //&lt;--------------------주목
                } catch (Exeption ex) { 
                    status.setRollbackOnly(); 
                } 
            } 
        });
    }
}</code></pre><p>TransactionTemplate은 개발자가 Transaction을 시작, 종료 시점을 명시적으로 결정할 수 있도록 Spring에서 제공하는 하나의 방법이다.</p>
<p>위 코드에서는 pointPlus()메소드를 사용하기위해  Try-Catch과 transactionManager를 주입받고 Transaction 속성을 설정해주고 execute 메서드 내에서 로직을 실행한다.트랜잭션 설정으 하기위해 상당히 많은 코드를 볼 수 있다. </p>
<hr>
<h2 id="선언적-트랜잭션--transactional">선언적 트랜잭션 = @Transactional</h2>
<pre><code>@Transactional
public void plusPoint() { //&lt;--------------------주목
    pointRepository.updatePoint(10);
}</code></pre><p>@Transactional 포함된 메서드가 호출될 경우 Spring은 해당 메서드에 대한 프록시(프록시패턴 디자인 패턴 중 하나)를 만드는데, PlatformTransactionManager를 사용해 트랜잭션을 시작하고, 정상 여부에 따라 커밋 또는 롤백을 알아서 해준다.</p>
<p>@Transactional 어노테이션을 plusPoint 메서드에 선언했다.
Spring이 plusPoint에 대한 프록시를 만들고 해당 로직이 잘 끝났으면 커밋 오류 나면 롤백을 시켜준다.</p>
<p>즉 프로그래밍적 트랜잭션에서는 번거롭게 Try-Catch문을 통해 Commit, RollBack을 해주어야했지만 Spring에서는 @Transactional 하나로 DB에 무결성, 안정성을 보장할 수 있다.</p>
<hr>
<h1 id="transactional-annotation--지원-설정">@Transactional annotation  지원 설정</h1>
<ol>
<li><p>트랜잭션의 전파 유형</p>
</li>
<li><p>트랜잭션의 격리 수준</p>
</li>
<li><p>트랜잭션에 의해 래핑 된 연산에 대한 시간제한</p>
</li>
</ol>
<h2 id="트랜잭션의-전파-유형">트랜잭션의 전파 유형</h2>
<blockquote>
<p><strong>트랜잭션 전파(Transaction propagation)</strong> 
어떤 트랜잭션이 동작중인 과정에서 다른 트랜잭션을 실행할 경우 어떻게 처리하는 가에 대한 개념이다.</p>
</blockquote>
<h3 id="1-required">1. Required</h3>
<p>기본 전파 유형.
트랜잭션이 이미 있는 경우 현재 메서드가 해당 트랜잭션에 참여합니다.
트랜잭션이 존재하지 않으면 메서드에 대한 새 트랜잭션이 생성합니다.</p>
<p>REQUIRED
@Transactional(propagation = Propagation.REQUIRED) 
public void requiredExample(String user) { 
    // ... 
}</p>
<p>REQUIRED는 Default 이므로 생략이 가능합니다.</p>
<p>@Transactional
public void requiredExample(String user) { 
    // ... 
}</p>
<h3 id="2-requires-new">2. Requires New</h3>
<p>이 전파 유형은 항상 새 트랜잭션을 만듭니다
트랜잭션이 이미 존재하는 경우 새 트랜잭션이 완료될 때까지 일시 중단합니다.</p>
<p>Requires New</p>
<p>@Transactional(propagation = Propagation.REQUIRES_NEW)
public void requiresNewExample(String user) { 
    // ... 
}</p>
<h3 id="3-nested">3. Nested</h3>
<p>이 전파 유형은 중첩된 트랜잭션을 생성함.
트랜잭션이 이미 존재하는 경우 새 트랜잭션이 생성되어 기존 트랜잭션 내에 중첩됨.
트랜잭션이 존재하지 않으면 새 트랜잭션이 생성됨.</p>
<p>nested
@Transactional(propagation = Propagation.NESTED)
public void nestedExample(String user) { 
    // ... 
}</p>
<h3 id="4-supports">4. Supports</h3>
<p>이 전파 유형은 트랜잭션이 이미 존재하는 경우 트랜잭션을 지원.
트랜잭션이 존재하면 해당 트랜잭션 내에서 현재 메서드가 실행.
트랜잭션이 존재하지 않으면 트랜잭션 없이 메서드가 실행.</p>
<p>Supports
@Transactional(propagation = Propagation.SUPPORTS)
public void supportsExample(String user) { 
    // ... 
}</p>
<h3 id="5-mandatory">5. Mandatory</h3>
<p>이 전파 유형은 트랜잭션이 이미 존재해야 합니다.
트랜잭션이 존재하지 않으면 예외가 발생합니다.</p>
<p>Mandatory
@Transactional(propagation = Propagation.MANDATORY)
public void mandatoryExample(String user) { 
    // ... 
}</p>
<h3 id="6-not-supported">6. Not Supported</h3>
<p>이 전파 유형은 트랜잭션을 지원하지 않음.
트랜잭션이 존재하면 현재 메서드가 실행되는 동안 트랜잭션이 일시 중단됨.</p>
<p>@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void notSupportedExample(String user) {
    // ... 
}</p>
<h3 id="7-never">7. Never</h3>
<p>이 전파 유형은 현재 메서드가 실행될 때 트랜잭션이 존재하지 않는지 확인한다.
트랜잭션이 존재하면 예외가 발생한다.</p>
<p>never
@Transactional(propagation = Propagation.NEVER)
public void neverExample(String user) { 
    // ... 
}</p>
<hr>
<h2 id="트랜잭션의-격리-수준">트랜잭션의 격리 수준</h2>
<ol>
<li><p>Read Uncommitted</p>
</li>
<li><p>Read committed</p>
</li>
<li><p>Repeatable Read</p>
</li>
<li><p>Serializable</p>
</li>
</ol>
<p>Spring Boot JPA 프로젝트에서 기본 격리 수준은 일반적으로 READ_COMMITTED임</p>
<h3 id="read-uncommitted">Read Uncommitted</h3>
<pre><code>@Service
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
public class UserService {

    @Autowired  
    private UserRepository userRepository;  

    public void updateUser(User user) {  
        userRepository.save(user);  
    }  
}</code></pre><p>이 격리 수준을 가진 트랜잭션은 다른 concurrent 트랜잭션의 커밋되지 않은 데이터를 읽습니다.</p>
<p>또한 Nonrepeatable read와 Phantom read가 모두 발생할 수 있음
즉 행을 다시 읽거나 범위 쿼리를 다시 실행할 때 다른 결과를 얻을 수 있음</p>
<hr>
<h3 id="read-committed">Read Committed</h3>
<pre><code>@Service
@Transactional(isolation = Isolation.READ_COMMITTED)
public class UserService {

    @Autowired  
    private UserRepository userRepository;  

    public User getUserById(Long id) {  
        return userRepository.findById(id)  
            .orElseThrow(() -&gt; new EntityNotFoundException(&quot;User not found&quot;));  
    }  
}</code></pre><p>concurrent 트랜잭션에서 커밋되지 않은 변경 사항은 영향을 미치지 않지만, 트랜잭션이 변경 사항을 커밋하면 다시 쿼리 하여 결과가 변경될 수 있음</p>
<hr>
<h3 id="repeatable-read">Repeatable Read</h3>
<pre><code>

@Service
@Transactional(isolation = Isolation.REPEATABLE_READ)
public class UserService {

    @Autowired  
    private UserRepository userRepository;  

    public User getUserById(Long id) {  
        return userRepository.findById(id)  
            .orElseThrow(() -&gt; new EntityNotFoundException(&quot;User not found&quot;));  
    }  
}</code></pre><p>concurrent 트랜잭션에서 커밋되지 않은 변경 사항의 영향을 받지 않음
단)한 트랜잭션 안에서 일정 범위의 레코드를 두 번 이상 읽었을 때, 첫번째 쿼리에서 없던 레코드가 두번째 쿼리에서 나타남</p>
<p>트랜잭션 도중 새로운 레코드 삽입을 허용하기 때문에 나타나는 현상임</p>
<hr>
<h3 id="serializable">Serializable</h3>
<pre><code>@Service
@Transactional(isolation = Isolation.SERIALIZABLE)
public class UserService {

    @Autowired  
    private UserRepository userRepository;  

    public User getUserById(Long id) {  
        return userRepository.findById(id)  
            .orElseThrow(() -&gt; new EntityNotFoundException(&quot;User not found&quot;));  
    }  
}</code></pre><p>앞서 언급한 모든 동시성 부작용을 방지하지만, concurrent 호출을 순차적으로 실행함
즉 트랜잭션 그룹을 정말로 serial 하게 실행하는 것과 동일한 결과를 가져옴</p>
<hr>
<h1 id="참고자료">참고자료</h1>
<p><a href="https://itjava.tistory.com/33">https://itjava.tistory.com/33</a>
<a href="https://colevelup.tistory.com/34">https://colevelup.tistory.com/34</a>
<a href="https://www.youtube.com/watch?v=taAp_u83MwA&amp;t=219s">https://www.youtube.com/watch?v=taAp_u83MwA&amp;t=219s</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[블로킹 vs 논블로킹,동기(sync) vs 비동기(async)]]></title>
            <link>https://velog.io/@winsome_joo/%EB%B8%94%EB%A1%9C%ED%82%B9-vs-%EB%85%BC%EB%B8%94%EB%A1%9C%ED%82%B9%EB%8F%99%EA%B8%B0sync-vs-%EB%B9%84%EB%8F%99%EA%B8%B0async</link>
            <guid>https://velog.io/@winsome_joo/%EB%B8%94%EB%A1%9C%ED%82%B9-vs-%EB%85%BC%EB%B8%94%EB%A1%9C%ED%82%B9%EB%8F%99%EA%B8%B0sync-vs-%EB%B9%84%EB%8F%99%EA%B8%B0async</guid>
            <pubDate>Wed, 24 Jul 2024 18:03:49 GMT</pubDate>
            <description><![CDATA[<h1 id="블로킹blocking과-논블로킹non-blocking">블로킹(Blocking)과 논블로킹(Non-Blocking)</h1>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/dbbbdc92-5a0c-463f-8d49-d0414ed35986/image.png" alt=""></p>
<p>Blocking: 자신의 작업을 진행하다가 다른 주체에 어떠한 요청을 했을 때 다른 주체에 작업이 끝날 때까지 <strong>기다렸다가</strong> 자신의 작업을 시작하는 것</p>
<p>Non-Blocking: 다른 주체의 작업 완료와 <strong>관련없이</strong> 자신의 작업을 하는 것 </p>
<blockquote>
<p>위 둘의 가장 큰 차이점은 다른 주체가 작업을 할 때 자신의 <strong>제어권</strong> 유무임</p>
</blockquote>
<ul>
<li>Blocking은 제어권이 없음</li>
<li>Non-Blocking은 제어권 있음 </li>
</ul>
<hr>
<h1 id="동기sync와-비동기async">동기(Sync)와 비동기(Async)</h1>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/652dbe6d-9580-41cd-a3b4-87df1aac4cd7/image.png" alt=""></p>
<p>동기(Sync): 요청한 작업이 끝나는 동시에 <strong>해당 작업의 결과 값을 바로 처리함</strong></p>
<p>비동기(Async):요청한 작업이 끝나도 <strong>해당 작업의 결과를 처리할 수도 안 할 수도있음</strong></p>
<blockquote>
<p>위 둘의 가장 큰 차이점은 요청 결과를 돌려 받았을 때 <strong>결과 완료 여부에 대한 관심도</strong></p>
</blockquote>
<ul>
<li>동기는 요청 작업 완료 결과에 관심이 많아 결과를 받고 바로 처리함</li>
<li>비동기는 요청 작업 완료 결과 값에 관심이 적어 결과를 받고 처리할 수 도 있고 안 할 수도 있음</li>
</ul>
<hr>
<h1 id="비동기의-성능-이점">비동기의 성능 이점</h1>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/6722ca48-b446-473f-8882-a0336bde1241/image.png" alt=""></p>
<p>보통 비동기 특징을 이용하여 성능과 연관지어 말한다. 왜냐하면 요청한 작업에 대하여 완료 여부를 신경쓰지 않고 자신의 그다음 작업을 수행한다는 것은, I/O 작업과 같은 느린 작업이 발생할 때, 기다리지 않고 다른 작업을 처리하면서 동시에 처리하여 멀티 작업을 진행할수 있기 때문이다. 이는 전반적인 시스템 성능 향상에 도움을 줄 수 있다.</p>
<hr>
<h1 id="4가지-조합">4가지 조합</h1>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/fd92411c-98b0-482b-ae66-f490aac50885/image.png" alt="">1. Sync Blocking (동기 + 블로킹)
2. Async Blocking (비동기 + 블로킹)
3. Sync Non-Blocking (동기 + 논블로킹) 
4. Async Non-Blocking (비동기 + 논블로킹)</p>
<hr>
<h2 id="sync-blocking-조합">Sync Blocking 조합</h2>
<p>Sync Blocking 조합은 다른 작업이 진행되는 동안 자신의 작업을 처리하지 않고 (Blocking), 다른 작업의 완료 여부를 바로 받아 순차적으로 처리하는 (Sync) 방식이다. 다른 작업의 결과가 자신의 작업에 영향을 주는 경우에 활용할 수 있다.</p>
<h3 id="적용-프로그램-예시">적용 프로그램 예시<img src="https://velog.velcdn.com/images/winsome_joo/post/baa1089f-56ed-4dae-affd-23e42894959e/image.png" alt=""></h3>
<p>대표적으로  C나 JAVA의 코드 실행 후 커맨드에서 입력을 받는 경우가 이에 해당된다. 사용자로부터 입력을 받아야 그 입력값을 가지고 내부 처리를 하여 결과값을 콘솔에 출력해주기 때문에 순차적인 작업이 요구된다. 내부적으로 본다면 실행 코드가 콘솔창을 띄우고 Please enter your name 텍스트를 치고 난 다음 사용자의 리턴값이 필요하기 때문에 제어권을 시스템에서 사용자로 넘겨 사용자가 값을 입력할때까지 기다리는 것이다.</p>
<hr>
<h2 id="async-non-blocking-조합">Async Non-Blocking 조합</h2>
<p>Async Non Blocking 조합은 다른 작업이 진행되는 동안에도 자신의 작업을 처리하고 (Non Blocking), 다른 작업의 결과를 바로 처리하지 않아 작업 순서가 지켜지지 않는 (Async) 방식이다. 다른 작업의 결과가 자신의 작업에 영향을 주지 않은 경우에 활용할 수 있다.</p>
<h3 id="적용-프로그램-예시-1">적용 프로그램 예시<img src="https://velog.velcdn.com/images/winsome_joo/post/beb68d1e-8900-4d0f-a893-6bf0ed832d69/image.png" alt=""></h3>
<p>웹 브라우저의 파일 다운로드가 비동기 논블로킹을 활용하는 예시 라고 할 수 있다. 웹 브라우저는 웹 사이트에서 파일을 다운로드할 때, 파일의 전송이 완료될 때까지 다른 작업을 하지 않고 기다리는 것이 아니라, 다른 탭이나 창을 열거나 웹 서핑을 할 수 있다. 이는 웹 브라우저가 파일 다운로드를 비동기적으로 처리하고, 콜백 함수를 통해 다운로드가 완료되면 알려주는 방식으로 구현되어 있기 때문이다.</p>
<hr>
<h2 id="sync-non-blocking-조합">Sync Non-Blocking 조합</h2>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/af7310db-1121-489b-9fa1-90c0e48f7156/image.png" alt=""></p>
<p>Sync Non-Blocking 조합은 다른 작업이 진행되는 동안에도 자신의 작업을 처리하고 (Non Blocking), 다른 작업의 결과를 바로 처리하여 작업을 순차대로 수행 하는 (Sync) 방식이다.</p>
<p>해당 케이스는 흔히 사용되지 않는다.</p>
<hr>
<h2 id="async-blocking-조합">Async Blocking 조합</h2>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/ab606b0a-a6a9-4991-9a6b-11f9d24d6c97/image.png" alt=""></p>
<p>Async Blocking 조합은 다른 작업이 진행되는 동안 자신의 작업을 멈추고 기다리는 (Blocking), 다른 작업의 결과를 바로 처리하지 않아 순서대로 작업을 수행하지 않는 (Async) 방식이다. Async-blocking 의 경우는 실무에서 잘 마주하기 쉽지 않아 다룰일이 거의 없다. 그래서 그냥 넘어가도 크게 문제는 없다.</p>
<h4 id="안티-패턴인-async-blocking">안티 패턴인 Async Blocking</h4>
<p>Sync-blocking 수행과 큰 차이가 없다.
보통 Async-blocking은 개발자가 비동기 논블록킹으로 처리 하려다가 실수하는 경우에 발생하거나, 자기도 모르게 블로킹 작업을 실행하는 의도치 않은 경우에 사용된다. 그래서 이 방식을 안티 패턴(anti-pattern)이라고 치부하기도 한다.</p>
<hr>
<h1 id="자료-출처">자료 출처</h1>
<p><a href="https://www.youtube.com/watch?v=oEIoqGd-Sns&amp;t=516s">https://www.youtube.com/watch?v=oEIoqGd-Sns&amp;t=516s</a></p>
<p><a href="https://inpa.tistory.com/entry/%F0%9F%91%A9%E2%80%8D%F0%9F%92%BB-%EB%8F%99%EA%B8%B0%EB%B9%84%EB%8F%99%EA%B8%B0-%EB%B8%94%EB%A1%9C%ED%82%B9%EB%85%BC%EB%B8%94%EB%A1%9C%ED%82%B9-%EA%B0%9C%EB%85%90-%EC%A0%95%EB%A6%AC">https://inpa.tistory.com/entry/%F0%9F%91%A9%E2%80%8D%F0%9F%92%BB-%EB%8F%99%EA%B8%B0%EB%B9%84%EB%8F%99%EA%B8%B0-%EB%B8%94%EB%A1%9C%ED%82%B9%EB%85%BC%EB%B8%94%EB%A1%9C%ED%82%B9-%EA%B0%9C%EB%85%90-%EC%A0%95%EB%A6%AC</a></p>
<p><a href="https://sujinhope.github.io/2021/06/13/Network-%EB%8F%99%EA%B8%B0vs%EB%B9%84%EB%8F%99%EA%B8%B0,-%EB%B8%94%EB%A1%9C%ED%82%B9vs%EB%85%BC%EB%B8%94%EB%A1%9C%ED%82%B9%EC%9D%98-%EC%B0%A8%EC%9D%B4.html">https://sujinhope.github.io/2021/06/13/Network-%EB%8F%99%EA%B8%B0vs%EB%B9%84%EB%8F%99%EA%B8%B0,-%EB%B8%94%EB%A1%9C%ED%82%B9vs%EB%85%BC%EB%B8%94%EB%A1%9C%ED%82%B9%EC%9D%98-%EC%B0%A8%EC%9D%B4.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[HTTP & HTTPS]]></title>
            <link>https://velog.io/@winsome_joo/HTTP-HTTPS</link>
            <guid>https://velog.io/@winsome_joo/HTTP-HTTPS</guid>
            <pubDate>Thu, 18 Jul 2024 00:52:45 GMT</pubDate>
            <description><![CDATA[<h1 id="http란">HTTP란?</h1>
<p>HTTP(Hypertext Transfer Protocol)는 클라이언트와 서버 간 HTML과 같은 하이퍼미디어 문서를 전송하기 위한 통신 규칙 세트 또는 프로토콜이다. 
<img src="https://velog.velcdn.com/images/winsome_joo/post/52fe4156-1043-4f57-950d-3ac94af2fd8a/image.png" alt=""></p>
<p>Ex) 사용자가 웹 사이트에 방문해서 웹 브라우저를 통해 웹서버에 HTTP 요청을 전송하면 웹서버에서는 HTTP 응답을 한다.</p>
<hr>
<h1 id="http의-구조">HTTP의 구조</h1>
<p>HTTP는 애플리케이션 레벨의 프로토콜로 TCP/IP 위에서 작동하며 80포트에서 사용한다. HTTP는 상태를 가지고 있지 않는 Stateless 프로토콜이며 Start Line(Status Line), Headers, Body 등으로 구성된다. </p>
<h3 id="http-request-message">HTTP Request Message</h3>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/ef1d40a5-869b-46b1-97ed-815fd8a8f6f4/image.png" alt=""></p>
<h3 id="http-response-message">HTTP Response Message</h3>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/6e6515ba-c87a-4d27-b739-7bde93d5aa39/image.png" alt=""></p>
<p>HTTP는 무상태성이라는 장점으로 서버확장성이 높다는 장점이 있지만 치명적인 보안 단점이 있다.
데이터를 주고 받을 때 평문 데이터를 전송하는 프로토콜이기 때문에 비밀번호나 주민등록번호를 주고 받으면 제 3자가 정보를 조회할 수 있다는 점이다. 이러한 문제를 해결하기 위해 등장한 것이 HTTPS다.</p>
<hr>
<h1 id="htpps란">HTPPS란?</h1>
<p>HTTPS는 HTTP에 SSL을 사용하여 데이터 암호화가 추가된 프로토콜이다. HTTPS는 HTTP와 다르게 443번 포트를 사용하며, 네트워크 상에서 중간에 제3자가 정보를 볼 수 없도록 암호화를 지원하고 있다.</p>
<p>HTTP 자체를 암호화 하는 것이 아닌 HTTP 메세지 BODY를 암호화 한는 것이다.</p>
<h3 id="ssl">SSL</h3>
<p>Secure Sokects Layer의 약자이며 웹 서버와 웹 브라우저간 보안을 위해 만든 프로토콜이다.
대칭키/ 비대칭 기반을 사용한다.</p>
<h3 id="대칭키-암호화와-비대칭키-암호화">대칭키 암호화와 비대칭키 암호화</h3>
<p>앞서 언급하였듯이 SLL을 사용하는 HTTPS는 대칭키 암호화 방식과 비대칭키 암호화 방식을 모두 사용하고 있다. 각각의 암호화 방식은 다음과 같다.</p>
<p>대칭키 암호화</p>
<ul>
<li>클라이언트와 서버가 동일한 키를 사용해 암호화/복호화를 진행함</li>
<li>키가 노출되면 매우 위험하지만 연산 속도가 빠름</li>
</ul>
<p>비대칭키 암호화</p>
<ul>
<li>1개의 쌍으로 구성된 각각의 공개키와 개인키를 암호화/복호화 하는데 사용함</li>
<li>키가 노출되어도 비교적 안전하지만 연산 속도가 느림</li>
</ul>
<h3 id="비대칭키-암호화">비대칭키 암호화</h3>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/1f3fec5e-1735-4b30-bf98-05b0e36f0639/image.png" alt=""></p>
<p>암호화를 공개키로 하느냐 개인키로 하느냐에 따라 얻는 효과가 다른데, 공개키와 개인키로 암호화하면 각각 다음과 같은 효과를 얻을 수 있다.</p>
<p>공개키 암호화: 공개키로 암호화를 하면 개인키로만 복호화할 수 있다. 
*<em>-&gt; 개인키는 나만 가지고 있으므로, 나만 볼 수 있다. *</em></p>
<p>개인키 암호화: 개인키로 암호화하면 공개키로만 복호화할 수 있다. 
<strong>-&gt; 공개키는 모두에게 공개되어 있으므로, 내가 인증한 정보임을 알려 신뢰성을 보장할 수 있다.</strong></p>
<hr>
<h1 id="https-동작과정">HTTPS 동작과정</h1>
<p>HTTPS는 대칭키 암호화와 비대칭키 암호화를 모두 사용하여 빠른 연산 속도와 안정성을 모두 얻고 있다.</p>
<p>처음 연결을 성립하여 안전하게 세션키를 공유하는 과정(HTTPS 연결 과정 Hand-Shaking)에서 비대칭키가 사용되는 것이고, 이후에 데이터를 교환하는 과정에서 빠른 연산 속도를 위해 대칭키가 사용되는 것이다</p>
<p>그렇다면 가장 중요한 내용인 HTTPS의 동작 방식에 대해서 알아보자.</p>
<p>HTTPS의 경우 웹 브라우저와 웹 서버말고 추가적으로 CA(Certificate Authority)라는 인증 기관이 추가되어 웹 브라우저, 웹 서버, CA 세개의 주체가 키를 주고 받으며 하나의 대칭키를 생성한다고 생각할 수 있다.</p>
<h3 id="1-웹-서버사이트에서-인증기관ca에게-사이트-정보와-사이트-공개키를-전송한다">1. 웹 서버(사이트)에서 인증기관(CA)에게 사이트 정보와 사이트 공개키를 전송한다.</h3>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/3810a84d-3b17-444a-aa7f-e7b3edc30482/image.png" alt=""></p>
<h3 id="2-인증기관에서는-전달받은-데이터를-검증-후-인증기관의-개인키로-암호화서명한다">2. 인증기관에서는 전달받은 데이터를 검증 후 인증기관의 개인키로 암호화(서명)한다.</h3>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/7d9f3c5e-91e8-4790-bd5e-af545d54ec29/image.png" alt=""></p>
<h3 id="3-사이트-인증서가-생성되어-이-인증서를-웹-서버사이트에게-인증서를-전달한다">3. 사이트 인증서가 생성되어 이 인증서를 웹 서버(사이트)에게 인증서를 전달한다.</h3>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/cf1b9d73-22be-47a8-9b8f-06ea4a854431/image.png" alt=""></p>
<h3 id="4-그후-인증기관ca은-웹-브라우저사용자에게-인증기관의-공개키를-제공하고-사용자-브라우저에-자동으로-내장된다">4. 그후, 인증기관(CA)은 웹 브라우저(사용자)에게 인증기관의 공개키를 제공하고 사용자 브라우저에 자동으로 내장된다.</h3>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/e61a6b54-880e-4cb1-a653-5849a46fa537/image.png" alt=""></p>
<h3 id="5-모든-준비가-끝나고-웹-브라우저사용자는-웹-서버사이트에게-접속을-요청한다">5. 모든 준비가 끝나고 웹 브라우저(사용자)는 웹 서버(사이트)에게 접속을 요청한다.</h3>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/d29bc652-bd6b-4617-8187-a89d2ca64ec4/image.png" alt=""></p>
<h3 id="6-웹-서버사이트는-웹-브라우저사용자에게-인증기관ca에서-받은-사이트-인증서를-준다">6. 웹 서버(사이트)는 웹 브라우저(사용자)에게 인증기관(CA)에서 받은 사이트 인증서를 준다.</h3>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/864cf014-94db-42a0-8d92-f9c849572234/image.png" alt=""></p>
<h3 id="7-웹-브라우저사용자는-인증기관-공개키를-사용하여-사이트-인증서를-복호화하여-사이트-정보와-사이트-공개키를-얻을-수-있다">7. 웹 브라우저(사용자)는 인증기관 공개키를 사용하여 사이트 인증서를 복호화하여 사이트 정보와 사이트 공개키를 얻을 수 있다.</h3>
<p> <img src="https://velog.velcdn.com/images/winsome_joo/post/58cec811-fd22-4270-b9ba-26a7fce7678d/image.png" alt=""></p>
<h3 id="8-사이트-공개키를-활용하여-사용자는-통신에-사용할-대칭키세션키를-암호화하여-웹-서버사이트에게-전달한다">8. 사이트 공개키를 활용하여 사용자는 통신에 사용할 대칭키(세션키)를 암호화하여 웹 서버(사이트)에게 전달한다.</h3>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/09b2f345-c3b2-483a-8049-449cbcfeeea9/image.png" alt="">
<img src="https://velog.velcdn.com/images/winsome_joo/post/5cb490b3-3040-48e1-ae7d-2d65bc0d0bfb/image.png" alt=""></p>
<h3 id="9-웹-서버사이트는-자신이-가지고-있는-개인키를-활용하여-대칭키세션키를-복호화하여-대칭키를-얻는다">9. 웹 서버(사이트)는 자신이 가지고 있는 개인키를 활용하여 대칭키(세션키)를 복호화하여 대칭키를 얻는다.</h3>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/268a2e2e-44c0-4b2f-9c18-9c20e8021975/image.png" alt=""></p>
<h3 id="10-이후-대칭키를-활용하여-암호화하여-통신을-진행한다">10. 이후 대칭키를 활용하여 암호화하여 통신을 진행한다.</h3>
<hr>
<h1 id="참고자료">참고자료</h1>
<p><a href="https://hahahoho5915.tistory.com/62">99CORN- HTTP Request/Response 구조</a></p>
<p><a href="https://velog.io/@hyoribogo/what-is-the-defference-between-http-and-https">https://velog.io/@hyoribogo/what-is-the-defference-between-http-and-https</a>
<a href="https://mangkyu.tistory.com/98">https://mangkyu.tistory.com/98</a></p>
<p><a href="https://rnclf1005.tistory.com/11">https://rnclf1005.tistory.com/11</a>
<a href="https://www.youtube.com/watch?v=wPdH7lJ8jf0&amp;t=339s">https://www.youtube.com/watch?v=wPdH7lJ8jf0&amp;t=339s</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[이터레이터 패턴]]></title>
            <link>https://velog.io/@winsome_joo/%EC%9D%B4%ED%84%B0%EB%A0%88%EC%9D%B4%ED%84%B0-%ED%8C%A8%ED%84%B4</link>
            <guid>https://velog.io/@winsome_joo/%EC%9D%B4%ED%84%B0%EB%A0%88%EC%9D%B4%ED%84%B0-%ED%8C%A8%ED%84%B4</guid>
            <pubDate>Wed, 10 Jul 2024 14:48:19 GMT</pubDate>
            <description><![CDATA[<h1 id="행위-패턴-behavioral-pattern">행위 패턴 (Behavioral Pattern)</h1>
<p>행위 패턴은 클래스나 객체들이 서로 상호작용하는 방법이나 책임 분배 방법을 정의하는 패턴으로 총 11개의 패턴이 있다.</p>
<p>행위 패턴은 하나의 객체로 수행할 수 없는 작업을 여러 객체로 분배하면서 결합도를 최소화 할 수 있도록 도와준다.</p>
<p>결론적으로 행위 패턴은 코드의 유지보수성과 가독성을 향상시키며 재사용성을 증가시킨다.</p>
<hr>
<h1 id="이터레이터-패턴">이터레이터 패턴</h1>
<p>11가지의 행위 패턴 중 오늘은 이터레이터 패턴에 대해서 정리해보려고한다.</p>
<h2 id="이터레이터-패턴이란">이터레이터 패턴이란?</h2>
<p>이터레이턴 패턴이란 이터레이터를 사용하여 컬렉션 요소들에  접근하는 디자인 패턴이다.
이를 통해 순회할 수 있는 여러가지 자료형의 구조와는 상관 없이 이터레이터라는 하나의 인터페이스로 순회가능하다.</p>
<p>쉽게 말해 이터레이터를 하나 만들어 두면 어떤 구조의 컬렉션이든 순회할 수 있다.</p>
<ul>
<li>컬렉션: 객체들을 묶어 자료의 구조를 취하는 데이터 집합(ex 리스트, 트리 , 그래프)</li>
</ul>
<h2 id="for문을-통해-단순-순회하면-되지-않는가">for문을 통해 단순 순회하면 되지 않는가?</h2>
<p>리스트나 보통배열의 경우 연속적인 데이터 집합이기 때문에 간단한 for문으로 순회할 수 있다. 하지만 해시, 트리와 같은 컬렉션은 데이터 저장순서가 정해지지 않고 적재되기 때문에, 각 요소들을 어떤 기준으로 접근해야할지 애매해진다.</p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/28f251fb-9ff2-41cb-a95b-e8c8dc668fca/image.png" alt=""></p>
<p>이처럼 복잡하게 얽혀있는 자료 컬렉션들을 순회하는 알고리즘 전략을 정의하는 것을 이터레이터 패턴이라고 한다.</p>
<p>컬렉션 객체 안에 들어있는 모든 원소들에 대한 접근 방식이 공통화 되어 있다면 어떤 종류의 컬렉션에서도 이터레이터만 뽑아내면 여러 전략으로 순회가 가능해 보다 다형(多形) 적인 코드를 설계할 수 있게 된다</p>
<p>이밖에도 이터레이터 패턴은 별도의 이터레이터 객체를 반환 받아 이를 이용해 순회하기 때문에, 집합체의 내부 구조를 노출하지 않고 순회 할 수 있다는 장점도 있다.</p>
<hr>
<h2 id="이터레이터-패턴-구조">이터레이터 패턴 구조</h2>
<p>이터레이터 패턴의 4가지 구성요소는 아래와 같다.</p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/b46f4637-ef20-402e-b45d-65f12781aeda/image.png" alt=""></p>
<p>Aggregate (인터페이스) : ConcreateIterator 객체를 반환하는 인터페이스를 제공한다.</p>
<ul>
<li><p>iterator() : ConcreateIterator 객체를 만드는 팩토리 메서드</p>
</li>
<li><p>쉽게 컬렉션이라고 볼 수 있음</p>
</li>
</ul>
<p>ConcreateAggregate (클래스) : 여러 요소들이 이루어져 있는 데이터 집합체
Iterator (인터페이스) : 집합체 내의 요소들을 순서대로 검색하기 위한 인터페이스를 제공한다.</p>
<ul>
<li>hasNext() : 순회할 다음 요소가 있는지 확인 (true / false)</li>
<li>next() : 요소를 반환하고 다음 요소를 반환할 준비를 하기 위해 커서를 이동시킴</li>
</ul>
<p>ConcreateIterator (클래스) : 반복자 객체</p>
<ul>
<li>ConcreateAggregate가 구현한 메서드로부터 생성되며, ConcreateAggregate 의 컬렉션을 참조하여 순회한다.</li>
<li>어떤 전략으로 순회할지에 대한 로직을 구체화 한다.</li>
</ul>
<hr>
<h2 id="코드구현">코드구현</h2>
<pre><code>// 집합체 객체 (컬렉션)
interface Aggregate {
    Iterator iterator();
}

class ConcreteAggregate implements Aggregate {
    Object[] arr; // 데이터 집합 (컬렉션)
    int index = 0;

    public ConcreteAggregate(int size) {
        this.arr = new Object[size];
    }

    public void add(Object o) {
        if(index &lt; arr.length) {
            arr[index] = o;
            index++;
        }
    }

    // 내부 컬렉션을 인자로 넣어 이터레이터 구현체를 클라이언트에 반환
    @Override
    public Iterator iterator() {
        return new ConcreteIterator(arr);
    }
}</code></pre><pre><code>// 반복체 객체
interface Iterator {
    boolean hasNext();
    Object next();
}

class ConcreteIterator implements Iterator {
    Object[] arr;
    private int nextIndex = 0; // 커서 (for문의 i 변수 역할)

    // 생성자로 순회할 컬렉션을 받아 필드에 참조 시킴
    public ConcreteIterator(Object[] arr) {
        this.arr = arr;
    }

    // 순회할 다음 요소가 있는지 true / false
    @Override
    public boolean hasNext() {
        return nextIndex &lt; arr.length;
    }

    // 다음 요소를 반환하고 커서를 증가시켜 다음 요소를 바라보도록 한다.
    @Override
    public Object next() {
        return arr[nextIndex++];
    }
}</code></pre><h3 id="사용-흐름">사용 흐름</h3>
<pre><code>public static void main(String[] args) {
    // 1. 집합체 생성
    ConcreteAggregate aggregate = new ConcreteAggregate(5);
    aggregate.add(1);
    aggregate.add(2);
    aggregate.add(3);
    aggregate.add(4);
    aggregate.add(5);

    // 2. 집합체에서 이터레이터 객체 반환
    Iterator iter = aggregate.iterator();

    // 3. 이터레이터 내부 커서를 통해 순회
    while(iter.hasNext()) {
        System.out.printf(&quot;%s → &quot;, iter.next());
    }
}</code></pre><p><img src="https://velog.velcdn.com/images/winsome_joo/post/f411c357-747f-4c45-9dd3-f344852c9e18/image.png" alt=""></p>
<hr>
<h2 id="이터레이터-패턴-특징">이터레이터 패턴 특징</h2>
<h3 id="패턴-사용-시기">패턴 사용 시기</h3>
<ul>
<li>컬렉션에 상관없이 객체 접근 순회 방식을 통일하고자 할 때</li>
<li>컬렉션을 순회하는 다양한 방법을 지원하고 싶을 때</li>
<li>컬렉션의 복잡한 내부 구조를 클라이언트로 부터 숨기고 싶은 경우 (편의 + 보안)</li>
<li>데이터 저장 컬렉션 종류가 변경 가능성이 있을 때</li>
<li>클라이언트가 집합 객체 내부 표현 방식을 알고 있다면, 표현 방식이 달라지면 클라이언트 코드도 변경되어야 하는 문제가 생긴다.</li>
</ul>
<h3 id="패턴-장점">패턴 장점</h3>
<ul>
<li>일관된 이터레이터 인터페이스를 사용해 여러 형태의 컬렉션에 대해 동일한 순회 방법을 제공한다.</li>
<li>컬렉션의 내부 구조 및 순회 방식을 알지 않아도 된다.</li>
<li>집합체의 구현과 접근하는 처리 부분을 반복자 객체로 분리해 결합도Visit Website를 줄 일 수 있다.</li>
<li>Client에서 iterator로 접근하기 때문에 ConcreteAggregate 내에 수정 사항이 생겨도 iterator에 문제가 없다면 문제가 발생하지 않는다.</li>
<li>순회 알고리즘을 별도의 반복자 객체에 추출하여 각 클래스의 책임을 분리하여 단일 - 책임 원칙(SRP)Visit Website를 준수한다.</li>
<li>데이터 저장 컬렉션 종류가 변경되어도 클라이언트 구현 코드는 손상되지 않아 수정에는 닫혀 있어 개방 폐쇄 원칙(OCP)Visit Website를 준수한다.</li>
</ul>
<h3 id="패턴-단점">패턴 단점</h3>
<ul>
<li>클래스가 늘어나고 복잡도가 증가한다.</li>
<li>만일 앱이 간단한 컬렉션에서만 작동하는 경우 패턴을 적용하는 것은 복잡도만 증가할 수 있다.</li>
<li>이터레이터 객체를 만드는 것이 유용한 상황인지 판단할 필요가 있다.</li>
<li>구현 방법에 따라 캡슐화를 위배할 수 있다.</li>
</ul>
<hr>
<h2 id="참고자료">참고자료</h2>
<p><a href="https://inpa.tistory.com/entry/GOF-%F0%9F%92%A0-%EB%B0%98%EB%B3%B5%EC%9E%90Iterator-%ED%8C%A8%ED%84%B4-%EC%99%84%EB%B2%BD-%EB%A7%88%EC%8A%A4%ED%84%B0%ED%95%98%EA%B8%B0">InpaDev-반복자Iterator-패턴-완벽-마스터하기</a></p>
<p><a href="https://www.youtube.com/watch?v=T3sXKtlr0Ow">GIS DEVELOPER-GoF의 Design Pattern - 2. Iterator(유튜브)</a></p>
<p><a href="https://gr-st-dev.tistory.com/532">호락호락한순무-[Dev] 디자인 패턴 중 행위 패턴이란 무엇이지 알아보자</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[데코레이터 패턴]]></title>
            <link>https://velog.io/@winsome_joo/Decorator-Pattern</link>
            <guid>https://velog.io/@winsome_joo/Decorator-Pattern</guid>
            <pubDate>Wed, 03 Jul 2024 07:45:37 GMT</pubDate>
            <description><![CDATA[<h1 id="디자인-패턴이란">디자인 패턴이란?</h1>
<p>공통적으로 발생하는 문제에 대해서 재사용 가능한 해결책을 의미한다.
다른 상황에 맞게 사용될 수 있는 문제를 해결하는데 사용되는 템플릿임</p>
<p>디자인 패턴을 학습하면 확장성이 높고 유연한 개발이 가능해진다.</p>
<p>GOF의 디자인 패턴은 <strong>3가지로 나뉜다 생성 패턴, 행위 패턴, 구조 패턴</strong>
오늘은 구조 패턴과 그 중 <strong>데코레이터 패턴</strong>을 알아보려고한다.</p>
<hr>
<h1 id="구조-패턴이란">구조 패턴이란?</h1>
<p>클래스와 객체를 더 큰 구조로 만들 수 있게 구성을 사용하는 패턴을 의미한다.
보통 규모가 있는 객체지향 프로그램을 구현할 경우 사용된다.
<img src="https://velog.velcdn.com/images/winsome_joo/post/16f4004d-6297-4123-a717-8e12a9ca59b6/image.png" alt=""></p>
<ul>
<li>독립적으로 개발한 클래스 라이브러리를 마치 하나인 것처럼 사용</li>
<li>여러 인터페이스를 합성하여 서로 다른 인터페이스들의 통일된 추상을 제공</li>
<li>인터페이스나 구현을 복합하는 것이 아니라 객체를 합성하는 방법을 제공</li>
</ul>
<hr>
<h1 id="데코레이터-패턴">데코레이터 패턴</h1>
<p> 데코페이터 패턴은 뜻 그대로 기능을 마치 장식처럼 계속 추가할 수 있는 패턴이다.
 심지어 실행 중에 동적으로 기능을 변경 또는 확장을 할 수 있는 패턴이다.</p>
<p> 데코레이터 패턴의 핵심은 <strong>Composition과 다형성</strong>이다.</p>
<p> Composition(구성)은 상속과 다르다.
 상속은 고정된 특성을 물려받는 것이고, 구성은 필요한 기능을 포함하여 유연하게 조합할 수 있는  방식
 상속: 부모 클래스를 오버라이딩해서 메소드를 재정의 
 구성: 부모 클래스를 Private 변수로 가져와서 해당 기능을 사용 </p>
<p> <a href="https://it-mesung.tistory.com/39">상속과 구성에 자세한 내용은 이곳을 참고</a></p>
<h3 id="클래스-다이어그램-예시">클래스 다이어그램 예시</h3>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/bfaf7562-479f-462a-ab61-e3f1069e6a9d/image.png" alt=""></p>
<p> Strings는 문자열을 여러개 가지고 있는 클래스이며 <strong>장식 당하는 대상</strong>
 Decorator는 String을 <strong>장식할 클래스임</strong>
 <strong>Item 클래스를 통해서</strong> Strings와 Decorator를 사용할 수 있게된다. </p>
<h3 id="실제-사용-사례">실제 사용 사례</h3>
<p>  <img src="https://velog.velcdn.com/images/winsome_joo/post/5aa6718c-9dfa-40a4-b49d-3735892a2357/image.png" alt=""></p>
<p><strong>Item</strong>을 인터페이스를 통해 클래스를 구현한다면 기본적인 문자열로 이루어진 String 클래스에 Decorator 클래스 기능을 유연하게 확장할 수 있다.</p>
<p><strong>SideDecorator 클래스</strong>는 문자열에 쌍따옴표 
<strong>BoxDecorator 클래스</strong>는 문자열에 박스
<strong>LineNumberDecorator 클래스</strong>는 번호를 각각 추가할 수 있다</p>
<p>기능을 추가하고 싶으면 위와 같이 각 데코레이터 클래스를 추가해주면 된다.</p>
<h3 id="참고-코드">참고 코드</h3>
<p>** Item 클래스 **
<img src="https://velog.velcdn.com/images/winsome_joo/post/94b0ec79-ed95-4ff5-98eb-758a21c63ddd/image.png" alt=""></p>
<p> ** String 클래스 **
 <img src="https://velog.velcdn.com/images/winsome_joo/post/f73a7c06-e2dd-4e41-8e79-55ce92c03316/image.png" alt=""></p>
<p>** Decorator 클래스 **
<img src="https://velog.velcdn.com/images/winsome_joo/post/5cfd9a55-45a4-4831-93f7-6f4d03933b07/image.png" alt=""></p>
<p>** LineNumberDecorator 클래스 **
<img src="https://velog.velcdn.com/images/winsome_joo/post/716d36dd-8ce0-4da2-8b1c-5fd28eb2a245/image.png" alt=""></p>
<p> ** 사용 코드 **</p>
<p> <img src="https://velog.velcdn.com/images/winsome_joo/post/66149639-a682-4978-af42-09a9f2ef7a9e/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/154f366c-f597-4eb6-a2e5-3559d375a01f/image.png" alt=""></p>
<hr>
<h1 id="참고-자료">참고 자료</h1>
<p> <a href="https://www.youtube.com/watch?v=UTmY_oB4V8I%5D">GIS DEVELOPER- GoF의 Design Pattern - 15. Decorator</a> &lt;-- 다른 디자인 패턴에 대한 내용도 동영상으로 잘 정리해둠
 <a href="https://velog.io/@ha0kim/Design-Pattern-%EA%B5%AC%EC%A1%B0-%ED%8C%A8%ED%84%B4Structural-Patterns">Design Pattern : 구조 패턴(Structural Patterns)</a>
 <a href="https://devscb.tistory.com/87">SCB 개발자 이야기- 디자인패턴이란?</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[RDS 띄우고 EC2로 연결해보기]]></title>
            <link>https://velog.io/@winsome_joo/RDS-%EB%9D%84%EC%9A%B0%EA%B3%A0-EC2%EB%A1%9C-%EC%97%B0%EA%B2%B0%ED%95%B4%EB%B3%B4%EA%B8%B0</link>
            <guid>https://velog.io/@winsome_joo/RDS-%EB%9D%84%EC%9A%B0%EA%B3%A0-EC2%EB%A1%9C-%EC%97%B0%EA%B2%B0%ED%95%B4%EB%B3%B4%EA%B8%B0</guid>
            <pubDate>Sat, 11 May 2024 17:05:44 GMT</pubDate>
            <description><![CDATA[<h1 id="1--rds-인스탄스-생성">1.  RDS 인스탄스 생성</h1>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/c7e9ea16-7f39-459a-ba68-7a00787a5602/image.png" alt=""></p>
<ul>
<li><strong>DB 종류 선택</strong><ul>
<li>데이터베이스 생성 방식 선택: 표준 생성</li>
<li>Mysql</li>
</ul>
</li>
<li><strong>DB 설정 입력</strong><ul>
<li>템플릿: 프리 티어</li>
<li>DB 인스턴스 식별자에 원하는 데이터베이스 이름을 입력하고 마스터 사용자 이름과 마스터 암호 입력</li>
<li>데이터베이스 이름, 마스터 이름, 비밀번호는 실제로 DB에 접근할 때 사용할 정보이므로 신중하게 입력하고 반드시 기억해두어야 한다</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/2fc91986-3a5a-45fc-9895-cb934abe1392/image.png" alt=""></p>
<ul>
<li><p><strong>스토리지 자동 조정 활성화 해제</strong></p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/65be00e6-b506-4fbb-8c87-a6763404ba7f/image.png" alt=""></p>
</li>
</ul>
<pre><code>- 체크했을 경우 : 개발 진행 중 임계값이 초과되는 경우 자동으로 스토리지가 늘어나 추가 금액이 붙을 수 있음!</code></pre><ul>
<li><p><strong>보안그룹 설정(연결)</strong></p>
<ul>
<li>퍼블릭 엑세스: 예</li>
<li>VPC 보안 그룹(방화벽): 새로 생성 클릭 → 새 VPC 보안 그룹 이름 입력</li>
</ul>
</li>
<li><p><strong>추가 구성</strong></p>
<ul>
<li>백업: &#39;자동 백업을 활성화합니다&#39; 체크 해제</li>
<li>유지 관리: &#39;마이너 버전 자동 업그레이드 사용&#39; 체크 해제</li>
</ul>
<hr>
</li>
</ul>
<h1 id="2-현재-보안-그룹-확인">2. 현재 보안 그룹 확인</h1>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/0c77cf5b-f2d9-4433-a44c-fdd9f01acd19/image.png" alt=""></p>
<ol>
<li>RDS 인바운드 규칙에 EC2 보안 그룹 ID 입력<ul>
<li>&#39;인바운드 규칙 편집&#39; 클릭 → 규칙 추가 클릭하여 새 인바운드 규칙 작성 후 저장</li>
<li>새 인바운드 규칙 내용<ul>
<li>유형: MYSQL/Aurora</li>
<li>프로토콜: TCP</li>
<li>포트 범위: 3306</li>
<li>소스: 사용자...</li>
</ul>
</li>
</ul>
</li>
</ol>
<h1 id="3-파라미터-그룹-설정">3. 파라미터 그룹 설정</h1>
<ul>
<li><strong>파리미터 그룹 생성</strong></li>
</ul>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/a4cb2861-7eda-427f-9696-d7057dfc1658/image.png" alt=""></p>
<ul>
<li><strong>Time Zone, Character set, Collation, Max Connection 설정</strong></li>
</ul>
<p>파라미터 그룹 클릭 후 편집 눌러서 값 변경하기  아래처럼 변경하기</p>
<ul>
<li>timezome→ Asia/Seoul</li>
<li>max_connections → 150</li>
<li>파라미터 char_ -&gt; 값 utf8로 변경</li>
<li>collaction_ -&gt; 값 utf8mb4_general_ci</li>
</ul>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/62c99a18-a318-46ce-822a-8652f3bb3e27/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/f15d8739-8e79-4cdf-97e5-0434956e1002/image.png" alt=""></p>
<ul>
<li><strong>RDS 파라미터 그룹 변경</strong><ul>
<li>RDS 인스턴스 이동 → 수정 클릭</li>
<li>DB 파라미터 그룹을 새로 생성한 파라미터 그룹으로 변경 (ex. my-rds-parameter-group)</li>
<li>DB 인스턴스 수정 사항 확인</li>
<li>수정 예약은 &#39;즉시 적용&#39; 선택하고 &#39;DB 인스턴스 수정&#39; 클릭</li>
</ul>
</li>
</ul>
<hr>
<h1 id="4-rds-접속-테스트">4. RDS 접속 테스트</h1>
<ol>
<li>로컬 PC 접속</li>
</ol>
<p>MySQL Workbench에 New Connection 생성</p>
<ul>
<li><p>Hostname: RDS 엔드포인트</p>
</li>
<li><p>Username: RDS 생성 시 입력했던 정보 (마스터 사용자 이름)</p>
</li>
<li><p>Password: RDS 생성 시 입력했던 정보 (마스터 암호)</p>
</li>
</ul>
<ol start="2">
<li>EC2에서 접속</li>
</ol>
<pre><code class="language-bash"># ubuntu에서 MySQL 설치
sudo apt-get update
sudo apt-get install mysql-server

# MySQL 명령어로 접속 시도
mysql -u {마스터 사용자 이름} -p --host {엔드포인트}</code></pre>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/d345b1c0-d786-412e-a08d-60871e68ddad/image.png" alt=""></p>
<h1 id="참고자료">참고자료</h1>
<p><a href="https://rovemin.tistory.com/27">https://rovemin.tistory.com/27</a> ← main 자료</p>
<p><a href="https://debut12.tistory.com/34">https://debut12.tistory.com/34</a> ← 보조 자료</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Ec2 설치 및 접근하기 + 자바 설정]]></title>
            <link>https://velog.io/@winsome_joo/Ec2-%EC%84%A4%EC%B9%98-%EB%B0%8F-%EC%A0%91%EA%B7%BC%ED%95%98%EA%B8%B0-%EC%9E%90%EB%B0%94-%EC%84%A4%EC%A0%95</link>
            <guid>https://velog.io/@winsome_joo/Ec2-%EC%84%A4%EC%B9%98-%EB%B0%8F-%EC%A0%91%EA%B7%BC%ED%95%98%EA%B8%B0-%EC%9E%90%EB%B0%94-%EC%84%A4%EC%A0%95</guid>
            <pubDate>Sun, 28 Apr 2024 14:15:28 GMT</pubDate>
            <description><![CDATA[<h1 id="1-인스탄스-생성하기">1. 인스탄스 생성하기</h1>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/d5657fd6-d9d7-4fe5-bc85-08750c34f736/image.png" alt=""></p>
<ul>
<li><strong>AMI</strong>:  Ubuntu 선택</li>
<li><strong>키페어</strong><ul>
<li>키페어명은 내가원하는 이름</li>
<li>키페어 유형은 RSA</li>
<li>프라이빗 키파일 형식은 .pem</li>
</ul>
</li>
</ul>
<p>다운 받은 후 다시 다운 불가하기 때문에 잘 저장해두기 </p>
<ul>
<li><strong>네트워크 설정</strong><ul>
<li>보안 그룹 선택 후 내 IP에서 SSH 트래픽 허용 (NACL단에서 설정하는 것임)</li>
</ul>
</li>
<li><strong>스토리지 구성</strong><ul>
<li>1X 30 gib gp2 루트 볼륨</li>
</ul>
</li>
</ul>
<p><strong>인스턴스 시작하기</strong></p>
<hr>
<h1 id="2-탄력적-ip-추가">2. 탄력적 IP 추가</h1>
<p>AWS EC2 인스턴스는 서버를 중지하고 다시 실행시키면 퍼블릭 IP 가 변경되기 때문에 클라이언트가 사용할 수 있는 변하지 않는 IP 가 필요하다.</p>
<p>탄력적 IP (Elastic IP) 란 외부에서 인스턴스에 접근 가능한 고정 IP 입니다.</p>
<p>탄력적 IP 는 만들어놓고 사용하지 않더라도 과금이 되기 때문에 필요한 만큼만 생성하는 것이 중요하다.</p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/93073e13-2750-4021-88e3-27a71ea0c383/image.png" alt=""></p>
<ul>
<li>위 사진처럼 탄력적 ip에서 탄력적 ip 주소 할당 클릭 후 <strong>탄력적 IP 생성</strong></li>
</ul>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/2e5133f4-33d9-4ce8-a9ee-f7739a2c0611/image.png" alt=""></p>
<ul>
<li><p>생성한 탄력적 ip에 인스탄스 연결하기</p>
<ul>
<li><p>퍼블릭 IPv4 주소</p>
</li>
<li><p>프라이빗 IPv4 주소</p>
<p>위 주소 연결해주고 인스턴스에서 탄력적 ip로 변경되었는지 확인</p>
</li>
</ul>
</li>
</ul>
<hr>
<h1 id="3-보안-그룹-설정">3. 보안 그룹 설정</h1>
<p>인스턴스 정보 요약 화면에서 하단에 <strong>‘보안’</strong> 클릭</p>
<p>즉 내가 선택하고 싶은 인스탄스 보안 그룹에서 인바운드 규칙을 추가해준다.</p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/9e4e9bcc-a453-402c-8f6f-4fac7aac5b3c/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/3c220b12-4967-48e8-9052-52ccd2b063ad/image.png" alt=""></p>
<p><strong>[SG  규직 설정]</strong> </p>
<table>
<thead>
<tr>
<th>유형</th>
<th>프로토콜</th>
<th>포트 범위</th>
<th>소스</th>
<th>설명 - 선택 사항</th>
</tr>
</thead>
<tbody><tr>
<td>SSH</td>
<td>TCP</td>
<td>22</td>
<td>내 IP</td>
<td>My Local SSH</td>
</tr>
<tr>
<td>HTTP</td>
<td>TCP</td>
<td>80</td>
<td>Anywhere-IPv4</td>
<td>HTTP</td>
</tr>
<tr>
<td>HTTPS</td>
<td>TCP</td>
<td>443</td>
<td>Anywhere-IPv4</td>
<td>HTTPS</td>
</tr>
<tr>
<td>사용자 지정 TCP</td>
<td>TCP</td>
<td>8080</td>
<td>Anywhere-IPv4</td>
<td>Spring Boot Port</td>
</tr>
</tbody></table>
<hr>
<h1 id="4-ec2-접속-해보기">4. Ec2 접속 해보기</h1>
<p><strong>참고 블로그</strong> :<a href="https://velog.io/@spamdong/PuTTy-%EC%84%A4%EC%B9%98-%EB%B0%8F-%EC%82%AC%EC%9A%A9%EB%B2%95">https://velog.io/@spamdong/PuTTy-설치-및-사용법</a></p>
<h3 id="putty란">PuTTy란?</h3>
<ul>
<li>암호화 기능을 비롯 수 많은 기능을 포함하고 있어 윈도우에서 리눅스 환경으로 접속하는데 가장 좋은 프로그램</li>
</ul>
<h3 id="왜-사용해야하는가">왜 사용해야하는가?</h3>
<ul>
<li>아래 사진은 AWS Doc이다. PuTTy를 사용하는 방법이 있는 것을 확인할 수 있을정도로 자주 사용됨</li>
<li>이전 작업 내용을 확인이 가능함(Log)</li>
<li>PuTTY는 한번 설정한 사용자 환경은 저장이 되어있어 있기 때문에 재 실행시 이전 환경을 그대로 유지가 가능(글자 크기, 글자 색깔)</li>
</ul>
<h2 id="putty로-ec2-접근-과정">Putty로 EC2 접근 과정</h2>
<ul>
<li><strong>HostName에 아까 받은 인스탄스의 퍼블릭 IPv4 주소 입력</strong></li>
</ul>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/57495e7c-1957-46b1-a306-38a1806179ae/image.png" alt=""></p>
<ul>
<li><strong>Auth-SSH-Credantial에서 privatekey 넣어주기</strong></li>
</ul>
<p>참고로 puttygen을 통해pem키를 ppk로 변경한 상태다. 
이 내용이 궁금하면 참고한 블로그를 확인하길 바란다. </p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/24ecdc48-7196-4fd6-b1a0-b81d13764c89/image.png" alt=""></p>
<ul>
<li><strong>login as</strong>: ubuntu 입력해주고 접속하기</li>
</ul>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/3d355730-126d-45d3-8340-550c8dab2ec6/image.png" alt=""></p>
<hr>
<h1 id="5-ec2에-자바-설정">5. EC2에 자바 설정</h1>
<p><strong>1. JDK 설치 (Java 17 설치)</strong></p>
<pre><code class="language-java">sudo apt-get update
sudo apt-get install openjdk-17-jdk</code></pre>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/ae13ba03-95fe-4240-8ff5-a4294668e89c/image.png" alt=""></p>
<hr>
<h2 id="참고자료">참고자료</h2>
<p><a href="https://rovemin.tistory.com/27">https://rovemin.tistory.com/27</a> ← main 자료 </p>
<p><a href="https://bcp0109.tistory.com/356">https://bcp0109.tistory.com/356</a> ← Ec2 설정 추가 자료</p>
<p> <a href="https://velog.io/@spamdong/PuTTy-%EC%84%A4%EC%B9%98-%EB%B0%8F-%EC%82%AC%EC%9A%A9%EB%B2%95">https://velog.io/@spamdong/PuTTy-설치-및-사용법</a> ← putty 사용법</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Throw와 Throws ]]></title>
            <link>https://velog.io/@winsome_joo/Throw%EC%99%80-Throws</link>
            <guid>https://velog.io/@winsome_joo/Throw%EC%99%80-Throws</guid>
            <pubDate>Thu, 04 Apr 2024 07:38:18 GMT</pubDate>
            <description><![CDATA[<h1 id="📌-throw-예외-발생시키기">📌 Throw: 예외 발생시키기</h1>
<p>키워드 throw를 사용해서 프로그래머가 고의로 예외를 발생시킬 수 있다.</p>
<p><strong>방법</strong>
1 . 연산자 new를 이용해서 발생시키려는 예외 클래스의 객체를 만든다.</p>
<pre><code class="language-java"> Exception e= new Exception(&quot;고의로 발생시킴&quot;);</code></pre>
<p>2 . 키워드 throw를 이용해서 예외를 발생시킨다.</p>
<pre><code class="language-java"> throw e</code></pre>
<ul>
<li>객체를 만드는 것으로  예외가 발생하는 것이 아니라 throw로 던져야지 발생하게 됨 </li>
<li>&quot;고의로 발생시킴&quot; 이라는 매개변수로 넘긴 문자열은 printStackTrave()나 getmessage()로 확인할 수 있다.</li>
</ul>
<h2 id="예시-코드">예시 코드</h2>
<p>아래 예시처럼 throw new Exception(&quot;고의로 발생시켰음.&quot;) 처럼 <span style=color:Orange>한줄로 예외 발생시키고 던지는 것을 더 많이 사용한다.</span></p>
<pre><code class="language-java">class Tes {
    public static void main(String[] args) {
        try {
            Exception e = new Exception(&quot;고의로 발생시켰음.&quot;);
            throw e; // 예외를 발생시킴
//            throw new Exception(&quot;고의로 발생시켰음.&quot;); // 위  두 줄을 한 줄로 작성
        } catch(Exception e) {
            System.out.println(&quot;에러 메시지 : &quot; + e.getMessage());
            e.printStackTrace();
        }
        System.out.println(&quot;프로그램이 정상 종료되었음.&quot;);
    }
}</code></pre>
<hr>
<h1 id="📌-throws-메서드-예외-선언하기">📌 Throws: 메서드 예외 선언하기</h1>
<p>throw는 예외를 생성하는 키워드라는 것을 알았다. 하지만 비슷하게 생긴 throws는 완전 다른 역할인 예외를 처리하는 방법 중 하나다.</p>
<p>예외를 처리하는 방법은 다음 2가지 방법이 있다.</p>
<ul>
<li>try-catch: 예외가 발생한 곳에서 바로 처리 </li>
<li>throws: 메소드 내에서 발생할 수 있는 예외를 선언하고 호출한 곳으로 던져서 처리 
<span style=color:Orange>단 호출한 곳에서 try-catch로 예외를 처리해줘야함</span></li>
</ul>
<p><strong>방법</strong>
예외가 여러 개인 경우 쉼표(,)로 구분한다.</p>
<pre><code class="language-java">  void method() throws Exception1, Exception2, ... ExceptionN {
         // 메서드의 내용
    }</code></pre>
<p>만약 아래와 같이 모든 예외의 최고 조상인 Exception 클래스를 메서드에 선언하면, 이 메서드는 모든 종류의 예외가 발생할 가능성이 있다는 뜻</p>
<pre><code class="language-java">void method() throws Exception {
         // 메서드의 내용
    }</code></pre>
<h2 id="예시-코드-1">예시 코드</h2>
<pre><code class="language-java">class ExceptionEx14 {
    public static void main(String[] args) {
        try  {
                method1();        
        } catch (Exception e)    {
                System.out.println(&quot;main메서드에서 예외가 처리되었습니다.&quot;);
                e.printStackTrace();
        }
    }    // main메서드의 끝

    static void method1() throws Exception {
        throw new Exception();
    }    // method1()의 끝
} // class의 끝</code></pre>
<ol>
<li>method1 () 메소드에서 발생할 수 있는 예외를 throws 옆에 정의해줌</li>
<li>main메소드에서 method1() 메소드 호출</li>
<li>method1 () 메소드에서 예외발생</li>
<li>method1 () 메소드 호출하며 발생된 예외가 main메소드로 넘어옴</li>
<li>main메소드의 catch문에서 예외처리</li>
</ol>
<h1 id="📌-참고-자료">📌 참고 자료</h1>
<p><a href="https://velog.io/@thdqudgns/Java-Java%EC%9D%98-%EC%A0%95%EC%84%9D-%EC%A0%95%EB%A6%AC-%EC%98%88%EC%99%B8%EC%B2%98%EB%A6%AC">송병훈-Java의 정석 정리 (예외처리)</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Period.between() 두 날짜 사이 비교]]></title>
            <link>https://velog.io/@winsome_joo/Period.between%EB%91%90-%EB%82%A0%EC%A7%9C-%EC%82%AC%EC%9D%B4-%EB%B9%84%EA%B5%90</link>
            <guid>https://velog.io/@winsome_joo/Period.between%EB%91%90-%EB%82%A0%EC%A7%9C-%EC%82%AC%EC%9D%B4-%EB%B9%84%EA%B5%90</guid>
            <pubDate>Wed, 03 Apr 2024 01:01:54 GMT</pubDate>
            <description><![CDATA[<p>과거 대학 입학 날짜 2016년 3월 2일 ~ 졸업 날인 2024년 2월 20일 
사이 기간을 알아 보고 싶다면 어떻게 해야 할까? </p>
<p>두 날짜 사이의 차이를 계산을 도와주는 <strong>Period.between() 을 사용하여 알 수 있다.</strong></p>
<hr>
<h1 id="localdatetime">LocalDateTime</h1>
<p>LocalDateTime은 날짜 데이터와 시간 데이터를 가지는 클래스다.
(LocalDate는 날짜만 저장)</p>
<p>두 LocalDateTime 인스턴스의 차이를 구하는 메서드는 존재하지 않아 위에서 언급한  <strong>Period.between()를 사용한다.</strong></p>
<hr>
<h1 id="period-와-duration"><strong>Period 와 Duration</strong></h1>
<h2 id="periodbetween"><strong>Period.between()</strong></h2>
<h3 id="사용-예제">사용 예제</h3>
<pre><code class="language-java">LocalDate startDate = LocalDate.of(1939, 9, 1);
LocalDate endDate = LocalDate.of(1945, 9, 2);

Period period = Period.between(startDate, endDate);

System.out.println(&quot;Years: &quot; + period.getYears());
System.out.println(&quot;Months: &quot; + period.getMonths());
System.out.println(&quot;Days: &quot; + period.getDays());</code></pre>
<h3 id="결과">결과</h3>
<pre><code class="language-java">Years: 6
Months: 0
Days: 1</code></pre>
<p>두 LocalDateTime 인스턴스 사이의 년, 월, 일 차이를 구하기 위해서는 Period 클래스의 between() 메서드를 사용
 
Period.between() 메서드 특징</p>
<ul>
<li>두 날짜 사이의 간격을 년/월/일 단위로 반환한다.</li>
<li>&quot;x년 y개월 z일&quot; 형식의 데이터가 반환된다. 따라서, getDays() 메서드를 호출하면 두 날짜 사이의 일수가 아닌 &quot;z일&quot; 부분만 반환된다.<ul>
<li>getYears()</li>
<li>getMonths()</li>
<li>getDays()</li>
</ul>
</li>
</ul>
<hr>
<h2 id="durationbetween"><strong>Duration.between()</strong></h2>
<h3 id="사용-예제-1">사용 예제</h3>
<pre><code class="language-java">LocalTime start = LocalTime.of(10, 35, 40);
//10시 35분 40초
LocalTime end = LocalTime.of(10, 36, 50, 800);
//10시 36분 50초 800나노초
Duration duration = Duration.between(start, end);

System.out.println(&quot;Seconds: &quot; + duration.getSeconds());
System.out.println(&quot;Nano Seconds: &quot; + duration.getNano());</code></pre>
<h3 id="결과-1">결과</h3>
<pre><code class="language-java">Seconds: 70
Nano Seconds: 800</code></pre>
<ul>
<li>두 시간 사이의 간격을 초나 나노 초 단위단위로 반환한다.</li>
<li><code>getSeconds()</code>  사용시 초, <code>getNano()</code> 나노초 반환</li>
</ul>
<hr>
<h1 id="period로-사이-기간-구하기">Period로 사이 기간 구하기</h1>
<h2 id="1--localdatetime을-localdate로-변환">1.  <strong>LocalDateTime을 LocalDate로 변환</strong></h2>
<p>만약 날짜를 LocalDateTime형식으로 받는다면 시간 데이터는 분리한다.</p>
<p>xxxx년x월 ~xxxx년x월 사이에 기간을 구분해야 하기 때문에 시간 데이터는 필요 없다.  따라서 <strong><code>toLocalDate()</code>  사용</strong> </p>
<h3 id="사용-예시">사용 예시</h3>
<pre><code class="language-java">LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime);
System.out.println(localDateTime.toLocalDate());
</code></pre>
<h3 id="결과-2">결과</h3>
<pre><code>2021-11-08T12:42:11.769062
2021-11-08</code></pre><h2 id="2-periodbetween-사용-하기">2. <strong>Period.between() 사용 하기</strong></h2>
<h3 id="사용-예시-1">사용 예시</h3>
<pre><code class="language-java">LocalDateTime registerAt = user.getRegisterAt();
 LocalDateTime nowRegisterAt = LocalDateTime.now();

 Period diff = Period.between(registerAt.toLocalDate(), nowRegisterAt.toLocalDate());


  System.out.printf(&quot;두 날짜 사이 기간: %d년 %d월 %d일&quot;,
          diff.getYears(), diff.getMonths(), diff.getDays());</code></pre>
<p> diff.getYears(), diff.getMonths(), diff.getDays())메소드는 int형으로 반환 됨</p>
<h3 id="결과-3">결과</h3>
<pre><code class="language-java">두 날짜 사이 기간: 1년 8월 22일</code></pre>
<h3 id="결과-4">결과</h3>
<pre><code class="language-java">System.out.println(diff);
P1Y8M22D</code></pre>
<hr>
<h1 id="참고-자료">참고 자료</h1>
<p><a href="https://covenant.tistory.com/255">https://covenant.tistory.com/255</a></p>
<p><a href="https://www.daleseo.com/java8-duration-period/">https://www.daleseo.com/java8-duration-period/</a></p>
<p>남궁성-자바의정석 P528~541</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring에서의 IoC와 DI ]]></title>
            <link>https://velog.io/@winsome_joo/Spring%EC%97%90%EC%84%9C%EC%9D%98-IoC%EC%99%80-DI</link>
            <guid>https://velog.io/@winsome_joo/Spring%EC%97%90%EC%84%9C%EC%9D%98-IoC%EC%99%80-DI</guid>
            <pubDate>Tue, 26 Mar 2024 15:45:41 GMT</pubDate>
            <description><![CDATA[<h1 id="제어의-역전--inversion-of-control-ioc">제어의 역전  <strong>(Inversion Of Control, IoC)</strong></h1>
<p><strong>프로그램의 흐름을 직접 제어하는 것이 아니라 외부에 제어권을 넘겨 관리하게 하는 것을 제어의 역전이라고한다.</strong></p>
<p><span style=color:Orange>상세히 말하면 객체의 생성과 관리를 외부에서 한다면 제어권을 넘기게 되어 제어의 역전이 발생한 것이다.</span></p>
<hr>
<h1 id="프레임워크와-라이브러리">프레임워크와 라이브러리</h1>
<p>프레임워크는 제어의 역전 개념이 적용된 대표적인 기술이다.
<strong>프레임워크와 라이브러리를 구분할 때 IOC 개념이 중요하다.</strong></p>
<h3 id="library"><strong>Library</strong></h3>
<p>개발자는 필요한 Library 들을 <strong>선택하고, 연결하고, 설정하는</strong> 모든걸 다 직접 해야함</p>
<p><span style=color:Orange>세부적으로 보면 라이브러리를 통해 객체를 생성하고 
메소드를 호출하는 것을 개발자가 직접하기에 제어권이 
코드 자체(개발자)에게 있는 것이다.</span></p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/dba2892e-d4cf-478d-bd03-7bb88ddf2edc/image.png" alt=""></p>
<h3 id="framework"><strong>Framework</strong></h3>
<p>개발자가 직접 구현한것 혹은 Library 들을 <strong>연결하고, 설정하는</strong> 것들을 제공함</p>
<p><span style=color:Orange>개발자가 기능 구현에 필요한 특정 코드를 프레임워크에 작성하면
프레임워크가 알아서 객체를 생성하고 메소드를 호출해준다. 
즉 제어권이 프레임워크에 있는 것이다.</span></p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/7d5d5c89-8c92-4d2b-b20e-756764f7dadb/image.png" alt=""></p>
<hr>
<h1 id="spring-프레임워크에서의-ioc">Spring 프레임워크에서의 IoC</h1>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/c43cc265-c754-4e83-b54c-e00e09501b7d/image.png" alt=""></p>
<p>스프링에서는 사용할 객체를 직접 생성하지 않고 객체의 생성과 생명주기 관련해서는 Spring 컨테이너에 위임을 하여 제어권을 넘기게 된다.  이것이 Spring에서의 제어의 역전 IoC다.</p>
<p>IoC를 통해 ID(의존성 주입), 관점 지향 프로그래밍(AOP)등이 가능해지는 것이다.  이번 포스팅 글에서는 Spring에서의 DI를 집중적으로 다루어 보려고 한다. </p>
<h3 id="빈-등록">빈 등록</h3>
<ul>
<li><p>스프링 빈 자동 등록 방법: @Repository, @Service, @Contorller, @Component <span style=color:Orange> 
&lt;-@ComponentScan </span></p>
</li>
<li><p>스프링 빈 수동 등록 방법: @Bean + Method</p>
<p><a href="https://taehoung0102.tistory.com/75">참고 블로그 : 2가지 빈 등록 방식</a></p>
</li>
</ul>
<h3 id="빈-사용">빈 사용</h3>
<ul>
<li>@Autowired</li>
</ul>
<hr>
<h1 id="의존성--주입di">의존성  주입(DI)</h1>
<p>의존성  주입은 제어 역전의 방법 중 하나로, 사용할 객체를 직접 생성하지 않고 외부 컨테이너가 생성한 객체를 주입받아 사용하는 방식이다. </p>
<h2 id="autowired">@Autowired</h2>
<p>  스프링 컨테이너에서 객체를 찾아 의존 객체 타입에 맞게 넣어준다.</p>
<h1 id="의존관계-주입의-4가지-방법">의존관계 주입의 4가지 방법</h1>
<ul>
<li>생성자 주입</li>
<li>수정자 주입</li>
<li>필드 주입</li>
<li>일반 메서드 주입</li>
</ul>
<h2 id="생성자-주입">생성자 주입</h2>
<h3 id="쉬운-이해를-위한-코드"><strong>쉬운 이해를 위한 코드</strong></h3>
<pre><code class="language-java">@Component
public class OrderServiceImpl implements OrderService {

     private final MemberRepository memberRepository;
     private final DiscountPolicy discountPolicy;

 @Autowired
 public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicydiscountPolicy) {
         this.memberRepository = memberRepository;
         this.discountPolicy = discountPolicy;
 }
}</code></pre>
<ul>
<li>이름 그대로 생성자를 통해서 의존 관계를 주입 받는 방법</li>
<li><strong>Final 적용 가능하여</strong> 생성자 호출시점에  의존 객체가 딱 1번만 주입되는 것이 보장된다. 의존 객체를 변경하지 않을 경우에 사용함</li>
</ul>
<h3 id="실제-현업에서-사용하는-코드requiredargconstructor--private-final"><strong>실제 현업에서 사용하는 코드(</strong>@RequiredArgConstructor + private final<strong>)</strong></h3>
<pre><code class="language-java">@Component
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {

     private final MemberRepository memberRepository;
     private final DiscountPolicy discountPolicy;


    /*  
      public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicydiscountPolicy) {
         this.memberRepository = memberRepository;
         this.discountPolicy = discountPolicy;
 }
     */

}</code></pre>
<ul>
<li>@RequiredArgsConstructor 기능을 사용하면 final이 붙은 필드를 모아서 생성자를 자동으로 만들어줌</li>
<li>주석 처리된 생성자가 RequiredArgsConstructor로 인해 생성되었지만 안 보이는 것임</li>
</ul>
<hr>
<h2 id="수정자-주입">수정자 주입</h2>
<pre><code class="language-java">@Component
public class OrderServiceImpl implements OrderService {

     private MemberRepository memberRepository;
     private DiscountPolicy discountPolicy;

     @Autowired
     public void setMemberRepository(MemberRepository memberRepository) {
             this.memberRepository = memberRepository;}

     @Autowired
     public void setDiscountPolicy(DiscountPolicy discountPolicy) {
             this.discountPolicy = discountPolicy;}
}</code></pre>
<ul>
<li>setter라 불리는 필드의 값을 변경하는 수정자 메서드를 통해서 의존관계를 주입하는 방법</li>
<li>선택, 변경 가능성이 있는 의존관계에 사용</li>
</ul>
<hr>
<h2 id="필드-주입">필드 주입</h2>
<pre><code class="language-java">@Component
public class OrderServiceImpl implements OrderService {

     @Autowired
     private MemberRepository memberRepository;

     @Autowired
     private DiscountPolicy discountPolicy;
}</code></pre>
<ul>
<li>이름 그대로 필드에 바로 주입하는 방법</li>
<li>코드가 간결해서 많은 개발자들을 유혹하지만 외부에서 변경이 불가능해서 테스트 하기 힘들다는 치명적인 단점이 있음</li>
</ul>
<p>Test 코드를 짤 때 순수 자바로 단위 Test Code를 만든다고 한다.<br>스프링을 띄우고 하나 하나 테스트를 돌리면 굉장히 시간이 오래 걸리기 때문이다.</p>
<hr>
<h2 id="일반-메서드-주입">일반 메서드 주입</h2>
<pre><code class="language-java">@Component
public class OrderServiceImpl implements OrderService {

     private MemberRepository memberRepository;
     private DiscountPolicy discountPolicy;

@Autowired
public void init(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
         this.memberRepository = memberRepository;
         this.discountPolicy = discountPolicy;
 }
}</code></pre>
<ul>
<li>일반 메서드를 통해서 주입 받는 방법</li>
<li>한번에 여러 필드를 주입 받을 수 있다.</li>
<li>생성자 주입과 다를게 많이 없어서 많이  사용하지 않는다고 한다.</li>
</ul>
<hr>
<h2 id="결론">결론</h2>
<p>항상 생성자 주입을 선택하고 그리고 가끔 의존 객체를 변경할 상황이 생긴다면 수정자 주입을 선택하면 된다. 
일반 메서드 주입, 필드 주입은 사용하지 않는게 좋다.</p>
<hr>
<h1 id="참고자료">참고자료</h1>
<ul>
<li>Arron(ASAC_04)-  Spring Boot 의 등장 및 특장점, 기본 Annotations</li>
<li>김영한- 스프링 기본편(DI편)</li>
<li>장정우- 스프링 부트 핵심가이드(P2~P11)</li>
<li><a href="https://bitkunst.tistory.com/entry/ABOUTSeries-12-IoC-Inversion-of-Control-%EC%A0%9C%EC%96%B4%EC%9D%98-%EC%97%AD%EC%A0%84-DI-Dependency-Injection-%EC%9D%98%EC%A1%B4%EC%84%B1-%EC%A3%BC%EC%9E%85">bitkunst- DI, IOC...</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[자바 예외 처리: Try-Catch]]></title>
            <link>https://velog.io/@winsome_joo/%EC%9E%90%EB%B0%94-%EC%98%88%EC%99%B8-%EC%B2%98%EB%A6%AC-Try-Catch</link>
            <guid>https://velog.io/@winsome_joo/%EC%9E%90%EB%B0%94-%EC%98%88%EC%99%B8-%EC%B2%98%EB%A6%AC-Try-Catch</guid>
            <pubDate>Tue, 26 Mar 2024 09:32:09 GMT</pubDate>
            <description><![CDATA[<h1 id="📌-예외-처리란">📌 예외 처리란?</h1>
<p>프로그램이 예기치 못하게 종료될 수 있는 오류는 에러와 예외로 나뉘고 예외는 프로그래머가 미리 처리할 수 있다고 앞 포스팅 글에서 정리했었다. 이 개념을 바탕으로 예외처리에 대한 정의는 다음과 같다.</p>
<blockquote>
<p><strong>예외처리</strong> : 프로그램 실행 시 발생할 수 있는 예기치 못한 예외의 발생에 대비한 코드를 작성하는 것</p>
</blockquote>
<ul>
<li>예외처리의 목적은 예외의 발생으로 인한 실행 중인 프로그램의 비정상적인 종료를 막고 정상적인 실행 상태를 유지하게 하는 것임</li>
</ul>
<p>발생한 예외를 처리하지 못하면 비정상적으로 프로그램이 종료되며 화면에 에러 종류가 출력되는데
Uncaught exception(처리 되지 않은 예외)를 JVM의 Uncaught exception handler(예외처리기)가 받아서 예외의 원인을 화면에 출력해주는 것이다.</p>
<hr>
<h1 id="📌-try-catch로-처리하기">📌 Try-Catch로 처리하기</h1>
<p>예외는 Try-Catch를 통해 처리할 수있다.
<span style=color:Orange>Try 블록에는</span> 예외가 발생할 수 있는 코드를 넣는다.
<span style=color:Orange>Catch에는</span> 예외가 발생할 경우, 이를 처리하는 문장을 넣는다.</p>
<h2 id="작성-예시">작성 예시</h2>
<pre><code class="language-java">try {
    // 예외가 발생할 가능성이 있는 문장들을 넣는다.

} catch (Exception1 e1) {
    // Exception1 이 발생했을 경우, 이를 처리하기 위한 문장을 적는다.
} catch (Exception2 e2) {
    // Exception2 이 발생했을 경우, 이를 처리하기 위한 문장을 적는다.
}  catch (Exception3 e3) {
    // Exception3 이 발생했을 경우, 이를 처리하기 위한 문장을 적는다.
}</code></pre>
<h2 id="코드-예시-try-catch-특징">코드 예시: try catch 특징</h2>
<p>다음 코드에서 주목할 점은 에러가 발생하면 그 아래 코드는 실행되지 않는다는 것이다.
System.out.println(0 / 0); 부분에서 ArithmeticException 에러가 발생했을 시 아래 
System.out.println(4)코드는 실행되지 않는 것을 볼 수 있다.</p>
<p><span style=color:Orange>따라서 예외가 발생한 위치 이후에 있는 try블럭의 문장들은 수행되지 않기 때문에 
  try 블럭에 포함시킬 코드의 범위를 잘 선택해야한다.</span></p>
<pre><code class="language-java">class aaaa {
    public static void main(String args[]) {
        System.out.println(1);
        System.out.println(2);
        try {
            System.out.println(3);
            System.out.println(0 / 0); // 0으로 나눠서 고의로 ArithmeticException 에러 발생.
            System.out.println(4); // 실행되지 않는다.

        } catch (ArithmeticException ae) {
            System.out.println(5);

        } // try-catch의 끝
        System.out.println(6);
    } 
}

출력값
1
2
3
5
6
</code></pre>
<h2 id="excecption-클래스-타입으로는-마지막에-처리하기">Excecption 클래스 타입으로는 마지막에 처리하기</h2>
<p>다음 예시에서 첫번째 catch문에서 ArithmeticException 예외를 잡아주어 두번째 catch블럭은 검사하지 않게 된다.</p>
<p>만약 try 블럭 내에서 ArithmeticException 이 아닌 다른 종류의 예외가 발생한 경우에는
두번째 catch블럭인 Exception 클래스 타입의 참조변수를 선언한 곳에서 처리되었을 것이다.</p>
<p><span style=color:Orange>이렇게 마지막에 Exception 타입으로 catch 해주면 어떤 종류의 예외가 
  발생하더라도 이 catch블록 의해 처리하게할 수 있다.</span></p>
<p><span style=color:Orange>주의할 점은 맨 앞 catch 블록에 Exception클래스 타입으로 예외를 잡으면 세부 예외를 파악하기 어렵기 때문에 맨 앞 catch에 Exception클래스 사용은 자제하는 것이 좋다.</span></p>
<pre><code class="language-java">class aaaa {
    public static void main(String args[]) {
        System.out.println(1);
        System.out.println(2);
        try {
            System.out.println(3);
            System.out.println(0 / 0); // 0으로 나눠서 에러 발생.
            System.out.println(4); // 실행되지 않는다.

        } catch (ArithmeticException ae) {
            if (ae instanceof ArithmeticException) {
                System.out.println(&quot;true&quot;);
      }
            System.out.println(&quot;ArithmeticException&quot;);

        } catch (Exception e) {
            System.out.println(&quot;Exception&quot;);
        } // try-catch의 끝
        System.out.println(6);
    } // main메서드의 끝
}

출력값.
1
2
3
true
ArithmeticException
6</code></pre>
<hr>
<h1 id="📌-printstacktrace와-getmessage">📌 printStackTrace()와 getMessage()</h1>
<p> 예외가 발생하면 예외 객체가 생성된다. 
  <span style=color:Orange>예외객체 타입</span>과 catch 블록에 <span style=color:Orange>참조변수 타입</span>이 일치하면 예외 객체가 참조 변수에 할당된다. </p>
<p>예외 객체 내에는 예외에 관련된 정보가 들어있고, 객체의 예외 정보를 볼 수 있는 메소드는 여러개 있는데 그 중에서 대표적엔 메소드는 2개다.</p>
<ul>
<li>printStackTarce(): 예외발생 당시의 호출스택에 있었던 메서드의 정보와 예외 메시지를 화면에 츨력한다.
<span style=color:Orange>Exception 이 발생한 이유와 위치는 어디에서 발생했는지 전체적인 단계를 다 출력</span></li>
</ul>
<ul>
<li>getMessage(): 발생한 예외 클래스의 인스턴스에 저장된 메시지를 String으로 반환해준다. 
<span style=color:Orange>Exception의 유형도 없이 정말 간단하게 왜 에러가 발생하였는지 보여주기만함</span></li>
</ul>
<h2 id="사용-예시">사용 예시</h2>
<p> 아래 예시에서는  throw를 통해 예외를 발생시켰는데 다음 포스팅글에서 자세히 다루려고한다.</p>
<pre><code class="language-java">class Tes {
    public static void main(String[] args) {
        try {
            Exception e = new Exception(&quot;고의로 발생시켰음.&quot;);
            throw e; // 예외를 발생시킴
//            throw new Exception(&quot;고의로 발생시켰음.&quot;); // 위  두 줄을 한 줄로 작성
        } catch(Exception e) {
            System.out.println(&quot;에러 메시지 : &quot; + e.getMessage());
            e.printStackTrace();
        }
        System.out.println(&quot;프로그램이 정상 종료되었음.&quot;);
    }
}</code></pre>
<p>참고 log4에서는 e.printStackTrace()를 log 안에 담을수 없기 떄문에
log.error(&quot;error : &quot;, e); 로 사용하면 된다.</p>
<hr>
<h1 id="📌-참고자료">📌 참고자료</h1>
<p> <a href="https://lnsideout.tistory.com/entry/JAVA-etoString-egetMessage-eprintStackTrace-%EC%98%88%EC%99%B8%EC%B2%98%EB%A6%AC">주니어녕- e.toString(), e.getMessage(), e.printStackTrace() 예외처리</a></p>
<p> <a href="https://velog.io/@mingseok/%EC%98%88%EC%99%B8%EC%B2%98%EB%A6%AC%ED%95%98%EA%B8%B0-try-catch%EB%AC%B8">mingseok-예외처리하기 - try-catch문, 코드참고</a></p>
<p> 남궁성- 자바의 정석 P414~P430</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Checked Exception와 Unchecked Exception]]></title>
            <link>https://velog.io/@winsome_joo/%EC%9E%90%EB%B0%94-%EC%98%88%EC%99%B8%EC%B2%98%EB%A6%AC</link>
            <guid>https://velog.io/@winsome_joo/%EC%9E%90%EB%B0%94-%EC%98%88%EC%99%B8%EC%B2%98%EB%A6%AC</guid>
            <pubDate>Sun, 24 Mar 2024 06:21:47 GMT</pubDate>
            <description><![CDATA[<h1 id="📌-프로그램-오류">📌 프로그램 오류</h1>
<p>프로그램이 실행 중 오작동 하거나 비정상적으로 종료하게 하는 원인을  프로그램 <span style=color:Orange>  에러, 오류</span> 라고한다.</p>
<p><span style=color:Orange>  에러</span>는 발생 시점에 따라 <span style=color:Orange>컴파일 에러, 런타임 에러</span>로 나눌 수 있다. 
이외에도 <span style=color:Orange> 논리적 에러</span>가 있는데 컴파일도 잘되고 실행도 잘되는데 의도와 다르게 동작하는 것을 의미한다.</p>
<h2 id="에러-종류">에러 종류</h2>
<blockquote>
<p><strong>컴파일 에러</strong>: 컴파일 시에 발생하는 에러 </p>
</blockquote>
<blockquote>
<p><strong>런타임 에러</strong>: 실행 시에 발행하는 에러 </p>
</blockquote>
<blockquote>
<p><strong>논리적 에러</strong>: 실행은 되지만, 의도와 다르게 동작하는 것</p>
</blockquote>
<p>컴파일 에러 ex) 보통 문법에러로 int i=&quot;this is error&quot;,int형에 String타입 넣는 경우</p>
<p>런타임 에러 ex) 특정 객체가 매개변수로 값을 받아왔는데 값이 Null 인경우</p>
<p>논리적 에러 ex) 창고의 재고가 음수가 되는 경우, 게임 프로그램에서 비행기가 총알을 맞아도 죽지 않은 경우 </p>
<hr>
<h1 id="📌-런타임-에러">📌 런타임 에러</h1>
<h2 id="런타임-에러-발생-시점">런타임 에러 발생 시점</h2>
<p>.java 파일을 -&gt; .class 파일로 변환하는 과정을 컴파일이라는 것을 앞 포스팅글에서 정리했었다.
이 과정에서 컴파일러가 소스 코드의 오타, 잘못된 구문, 자료형 체크등을 다 해준 후 컴파일 오류 여부를 알려준다. </p>
<p>주목할 점은 컴파일 에러 없이 .class파일이 만들어 졌어도 프로그램 실행 시에 에러가 발생하지 않는 것은 아니다. 컴파일러가 실행도중에 발생할 수 있는 잠재적인 에러까지 검사할 수 없기 때문이다.</p>
<p>따라서 자바 프로그램 실행 중 많은 에러가 발생할 수 있고 런타임 에러가 발생할 수 있는 모든 경우의 수를 고려하여 대비하는 것이 좋다.</p>
<hr>
<h2 id="런타임-에러오류-종류">런타임 에러(오류) 종류</h2>
<p>자바 프로그램 실행 시 발생할  수 있는 오류를 두가지로 구분할 수 있다.</p>
<blockquote>
<p><strong>에러</strong> : 프로그램 코드에 의해서 수습될 수 없는 심각한 오류 </p>
</blockquote>
<blockquote>
<p><strong>예외</strong> : 프로그램 코드에 의해서 수습될 수 있는 다소 미약한 오류</p>
</blockquote>
<p><span style=color:Orange>Error</span>가 발생하면 프로그램의 비정상적인 종료는 막을 수 없지만, 
<span style=color:Orange>Exception</span>은 발생하더라도 프로그래머가 이에 대한 적절한 코드를 미리 작성해 놓으면 프로그램의 비정상적인 종료를 막을 수 있다.</p>
<p>Error ex) 메모리 부족(OutOfMemoryError)이나 스택오버플로우(StackOverFlow) 같이 복구할 수 없는 오류</p>
<p>Exception ex) 특정 객체가 매개변수로 값을 받아왔는데 값이 Null 인경우</p>
<hr>
<h1 id="📌-예외-클래스-계층-구조">📌 예외 클래스 계층 구조</h1>
<p>자바에서는 런타임 및 컴파일시 발생할 수 있는 Error,Exception를 클래스로 정의 했다.</p>
<p>모든 클래스의 조상은 Object 이고 Error,Exception역시 Object의 자손 클래스다.</p>
<h1 id="errorexception-클래스">Error,Exception 클래스</h1>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/65562969-dcec-46d8-a96e-d5a766a8a3f8/image.png" alt=""></p>
<h1 id="exception-클래스-세부">Exception 클래스 (세부)</h1>
<p>Exception 클래스는 아래 두가지로 세분화 된다.
<span style=color:Orange>Exception 자손 클래스(Checked), RuntimeException 클래스(Unchecked) </span></p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/461d706d-4beb-468a-9285-bcfb6bf9730d/image.png" alt=""></p>
<p>이 둘은 프로그램에 실수에 의한 것인가 아니면 외부에 외부에 영향 영항으로 발생한 것이냐에 따라 구분한다.
또한 Checked / Unchecked  Exception의 가장 핵심적인 차이는 &#39;반드시 예외 처리를 해야 하는가이다.</p>
<hr>
<h3 id="runtimeexception-unchecked-exception">RuntimeException (Unchecked Exception)</h3>
<p>프로그래머 실수에 의해 프로그램 내부에서 발생할 수있는 예외, <span style=color:Orange> 런타임시 발생한다. </span></p>
<p><strong>특징</strong></p>
<ul>
<li>어떤 상황에서 발생되는지 예측할 수 없기에, 어떻게 복구해야할지 전혀 알 수 없다.</li>
<li><span style=color:Orange>그래서 로그를 되게 잘 남겨야한다. 그게 Unchecked Exception 처리의 가장 근본, 원칙</span></li>
<li><span style=color:Orange>명시적으로 에러 처리하지 않아도 됨</span></li>
<li>따라서 에러를 일부러 일으키는 코드가 있더라도 try - catch 처리하지 않더라도 컴파일도 되고 실행까지 가능함</li>
</ul>
<p><strong>예시)</strong></p>
<ul>
<li>Arrayindexoutofboundsexception: 배열의 범위를 벗어남 </li>
<li>Nullpointerexception: 실제 값이 아닌 null을 가지고 있는 객체/변수를 호출할 때 발생</li>
<li>Arithmeticexception:  정수를 0으로 나눌 때</li>
</ul>
<hr>
<h3 id="exception-자손-클래스checked-exception">Exception 자손 클래스(Checked Exception)</h3>
<p>사용자 실수와 같은 주로 외부 영향으로 발생할 수 있는 예외들 , <span style=color:Orange>컴파일시 발생한다.</span></p>
<p><strong>특징</strong></p>
<ul>
<li>충분히 예상가능한 에러이기에, 콕 집어 복구가 꼭 필요한 예외</li>
<li>Checked Exception예외는 처리 안 하면 IDE에서 빨간색 라인이 생기면서 컴파일 자체가 안됨</li>
<li>따라서 <span style=color:Orange>Checked Exception는 반드시 예외 처리를 해줘야함</span></li>
</ul>
<p><strong>예시)</strong></p>
<ul>
<li>IOException : 휴먼은 충분히 이상한걸 입력할 수 있다.</li>
<li>FileNotFoundException: 존재하지 않는 파일의 이름을 입력 </li>
<li>SQLException : 데이터베이스 접속은 충분히 갑자기 끊길 수 있다.</li>
</ul>
<hr>
<h1 id="📌-헷갈렸던-개념">📌 헷갈렸던 개념</h1>
<p>글 초입에 에러 종류를 컴파일 에러, 런타임에러, 논리적 에러가 있다고 설명했었다.
이후 예외 종류를 Checked Exception과 Unchecked Exception로 나누었을 때 에러,예외를 너무 쪼개서 머리가 혼잡했었다. 그래서 총 정리하면 다음과 같다.</p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/c34b8d51-f0d0-4302-b78e-ba2b1ee35a84/image.png" alt=""></p>
<p>Checked Exception은 컴파일 예외클래스들을 가리키는 것이고, Unchecked Exception은 런타임 예외클래스들을 가리키는 것으로 보면 된다</p>
<p>그냥 컴파일 / 런타임 예외로 분류하면 되지, 또다시 Checked / Unchecked Exception으로 재분류 한 이유는 코드적 관점에서 예외 처리 동작을 필수 지정 유무에 따라 나뉘기 때문이다.</p>
<p>즉 Checked Exception는 반드시 예외처리를 해야하고, Unchecked Exception는 명시적으로 처리를 안해도 되었기 때문이다.</p>
<hr>
<h1 id="참고자료">참고자료</h1>
<p><a href="https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%97%90%EB%9F%ACError-%EC%99%80-%EC%98%88%EC%99%B8-%ED%81%B4%EB%9E%98%EC%8A%A4Exception-%F0%9F%92%AF-%EC%B4%9D%EC%A0%95%EB%A6%AC">인파- 자바 에러(Error) 와 예외 클래스(Exception) 💯 이해하기
</a></p>
<p><a href="https://velog.io/@new_wisdom/Exception">✨New Wisdom✨·- [Java] Exception에 대하여</a></p>
<p>남궁성-자바의 정석 P414~P435</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자바 컴파일 과정 및 JVM]]></title>
            <link>https://velog.io/@winsome_joo/%EC%9E%90%EB%B0%94-%EC%BB%B4%ED%8C%8C%EC%9D%BC-%EA%B3%BC%EC%A0%95-%EB%B0%8F-JVM</link>
            <guid>https://velog.io/@winsome_joo/%EC%9E%90%EB%B0%94-%EC%BB%B4%ED%8C%8C%EC%9D%BC-%EA%B3%BC%EC%A0%95-%EB%B0%8F-JVM</guid>
            <pubDate>Thu, 21 Mar 2024 16:31:47 GMT</pubDate>
            <description><![CDATA[<h1 id="📌-자바와-jvm">📌 자바와 JVM</h1>
<p>Java는 JVM이라는 가상 머신을 통해 OS 종류와는 관계 없이 구동 환경만 적합하면 코드를 실행할 수 있다. 따라서 Java의 특징적인 컴파일 환경, JVM의 구조 등을 정리하려 한다.</p>
<hr>
<h1 id="📌-jvm을-사용하지-않는다면">📌 JVM을 사용하지 않는다면?</h1>
<p>C언어를 예시로 한번 살펴 보려고한다. 
C는 컴파일 시 바로 Binary code인 기계어로 변환이된다.
이때 특정 OS, CPU 구조를 사용하는 컴파일러에 의해서 컴파일 됐으며, 
다른 OS, CPU 구조를 사용하는 환경에서는 이 기계어를 읽을 수 없게 된다.</p>
<hr>
<h1 id="📌-자바의-컴파일">📌 자바의 컴파일</h1>
<p>자바 컴파일 과정은 소스 파일을 JVM이 읽을 수 있는 바이트 코드로 변경하는 과정이다.</p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/acb19ffa-0eba-4a99-a7c6-48fba0d72d4f/image.png" alt=""></p>
<ol>
<li>개발자가 소스코드 .java 파일을 작성한다.</li>
<li>Java compiler인 javac이 <span style=color:Orange>.java 파일(소스 코드) -&gt; .class 파일(바이트 코드)로</span> 변환해준다.</li>
</ol>
<hr>
<h1 id="📌-자바의-런타임">📌 자바의 런타임</h1>
<p>자바 런타임 과정은 JVM에서 컴파일된 바이트 코드가 실제로 실행되는 단계이다. 아래는 JVM의 구조다.</p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/80ffbfbb-fe3d-49cf-8cd9-fc1c7c9a8581/image.png" alt=""></p>
<ol start="3">
<li>런타임시, 컴파일된 바이트 코드를 JVM의 클래스로더(Class Loader)에게 전달한다.</li>
</ol>
<ol start="4">
<li>클래스 로더는 동적 로딩(Dynamic Loading)을 통해 필요한 클래스들을 로딩 및 링크하여 런타임 데이터 영역(Runtime Data Area), 즉 JVM의 메모리에 올린다.</li>
</ol>
<h3 id="클래스-로더-세부-동작">클래스 로더 세부 동작</h3>
<p>로드: 클래스 파일을 가져와서 JVM의 메모리에 로드한다.
Linking을 통해 <span style=color:Orange> 로드된 .class 파일들을 검증, 준비, 해석과정을 거친다.</p>
<ul>
<li>검증: 자바 언어 명세(Java Language Specification) 및 JVM 명세에 명시된 대로 구성되어 있는지 검사한다.</li>
<li>준비: 클래스가 필요로 하는 메모리를 할당한다. (필드, 메서드, 인터페이스 등)</li>
<li>분석: 클래스의 상수 풀 내 모든 심볼릭 레퍼런스를 다이렉트 레퍼런스로 변경한다.<ul>
<li>초기화: 클래스 변수들을 적절한 값으로 초기화한다. (static 필드)</li>
</ul>
</li>
</ul>
<ol start="5">
<li><span style=color:Orange> 실행엔진</span>(Execution Engine)은 JVM 메모리에 올라온 바이트 코드들을 명령어 단위로 하나씩 가져와서 실행한다. </li>
</ol>
<p>이 때 실행 엔진은 두 가지 방식을 함께 사용해 실행한다. 인터프리터 컴파일 방식은 코드를 한줄씩 읽어 해석하기 때문에 속도가 느리다. JIT는 느린 인터프리터 방식을 보완해준다.</p>
<blockquote>
<p>인터프리트: 바이트 코드 명령어를 하나씩 읽어서 해석하고 실행한다.
JIT 컴파일러: 프로그램 실행 중 자주 사용되는 바이트코드 부분을 실시간으로 기계어로 컴파일하여 실행 속도를 향상시킴</p>
</blockquote>
<p>  <span style=color:Orange>Byte code</span>: &quot;가상 머신이 읽을 수 있는 이진 코드&quot; 
<span style=color:Orange>Binary code</span>: &quot;기계가 읽을 수 있는 이진 코드&quot; </p>
<hr>
<h1 id="📌-jvm-내-runtime-data-area">📌 JVM 내 RUNTIME DATA AREA</h1>
<p>JVM이 운영체제로부터 할당받은 메모리영역이다.
  <img src="https://velog.velcdn.com/images/winsome_joo/post/20f23bc6-ebcd-4029-a6aa-739a465f41a9/image.png" alt=""></p>
<p>Method Area : 클래스에 대한 정보가 올라오는 영역. 모든 쓰레드가 공유
Heap : new 키워드를 통해 생성된 인스턴스가 생성되는 영역. 모든 쓰레드가 공유
Stack : 지역변수, 매개변수, 리턴값 등 임시적으로 사용되는 값들이 저장되는 영역
PC Register : 현재 쓰레드가 실행되는 부분의 주소와 명령을 저장하는 영역
Native Method Stack : Native 언어로 작성된 코드를 실행하기 위한 영역</p>
<hr>
<h1 id="참고자료">참고자료</h1>
<p>  <a href="https://yeon-kr.tistory.com/118">당근케잌- 왜 JVM이 필요한가?</a></p>
<p>  <a href="https://velog.io/@minseojo/Java-%EC%9E%90%EB%B0%94-%EC%BB%B4%ED%8C%8C%EC%9D%BC-%EA%B3%BC%EC%A0%95-JVM-%EB%82%B4%EB%B6%80-%EA%B5%AC%EC%A1%B0">조민서-자바 컴파일 과정 &amp; JVM 내부 구조</a></p>
<p><a href="https://doozi0316.tistory.com/entry/1%EC%A3%BC%EC%B0%A8-JVM%EC%9D%80-%EB%AC%B4%EC%97%87%EC%9D%B4%EB%A9%B0-%EC%9E%90%EB%B0%94-%EC%BD%94%EB%93%9C%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%EC%8B%A4%ED%96%89%ED%95%98%EB%8A%94-%EA%B2%83%EC%9D%B8%EA%B0%80">doozi- JVM이란? 개념 및 구조</a></p>
<p><a href="https://velog.io/@impala/JAVA-JVM-Runtime-Data-Area">impala- Runtime Data Area</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[정규화 ]]></title>
            <link>https://velog.io/@winsome_joo/%EC%A0%95%EA%B7%9C%ED%99%94-BCNF</link>
            <guid>https://velog.io/@winsome_joo/%EC%A0%95%EA%B7%9C%ED%99%94-BCNF</guid>
            <pubDate>Tue, 19 Mar 2024 05:03:23 GMT</pubDate>
            <description><![CDATA[<h1 id="📌-정규화란">📌 정규화란?</h1>
<p>데이터 정합성(데이터의 정확성과 일관성을 유지하고 보장)과 이상현상 해결을 위해 엔티티를 작은 단위로 분리하는 과정</p>
<ul>
<li>정규화를 하는 경우 조회성능은 처리조건에 따라 향상될 수도 있고, 저하될 수도 있음</li>
<li>단 입력, 수정, 삭제 성능은 향상됨</li>
</ul>
<hr>
<h1 id="📌anomaly-문제-상황-이상현상">📌Anomaly 문제 상황 (이상현상)</h1>
<h2 id="삭제-이상">삭제 이상</h2>
<p>튜플 삭제 시 같이 저장된 다른 정보까지 연쇄적으로 삭제되는 현상</p>
<h2 id="삽입-이상">삽입 이상</h2>
<p>튜플 삽입 시 특정 속성에 해당하는 값이 없어 NULL을 입력해야 하는 현상</p>
<h2 id="수정-이상">수정 이상</h2>
<p>튜플 수정 시 중복된 데이터의 일부만 수정되어 일어나는 데이터 불일치 현상</p>
<hr>
<h1 id="📌-제-1-정규화">📌 제 1 정규화</h1>
<p>데이터 베이스의 Table내 하나의 컬럼에 여러 값이 들어가 있는 상황에서
<span style= color:Orange>데이터베이스의 각 컬럼이 하나의 데이터만 가지도록 하는 과정이다.</sapn></p>
<p>즉, 각 컬럼이 하나의 데이터만 저장하고, 여러 값을 가지지 않게 Table을 분리한다.</p>
<h2 id="제-1-정규화-적용-전">제 1 정규화 적용 전</h2>
<p>DBMS에 대한 내용을 담은  topic table이 아래와 같이 있다.</p>
<ul>
<li>하나의 tag 컬럼안에 여러 데이터들이 들어가 있다. <img src="https://velog.velcdn.com/images/winsome_joo/post/1a865a46-55b0-4330-bbd3-efdb4b9c6298/image.png" width="100%" height="30%">


</li>
</ul>
<h3 id="발생할-수-있는-단점">발생할 수 있는 단점</h3>
<p>단점 1. DBMS에서 가지고 있는 tag값을 조회하기 어렵다. </p>
<ul>
<li>where 프로그램=&#39;rdb&#39;가아닌 where 프로그램 LIKE &#39;%rdb%&#39;으로 찾아야함 </li>
</ul>
<p>단점 2. tag 값 수정시 두개의 값을 수정해줘야하는 번거로움이 있음 </p>
<p>단점 3. Order By할 때 정렬에 어려움이 있음 </p>
<hr>
<h2 id="제-1-정규화-적용-후">제 1 정규화 적용 후</h2>
<p>위 사진에서 볼 수 있듯이 tag 컬럼에 여러 data가 들어가 있는 것을 확인했다.
이에 따라 Topic table과 Tag table로 분리하려한다. </p>
<h3 id="✔️-table-분리할-때-체크해야하는-부분">✔️ Table 분리할 때 체크해야하는 부분</h3>
<ol>
<li>증복된 컬럼이 어느 컬럼에서 발생하는지 확인 후 table을 분리한다.</li>
</ol>
<ul>
<li>예시에서는 tag table을 topic으로 부터 분리했다.</li>
</ul>
<ol start="2">
<li>Cardinarity 확인</li>
</ol>
<ul>
<li>테이블을 분리했을 때 각 table이 어떤 관계를 맺고있는지 확인해야한다.</li>
</ul>
<ol start="3">
<li>Cardinarity가 N:M이면 두 Table간 맵핑 Table을 만들어주고, 아니면 table만 분리한다.</li>
</ol>
<ul>
<li>예시에서 하나의 topic은 여러개의 tag를 가질 수 있다. title은 rdb, free등 2개 이상의 tag를 가짐</li>
<li>하나의 tag는 여러개 topic을 가질 수있다. rdb는 MYSQL에도, ORACLE에서 사용된다.</li>
</ul>
<h2 id="topic-table">Topic Table</h2>
<img src="https://velog.velcdn.com/images/winsome_joo/post/02aaf5db-1eb1-424c-9f06-d90c2e4a5725/image.png" width="100%" height="30%">

<h2 id="mapping-table">Mapping Table</h2>
<img src=https://velog.velcdn.com/images/winsome_joo/post/899c6ffb-b586-43a0-8c0f-1368ee572c3c/image.png width="25%" height="30%">

<h2 id="tag-table">Tag Table</h2>
<img src=https://velog.velcdn.com/images/winsome_joo/post/941b0be3-87b9-43af-9676-0e488be9c7fd/image.png width="25%" height="30%">


<h2 id="장점">장점</h2>
<ul>
<li>데이터의 수정, 삭제, 삽입 연산에 이상 문제 방지</li>
<li>데이터 구조가 단순해지고 명확해진다</li>
</ul>
<hr>
<h1 id="📌-제-2-정규화">📌 제 2 정규화</h1>
<blockquote>
<p>제 1 정규화에서 참고했던 자료들이 제2, 제3 정규화에서 다소 오해를 불러일으킬 수 있어
제 2 정규화부터는 다른 자료를 참고하여 글을 썼다. </p>
</blockquote>
<p>하나의 테이블에 복합키 결정자가 있을 때, 복합키의 부분집합이 결정자가 되면 안된다. 따라서 복합키의 <span style=color:orange>부분집합 결정자 부분과 종속되는 일반 속성을</sapn>  다른 하나의 테이블로 분리해주는 과정이다.</p>
<p>쉽게 설명하면, 현재 테이블의 주제와 관련없는 컬럼을 다른 테이블로 빼는 작업이다.</p>
<h2 id="제-2-정규화-적용-전">제 2 정규화 적용 전</h2>
<p>해당 예시에서 기본키는 (학생번호, 강좌이름)으로 복합키라는 것을 알아두자.
<img src="https://velog.velcdn.com/images/winsome_joo/post/fbf48a9d-ff46-4251-a64b-c011aed3f143/image.png" alt=""></p>
<ul>
<li><p>성적은 (학생번호, 강좌이름) 복합키에 종속된다.
(학생번호, 강좌이름) --&gt; (성적)</p>
</li>
<li><p>강의실은 복합키의 부분집합인 (강좌 이름)에 종속된다. 
(강좌이름) --&gt; (강의실)</p>
</li>
</ul>
<p>즉, 기본키(학생번호, 강좌이름)의 부분키인 강좌이름이 결정자이기 때문에 위의 테이블의 경우 다음과 같이 기존의 테이블에서 강의실을 분해하여 별도의 테이블로 관리하여 제2 정규형을 만족시킬 수 있다.</p>
<h3 id="발생하는-단점">발생하는 단점</h3>
<p>단점 1. 하나의 테이블에 강좌이름, 강의실 데이터가 중복으로 들어가고 있다. </p>
<hr>
<h2 id="제-2-정규화-적용-후">제 2 정규화 적용 후</h2>
<p>제2 정규형을 적용 대상인 수강강좌 Table에 제2 정규화를 적용하여  수강, 강의실 2개의 table로 나누었다.
이제 수강 Table 내 복합키 부분집합에 종속되는 일반 속성은 존재하지 않는다.</p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/90601a90-39ed-4362-8b53-f56685d4938a/image.png" alt=""></p>
<h2 id="장점-1">장점</h2>
<ul>
<li>더 이상 강좌이름과, 강의실 데이터가 중복으로 들어가지 않게 된 것을 확인할 수 있다.</li>
</ul>
<hr>
<h1 id="📌-제-3-정규화">📌 제 3 정규화</h1>
<p><span style= color:Orange>제2 정규화를 완료한 테이블에서, 이행적 함수 종속성을 제거하는 과정이다.</span>
이행적 종속이라는 것은 A -&gt; B, B -&gt; C가 성립할 때 A -&gt; C가 성립되는 것을 의미한다.</p>
<p>쉽게 말하면 주식별자가 아닌 모든 속성 간에는 서로 종속될 수 없는 것이다.</p>
<h2 id="제-3-정규화-적용-전">제 3 정규화 적용 전</h2>
<p>테이블에서 학생 번호는 강좌 이름을 결정하고 있고, 강좌 이름은 수강료를 결정하고 있다. 그렇기 때문에 이를 (학생 번호, 강좌 이름) 테이블과 (강좌 이름, 수강료) 테이블로 분해해야 한다.</p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/4dbb024e-d11a-4cc1-be33-abe9dd1ee860/image.png" alt="">강좌이름은 학생번호에 종속된다.
(학생번호) --&gt; (강좌 이름)</p>
<p>수강료는 강좌이름에 종속된다.
(강좌이름) --&gt; (수강료)</p>
<h3 id="발생하는-단점-1">발생하는 단점</h3>
<p>단점 1. 501번 학생이 강좌를 자료구조로 변경하고 싶을 때 수강료를 따로 20000원으로 수정해야하는 번거로움이 있음</p>
<hr>
<h2 id="제-3-정규화-적용-후">제 3 정규화 적용 후</h2>
<p>제 3 정규형 적용 대상인 계절학기 Table에 제3 정규화를 적용하여  계절수강, 수강료 2개의 Table로 나누었다.
이제  계절수강 Table 내 주식별자가 아닌 다른 일반 속성에 종속되는 값은 없다.</p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/7c41c492-342c-4bea-8f70-d6ed00f6348b/image.png" alt=""></p>
<hr>
<h1 id="참고자료">참고자료</h1>
<p><a href="https://www.youtube.com/watch?v=Y1FbowQRcmI">애플코딩: 정규화</a></p>
<p><a href="https://hstory0208.tistory.com/entry/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EC%A0%95%EA%B7%9C%ED%99%94Normalization%EB%9E%80-%EC%98%88%EC%8B%9C%EB%A5%BC-%ED%86%B5%ED%95%B4-%EC%89%BD%EA%B2%8C-%EC%9D%B4%ED%95%B4%ED%95%B4%EB%B3%B4%EC%9E%90">hyun: 단계별 정규화 정의</a></p>
<p><a href="https://mangkyu.tistory.com/28">망나니 개발자: 정규화 정의</a></p>
<p>ASAC 04 애런: 정규화 정의</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TRANSACTION: ISOLATION LEVEL]]></title>
            <link>https://velog.io/@winsome_joo/TRANSACTION-Isolation-Level</link>
            <guid>https://velog.io/@winsome_joo/TRANSACTION-Isolation-Level</guid>
            <pubDate>Sun, 17 Mar 2024 15:45:01 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>** !! 글을 읽기 전 필독 !!**
DBMS 마다 격리 수준에 대한 내용이 다를 수 있으니 보다 정확하게 알기 위해서는 공식 문서를 확인해야 한다. 필자는 MySQL 에서 제공하는 격리수준을 기준으로 하였다. 참고로 MySQL의 기본 격리수준은 Repeatable Read이다.</p>
</blockquote>
<h1 id="📌-isolation-level-트랜잭션-격리-수준">📌 ISOLATION LEVEL: 트랜잭션 격리 수준</h1>
<p>여러 트랜잭션이 동시에 처리될 때, 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있도록 허용할지 말지를 결정하는 것이다. </p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/35fb9ca8-7808-4e05-a051-58c6169a7920/image.png" alt=""></p>
<ul>
<li>표준적으로 0~3 Level 총 4개가 존재한다.</li>
<li>Level이 올라갈수록 격리 수준이 높아지지만 성능이 떨어진다.</li>
<li>데이터 정확성과 성능이 반비례하기 때문에 상황에 맞게 잘 선택해야함 </li>
</ul>
<hr>
<h1 id="📌-왜-트랜잭션-격리-수준이-필요할까">📌 왜 트랜잭션 격리 수준이 필요할까?</h1>
<p>Isolation Level에 대한 조정은, 동시성과 데이터 무결성에 연관되어 있음</p>
<ul>
<li>Level 낮을 수록 동시성은 증가 데이터 무결성에 문제가 발생확률 증가</li>
<li>Level 높을 수록 동시성은 감소 데이터 무결성에 문제가 발생확률 감소</li>
</ul>
<p>즉 상황에 따라 처리해야하는 데이터 특성이 다를 것이다. 따라서 트랜잭션 격리 수준을 각 Level로 나누어 상황에 따라 동시성이 높은 Level, 데이터 무결성이 높은 Level을 선택할 수 있게 하기위해 존재한다.</p>
<hr>
<h1 id="📌-read-uncommitted-레벨-0">📌 Read Uncommitted (레벨 0)</h1>
<ul>
<li>SELECT 문장이 수행되는 동안 해당 데이터에 Shared Lock이 걸리지 않는 계층</li>
<li>트랜잭션에서 처리중이거나, 아직 Commit되지 않은 데이터를 다른 트랜잭션이 읽는 것을 허용하는 계층 </li>
<li>데이터 베이스의 일관성을 유지하는 것이 불가능함 </li>
</ul>
<h2 id="발생할-수-있는-문제-dirty-read">발생할 수 있는 문제: DIRTY-READ</h2>
<p>커밋되지 않은 수정중인 데이터를 다른 트랜잭션에서 읽을 수 있도록 허용할 때 발생하는 현상</p>
<p>어떤 트랜잭션에서 아직 실행이 끝나지 않은 상황에서 다른 트랜잭션에 의한 변경사항을 보게되는 경우</p>
<h3 id="상황-예시">상황 예시</h3>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/32ee41df-c716-4def-8c96-906f7e64e7dd/image.png" alt=""></p>
<ol>
<li>DB에는 10만원을 가지고 있는 계좌가 있다.</li>
<li>Transaction A는 DB에 Read 요청을한다. -&gt;계좌의 10만원 확인</li>
<li>Transaction A는 DB에 5만원 입금 Write 요청을한다. -&gt; DB의 계좌는 15만원이 됨<span style="color:Orange"> </li>
<li>Transaction A의 Commit은 완료되지 않았는데 Transaction B가 DB에 Read가 가능하다.</li>
<li>Transaction B는 15만원의 계좌금액을 확인한다.</li>
<li>이 때 Commit이 완료되지 않은 Transaction A에 Rollback이 생겨 DB의 계좌는 10만원이 된다.</li>
<li>즉 DB에는 10만원이 있는데 Transaction B는 15만원이 조회되는 DIRTY-READ 상황이 발생함</span></li>
</ol>
<p>하지만 데이터가 잘 처리되어서 RollBack이 안 되었다면 동시에 데이터를 처리했기 때문에 빠른 성능을 보이게 되었을 것임, 즉 DB의 일관성, 고 신뢰성을 낮지만 성능은 높을 것을 확인할 수 있다.</p>
<hr>
<h1 id="📌-read-committed-레벨-1">📌 Read Committed (레벨 1)</h1>
<ul>
<li>SELECT 문장이 수행되는 동안 해당 데이터에 Shared Lock이 걸리는 계층</li>
<li>트랜잭션이 수행되는 동안 다른 트랜잭션이 접근할 수 없어 대기하게 하는 계층 </li>
<li>Commit 이루어진 트랜잭션만 조회가능</li>
<li>Commit 완료된 데이터만 읽을 수 있기 때문에 DIRTY-READ문제를 해결할 수 있다.</li>
</ul>
<h2 id="발생할-수-있는-문제-non-reapeatable-read">발생할 수 있는 문제: NON-REAPEATABLE READ</h2>
<p>트랜잭션 내에서 같은 데이터를 여러 번 조회할 때 읽은 데이터가 서로 다른 값으로 나오는 문제 </p>
<h3 id="상황-예시-1">상황 예시</h3>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/118f6069-4e87-40db-bb30-fc37b3b35456/image.png" alt=""></p>
<p>1, DB에는 10만원을 가지고 있는 계좌가 있다.
2. Transaction A는 DB에 Read 요청을한다. -&gt;계좌의 10만원 확인
3. Transaction A는 DB에 5만원 입금 Write 요청을한다. -&gt; DB의 계좌는 15만원이 됨
<span style="color:Orange"> 4. Transaction A의 Commit은 완료되지 않아서 Transaction B는 Transaction A 실행 전 데이터인 10만원을 읽어 옴
5. Transaction A 가 Commit을 완료하고,  Transaction B가 다시 Read하면 15만원을 읽어온다.
6. 즉 Transaction B는 같은 DATA를 읽기 요청을 헀는데 서로 다른 DATA가 나오며 문제 발생
</span>
여기서 헷갈렸는데 이해한 부분은 Transaction B내에서 Read 요청을 2번 이상 했을 때 다른 Data가 Read된다는 것이었다.</p>
<hr>
<h1 id="📌-repeatable-read-레벨-2">📌 Repeatable Read (레벨 2)</h1>
<ul>
<li>트랜잭션이 완료될 때까지 SELECT 문장이 사용되는 모든 데이터에 Shared Lock이 걸리는 계층</li>
<li>트랜잭션이 범위 내에서 조회한 데이터 내용이 항상 동일함을 보장하는 계층</li>
<li>앞선 NON-REAPEATABLE READ의 상황 예시 5번에서 Transaction A가 Commit을 
완료해도 10만원을 읽어오게 함</li>
<li>다른 사용자는 트랜잭션 영역에 해당되는 데이터에 대한 수정 불가능</li>
</ul>
<h2 id="발생할-수-있는-문제-phantom-read">발생할 수 있는 문제: Phantom Read</h2>
<p>한 트랜잭션 안에서 일정 범위의 레코드를 두 번 이상 읽었을 때, 첫번째 쿼리에서 없던 레코드가 두번째 쿼리에서 나타나는 현상</p>
<p>트랜잭션 도중 새로운 레코드 삽입을 허용하기 때문에 나타나는 현상임</p>
<h3 id="상황-예시-2">상황 예시</h3>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/bdb5a14f-b40a-4e36-9d30-5c43c52062b6/image.png" alt=""></p>
<ol>
<li>DB에는 10만원을 가지고 있는 계좌가 있다.</li>
<li>Trasaction B가 은행계좌 수 조회를 하는 Read 쿼리를 날림 -&gt; 계좌 갯수 1반환 </li>
<li>Transaction A가 새로운 계좌를 5만원이 들어있는 계좌를 생성</li>
<li>이후 Trasaction B가 은행계좌 수 조회하는 Read 쿼리 날림 -&gt; 계좌 갯수 2반환 </li>
<li>한 트랜잭션 에서 다른 값을 반환하게 됨</li>
</ol>
<p>레코드가 추가된 상황에는 Repeatable Read가 적용되지 않아 동일한 값이 보장되지 않은 것임 </p>
<hr>
<h1 id="📌-serializable-레벨-3">📌 Serializable (레벨 3)</h1>
<ul>
<li>트랜잭션이 완료될 때까지 SELECT 문장이 사용되는 모든 데이터에 Shared Lock이 걸리는 계층</li>
<li>모든 Transaction들은 모두 순차적으로 실행하게 되는 계층임 </li>
<li>다른 사용자는 트랜잭션 영역에 해당되는 데이터에 대한 수정 및 입력 불가능</li>
</ul>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/202fd1e9-8137-403c-b445-7c88199a5794/image.png" alt=""></p>
<ol>
<li>Transaction A Commit이 완료된다.</li>
<li>Transaction B가 실행된다.</li>
</ol>
<hr>
<h1 id="📌-정리">📌 정리</h1>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/fec41825-e686-477a-9c78-cfdbab140ae1/image.png" alt=""></p>
<p><strong>Read Committed</strong> : 아직 커밋되지 않은 데이터를 읽을 수 있다.
<strong>Read Committed</strong>: 커밋된 데이터만 읽을 수 있다.
<strong>Repeatable Read</strong>: 특정 데이터를 반복조회시 같은 값을 반환한다.
<strong>Serializable</strong>: 트랜잭션이 순차적으로 실행된다.</p>
<hr>
<h1 id="참고자료">참고자료</h1>
<p><a href="https://gyoogle.dev/blog/computer-science/data-base/Transaction%20Isolation%20Level.html">낮은 단계 Isolation Level을 활용할 때 발생하는 현상들</a></p>
<p><a href="https://www.youtube.com/watch?v=taUeIi6a6hk&amp;t=455s">[10분 테코톡] 로건의 Transaction</a></p>
<p><a href="https://dar0m.tistory.com/225">정리의 표 참고</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TRANSACTION과 ACID]]></title>
            <link>https://velog.io/@winsome_joo/TRANSACTION%EA%B3%BC-ACID</link>
            <guid>https://velog.io/@winsome_joo/TRANSACTION%EA%B3%BC-ACID</guid>
            <pubDate>Sat, 16 Mar 2024 10:34:24 GMT</pubDate>
            <description><![CDATA[<h1 id="📌-transaction">📌 TRANSACTION</h1>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/53869dbc-f2f8-4ee4-b2f5-786a288ae23a/image.png" alt=""></p>
<h2 id="transaction이란">TRANSACTION이란?</h2>
<p>DB에 요청시 한 스텝에서 모두 처리되어야 하는 SQL 요청을 하나로 묶은 단위다.</p>
<ul>
<li>TrancSaction의 연산은 RollBack, Commit 두가지다.<ul>
<li>하나의 SQL 이라도 처리되지 않으면 요청 전 상태로 RollBack되는 것이 특징. </li>
<li>트랜잭션 내 SQL문들이 모두 성공하는 경우 Commit되어 DB에 반영되는 것이 특징.</li>
</ul>
</li>
<li>위 사진을 보면 읽기, 쓰기, 지우기, 읽기가 한 스텝에 처리 되어야하는 TRANSACTION임</li>
</ul>
<h2 id="transaction이-필요한-경우">TRANSACTION이 필요한 경우</h2>
<h3 id="상황-가정">상황 가정</h3>
<ul>
<li>A는 계좌에 10만원 , B는 계좌에 0원이 있는 상태이다. </li>
<li>A가 B에게 돈을 송금하는 경우를 가정해본다.</li>
</ul>
<h3 id="db내에-작업은-두가지로-나뉨">DB내에 작업은 두가지로 나뉨</h3>
<ol>
<li>A에 계좌에 10만원을 출금 작업 (잔고:10만원-&gt; 0원)</li>
</ol>
<ol start="2">
<li>B계 계좌에 10만원을 입금 작업(잔고: 0원 -&gt; 10만원) </li>
</ol>
<p>하지만
1번 작업을 진행 후 에러가 발생하면 A의 계좌는 0원, B의 계좌도 0원인 상태이다.</p>
<p>해결 방법으로는 두 작업에 Transaction을 적용하여 묶는다. 
1번, 2번 작업을 논리적으로 한가지 작업으로 묶으면 성공시 Commit을 통해 DB에 반영 
실패시 RollBack을 통해 원 상태 복귀로 A와 B 두 계좌가 0원인 상황이 발생하지 않게 된다.</p>
<hr>
<h1 id="📌-acid">📌 ACID</h1>
<h1 id="acid란">ACID란?</h1>
<p>DB에 있는 데이터의 고신뢰성을 보장하기 위해서 TRANSACTION이 필요하다는 것을 확인했다.
그렇다면 ACID는 무엇일까?</p>
<p>ACID는 DB에서 TRANSACTION이 안전하게 수행되기 위해서 보장되어야 하는 성질 
원자성(Atomicity), 일관성(Consistency), 격리성(Isolation), 지속성(Durability) 를 의미하는 ACID 로 알려져 있다.</p>
<h2 id="원자성atomicity">원자성(Atomicity)</h2>
<p>트랜잭션은 DB에 모두 반영되거나, 전혀 반영되지 않아야 한다는 것을 의미한다.
(즉 완료되지 않은 트랜잭션의 중간 상태를 DB에 반영하면 안 된다)
TrancSaction의 두가지 연산 Commit, RollBack을 통해 보장해줄 수 있다.</p>
<p>원자성이 보장되면 A의 계좌에서 10만원이 출금되었는데 B의 계좌에서 10만원이 입금되지 않는 경우는 없을 것이다.</p>
<h2 id="일관성consistency">일관성(Consistency)</h2>
<p>일관성은 데이터베이스의 상태가 일관되어야 한다는 성질이다. 하나의 트랜잭션 전후에 데이터베이스의 상태는 이전과 같이 유효해야 한다.
(즉, 트랜잭션이 일어난 이후 DB에 여러제약 조건에 맞는 상태를 보장해준다는 의미.)</p>
<p>마이너스 통장을 허락하지 않는다는 DB에 제약조건이 있다면 이 조건을 만족하지 못 한다면 Transaction은 바로 RollBack하게 될 것임</p>
<h2 id="격리성isolation">격리성(Isolation)</h2>
<p>둘 이상의 트랜잭션이 동시에 실행되고 있을 때, 어떤 트랜잭션도 다른 트랜잭션 연산에 끼어들 수 없다.</p>
<p>A 통장에서 10만원이 출금되고 B 통장에 10만원이 입금되지 않은 중간 상황에, 다른 Transaction이 조회하면 안 되는 것임 </p>
<blockquote>
<p><strong>Isolation Level (격리 수준)</strong> : Transaction 독립(고립)의 <strong>정도</strong>에 대한 정의</p>
</blockquote>
<ul>
<li>Isolation Level은 Transaction 간 격리를 시키지 않은것(L0)에서부터 완벽한 격리(L3, 직렬화)까지 총 4단계가 존재한다.<ul>
<li>단계가 낮을 수록 단일 시간내에 많은 Transacton을 처리할 수 있지만 데이터 정확도가 낮아질 수 있다.</li>
<li>DBMS는 여러 종류의 isolation level을 제공하고, 개발자는 이중에서 어떤 레벨로 트랜잭션을 동작시킬지 설정할 수 있다. </li>
</ul>
</li>
</ul>
<p>Isolation Level과 단계별 에러는 다음 포스팅 글을 참고!</p>
<h2 id="지속성durability">지속성(Durability)</h2>
<p> 트랜잭션이 성공적으로 완료되었으면 결과는 영구히 DB에 반영되어야한다.</p>
<p>트랜젝션 조작을 하드 디스크에 로그로 기록하고 시스템에 이상이 발생하면 그 로그를 사용해 이상 발생 전까지 복원하는 것으로 지속성을 실현하고 있다.</p>
<p> A가 B에 10만원 송금을 성공했다면 은행 시스템에 에러가 발생했더라도 10만원 송금 성공된 상태로 복구할 수 있어야한다.</p>
<h1 id="참고자료">참고자료</h1>
<p><a href="https://www.youtube.com/watch?v=e9PC0sroCzc&amp;t=203">[10분 테코톡]예지니어스의 트랜잭션</a></p>
<p><a href="https://www.youtube.com/watch?v=taUeIi6a6hk&amp;t=455s">[10분 테코톡] 로건의 Transaction</a></p>
<p><a href="https://www.youtube.com/watch?v=aX9c7z9l_u8">[10분 테코톡] 🐤 샐리의 트랜잭션</a></p>
<p><a href="%5Dhttps://engineerinsight.tistory.com/210">[DB] 트랜잭션 ACID란? (Atomicity, Consistency, Durability, Isolation)</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[DB와 DBMS]]></title>
            <link>https://velog.io/@winsome_joo/DB%EC%99%80-DBMS</link>
            <guid>https://velog.io/@winsome_joo/DB%EC%99%80-DBMS</guid>
            <pubDate>Wed, 13 Mar 2024 14:24:09 GMT</pubDate>
            <description><![CDATA[<h1 id="📌-db와-dbms">📌 DB와 DBMS</h1>
<h2 id="db">DB</h2>
<p>데이터 저장소 </p>
<ul>
<li>CSV 혹은 EXCEL 같은 다양한 데이터 형태로 저장되어있는 저장소<h2 id="dbms">DBMS</h2>
DB(데이터 저장소)기능 + 엔진(데이터를 정의 및 조작하는 기능)을 가진 응용 프로그램</li>
<li>DB Management System 으로써 위 DB 에 대한 CRUD 엔진, 관리 등 제공</li>
<li>DBMS마다 엔진이 다르므로 사용하는 쿼리문이 다름
ex) Mysql Select 명령어, PostGres Select 쿼리 명령어가 다름</li>
</ul>
<hr>
<h1 id="📌-관계형비관계형-dbms">📌 관계형/비관계형 DBMS</h1>
<p>데이터 베이스는 관계형 데이터베이스, 비관계형 데이터 베이스 두가지로 구분된다.
관계형 데이터 베이스는 데이터를 관리할 때 SQL을 사용하고 데이터마다 연결할 수있어 RDBMS라고도 불린다. 비관계형 데이터 베이스는 SQL을 사용하지 않기 때문에 NO SQL 데이터 베이스라고 불리기도 한다. </p>
<h2 id="관계형-데이터베이스rdbms">관계형 데이터베이스(RDBMS)</h2>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/9a25006c-fe31-4381-9b9c-4ab80b532474/image.png" alt=""></p>
<p>RDBMS는 데이터를 행과 열의 형태인 테이블로 데이터를 저장하며, 테이블 간의 관계를 정의할 수 있다.
ex) 쇼핑물 서비스에서 상품정보 테이블과 판매사 테이블을 연결하여 두 데이터를 함께 사용할 수 있다.</p>
<h3 id="특징">특징</h3>
<ul>
<li>테이블간 데이터를 연결할 수 있기 때문에 복잡한 데이터를 표현할 수 있다.</li>
<li>SQL을 사용하려면 고정된 형식의 스키마가 필요하다. 처리하려는 데이터 속성별로 열(column)에 대한 정보를 미리 정해야 한다</li>
<li>Transaction으로 데이터 처리가 가능해 ACID를 준수할 수있음(고신뢰성, 무결성 준수 가능)</li>
</ul>
<h2 id="비관계형-데이터베이스no-sql">비관계형 데이터베이스(NO SQL)</h2>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/ea68074b-bb81-46ba-860e-5cb900f2e14b/image.png" alt=""></p>
<p>NoSQL은 키-값(key-value) 저장, 문서(document) 저장, 그래프(graph) 데이터 저장 등 다양한 형태의 데이터 저장 방식을 사용한다.</p>
<h3 id="특징-1">특징</h3>
<ul>
<li>NoSQL의 경우, 다른 구조의 데이터를 같은 컬렉션(=테이블)에 추가할 수 있다. SQL이 정해진 스키마를 따르지 않는다면 데이터를 추가할 수 없는 것과는 다름.</li>
<li>미리 정해둔 스키마가 없기 때문에 훨씬 더 유연하다. 언제든지 저장한 데이터를 조정할 수있음. </li>
<li>수평적 확장이 가능함 (데이터 베이스를 분산되어 늘릴 수 있음)</li>
</ul>
<h2 id="용어-구분">용어 구분</h2>
<p>SQL에서의 테이블(table) -&gt; NoSQL에서는 컬렉션(Collection)
SQL에서의 레코드(record) -&gt; NoSQL에서는 문서(document)</p>
<hr>
<h1 id="📌-관계형-vs-비관계형-언제-사용하면-좋을까">📌 관계형 vs 비관계형, 언제 사용하면 좋을까?</h1>
<p>둘은 데이터 저장 방식이 다르고 DB 확장 방식도 다른 것을 확인했다.
그렇기에 각 DB를 사용하기 적절한 상황도 다르다. 다음은 어는 상황에 관계형, 비관계형 DB를 사용하면 좋은지 정리했다.</p>
<h2 id="📖-sql-기반의-관계형-데이터베이스를-사용하는-케이스">📖 SQL 기반의 관계형 데이터베이스를 사용하는 케이스</h2>
<h3 id="데이터베이스의-acid-성질을-준수해야-하는-경우">데이터베이스의 ACID 성질을 준수해야 하는 경우</h3>
<p>ACID는 Atomicity(원자성), Consistency(일관성), Isolation(격리성), Durability(지속성)을 의미한다.
데이터베이스에서 트랜잭션이 실행되는 과정에서 안정성을 보장하기 위해 필요한 성질이다.
 
SQL을 사용하면 데이터베이스와 상호 작용하는 방식을 정확하게 규정할 수 있기 때문에, 데이터베이스에서 데이터를 처리할 때 발생할 수 있는 예외적인 상황을 줄이고, 데이터베이스의 무결성을 보호할 수 있다.
 
전자 상거래, 금융 서비스 등의 소프트웨어 개발에서는 반드시 데이터베이스의 ACID 성질을 준수해야 한다. 이러한 경우 일반적으로 SQL을 이용한 관계형 데이터베이스를 사용한다.
 </p>
<h3 id="소프트웨어에-사용되는-데이터가-구조적이고-일관적인-경우">소프트웨어에 사용되는 데이터가 구조적이고 일관적인 경우</h3>
<p>소프트웨어(프로젝트)의 규모가 많은 서버를 필요로 하지 않고, 일관된 데이터를 사용하는 경우 관계형 데이터베이스를 사용하는 사례가 많다.
다양한 데이터 유형과 높은 트래픽을 지원하도록 설계된 NoSQL 데이터베이스를 사용해야만 하는 이유가 없기 때문이다.</p>
<h2 id="📖-nosql-기반의-비관계형-데이터베이스를-사용하는-케이스">📖 NoSQL 기반의 비관계형 데이터베이스를 사용하는 케이스</h2>
<h3 id="데이터의-구조가-거의-없거나-전혀-없는-대용량의-데이터를-저장하는-경우">데이터의 구조가 거의 없거나 전혀 없는 대용량의 데이터를 저장하는 경우</h3>
<p>대부분의 NoSQL 데이터베이스는 저장할 수 있는 데이터의 유형에 제한이 없다. 필요에 따라 언제든지 데이터의 새 유형을 추가할 수 있으며 소프트웨어 개발에 정형화되지 않은 많은 양의 데이터가 필요할 경우 NoSQL을 적용하는 것이 효율적일 수 있다.
 </p>
<h3 id="클라우드-컴퓨팅-및-저장공간을-최대한-활용하는-경우">클라우드 컴퓨팅 및 저장공간을 최대한 활용하는 경우</h3>
<p>클라우드 기반으로 데이터베이스를 구축하면 저렴한 비용으로 솔루션을 제공받을 수 있다. 소프트웨어에 데이터베이스의 확장성이 중요하다면 NoSQL 데이터베이스를 사용하는 것이 좋다.
 </p>
<h3 id="빠르게-서비스를-구축하는-과정에서-데이터-구조를-자주-수정하는-경우">빠르게 서비스를 구축하는 과정에서 데이터 구조를 자주 수정하는 경우</h3>
<p>NoSQL 데이터베이스의 경우 스키마를 미리 준비할 필요가 없기 때문에 빠르게 개발하는 과정에 매우 유리하다. 따라서 시장에 프로토타입을 빨리 출시해야 하는 경우에 NoSQL이 적합하다.
또한, 소프트웨어 버전 별로 많은 다운타임 없이 데이터 구조를 자주 업데이트해야 하는 경우, 스키마를 매번 수정해야 하는 관계형 데이터베이스보다 NoSQL 기반의 비관계형 데이터베이스를 사용하는 게 적합하다.
다운타임(Downtime) : 은행 점검 시간과 같이 데이터베이스 서버를 오프라인으로 전환하여 데이터 처리를 진행하는 작업 시간</p>
<hr>
<h3 id="참고자료">참고자료</h3>
<p><a href="https://ittrue.tistory.com/195">- 관계형 vs 비관계형 적절한 사용 상황 참고</a>
<a href="https://ant-programmer.tistory.com/60">- 사진 참고</a>
<a href="https://lifelong-education-dr-kim.tistory.com/entry/%EA%B4%80%EA%B3%84%ED%98%95%EA%B3%BC-%EB%B9%84%EA%B4%80%EA%B3%84%ED%98%95-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B2%A0%EC%9D%B4%EC%8A%A4%EC%9D%98-%EC%A2%85%EB%A5%98%EC%99%80-%ED%8A%B9%EC%A7%95">- DB 및 DBMS 참고</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[ [실습]“Private” EC2 외부 접근 허용 : OUTBOUND를 위한 NAT INSTANCE 설정]]></title>
            <link>https://velog.io/@winsome_joo/Private-EC2-%EC%99%B8%EB%B6%80-%EC%A0%91%EA%B7%BC-%ED%97%88%EC%9A%A9-OUTBOUND%EB%A5%BC-%EC%9C%84%ED%95%9C-NAT-INSTANCE-%EC%84%A4%EC%A0%95</link>
            <guid>https://velog.io/@winsome_joo/Private-EC2-%EC%99%B8%EB%B6%80-%EC%A0%91%EA%B7%BC-%ED%97%88%EC%9A%A9-OUTBOUND%EB%A5%BC-%EC%9C%84%ED%95%9C-NAT-INSTANCE-%EC%84%A4%EC%A0%95</guid>
            <pubDate>Tue, 12 Mar 2024 15:32:53 GMT</pubDate>
            <description><![CDATA[<h1 id="📌-nat-instance-역할을-할-ec2-public-subnet-인스턴스-만들기"><strong>📌 NAT Instance</strong> 역할을 할 <strong>EC2 (Public Subnet)</strong> 인스턴스 만들기</h1>
<h2 id="ami">AMI</h2>
<p>AMI는 AMI 커뮤니티에서 <code>**amazon/amzn-ami-vpc-nat-2018.03.0.20230807.0-x86_64-ebs</code> 을 검색해서 넣어준다.**</p>
<p>AWS 공식 NAT 인스턴스 AMI (Pre-configured Amazon Linux AMI) 는 이제 미지원하기 때문이다.</p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/c8554452-dd45-47d9-ad16-9a35ca2f42c7/image.png" alt=""></p>
<h2 id="키페어">키페어</h2>
<p>키는 이전에 Bastion과 Private_Instance를 연결할 때 사용했던 Public key를 넣어준다.</p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/45c948e2-5354-4b0b-aa61-e38de4bcab06/image.png" alt=""></p>
<h2 id="subnet-및-sg-설정">SUBNET 및 SG 설정</h2>
<p><strong>subnet</strong>은 Bastion에 할당되어있는 Public Subnet을 할당해준다.</p>
<p><strong>보안 그룹</strong> 같은 경우<code>nat-instance-sg</code> 라는 이름으로 구분하기 쉽게 만들고 아래와같이 설정했다.</p>
<ul>
<li><strong>SSH</strong>, Source Type : <strong>Anywhere</strong>, Source : <strong>0.0.0.0/0 (모든 트래픽)</strong></li>
<li><strong>HTTP</strong>, Source Type : <strong>Custom</strong>, Source : 172<strong>.16.0.0/16 (로컬)</strong></li>
<li><strong>HTTPS</strong>, Source Type : <strong>Custom</strong>, Source : 172<strong>.16.0.0/16 (로컬)</strong></li>
<li>참고로 Private Instance는 <strong>172.16.3.25의 Private Ip를 갖고 있다</strong>.</li>
</ul>
<p>위와 같이 설정한 이유는 Private instance로부터 SSH, HTTP, HTTPS요청을 받을 것이기 때문이다.</p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/46488e9a-4a29-479a-9bff-22071e60a4da/image.png" alt=""></p>
<h2 id="network-설정에서-sourcedestination-check-옵션에서-stop-체크-필요-필요">Network 설정에서 Source/Destination Check 옵션에서 <strong>STOP 체크 필요 필요</strong></h2>
<p>NAT INSTANCE를 만들어줬다면  Source/Destination Check 옵션에서 <strong>STOP 체크 필요 필요하다.</strong> </p>
<p>이유는 NAT (Network Address Translation) 의 정의에 따라 Src/Dst 는 수행하면 안되기 때문이다.</p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/a7211b18-879a-4ac0-b7f9-89e791de9344/image.png" alt=""></p>
<hr>
<h1 id="📌-private-서브넷의-route-table-에-00000-트래픽에-대해-nat-instance-로-가게-설정"><strong>📌</strong> Private 서브넷의 <strong>Route Table</strong> 에 <code>0.0.0.0/0</code> 트래픽에 대해 <strong>NAT Instance</strong> 로 가게 설정</h1>
<h2 id="private-서브넷의-route-table-생성-및-설정">Private 서브넷의 <strong>Route Table 생성 및 설정</strong></h2>
<p>Private Instance에서 외부로 요청하는 모든<code>0.0.0.0/0</code> 트래픽은 Nat Instance로 보내려고한다.</p>
<p>Private Instance가 있는 private Subnet에 다음과 같이 <strong>Route Table을 설정해준다.</strong></p>
<ul>
<li><strong>Route Table</strong> 설정 시 <strong>NAT Instance EC2</strong> 인스턴스 명을 넣으면 자동으로 <strong>ENI</strong> 설정으로 변경</li>
</ul>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/f241f6da-a59d-4964-82da-ef688a86b297/image.png" alt=""></p>
<p>이제 Private Subnet에 설정해주면 Private Instance에서 발생하는 모든 트래픽은 다 Nat Instance로 가게된다.</p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/f08c2cfb-9276-4b8d-a5ce-e12c66fb8a54/image.png" alt=""></p>
<p><strong>주의)</strong> 만든 Route Table을 Private Instance가 있는  Private Subnet에 적용하는 것을 잊지 말자</p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/2314745c-b427-4f6a-b0cd-69958ace8e30/image.png" alt=""></p>
<h2 id="bastion-혹은-aws-console-의-session-manager-을-통해-private-ec2-에-접속한-뒤-외부요청해보기"><strong>Bastion</strong> (혹은 AWS Console 의 Session Manager) 을 통해 <strong>Private EC2</strong> 에 접속한 뒤 외부요청해보기</h2>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/585ae151-632e-4947-90bf-8fa71b2a2c5a/image.png" alt=""></p>
<ul>
<li><code>ping goole.com</code> 명령어를 치면 외부로 요청이 정상적으로 이뤄지는지 확인할 것 → <strong>실패</strong></li>
<li><strong>실패</strong> : 왜 그럴까? 아래 에서 NAT Instance 의 SG 의 인바운드에 ICMP 오픈 필요</li>
</ul>
<hr>
<h1 id="📌-nat-instance-ec2-의-sg-의-인바운드-규칙에-모든-icmp-요청에-대해-풀어주기"><strong>📌 NAT Instance EC2</strong> 의 <strong>SG</strong> 의 <strong>인바운드 규칙</strong>에 <strong>모든 ICMP 요청</strong>에 대해 풀어주기</h1>
<p><strong>NAT Instance EC2</strong> 의 <strong>SG</strong> 내 다음 <strong>인바운드 규칙을 추가해줘야한다.</strong> </p>
<ul>
<li><strong>All ICMP - IPv4</strong>, Source Type : <strong>Custom</strong>, Source : 172<strong>.16.0.0/16 (로컬)</strong></li>
<li>참고로 Private Instance는 172.16.3.25의 Private Ip를 갖고 있다.</li>
</ul>
<p>추가해주는 이유는 NAT에 INBOUND는 Private_Instance에서 오는 요청이기 때문이다.</p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/e34b4f28-5c32-45c5-9bfe-50876824806b/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/6249ba6a-3661-491a-b318-9155b0f0028a/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[실습] “Private” EC2 생성 후 외부 접근 허용 : INBOUND 를 위한 BASTION 설정]]></title>
            <link>https://velog.io/@winsome_joo/%EC%8B%A4%EC%8A%B5-Private-EC2-%EC%83%9D%EC%84%B1-%ED%9B%84-%EC%99%B8%EB%B6%80-%EC%A0%91%EA%B7%BC-%ED%97%88%EC%9A%A9-Inbound-%EB%A5%BC-%EC%9C%84%ED%95%9C-Bastion-%EC%84%A4%EC%A0%95</link>
            <guid>https://velog.io/@winsome_joo/%EC%8B%A4%EC%8A%B5-Private-EC2-%EC%83%9D%EC%84%B1-%ED%9B%84-%EC%99%B8%EB%B6%80-%EC%A0%91%EA%B7%BC-%ED%97%88%EC%9A%A9-Inbound-%EB%A5%BC-%EC%9C%84%ED%95%9C-Bastion-%EC%84%A4%EC%A0%95</guid>
            <pubDate>Tue, 12 Mar 2024 15:25:42 GMT</pubDate>
            <description><![CDATA[<h1 id="📌-사전준비-local과-bastion-ssh-터널링을-위해-키페어-생성하기">📌 사전준비 Local과 Bastion SSH 터널링을 위해 키페어 생성하기</h1>
<p><code>**Local-to-bastion.pem**</code>이라는 Private key를 생성해준다.</p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/bb44c51a-3eb2-48db-80c9-67ac4fdb72ff/image.png" alt=""></p>
<p>Local에 다운로드 되어있는 것을 확인했다.</p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/0abe8285-1bb1-4774-b6ed-0d794d6e27ba/image.png" alt=""></p>
<hr>
<h1 id="📌-bastion-호스트-역할을-할-ec2-public-subnet-인스턴스-만들기">📌 <strong>Bastion</strong> 호스트 역할을 할 <strong>EC2 (Public Subnet)</strong> 인스턴스 만들기</h1>
<p>Public Subnet에 Bastion이라는 인스탄스를 만들어준다.</p>
<p>주의할 점은 INBOUND 규칙에  SSH 프로토콜과 22Port를 열어줘야한다. </p>
<p>이후 내 Local 컴퓨터에서 SSH로 Bation에 접근해야 하기 때문이다. </p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/c34965c4-9a36-427c-abd5-9aa930809847/image.png" alt=""></p>
<p>이후 Local과의 SSH 통신을 위해 아까 만들어둔 Private Key에 대한 Public Key를 주입해준다.</p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/e6e36a45-bb60-4deb-ba3b-980c042a2eec/image.png" alt=""></p>
<h2 id="bastion-생성-확인-후-연결해보기">Bastion 생성 확인 후 연결해보기</h2>
<p>Pulbic Instance인 Bastion이 만들어진 것을 확인할 수 있다. (ROUTING TABLE과 IGW는 앞서 쓴 블로그에서 만든 것을 참고함)</p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/6f52728d-2827-4e9f-b39a-9e8442b1839f/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/6882a0df-9386-4ec1-b0e2-49ac9cc0b3de/image.png" alt=""></p>
<hr>
<h1 id="📌-추후-bastion-에서-ec2-private-subnet-에-접근하기-위한-key-pair-pem-키-생성">📌 추후 <strong>Bastion</strong> 에서 <strong>EC2 (Private Subnet)</strong> 에 접근하기 위한 <strong>Key Pair (.pem 키)</strong> 생성</h1>
<p><strong><code>bastion-to-private.pem</code></strong> 이라는 Private key를 생성해준다.</p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/5a46b5dc-a8a8-48e9-a5e7-537cd3b359e4/image.png" alt=""></p>
<p>내 Local에 Private키가 잘 다운 받아져있는 것을 확인했다.</p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/7a8624db-0a2f-4b67-91d8-45d63d89d9f6/image.png" alt=""></p>
<hr>
<h1 id="📌-ec2-private-subnet-과제용-테스트-인스턴스-만들기"><strong>📌 EC2 (Private Subnet)</strong> 과제용 테스트 인스턴스 만들기</h1>
<p>Private Subnet에 Private Instance라는 인스탄스를 만들어준다.</p>
<p>주의할 점은 INBOUND 규칙에  SSH 프로토콜과 22Port를 열어줘야한다. </p>
<p>이후 내 Bation에서 SSH로 Private Instance에 접근해야 하기 때문이다. </p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/c153c012-1c9a-4e52-be1e-8c7136c4f4a6/image.png" alt=""></p>
<p>이후 Bastion과의 SSH 통신을 위해 아까 만들어둔 Private Key에 대한 Public Key를 주입해준다.</p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/743f9666-bc88-4372-bb74-4a0b18772f98/image.png" alt=""></p>
<h2 id="private-instance-생성-후-bastion에서-private-instance에-연결해보기">Private-Instance 생성 후 Bastion에서 Private-Instance에 연결해보기</h2>
<p>Private-Instance 생성 확인했다.</p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/d70d4633-5255-450c-833b-de17521ed82c/image.png" alt=""></p>
<p>Bastion에서 Private_Instance로 SSH 접근할 수 있는지 아래와 같이 Test해본다.
<code>ssh ec2-user@{target-private-ip}</code> 명령어를 통해 Private_Instance에 요청해본다.</p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/bf845d70-fbbd-4ac5-ba48-4160648ffd89/image.png" alt=""></p>
<h2 id="에러-발생">에러 발생</h2>
<p> <strong>Private EC2</strong> 에 SSH 접근을 위해서는 <strong>Key Pair (.pem 키)를 넣어서 함께 요청해야한다.</strong></p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/8b497cd7-e2b5-45cc-87b5-8537cfa88dcd/image.png" alt=""></p>
<hr>
<h1 id="📌-bastion-ec2-인스턴스-내-private-ec2-에-ssh-접속을-위한-pem-키-설정-후-접속-성공-확인"><strong>📌 Bastion EC2</strong> 인스턴스 내 <strong>Private EC2</strong> 에 <strong>SSH</strong> 접속을 위한 <strong>.pem 키</strong> 설정 후 접속 성공 확인</h1>
<p> <strong>Bastion EC2</strong> 의 터미널에서 나가지말고 <strong>.pem 키를</strong> vi편집기를 통해 만들어 준다. </p>
<ol>
<li>아까 다운 받은 아래 키 내용을 전체 복붙한다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/5e3d0e06-f16a-4906-8389-814fcd9cc890/image.png" alt=""></p>
<ol start="2">
<li><code>vi bastion-to-private.pem</code> 로 파일을 만들어 복사한 키 값을 넣어준다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/98b543a8-2315-48cc-9dc6-ee4af5f074bb/image.png" alt=""></p>
<ol start="3">
<li><code>chmod 400 bastion-to-private.pem</code>  읽기 권한 부여하여 SSH 접속시 해당 키 읽을 수 있게한다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/9e77622f-d437-4f6c-b97e-884461ad1b4b/image.png" alt=""></p>
<ol start="4">
<li><code>**ssh ec2-user@{target-private-ip} -i bastion-to-private.pem</code> 만든 Private key와 함께 다시 요청해본다.** </li>
</ol>
<p>Private_Instance 접속 성공한 것을 볼 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/94566231-0252-42b4-b99d-af7ff31fce5d/image.png" alt=""></p>
<hr>
<h1 id="📌-ssh-tunneling-으로-지금-내-컴퓨터-로컬에서-bastion-을-통해-private-ec2-에-ssh-접속해보기"><strong>📌 SSH Tunneling</strong> 으로 지금 내 컴퓨터 로컬에서 <strong>Bastion</strong> 을 통해 <strong>Private EC2</strong> 에 <strong>SSH</strong> 접속해보기</h1>
<p>위에서 만든 .pem 키를 사용하여 접속 <code>ssh -i {local-to-bastion-pem-location} ec2-user@{bastion-host-public-ip}</code></p>
<p>접속 성공을 확인했다.</p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/0fe4cb2c-a3f7-4f30-bae1-2f3269d4e2c7/image.png" alt=""></p>
<h2 id="bastion-ec2-에-ssh-tunneling-열기--ssh-통로를-위한-터널-열어두기"><strong>Bastion EC2</strong> 에 <strong>SSH Tunneling</strong> 열기 = SSH 통로를 위한 터널 열어두기</h2>
<p>SSH 통로를 위한 터널을 열어두는 작업이기에 <strong>새 터미널에 아래 명령어를 실행한채 계속 냅둬야함</strong></p>
<p><code>ssh -i **&quot;local-to-bastion.pem&quot;** -N -L 33322:{target-private-ip}:22 ec2-user@{bastion-host-public-ip}</code> </p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/bbcae9f7-c093-48e8-b8a8-88556b38f95c/image.png" alt=""></p>
<h2 id="새-터미널을-하나-더-열어서-통로로-명령어-수행하기">새 터미널을 하나 더 열어서 통로로 명령어 수행하기</h2>
<ul>
<li>위에서 열어놓았던 터널을 통해 <strong>Private EC2 에 직접 SSH</strong> 명령어를 수행할 수 있다.</li>
</ul>
<p><code>ssh -i **&quot;bastion-to-private.pem&quot;** -p 33322 ec2-user@**localhost**</code></p>
<ul>
<li><strong>주의 1</strong> : .pem 키는 2개가 있다. 1번 작업과 2번 작업 시 혼용하지 않도록 주의하라</li>
<li><strong>주의 2</strong> : 터널이 열리는 순간 <strong>Private EC2</strong> 는 내 로컬에서 접근 가능한 포트가 되기에<ul>
<li><strong>33322 포트의 localhost 로 접속해야한다는 점 꼭 유념하기 바란다</strong></li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/5f52b3c1-81a6-45f7-8fcb-35205aee3743/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/d480fd62-711e-4a98-9792-81174e6a600c/image.png" alt=""></p>
<p><strong>주의할 점은 PEM키는 읽기 모드로 변경해야 한다는 것이다.</strong> </p>
<p><img src="https://velog.velcdn.com/images/winsome_joo/post/bb42dc7f-b26d-443d-b0a1-3f18e65b565a/image.png" alt=""></p>
]]></description>
        </item>
    </channel>
</rss>