<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>journey</title>
    <link>https://joanne.tistory.com/</link>
    <description>하고 싶은 일을 하기 위한 여정</description>
    <language>ko</language>
    <pubDate>Tue, 14 Jul 2026 03:38:45 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>쪼앤</managingEditor>
    <image>
      <title>journey</title>
      <url>https://tistory1.daumcdn.net/tistory/4472393/attach/c0c1689e137243efa4d1f5d100c829e4</url>
      <link>https://joanne.tistory.com</link>
    </image>
    <item>
      <title>서비스는 꼭 인터페이스를 구현해야할까?</title>
      <link>https://joanne.tistory.com/303</link>
      <description>&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&lt;a href=&quot;https://seovalue.github.io/2022/01/07/why-service-needs-interface/&quot; target=&quot;_blank&quot;&gt;&lt;span&gt;https://seovalue.github.io/2022/01/07/why-service-needs-interface/&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</description>
      <category>Spring</category>
      <author>쪼앤</author>
      <guid isPermaLink="true">https://joanne.tistory.com/303</guid>
      <comments>https://joanne.tistory.com/303#entry303comment</comments>
      <pubDate>Fri, 7 Jan 2022 23:37:22 +0900</pubDate>
    </item>
    <item>
      <title>블로그 이전하기</title>
      <link>https://joanne.tistory.com/302</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;티스토리를 잘 쓰고 있었는데, 마음 한 켠에는 Github 블로그를 쓰고 싶다는 생각이 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 이번 기회에 옮겨보려고 한다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;글은 하나씩 대체할 생각이다 :)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a title=&quot;https://seovalue.github.io&quot; href=&quot;https://seovalue.github.io&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://seovalue.github.io&lt;/a&gt;&lt;/p&gt;</description>
      <author>쪼앤</author>
      <guid isPermaLink="true">https://joanne.tistory.com/302</guid>
      <comments>https://joanne.tistory.com/302#entry302comment</comments>
      <pubDate>Sun, 2 Jan 2022 00:23:04 +0900</pubDate>
    </item>
    <item>
      <title>[Effective Java] 아이템 9. try-finally보다는 try-with-resources를 사용하라.</title>
      <link>https://joanne.tistory.com/97</link>
      <description>&lt;blockquote data-ke-style=&quot;style2&quot;&gt;아이템 9. try-finally보다는 try-with-resources를 사용하라.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바 라이브러리에는 close 메서드를 호출해 직접 닫아줘야하는 자원이 많다. 예를 들자면, InputStream, OutputStream, Connection 등이 있다. 이러한 &quot;자원 닫아주기&quot; 행위는 놓치기 쉽기 때문에 예측할 수 없는 성능 문제로 이어지기도 한다. OutOfMemory와 같은..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전통적으로는 자원 닫힘을 보장하는 수단으로서 try-finally 구문이 사용되었다.&lt;/p&gt;
&lt;pre id=&quot;code_1639617457735&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;BufferedReader br = new BufferedReader(new FileReader(path));
try {
    return br.readLine();
} finally {
    br.close();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 자원을 여러개 사용하게 된다면 불필요한 try-catch-finally 문이&amp;nbsp;&lt;b&gt;중첩&lt;/b&gt;될 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 위와 같은 경우 br.readLine에서도 예외가 발생하고, br.close에서도 예외가 발생한다면 스택 추적 내역에는 두 예외 상황이 모두 리포트되는 것이 아니라 특정 한가지의 예외 정보는 남지 않게 되어 디버깅을 매우 어렵게 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1639617587195&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;try (InputStream in = new FileInputStream(src);
     OutputStream out = new FileOutputStream(dst)) {
     byte[] buf = new byte[BUFFER_SIZE];
     int n;
     while ((n = in.read(buf)) &amp;gt;= 0) 
         out.write(buf, 0, n);
 }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;try-with-resources를 사용하면 위와 같이 코드를 변경할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저, 복수의 자원에 대해서 try 구문 안에 작성함으로써 짧게 코드를 개선할 수 있다. 또한 문제 상황이 발생했을 때에도 그를 진단하기가 훨씬 좋다.&amp;nbsp; 만약, 위에서 readLine과 close가 함께 예외가 발생하면 둘 중 하나의 예외는 리포트되지 않는다고 했는데, try-with-resources를 사용하게 되면 스택 추적 내역에 숨겨진 예외도 출력되므로 프로그램 코드에서 가져와 볼 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 try-with-resources 절은 catch 구문과도 함께 사용할 수 있고, 불필요한 중첩 없이 다수의 예외를 처리할 수 있다.&lt;/p&gt;</description>
      <category>Java</category>
      <author>쪼앤</author>
      <guid isPermaLink="true">https://joanne.tistory.com/97</guid>
      <comments>https://joanne.tistory.com/97#entry97comment</comments>
      <pubDate>Thu, 16 Dec 2021 10:21:41 +0900</pubDate>
    </item>
    <item>
      <title>[Effective Java] 아이템 8. finalizer와 cleaner 사용을 피하라.</title>
      <link>https://joanne.tistory.com/96</link>
      <description>&lt;blockquote data-ke-style=&quot;style2&quot;&gt;아이템 8. finalizer와 cleaner 사용을 피하라.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 2장에서 이 부분이 이해하기에 가장 까다로웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바에서는 두 가지 객체 소멸자를 제공한다.&amp;nbsp; 그것이 바로 finalizer와 cleaner이다. 이 두 가지 객체 소멸자를 사용하면 명시적으로 바로 메모리를 해제할 수 있을까?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그건 아니다. 언젠가 해제될 순 있지만 곧바로 해제하는 것은 불가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;finalizer&lt;/b&gt;는 예측할 수 없고 상황에 따라 위험할 수 있다. 예를 들어, 불완전한 객체가 생성되고 해당 객체의 하위 객체에서 finalizer를 구현하며, finalizer의 정적 필드에 자신의 참조를 할당하여 가비지 컬렉터가 수집하지 못하게 막을 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;cleaner&lt;/b&gt;는 Java9부터 finalizer의 대체제로 제시된다. cleaner는 finalizer보다는 덜 위험하지만 여전히 예측할 수 없으며 느리고 불필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단히 알아보았는데, finalizer와 cleaner를 피해야하는 이유에 대해 몇 가지 더 알아보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1. 즉시 수행되지 않는다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체에 접근할 수 없게 된 다음, finalizer나 cleaner를 활용해서 파괴시키게 된다면 이는 언제 파괴될지 모른다. 예를 들어 File I/O 작업 실행한 상황에서 언제 자원이 회수될 지 모른다면, 열린 채로 대기하는 불필요한 자원이 쌓여 언젠간 문제를 발생시킬 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 언제 실행될지는 아예 모르는 것인가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 GC의 알고리즘에 달려있으며, 구현마다 다르다. 결과적으로는 finalizer와 cleaner의 수행 시점에 객체의 파괴 시점이 의존된다는 것은 문제이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2. 성능 문제를 일으킬 수 있다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Autocloseable 객체를 생성하고 GC가 수거하기까지 12ns가 걸렸다면, finalizer의 경우에는 550ns가 걸린다. 직접 테스트한 것은 아니고 책에서 나온 결과를 인용하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3. finalizer는 악의적인 공격에 노출될 수 있다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;finalizer로 어떻게 공격이 가능할까? finalizer는 객체를 생성할 때 취약점이 존재한다. 위에서도 잠깐 언급했지만, finalizer 내부에서 자신의 참조를 할당하게 된다면 GC에서 벗어나게 된다. 더불어 부분적으로 구성된 오브젝트 조차도 finalizer 내부에서 부활시킬 수 있다. 객체의 소멸에서 참조를 할당해버린다면 생성될 때 불완전한 조건으로 인해 완전히 생성되지 않은 오브젝트도 부활시킬 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;자세한 내용은 &lt;a href=&quot;https://yangbongsoo.tistory.com/8?category=919799&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;이 글&lt;/a&gt;을 참조하면 좋다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;그럼, finalizer와 cleaner는 언제 사용해야할까?&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;우선, 까먹고 자원의 회수를 잊은 경우에 대한 안전망으로써 활용할 수 있으며, 네이티브 피어 자원 회수용으로 사용하는 것이 좋다. 이와 같은 경우에도 불확실한 실행 시점과 성능 저하에 주의해야한다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;여기서 네이티브 피어란 일반적인 자바 코드가 아닌, C, C++과 같은 네이티브 언어로 작성된 메서드로 위임되므로 가비지 컬렉터에서 자원이 반납되는지 알 수 없는 코드를 말한다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Java</category>
      <author>쪼앤</author>
      <guid isPermaLink="true">https://joanne.tistory.com/96</guid>
      <comments>https://joanne.tistory.com/96#entry96comment</comments>
      <pubDate>Thu, 16 Dec 2021 10:14:57 +0900</pubDate>
    </item>
    <item>
      <title>[Effective Java] 아이템 7. 다 쓴 객체 참조를 해제하라.</title>
      <link>https://joanne.tistory.com/95</link>
      <description>&lt;blockquote data-ke-style=&quot;style2&quot;&gt;아이템 7. 다 쓴 객체 참조를 해제하라&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서 다루는 내용은, 말 그대로 다 쓴 객체 참조를 해제하라! 라는 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바를 사용하다 보면 GC라는 것이 동작한다. 따라서 우리는 다른 C++과 같이 메모리 관리를 필요로하는 언어보다 좀 더 메모리를 신경쓰지 않고, 프로그래밍을 할 수 있다는 장점이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹시라도 GC에 대해서 잘 모르는 독자가 있다면, &lt;a href=&quot;https://joanne.tistory.com/267&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;이 글&lt;/a&gt;을 참조하길 바란다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만, 우리가 신경쓰며 객체 참조를 해제해주어야할 때가 있다. 일반적으로 자기 메모리를 직접 관리하는 클래스라면 메모리 누수에 주의하여야한다. 예를 들어, 다음 코드에서 메모리 누수가 일어나는 위치를 찾아보자.&lt;/p&gt;
&lt;pre id=&quot;code_1639616379708&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Stack {
    private Object[] elems;
    private int size;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;
    
    public Stack() {
        elems = new Object[DEFAULT_INITIAL_CAPACITY];
    }
    
    public void push(Object o) {
        ensureCapacity();
        elems[size++] = o;
    }
    
    public Object pop() {
        if (size == 0) {
            throw new EmptyStackException();
        }
        return elems[--size];
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 코드에서는 스택이 커졌다가 줄어들었을 때 스택에서 꺼내진 객체들을 가비지 컬렉터가 회수하지 않는다. 프로그램에서 그 객체들을 더 이상 사용하지 않더라도 말이다. 왜냐하면, 이 스택 내부에서 그 객체들의 다 쓴 참조를 여전히 가지고 있기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다 쓴 참조라는 것은 앞으로 쓰지 않을 참조를 뜻하기도 한다. 위 코드에서는 elems 배열의 활성 영역 밖의 참조들이 모두 다 쓴 참조에 해당한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 가비지 컬렉션 언어에서는 이러한 경우 메모리 누수를 찾기가 매우 까다로워진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같은 경우에는 pop 메서드를 다음과 같이 수정할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1639616522154&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public Object pop() {
    if (size == 0) {
        throw new EmptyStackException();
    }
    Object result = elems[--size];
    elems[size] = null; // 다 쓴 참조를 해제한다.
    return result;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Java</category>
      <author>쪼앤</author>
      <guid isPermaLink="true">https://joanne.tistory.com/95</guid>
      <comments>https://joanne.tistory.com/95#entry95comment</comments>
      <pubDate>Thu, 16 Dec 2021 10:02:21 +0900</pubDate>
    </item>
    <item>
      <title>JPA에서 save와 saveAll은 어떤 차이를 가질까?</title>
      <link>https://joanne.tistory.com/301</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://seovalue.github.io/2021/12/09/jpa-save-and-save-all/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://seovalue.github.io/2021/12/09/jpa-save-and-save-all/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1641711034525&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;JPA save와 saveAll의 차이 - Milestone | Joanne Blog&quot; data-og-description=&quot;Student라는 간단한 도메인을 만들어서, save와 saveAll의 차이를 비교해보자.&quot; data-og-host=&quot;seovalue.github.io&quot; data-og-source-url=&quot;https://seovalue.github.io/2021/12/09/jpa-save-and-save-all/&quot; data-og-url=&quot;https://seovalue.github.io/2021/12/09/jpa-save-and-save-all/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b6STHe/hyM25dVXJY/kkfH3Wsei9tOVDnZLFWac1/img.jpg?width=3024&amp;amp;height=3024&amp;amp;face=0_0_3024_3024&quot;&gt;&lt;a href=&quot;https://seovalue.github.io/2021/12/09/jpa-save-and-save-all/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://seovalue.github.io/2021/12/09/jpa-save-and-save-all/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b6STHe/hyM25dVXJY/kkfH3Wsei9tOVDnZLFWac1/img.jpg?width=3024&amp;amp;height=3024&amp;amp;face=0_0_3024_3024');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;JPA save와 saveAll의 차이 - Milestone | Joanne Blog&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Student라는 간단한 도메인을 만들어서, save와 saveAll의 차이를 비교해보자.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;seovalue.github.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블로그 이전 중입니다 :)&lt;/p&gt;</description>
      <category>Spring</category>
      <author>쪼앤</author>
      <guid isPermaLink="true">https://joanne.tistory.com/301</guid>
      <comments>https://joanne.tistory.com/301#entry301comment</comments>
      <pubDate>Thu, 9 Dec 2021 20:03:46 +0900</pubDate>
    </item>
    <item>
      <title>DispatcherServlet의 @ResponseBody 응답 과정을 파고들어보자.</title>
      <link>https://joanne.tistory.com/293</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://seovalue.github.io/2022/01/02/digging-into-spring-web-flow/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://seovalue.github.io/2022/01/02/digging-into-spring-web-flow/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1641711087488&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Spring Web 요청 응답 흐름 파고들기 - Milestone | Joanne Blog&quot; data-og-description=&quot;  궁금증 @ResponseBody 가 달린 응답을 하게 되면, 언제 어디서 JSON으로 변환할까?&quot; data-og-host=&quot;seovalue.github.io&quot; data-og-source-url=&quot;https://seovalue.github.io/2022/01/02/digging-into-spring-web-flow/&quot; data-og-url=&quot;https://seovalue.github.io/2022/01/02/digging-into-spring-web-flow/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b6XHmk/hyM1Ikm6Ej/ZABJIE31Om1QnaihTGmEOk/img.jpg?width=3024&amp;amp;height=3024&amp;amp;face=0_0_3024_3024&quot;&gt;&lt;a href=&quot;https://seovalue.github.io/2022/01/02/digging-into-spring-web-flow/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://seovalue.github.io/2022/01/02/digging-into-spring-web-flow/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b6XHmk/hyM1Ikm6Ej/ZABJIE31Om1QnaihTGmEOk/img.jpg?width=3024&amp;amp;height=3024&amp;amp;face=0_0_3024_3024');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Spring Web 요청 응답 흐름 파고들기 - Milestone | Joanne Blog&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;  궁금증 @ResponseBody 가 달린 응답을 하게 되면, 언제 어디서 JSON으로 변환할까?&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;seovalue.github.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블로그 이전 중입니다 :)&lt;/p&gt;</description>
      <category>Spring</category>
      <author>쪼앤</author>
      <guid isPermaLink="true">https://joanne.tistory.com/293</guid>
      <comments>https://joanne.tistory.com/293#entry293comment</comments>
      <pubDate>Wed, 10 Nov 2021 14:18:36 +0900</pubDate>
    </item>
    <item>
      <title>모두의 네트워크 8장. 네트워크 전체 흐름 살펴보기</title>
      <link>https://joanne.tistory.com/292</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;모두의 네트워크 정리&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://joanne.tistory.com/285&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;1장. 네트워크의 첫걸음&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://joanne.tistory.com/286&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2장. 네트워크의 기본 규칙&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://joanne.tistory.com/287&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;3장. 물리 계층: 데이터를 전기 신호로 변환하기&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://joanne.tistory.com/288&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;4장. 데이터 링크 계층: 랜에서 데이터 전송하기&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://joanne.tistory.com/289&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;5장. 네트워크 계층: 목적지에 데이터 전달하기&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://joanne.tistory.com/290&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;6장. 전송 계층: 신뢰할 수 있는 데이터 전송하기&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://joanne.tistory.com/291&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;7장. 응용 계층: 애플리케이션에 데이터 전송하기&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://joanne.tistory.com/292&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;8장. 네트워크 전체 흐름 살펴보기&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 장에서는 OSI 모델의 각 계층 간에 데이터가 전달되고 처리되는 전체 과정에 대해 알아보자.&lt;/p&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;물리 계층
- 데이터를 전기 신호로 변환하는 데 필요하다.

데이터 링크 계층
- 랜에서 데이터를 송수신하는 데 필요하다.

네트워크 계층
- 다른 네트워크에 있는 목적지에 데이터를 전달하는 데 필요하다.

전송 계층
- 목적지에 데이터를 정확하게 전달하는 데 필요하다.

응용 계층
- 애플리케이션 등에서 사용하는 데이터를 송수신하는 데 필요하다.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1804&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WyWFM/btrkhp8f5D0/bGI5CiQHwoQfrWWV6Vt1p0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WyWFM/btrkhp8f5D0/bGI5CiQHwoQfrWWV6Vt1p0/img.png&quot; data-alt=&quot;모든 내용은 위 그림을 바탕으로 진행된다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WyWFM/btrkhp8f5D0/bGI5CiQHwoQfrWWV6Vt1p0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWyWFM%2Fbtrkhp8f5D0%2FbGI5CiQHwoQfrWWV6Vt1p0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;451&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1804&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;모든 내용은 위 그림을 바탕으로 진행된다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 이미지에서 네트워크는 총 몇 개로 나누어져 있을까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정답은, 192.168.1.0/24, 172.16.0.0/16, 192.168.10.0./24로 총 3개로 이루어져있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 사이트에 접속해야하므로 응용 계층에서 시작한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 브라우저에 URL을 입력하고 엔터를 누르면, 캡슐화가 시작된다. (3-way handshake는 이미 이루어져 연결되었다고 가정한다.) PC에서 웹 브라우저를 이용해 웹 서버의 웹 사이트에 접속하기 위한 요청을 보낼 때에는 HTTP 프로토콜을 사용한다. 요청 메서드, URI 등이 담긴 HTTP 메시지를 보낸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 데이터는 전송 계층에 전달된다. 전송 계층에서는 TCP 헤더가 붙어 세그먼트가 된다. TCP 헤더에서 어느 애플리케이션에 데이터를 보내야 하는지 식별하기 위해서는 &lt;b&gt;포트 번호&lt;/b&gt;가 필요하다. 즉, 출발지 포트 번호와 목적지 포트 번호가 필요하다. 출발지 포트 번호는 well-known 포트가 아닌 포트 중에서 무작위로 선택된다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Q. Well-known 포트 범위는?&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 3500번 포트를 사용했다고 가정해보자. 목적지의 포트 번호는 HTTP 프로토콜을 사용하기 때문에 80번이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음에는 데이터가 네트워크 계층에 전달된다. 네트워크 계층에서는 IP 헤더가 붙는다. IP 헤더에는 출발지 PC와 목적지 PC의 IP가 추가된다. 이렇게 IP 헤더가 붙어 패킷이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로는 데이터 링크 계층으로 전달된다. 데이터 링크 계층에서는 이더넷 헤더가 붙어 이더넷 프레임이 된다. 그리고 물리 계층에서 랜카드를 이용해 전기 신호로 변환되어 네트워크로 전송된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;스위치와 라우터에서의 데이터 전달과 처리&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1804&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WyWFM/btrkhp8f5D0/bGI5CiQHwoQfrWWV6Vt1p0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WyWFM/btrkhp8f5D0/bGI5CiQHwoQfrWWV6Vt1p0/img.png&quot; data-alt=&quot;모든 내용은 위 그림을 바탕으로 진행된다. 출처: 모두의 네트워크 그림 8-2&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WyWFM/btrkhp8f5D0/bGI5CiQHwoQfrWWV6Vt1p0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWyWFM%2Fbtrkhp8f5D0%2FbGI5CiQHwoQfrWWV6Vt1p0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;451&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1804&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;모든 내용은 위 그림을 바탕으로 진행된다. 출처: 모두의 네트워크 그림 8-2&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 위 그림을 참고해서, 스위치 A를 보자. 스위치 A는 데이터링크 계층에서 데이터를 전기 신호로 변환해 라우터 A로 전송한다. 스위치 A에서 데이터가 전기 신호로 변환되어 케이블을 통해 흘러가, 라우터 A에 도착하면 라우터 A는 데이터 링크 계층에서 이더넷 프레임의 목적지 MAC 주소와 자신의 MAC 주소를 비교한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 때, MAC 주소가 일치하면 이더넷 헤더와 트레일러를 분리하는 역캡슐화를 수행한다. 이후, 네트워크 계층에 전달하고 자신의 라우팅 테이블과 목적지 IP 주소를 비교한다. 라우터 A의 라우팅 테이블에서 목적지 IP 주소의 경로를 알 수 있기에, 라우팅을 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 그림에 따르면 출발지 IP인 192.168.1.10을 라우터 외부 IP인 172.16.0.1로 변경한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로, 데이터 링크 계층으로 전달해 라우터 B로 보내도록 이더넷 헤더와 트레일러를 붙여 캡슐화를 수행한다. 이후 물리 계층에서 데이터를 전기 신호로 변환해 네트워크로 전송한다. (즉, 전기 신호 형태로 라우터 A에서 라우터 B로 전달된다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라우터 B에서부터 스위치 B까지의 동작 또한 스위치 A에서, 라우터 A로 가는 동작과 동일하게 진행된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1546&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5GkiK/btrkcskqPsN/cjnWnQgQaoNEAVYlvFuNXK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5GkiK/btrkcskqPsN/cjnWnQgQaoNEAVYlvFuNXK/img.png&quot; data-alt=&quot;이미지 출처: 모두의 네트워크 그림 8-3&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5GkiK/btrkcskqPsN/cjnWnQgQaoNEAVYlvFuNXK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5GkiK%2FbtrkcskqPsN%2FcjnWnQgQaoNEAVYlvFuNXK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;387&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1546&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이미지 출처: 모두의 네트워크 그림 8-3&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 데이터가 전송되는 과정에서는 위 사진과 같은 과정을 반복한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;웹 서버에서의 데이터 전달과처리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터가 전기 신호로 웹 서버에 도착하면 웹 서버는 데이터 링크 계층에서 프레임의 목적지 MAC 주소와 자신의 MAC 주소를 비교해 일치하면 이더넷 헤더와 트레일러를 분리해 네트워크 계층에 전달한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네트워크 계층에서는 목적지 IP 주소와 서버의 IP 주소를 비교하고, 일치하면 IP 헤더를 분리해 전송 계층에 전달한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전송 계층에서는 목적지 포트 번호를 확인해 어떤 애플리케이션으로 전달할 지 식별한 후 TCP 헤더를 분리해 응용 계층에 전달한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;드디어.. 응용 계층에 도달했다!&lt;/p&gt;</description>
      <category>Network</category>
      <author>쪼앤</author>
      <guid isPermaLink="true">https://joanne.tistory.com/292</guid>
      <comments>https://joanne.tistory.com/292#entry292comment</comments>
      <pubDate>Tue, 9 Nov 2021 02:34:27 +0900</pubDate>
    </item>
    <item>
      <title>모두의 네트워크 7장. 응용 계층: 애플리케이션에 데이터 전송하기</title>
      <link>https://joanne.tistory.com/291</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;응용 계층의 역할&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 서비스를 요청하는 측을 클라이언트, 서비스를 제공하는 측을 서버라고 한다. 서버 측에는 웹 서버 프로그램과 메일 서버 프로그램 등이 있다. 이러한 애플리케이션은 응용 계층에서 동작한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 애플리케이션이 동작하는 계층이라 응용 계층이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(여기서는 세션 계층, 표현 계층을 모두 포함해 응용 계층이라고 칭한다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;응용 계층에서는 사용자측의 요청을 전달하기 위해 통신 대상이 이해할 수 있는 메시지로 변환하고 전송 계층으로 전달하는 역할을 한다. 이를 위해서는 응용 계층의 프로토콜을 사용해야한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HTTP / 웹 사이트 접속&lt;/li&gt;
&lt;li&gt;DNS / 이름 해석&lt;/li&gt;
&lt;li&gt;FTP / 파일 전송&lt;/li&gt;
&lt;li&gt;SMTP / 메일 송신&lt;/li&gt;
&lt;li&gt;POP3 / 메일 수신&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;HTTP란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트는 웹 사이트를 보기 위해 서버의 80번 포트를 사용해 HTTP 통신을 한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HTTP/1.0
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;요청을 보낼 때마다 연결했다 끊는 작업을 반복한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;HTTP/1.1
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;keepalive 기능이 추가되었다. 이는 연결을 한 번 수립하면 데이터 교환을 끝낼 때까지 유지하고, 데이터 교환을 모두 끝내면 연결을 끊는 구조이다. keepalive는 요청을 순서대로 처리하는 특징을 갖는다.&lt;/li&gt;
&lt;li&gt;keepalive 관련 흥미로운 글 - &lt;a href=&quot;https://devthomas.tistory.com/50&quot;&gt;nginx reload와 keep-alive (부제: zero-downtime은 사기일까?)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;HTTP/2.0
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;요청을 보낸 순서대로 응답을 반환하지 않아도 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 외에도 HTTP 프로토콜은 버전별로 추가적인 특징을 가지니, 한번 쯤 확인해보면 좋을 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고가 될 만한 링크를 첨부한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://ssungkang.tistory.com/entry/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-HTTP-11-VS-HTTP-20&quot;&gt;https://ssungkang.tistory.com/entry/네트워크-HTTP-11-VS-HTTP-20&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 외에도 7장에는 추가적으로 DNS 서버, 메일 서버의 동작이 포함되어있는데 매우 간단하게 포함되어있다. 그래서 따로 정리하지 않았다. 이후 성공과 실패를 결정하는 1%의 네트워크 원리를 정리하면서 DNS 서버와 관련된 자세한 글을 게재할 생각이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모두의 네트워크 정리하기&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://joanne.tistory.com/285&quot;&gt;1장. 네트워크의 첫걸음&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://joanne.tistory.com/286&quot;&gt;2장. 네트워크의 기본 규칙&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://joanne.tistory.com/287&quot;&gt;3장. 물리 계층: 데이터를 전기 신호로 변환하기&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://joanne.tistory.com/288&quot;&gt;4장. 데이터 링크 계층: 랜에서 데이터 전송하기&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://joanne.tistory.com/289&quot;&gt;5장. 네트워크 계층: 목적지에 데이터 전달하기&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://joanne.tistory.com/290&quot;&gt;6장. 전송 계층: 신뢰할 수 있는 데이터 전송하기&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://joanne.tistory.com/291&quot;&gt;7장. 응용 계층: 애플리케이션에 데이터 전송하기&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://joanne.tistory.com/292&quot;&gt;8장. 네트워크 전체 흐름 살펴보기&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Network</category>
      <author>쪼앤</author>
      <guid isPermaLink="true">https://joanne.tistory.com/291</guid>
      <comments>https://joanne.tistory.com/291#entry291comment</comments>
      <pubDate>Tue, 9 Nov 2021 02:08:01 +0900</pubDate>
    </item>
    <item>
      <title>모두의 네트워크 6장. 전송 계층: 신뢰할 수 있는 데이터 전송하기</title>
      <link>https://joanne.tistory.com/290</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;전송 계층의 역할&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물리 계층, 데이터 링크 계층, 네트워크 계층의 3계층이 있으면 목적지에 데이터를 보낼 순 있다. 하지만 데이터가 손상되거나 유실되더라도 이들 계층에서는 아무것도 해 주지 않는다. 목적지에 신뢰할 수 있는 데이터를 전달하기 위해 필요한 계층이 바로 전송 계층이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전송 계층에는 오류를 점검하는 기능이 있다. 오류 발생 시 데이터를 재전송하도록 요청한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 네트워크 계층은 목적지까지 데이터를 전달하고, 전송 계층에서는 데이터가 제대로 도착했는지 확인한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 전송 계층에서는 전송된 데이터의 목적지가 어떤 애플리케이션인지 식별하는 기능도 있다. 즉, 웹 브라우저로 전송하는 것인지 메일 프로그램으로 전송하는 것인지를 구별한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;연결형 통신과 비연결형 통신&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전송 계층의 특징은 신뢰성/정확성과 효율성으로 구분할 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;신뢰성/정확성: 데이터를 목적지에 문제없이 전달하는 것 (연결형 통신)&lt;/li&gt;
&lt;li&gt;효율성: 데이터를 빠르고 효율적으로 전달하는 것 (비연결형 통신)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전송 계층의 연결형 통신 프로토콜에는 TCP가 사용되고, 비연결형 통신에는 UDP가 사용된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;TCP의 구조&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TCP(Transmission Control Protocol): 신뢰성과 정확성을 우선으로 하는 연결형 통신 프로토콜&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TCP로 전송할 때 붙이는 헤더를 TCP 헤더라고 한다. TCP 헤더가 붙은 데이터를 세그먼트라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TCP 헤더에는 다음과 같은 정보가 담겨있다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. 출발지 포트 번호 16비트
2. 목적지 포트 번호 16비트
3. 일련 번호 32비트
4. 확인 응답 번호 32비트
5. 헤더 길이 4비트
6. 예약 영역 6비트
7. 코드 비트 6비트
8. 윈도우 크기 16비트
9. 체크섬 16비트
10. 긴급 포인터 16비트
11 옵션&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연결형 통신은 상대방을 확인하면서 데이터를 전송해야한다. 따라서 데이터를 전송하려면 연결을 확보해야한다. TCP 헤더의 7. 코드 비트는 총 6비트로 구성되어있는데, 연결의 제어 정보가 기록되는 곳이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;URG, ACK, PSH, RST, SYN, FIN 으로 구성되어있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 비트의 초깃값은 0이고 비트가 활성화되면 1이 된다. 연결 확립에는 SYN(연결 요청), ACK(확인 응답)이 사용된다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3-way handshake&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PC1과 PC2가 통신한다고 가정한다. 화살표는 방향을 나타낸다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;연결 확립을 요청한다. (SYN) [PC1 &amp;rarr; PC2]&lt;/li&gt;
&lt;li&gt;연결 확립을 응답하고, 연결 확립 요청을 한다. (SYN + ACK) [PC1 &amp;larr; PC2]&lt;/li&gt;
&lt;li&gt;연결 확립을 응답한다. (ACK) [PC1 &amp;rarr; PC2]&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4-way handshake&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연결을 끊을 때에는 FIN(연결 종료), ACK이 사용된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PC1과 PC2가 통신한다고 가정한다. 화살표는 방향을 나타낸다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;연결 종료를 요청한다. (FIN) [PC1 &amp;rarr; PC2]&lt;/li&gt;
&lt;li&gt;연결 종료를 응답한다. (ACK) [PC1 &amp;larr; PC2]&lt;/li&gt;
&lt;li&gt;연결 종료를 요청한다. (FIN) [PC1 &amp;rarr; PC2]&lt;/li&gt;
&lt;li&gt;연결 종료를 응답한다. (ACK) [PC1 &amp;rarr; PC2]&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;일련 번호와 확인 응답 번호의 구조&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TCP 헤더에서 3. 일련번호와 4. 확인 응답 번호에 대해 알아보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TCP는 데이터를 분할해서 보내는데 일련번호는 송신 측에서 수신 측에 이 데이터가 몇번째 데이터인지 알려주는 역할을 한다. 전송된 데이터에 일련번호를 부여하면 수신자는 원래 데이터의 몇번째 데이터를 받았는지 알 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확인 응답 번호는 수신 측이 몇번째 데이터를 수신했는지 송신 측에 알려주는 역할을 한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;윈도우 크기란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세그먼트 하나를 보낼 때마다 확인 응답을 반환하면 효율이 높지 않다. 따라서 세그먼트를 연속해서 보내고 난 다음 확인 응답을 반환하여 효율을 높일 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TCP 헤더의 8. 윈도우 크기는 얼마나 많은 용량의 데이터를 저장해둘 수 있는지를 나타낸다. 이 값의 초기값은 3-way 핸드셰이크를 할 때 판단한다. 이후, 여러 세그먼트를 연속해서 보낸 뒤 이를 버퍼에 저장하고, 확인 응답 또한 연속해서 받을 수 있다. 이때, 미리 알려준 버퍼의 크기 이내로 보낸다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;포트 번호의 구조&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전송 계층에서는 목적지의 애플리케이션을 식별하는 역할을 수행한다고 했었다. 목적지가 어떤 애플리케이션인지 식별하지 못하면 어느 애플리케이션의 데이터인지 알 수 없기 때문에 엉뚱한 곳으로 데이터가 전송될 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TCP 헤더의 1. 출발지 포트번호, 2. 목적지 포트번호를 사용해 이를 해결할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TCP 헤더에 포트 번호가 있기 때문에 어떤 애플리케이션인지 구분할 수 있다. 포트번호는 0~65535번을 사용할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0~1023번 포트는 주요 프로토콜이 사용하도록 예악되어있다. 이를 well-known 포트라고 한다. 1024는 예약되어있지만 잘 사용하지 않는 포트고, 1025 이상은 랜덤 포트라고 해서 클라이언트측의 송신 포트로 사용된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;UDP의 구조&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UDP(User Datagram Protocol)는 비연결형 통신에 사용되는 프로토콜이다. 데이터를 효율적으로 빠르게 보내는 것을 목표로 한다. 스트리밍, 동영상 등에 사용된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UDP 헤더에는 다음과 같은 것들이 있다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. 출발지 포트 번호 16비트
2. 목적지 포트 번호 16비트
3. 길이 16비트
4. 체크섬 16비트&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UDP를 사용하면 브로드캐스트로 세그먼트를 보낼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모두의 네트워크 정리하기&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://joanne.tistory.com/285&quot;&gt;1장. 네트워크의 첫걸음&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://joanne.tistory.com/286&quot;&gt;2장. 네트워크의 기본 규칙&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://joanne.tistory.com/287&quot;&gt;3장. 물리 계층: 데이터를 전기 신호로 변환하기&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://joanne.tistory.com/288&quot;&gt;4장. 데이터 링크 계층: 랜에서 데이터 전송하기&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://joanne.tistory.com/289&quot;&gt;5장. 네트워크 계층: 목적지에 데이터 전달하기&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://joanne.tistory.com/290&quot;&gt;6장. 전송 계층: 신뢰할 수 있는 데이터 전송하기&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://joanne.tistory.com/291&quot;&gt;7장. 응용 계층: 애플리케이션에 데이터 전송하기&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://joanne.tistory.com/292&quot;&gt;8장. 네트워크 전체 흐름 살펴보기&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Network</category>
      <author>쪼앤</author>
      <guid isPermaLink="true">https://joanne.tistory.com/290</guid>
      <comments>https://joanne.tistory.com/290#entry290comment</comments>
      <pubDate>Tue, 9 Nov 2021 01:57:54 +0900</pubDate>
    </item>
  </channel>
</rss>