<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>현이의 개발 공부방</title>
    <link>https://hyunspaceworkshop.tistory.com/</link>
    <description>안녕하세요!
현이의 개발 공부방입니다.</description>
    <language>ko</language>
    <pubDate>Tue, 2 Jun 2026 02:35:55 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>N_HYUN</managingEditor>
    <image>
      <title>현이의 개발 공부방</title>
      <url>https://tistory1.daumcdn.net/tistory/7021874/attach/5baec2e09f5048e693d034e02e84128b</url>
      <link>https://hyunspaceworkshop.tistory.com</link>
    </image>
    <item>
      <title>[내일배움캠프] - 2026.04.06(월)ㅣ스프링 플러스 프로젝트</title>
      <link>https://hyunspaceworkshop.tistory.com/34</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;과제에 들어가기 앞서..&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;737&quot; data-origin-height=&quot;402&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LKChM/dJMcabKyitw/CWNTHwZWuI111hsKUHmq01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LKChM/dJMcabKyitw/CWNTHwZWuI111hsKUHmq01/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LKChM/dJMcabKyitw/CWNTHwZWuI111hsKUHmq01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLKChM%2FdJMcabKyitw%2FCWNTHwZWuI111hsKUHmq01%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;737&quot; height=&quot;402&quot; data-origin-width=&quot;737&quot; data-origin-height=&quot;402&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이번 과제는 효율적으로 문제를 해결하기 위해 마일스톤을 참고하여 진행했으며, 문제 번호는 마일스톤 기준으로 나열하였습니다. &lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. 코드 개선 퀴즈 - @Transactional의 이해&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1480&quot; data-origin-height=&quot;610&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DK0Uz/dJMcaiv4BAn/onff31CD8ixQHSe5lGuWV1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DK0Uz/dJMcaiv4BAn/onff31CD8ixQHSe5lGuWV1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DK0Uz/dJMcaiv4BAn/onff31CD8ixQHSe5lGuWV1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDK0Uz%2FdJMcaiv4BAn%2Fonff31CD8ixQHSe5lGuWV1%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;1480&quot; height=&quot;610&quot; data-origin-width=&quot;1480&quot; data-origin-height=&quot;610&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;할 일 저장 기능을 구현한 API(/todos)를 호출할 때, 아래와 같은 에러가 발생하고 있어요.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;에러 로그 원문&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;137&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lTUZC/dJMcagkJR4z/J136ufO6Mc19SWmU5JNKL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lTUZC/dJMcagkJR4z/J136ufO6Mc19SWmU5JNKL0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lTUZC/dJMcagkJR4z/J136ufO6Mc19SWmU5JNKL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlTUZC%2FdJMcagkJR4z%2FJ136ufO6Mc19SWmU5JNKL0%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;2048&quot; height=&quot;137&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;137&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;에러가 발생하지 않고 정상적으로 할 일을 저장 할 수 있도록 코드를 수정해주세요.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;문제 풀이&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KXtAv/dJMcacbAqaz/bUiYKulYahEZq3s0pw16sk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KXtAv/dJMcacbAqaz/bUiYKulYahEZq3s0pw16sk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KXtAv/dJMcacbAqaz/bUiYKulYahEZq3s0pw16sk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKXtAv%2FdJMcacbAqaz%2FbUiYKulYahEZq3s0pw16sk%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;1280&quot; height=&quot;720&quot; data-filename=&quot;1.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;클래스 레벨에 @Transactional(readOnly = true) 가 선언되어 있어서 saveTodo() 메서드까지 읽기 전용으로 동작했었습니다 그로 인해 오류가 발생되고 있었고 해결 하기위해 기존 클래스에 선언되어있던 @Transactional을 saveTodo() 메서드에만 별도로 선언해주었습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. 코드 개선 퀴즈 - JPA의 이해&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1488&quot; data-origin-height=&quot;1294&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXzq3Z/dJMcaco7ST2/1pV2U5LdxSRyg0aJrKqzDK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXzq3Z/dJMcaco7ST2/1pV2U5LdxSRyg0aJrKqzDK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXzq3Z/dJMcaco7ST2/1pV2U5LdxSRyg0aJrKqzDK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXzq3Z%2FdJMcaco7ST2%2F1pV2U5LdxSRyg0aJrKqzDK%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;1488&quot; height=&quot;1294&quot; data-origin-width=&quot;1488&quot; data-origin-height=&quot;1294&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;  기획자의 긴급 요청이 왔어요! 아래의 요구사항에 맞춰 기획 요건에 대응할 수 있는 코드를 작성해주세요.&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;할 일 검색 시 weather 조건으로도 검색할 수 있어야해요.(weather 조건은 있을 수도 있고, 없을 수도 있어요!)&lt;/li&gt;
&lt;li&gt;할 일 검색 시 수정일 기준으로 기간 검색이 가능해야해요.(기간의 시작과 끝 조건은 있을 수도 있고, 없을 수도 있어요!)&lt;/li&gt;
&lt;li&gt;JPQL을 사용하고, 쿼리 메소드명은 자유롭게 지정하되 너무 길지 않게 해주세요&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;  필요할 시, 서비스 단에서 if문을 사용해 여러 개의 쿼리(JPQL)를 사용하셔도 좋습니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;문제 풀이&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;3-1.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Jzg4c/dJMcac3HpMc/FTSKKjfGZQreIjWjNdkHPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Jzg4c/dJMcac3HpMc/FTSKKjfGZQreIjWjNdkHPk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Jzg4c/dJMcac3HpMc/FTSKKjfGZQreIjWjNdkHPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJzg4c%2FdJMcac3HpMc%2FFTSKKjfGZQreIjWjNdkHPk%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;1280&quot; height=&quot;720&quot; data-filename=&quot;3-1.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;getTodos 메서드에서 문제 요구사항에 맞게 weather 조건으로 검색, 수정일 기준으로 기간 검색이 가능하게 weather, startDate, endDate 파라미터를 추가 후 @RequestParam 어노테이션을 적용해주었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;3-2.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1xTb8/dJMcagkJTFa/kXZg3RB6EdKKmla6B0rsq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1xTb8/dJMcagkJTFa/kXZg3RB6EdKKmla6B0rsq0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1xTb8/dJMcagkJTFa/kXZg3RB6EdKKmla6B0rsq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1xTb8%2FdJMcagkJTFa%2FkXZg3RB6EdKKmla6B0rsq0%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;1280&quot; height=&quot;720&quot; data-filename=&quot;3-2.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이후 Repository에서는 JPQL을 활용하여 동적 쿼리를 작성했습니다. 요구사항에서 각 조건이 있을 수도 있고 없을 수도 있다고 했기 때문에 :weather IS NULL OR t.weather = :weather 와 같은 방식으로 파라미터가 null이면 조건을 무시하고, 값이 있을 때만 필터링되도록 구현했습니다. startDate와 endDate도 동일한 방식으로 처리했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;3-3.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JRAiL/dJMcagd0aoX/lRaWNjzZk6NYKawi0gnYP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JRAiL/dJMcagd0aoX/lRaWNjzZk6NYKawi0gnYP0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JRAiL/dJMcagd0aoX/lRaWNjzZk6NYKawi0gnYP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJRAiL%2FdJMcagd0aoX%2FlRaWNjzZk6NYKawi0gnYP0%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;1280&quot; height=&quot;720&quot; data-filename=&quot;3-3.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;getTodos 메서드에서 Controller에서 받은 weather, startDate, endDate 파라미터를 그대로 Repository의 findByConditions에 전달했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;페이징 처리는 &lt;b&gt;PageRequest.of(page - 1, size)&lt;/b&gt; 로 구현하였습니다. 또한 JPA의 페이지 번호는 0부터 시작하기 때문에 사용자가 1페이지를 요청하면 내부적으로 0페이지로 변환되어야 합니다. 이를 위해 PageRequest.of(page - 1, size)와 같이 작성하였습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;6. JPA Cascade&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;  앗❗ 실수로 코드를 지웠어요!&lt;/blockquote&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;JPA의 cascade 기능을 활용해 할 일을 생성한 유저가 담당자로 등록될 수 있게 해주세요.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1634&quot; data-origin-height=&quot;1732&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lyzdD/dJMcafsBpUB/7ejczZQygdp9ZdEgKCqYTK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lyzdD/dJMcafsBpUB/7ejczZQygdp9ZdEgKCqYTK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lyzdD/dJMcafsBpUB/7ejczZQygdp9ZdEgKCqYTK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlyzdD%2FdJMcafsBpUB%2F7ejczZQygdp9ZdEgKCqYTK%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;1634&quot; height=&quot;1732&quot; data-origin-width=&quot;1634&quot; data-origin-height=&quot;1732&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;문제 풀이&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;6.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dizQsQ/dJMcabjtxTK/JL7j4OrzfDjpKvJg9IfgxK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dizQsQ/dJMcabjtxTK/JL7j4OrzfDjpKvJg9IfgxK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dizQsQ/dJMcabjtxTK/JL7j4OrzfDjpKvJg9IfgxK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdizQsQ%2FdJMcabjtxTK%2FJL7j4OrzfDjpKvJg9IfgxK%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;1280&quot; height=&quot;720&quot; data-filename=&quot;6.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;기존 코드의 경우 Todo 생성자에서 managers.add(new Manager(user, this))로 담당자를 리스트에 추가했는데, 문제는 Todo를 저장할 때 Manager는 별도로 저장하지 않으면 DB에 반영되지 않는다는 점이었습니다. 따라서 @OneToMany 어노테이션에 cascade = CascadeType.PERSIST를 추가하여 Todo가 저장될 때 연관된 Manager도 함께 저장되게 하여 별도로 managerRepository.save()를 호출하지 않아도 자동으로 담당자가 등록되게 하였습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;11. Transaction 심화&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;  매니저 등록 요청 시 로그를 남기고 싶어요! @Transactional의 옵션 중 하나를 활용하여 매니저 등록과 로그 기록이 각각 독립적으로 처리될 수 있도록 해봅시다.&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;매니저 등록 요청을 기록하는 로그 테이블을 만들어주세요.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DB 테이블명: log&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&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;li&gt;그 외 로그에 들어가는 내용은 원하는 정보를 자유롭게 넣어주세요.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;문제 풀이&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;11-1.png&quot; data-origin-width=&quot;435&quot; data-origin-height=&quot;200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AtQB5/dJMcad2z2Bv/dc99ipv5rWWzc74lDwpWtK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AtQB5/dJMcad2z2Bv/dc99ipv5rWWzc74lDwpWtK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AtQB5/dJMcad2z2Bv/dc99ipv5rWWzc74lDwpWtK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAtQB5%2FdJMcad2z2Bv%2Fdc99ipv5rWWzc74lDwpWtK%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;435&quot; height=&quot;200&quot; data-filename=&quot;11-1.png&quot; data-origin-width=&quot;435&quot; data-origin-height=&quot;200&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;먼저 매니저 요청시 로그를 기록하기 위해 Log Entity, LogRepository, LogService를 만들어 초기 세팅을 해주었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;11-2.png&quot; data-origin-width=&quot;1646&quot; data-origin-height=&quot;833&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBDuIs/dJMb99MFtw4/ss7SFpO2o2NOJj6R5sDyYk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBDuIs/dJMb99MFtw4/ss7SFpO2o2NOJj6R5sDyYk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBDuIs/dJMb99MFtw4/ss7SFpO2o2NOJj6R5sDyYk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBDuIs%2FdJMb99MFtw4%2Fss7SFpO2o2NOJj6R5sDyYk%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;1646&quot; height=&quot;833&quot; data-filename=&quot;11-2.png&quot; data-origin-width=&quot;1646&quot; data-origin-height=&quot;833&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;처음으로 Log Entity를 작성해주었습니다. 기본적으로 로그 코드, 로그 내용, 로그 발생 시간으로 구성했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;11-3.png&quot; data-origin-width=&quot;1027&quot; data-origin-height=&quot;529&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uKuL0/dJMcaiv4DbY/0Qrq3tlhnbWfoQpWZeVUkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uKuL0/dJMcaiv4DbY/0Qrq3tlhnbWfoQpWZeVUkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uKuL0/dJMcaiv4DbY/0Qrq3tlhnbWfoQpWZeVUkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuKuL0%2FdJMcaiv4DbY%2F0Qrq3tlhnbWfoQpWZeVUkK%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;1027&quot; height=&quot;529&quot; data-filename=&quot;11-3.png&quot; data-origin-width=&quot;1027&quot; data-origin-height=&quot;529&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;LogRepository는 JpaRepository를 상속받아 별도의 메서드 없이 기본 CRUD 기능만 사용했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;11-4.png&quot; data-origin-width=&quot;1681&quot; data-origin-height=&quot;913&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qvTmM/dJMcaiv4Db0/8glxbk0YtkMHTIyXv6DEHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qvTmM/dJMcaiv4Db0/8glxbk0YtkMHTIyXv6DEHK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qvTmM/dJMcaiv4Db0/8glxbk0YtkMHTIyXv6DEHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqvTmM%2FdJMcaiv4Db0%2F8glxbk0YtkMHTIyXv6DEHK%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;1681&quot; height=&quot;913&quot; data-filename=&quot;11-4.png&quot; data-origin-width=&quot;1681&quot; data-origin-height=&quot;913&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;LogService의 saveLog 메서드의 경우 @Transactional(propagation = Propagation.REQUIRES_NEW)를 적용했습니다. 이렇게 하면 매니저 등록 트랜잭션과 완전히 독립된 새로운 트랜잭션으로 실행되기 때문에 매니저 등록이 실패해서 롤백되더라도 로그는 반드시 저장됩니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;7. N+1&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1614&quot; data-origin-height=&quot;958&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VNAjm/dJMcabRgREw/lpJnw3QiDXnndgKOFIv6P0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VNAjm/dJMcabRgREw/lpJnw3QiDXnndgKOFIv6P0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VNAjm/dJMcabRgREw/lpJnw3QiDXnndgKOFIv6P0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVNAjm%2FdJMcabRgREw%2FlpJnw3QiDXnndgKOFIv6P0%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;1614&quot; height=&quot;958&quot; data-origin-width=&quot;1614&quot; data-origin-height=&quot;958&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;CommentController 클래스의 getComments() API를 호출할 때 N+1 문제가 발생하고 있어요. N+1 문제란, 데이터베이스 쿼리 성능 저하를 일으키는 대표적인 문제 중 하나로, 특히 연관된 엔티티를 조회할 때 발생해요.&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;N+1 로그&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;373&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cgvYfv/dJMcagdZ8UE/vjzZvQkSkulKuAaI5TYuOk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cgvYfv/dJMcagdZ8UE/vjzZvQkSkulKuAaI5TYuOk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cgvYfv/dJMcagdZ8UE/vjzZvQkSkulKuAaI5TYuOk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcgvYfv%2FdJMcagdZ8UE%2FvjzZvQkSkulKuAaI5TYuOk%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;2048&quot; height=&quot;373&quot; data-origin-width=&quot;2048&quot; data-origin-height=&quot;373&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;문제 풀이&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;7.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FqnZg/dJMcacJrSOc/kMTY3EB921k4TqchHwg1W1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FqnZg/dJMcacJrSOc/kMTY3EB921k4TqchHwg1W1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FqnZg/dJMcacJrSOc/kMTY3EB921k4TqchHwg1W1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFqnZg%2FdJMcacJrSOc%2FkMTY3EB921k4TqchHwg1W1%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;1280&quot; height=&quot;720&quot; data-filename=&quot;7.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;기존 코드에서는 쿼리문에 FETCH가 없었습니다. 이 때문에 댓글 목록을 조회할 때 각 댓글마다 연관된 유저를 별도 쿼리로 조회하는 N+1문제가 발생 했던것입니다. 해당 문제를 해결하기 위해 JOIN FETCH를 추가하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;JOIN FETCH는 연관된 엔티티를 한 번의 쿼리로 함께 조회합니다. 즉, 댓글 100개를 조회하더라도 단 한번의 쿼리만 실행됩니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;8. QueryDSL&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1354&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nM2Ox/dJMcagdZ8Vp/IuPVgYGqOx1CQRB5AteIZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nM2Ox/dJMcagdZ8Vp/IuPVgYGqOx1CQRB5AteIZ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nM2Ox/dJMcagdZ8Vp/IuPVgYGqOx1CQRB5AteIZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnM2Ox%2FdJMcagdZ8Vp%2FIuPVgYGqOx1CQRB5AteIZ0%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;1354&quot; height=&quot;768&quot; data-origin-width=&quot;1354&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JPQL로 작성된 findByIdWithUser 를 QueryDSL로 변경합니다.&lt;/li&gt;
&lt;li&gt;7번과 마찬가지로 N+1 문제가 발생하지 않도록 유의해 주세요!&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;문제 풀이&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;8-1.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/q88gb/dJMcaf7cHc9/3c3K6fEwxAH66YNfMxKquK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/q88gb/dJMcaf7cHc9/3c3K6fEwxAH66YNfMxKquK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/q88gb/dJMcaf7cHc9/3c3K6fEwxAH66YNfMxKquK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fq88gb%2FdJMcaf7cHc9%2F3c3K6fEwxAH66YNfMxKquK%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;1280&quot; height=&quot;720&quot; data-filename=&quot;8-1.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;QueryDSL을 사용하기 위해 일단 의존성을 먼저 추가해주었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;8-2.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eksHOo/dJMcabKyhxz/noCP5ftT0t9MebITOjQnck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eksHOo/dJMcabKyhxz/noCP5ftT0t9MebITOjQnck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eksHOo/dJMcabKyhxz/noCP5ftT0t9MebITOjQnck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeksHOo%2FdJMcabKyhxz%2FnoCP5ftT0t9MebITOjQnck%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;1280&quot; height=&quot;720&quot; data-filename=&quot;8-2.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;TodoQueryDslRepository 인터페이스에 searchTodos() 메소드를 선언했습니다. 검색 조건으로 제목, 닉네임, 생성일 범위를 받고 페이징 처리된 TodoSearchResponse 목록을 반환하도록 로직을 구성하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;8-3.png&quot; data-origin-width=&quot;1112&quot; data-origin-height=&quot;626&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JDL8K/dJMcagE5iix/dE6UANVEnDncjMgOnYpPD0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JDL8K/dJMcagE5iix/dE6UANVEnDncjMgOnYpPD0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JDL8K/dJMcagE5iix/dE6UANVEnDncjMgOnYpPD0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJDL8K%2FdJMcagE5iix%2FdE6UANVEnDncjMgOnYpPD0%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;1112&quot; height=&quot;626&quot; data-filename=&quot;8-3.png&quot; data-origin-width=&quot;1112&quot; data-origin-height=&quot;626&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;searchTodos() 메소드에서 QTodoSearchResponse Projections를 사용하여 문제 요구사항에 맞게 제목, 담당자 수, 댓글 수만 조회할 수 있게 하였습니다. 또한 동적 검색 조건은 BooleanBuilder를 활용해 null인 조건은 자동으로 무시되도록 처리하였으며, 결과는 PageImpl로 감싸 페이징 처리하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;8-4.png&quot; data-origin-width=&quot;1556&quot; data-origin-height=&quot;788&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cC8FLC/dJMcaiiy3cc/Fo72YhZqlEjrFBAISKsM31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cC8FLC/dJMcaiiy3cc/Fo72YhZqlEjrFBAISKsM31/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cC8FLC/dJMcaiiy3cc/Fo72YhZqlEjrFBAISKsM31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcC8FLC%2FdJMcaiiy3cc%2FFo72YhZqlEjrFBAISKsM31%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;1556&quot; height=&quot;788&quot; data-filename=&quot;8-4.png&quot; data-origin-width=&quot;1556&quot; data-origin-height=&quot;788&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;TodoRepository에 TodoQueryDslRepository를 상속 추가했습니다. 이렇게 하면 기존 JPA 메소드와 QueryDSL 메서드를 하나의 Repository에서 함께 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;8-5.png&quot; data-origin-width=&quot;1897&quot; data-origin-height=&quot;1164&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bus6Y1/dJMcaaY8cPI/jJUSj8RXCwU9cFCR1TUT3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bus6Y1/dJMcaaY8cPI/jJUSj8RXCwU9cFCR1TUT3K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bus6Y1/dJMcaaY8cPI/jJUSj8RXCwU9cFCR1TUT3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbus6Y1%2FdJMcaaY8cPI%2FjJUSj8RXCwU9cFCR1TUT3K%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;1897&quot; height=&quot;1164&quot; data-filename=&quot;8-5.png&quot; data-origin-width=&quot;1897&quot; data-origin-height=&quot;1164&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;findByIdWithUser() 메소드는 leftJoin(QTodo.todo.user).fetchJoin()을 사용해 Todo와 User를 한 번의 쿼리로 조회하여 요구사항에 맞게끔 N+1 문제를 방지했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;searchTodos() 메소드에서는 QTodoSearchResponse Projections를 활용해 필요한 필드인 제목, 담당자 수, 댓글 수만 선택적으로 조회했습니다. 동적 검색 조건은 buildSearchCondition 메서드에서 BooleanBuilder로 처리했으며, 각 파라미터가 null이면 해당 조건을 무시하고 값이 있을 때만 조건에 추가됩니다. 마지막으로 PageImpl로 감싸 페이징 처리된 결과를 반환했습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;10. QueryDSL을 사용하여 검색 기능 만들기&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;  일정을 검색하는 기능을 만들고 싶어요! 검색 기능의 성능 및 사용성을 높이기 위해 QueryDSL을 활용한 쿼리 최적화를 해보세요.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;❗Projections를 활용해서 필요한 필드만 반환할 수 있도록 해주세요.❗&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;새로운 API로 만들어주세요.&lt;/li&gt;
&lt;li&gt;검색 조건은 다음과 같아요.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;li&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;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&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;li&gt;해당 일정의 총 댓글 개수를 넣어주세요.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;검색 결과는 페이징 처리되어 반환되도록 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;문제 풀이&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;10-1.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/boZuVK/dJMcai3SUps/p0snlJtwCZo6XvhQYxzRSK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/boZuVK/dJMcai3SUps/p0snlJtwCZo6XvhQYxzRSK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/boZuVK/dJMcai3SUps/p0snlJtwCZo6XvhQYxzRSK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FboZuVK%2FdJMcai3SUps%2Fp0snlJtwCZo6XvhQYxzRSK%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;1280&quot; height=&quot;720&quot; data-filename=&quot;10-1.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;처음으로는 검색 결과로 반환할 DTO생성 후 로직을 구성하였습니다. 요구사항에 따라 모든 정보가 아닌 제목, 담당자 수, 댓글 수만 필드로 구성했습니다. 생성자에 @QueryProjection을 붙여 QueryDSL에서 타입 안전하게 Projections을 사용할 수 있도록 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;10-2.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1hh9w/dJMcaakxuK4/BbTlNg9zwXP5QwasPWDInK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1hh9w/dJMcaakxuK4/BbTlNg9zwXP5QwasPWDInK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1hh9w/dJMcaakxuK4/BbTlNg9zwXP5QwasPWDInK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1hh9w%2FdJMcaakxuK4%2FBbTlNg9zwXP5QwasPWDInK%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;1280&quot; height=&quot;720&quot; data-filename=&quot;10-2.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이후 TodoQueryDslRepository 클래스를 만든 후 searchTodos 메서드를 선언 후 안에 제목, 닉네임, 생성일 범위를 검색 조건으로 받게 하고, 페이징 처리된 TodoSearchResponse를 반환하도록 설계하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;10-3.png&quot; data-origin-width=&quot;1961&quot; data-origin-height=&quot;1179&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mu7sd/dJMcaaY8dLg/Ob56xNnjbfepo7pEYkephk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mu7sd/dJMcaaY8dLg/Ob56xNnjbfepo7pEYkephk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mu7sd/dJMcaaY8dLg/Ob56xNnjbfepo7pEYkephk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fmu7sd%2FdJMcaaY8dLg%2FOb56xNnjbfepo7pEYkephk%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;1961&quot; height=&quot;1179&quot; data-filename=&quot;10-3.png&quot; data-origin-width=&quot;1961&quot; data-origin-height=&quot;1179&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;searchTodos 메서드에서는 QTodoSearchResponse Projections로 필요한 필드만 조회하고, managers와 comments를 leftJoin으로 연결해 담당자 수와 댓글 수를 count()로 집계하도록 하였습니다. 동적 검색 조건은 BooleanBuilder로 처리하여 null인 조건은 자동으로 무시되도록 했으며, 결과는 PageImpl로 감싸서 반환하도록 하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;10-4.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dsJ3V3/dJMcaaY8dLj/9Y1M9dcPMkiEK8jjAr6ct0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dsJ3V3/dJMcaaY8dLj/9Y1M9dcPMkiEK8jjAr6ct0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dsJ3V3/dJMcaaY8dLj/9Y1M9dcPMkiEK8jjAr6ct0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdsJ3V3%2FdJMcaaY8dLj%2F9Y1M9dcPMkiEK8jjAr6ct0%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;1280&quot; height=&quot;720&quot; data-filename=&quot;10-4.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;마지막으로 기존에 있던 TodoRepository에 TodoQueryDslRepository를 상속 추가하여 기존 JPA 메서드와 QueryDSL 메서드를 하나의 Repository에서 함께 사용할 수 있도록 했습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. 코드 추가 퀴즈 - JWT의 이해&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;  기획자의 긴급 요청이 왔어요! 아래의 요구사항에 맞춰 기획 요건에 대응할 수 있는 코드를 작성해주세요.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;User의 정보에 nickname이 필요해졌어요.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;User 테이블에 nickname 컬럼을 추가해주세요.&lt;/li&gt;
&lt;li&gt;nickname은 중복 가능합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;프론트엔드 개발자가 JWT에서 유저의 닉네임을 꺼내 화면에 보여주길 원하고 있어요.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;문제 풀이&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2-1.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dI8QXn/dJMb9960nL0/jAfrfoa1KUuOKOS35AQ0u0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dI8QXn/dJMb9960nL0/jAfrfoa1KUuOKOS35AQ0u0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dI8QXn/dJMb9960nL0/jAfrfoa1KUuOKOS35AQ0u0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdI8QXn%2FdJMb9960nL0%2FjAfrfoa1KUuOKOS35AQ0u0%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;1280&quot; height=&quot;720&quot; data-filename=&quot;2-1.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;User 엔티티에 nickName 필드를 추가했습니다. 요구사항에서 닉네임은 중복 가능하다고 했기 때문에 @Column(unique = true)는 적용하지 않았으며, 생성자에도 nickName 파라미터를 추가하여 회원가입 시 닉네임이 저장될 수 있도록 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2-2.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oYD9L/dJMcabRgWcy/DHaIZ4VX9eEghs3yWCrAX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oYD9L/dJMcabRgWcy/DHaIZ4VX9eEghs3yWCrAX1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oYD9L/dJMcabRgWcy/DHaIZ4VX9eEghs3yWCrAX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoYD9L%2FdJMcabRgWcy%2FDHaIZ4VX9eEghs3yWCrAX1%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;1280&quot; height=&quot;720&quot; data-filename=&quot;2-2.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;JWT 생성 시 .claim(&quot;nickName&quot;, nickName)을 추가하여 토큰 안에 닉네임 정보를 포함시켰습니다. 이렇게 하면 프론트엔드에서 토큰을 디코딩해 별도의 API 호출 없이 닉네임을 바로 꺼내 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2-3.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMadp8/dJMcafF9WA2/U9Dk2kg3ETJmZHRKzT24J0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMadp8/dJMcafF9WA2/U9Dk2kg3ETJmZHRKzT24J0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMadp8/dJMcafF9WA2/U9Dk2kg3ETJmZHRKzT24J0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMadp8%2FdJMcafF9WA2%2FU9Dk2kg3ETJmZHRKzT24J0%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;1280&quot; height=&quot;720&quot; data-filename=&quot;2-3.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;JWT를 파싱할 때 claims.get(&quot;nickName&quot;, String.class)로 닉네임을 꺼내 httpRequest.setAttribute로 저장했습니다. 이렇게 저장된 값은 이후 ArgumentResolver에서 AuthUser를 생성할 때 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2-4.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zN8fQ/dJMcafF9WA8/17XswDLTWiqJ4VXg5Z9KM1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zN8fQ/dJMcafF9WA8/17XswDLTWiqJ4VXg5Z9KM1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zN8fQ/dJMcafF9WA8/17XswDLTWiqJ4VXg5Z9KM1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzN8fQ%2FdJMcafF9WA8%2F17XswDLTWiqJ4VXg5Z9KM1%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;1280&quot; height=&quot;720&quot; data-filename=&quot;2-4.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;AuthUser에는 nickName 필드와 생성자 파라미터를 추가했습니다. 또한 Spring Security 적용으로 인해 UserDetails를 구현하여 Security Context에서 인증 정보로 활용될 수 있도록 하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2-5.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cCw8ls/dJMcafzoGVs/YJ48jvoTqk2jkRuXRfioF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cCw8ls/dJMcafzoGVs/YJ48jvoTqk2jkRuXRfioF0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cCw8ls/dJMcafzoGVs/YJ48jvoTqk2jkRuXRfioF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcCw8ls%2FdJMcafzoGVs%2FYJ48jvoTqk2jkRuXRfioF0%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;1280&quot; height=&quot;720&quot; data-filename=&quot;2-5.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;JWT에서 파싱한 정보로 AuthUser를 생성하고 UsernamePasswordAuthenticationToken에 담아 SecurityContextHolder에 저장되게 하였습니다. 이렇게 하면 이후 요청 처리 과정에서 SecurityContext를 통해 인증된 사용자 정보를 가져올 수 있습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4. 테스트 코드 퀴즈 - 컨트롤러 테스트의 이해&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1836&quot; data-origin-height=&quot;248&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/budUlp/dJMcafe7tQ5/7Ckt2WK7qIvWvVN0cvq1I0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/budUlp/dJMcafe7tQ5/7Ckt2WK7qIvWvVN0cvq1I0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/budUlp/dJMcafe7tQ5/7Ckt2WK7qIvWvVN0cvq1I0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbudUlp%2FdJMcafe7tQ5%2F7Ckt2WK7qIvWvVN0cvq1I0%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;1836&quot; height=&quot;248&quot; data-origin-width=&quot;1836&quot; data-origin-height=&quot;248&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;테스트 패키지 org.example.expert.domain.todo.controller의 todo_단건_조회_시_todo가_존재하지_않아_예외가_발생한다() 테스트가 실패하고 있어요.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1686&quot; data-origin-height=&quot;766&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNjjsE/dJMcafTG1Qw/nqH5djx6y6LTdtlnjWKep1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNjjsE/dJMcafTG1Qw/nqH5djx6y6LTdtlnjWKep1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNjjsE/dJMcafTG1Qw/nqH5djx6y6LTdtlnjWKep1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNjjsE%2FdJMcafTG1Qw%2FnqH5djx6y6LTdtlnjWKep1%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;1686&quot; height=&quot;766&quot; data-origin-width=&quot;1686&quot; data-origin-height=&quot;766&quot;/&gt;&lt;/span&gt;&lt;/figure&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;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;문제 풀이&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;4.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lCkOM/dJMcahqrsfy/1NHsgbcZDtcKntJWHPM7L0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lCkOM/dJMcahqrsfy/1NHsgbcZDtcKntJWHPM7L0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lCkOM/dJMcahqrsfy/1NHsgbcZDtcKntJWHPM7L0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlCkOM%2FdJMcahqrsfy%2F1NHsgbcZDtcKntJWHPM7L0%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;1280&quot; height=&quot;720&quot; data-filename=&quot;4.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;코드를 살펴보면 테스트 이름이 예외가 발생했을 때의 기준으로 만들어져있는데 200을 기대하고 있습니다. 그로 인해 오류가 발생하던것이었습니다. 따라서 기대값을 BAD_REQUEST로 줘서 오류를 해결하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5. 코드 개선 퀴즈 - AOP의 이해&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1764&quot; data-origin-height=&quot;870&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Q7seM/dJMcajoaB9S/f7tE4n3bH71QiH4S8h4cPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Q7seM/dJMcajoaB9S/f7tE4n3bH71QiH4S8h4cPk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Q7seM/dJMcajoaB9S/f7tE4n3bH71QiH4S8h4cPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQ7seM%2FdJMcajoaB9S%2Ff7tE4n3bH71QiH4S8h4cPk%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;1764&quot; height=&quot;870&quot; data-origin-width=&quot;1764&quot; data-origin-height=&quot;870&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;  AOP가 잘못 동작하고 있어요!&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;UserAdminController 클래스의 changeUserRole() 메소드가 실행 전 동작해야해요.&lt;/li&gt;
&lt;li&gt;AdminAccessLoggingAspect 클래스에 있는 AOP가 개발 의도에 맞도록 코드를 수정해주세요.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;문제 풀이&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;5.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9AUvZ/dJMcacCFIs3/EgMRmhd5XPpdnfQvCUZqs0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9AUvZ/dJMcacCFIs3/EgMRmhd5XPpdnfQvCUZqs0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9AUvZ/dJMcacCFIs3/EgMRmhd5XPpdnfQvCUZqs0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9AUvZ%2FdJMcacCFIs3%2FEgMRmhd5XPpdnfQvCUZqs0%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;1280&quot; height=&quot;720&quot; data-filename=&quot;5.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;기존에는 @After라는 어노테이션이 붙어 있었고 경로 또한 잘못되어있었습니다. @After라는 어노테이션은 &quot;~이후에&quot; 라는 뜻 처럼 실행전이 아닌 실행후에 동작하며, 경로 자체도 changeUserRole()메소드가 아닌 getUser()메소드를 찾고 있기 때문에 위 사진 처럼 변경해주었습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;9. Spring Security&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;Spring Security를 도입하기로 결정했어요!&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기존 Filter와 Argument Resolver를 사용하던 코드들을 Spring Security로 변경해주세요.
&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;권한은 Spring Security의 기능을 사용해주세요.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;토큰 기반 인증 방식은 유지할 거예요. JWT는 그대로 사용해주세요.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;문제 풀이&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;9-1.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7j2Ay/dJMcagLQtwI/hFkgMDti6858vI29ysVXk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7j2Ay/dJMcagLQtwI/hFkgMDti6858vI29ysVXk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7j2Ay/dJMcagLQtwI/hFkgMDti6858vI29ysVXk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7j2Ay%2FdJMcagLQtwI%2FhFkgMDti6858vI29ysVXk1%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;1280&quot; height=&quot;720&quot; data-filename=&quot;9-1.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Spring Security도 사용하기전에 의존성 설정을 해야 사용할 수 있기때문에 의존성을 추가해주었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;9-2.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/V92Za/dJMcagLQtwY/3tEPKB7VRDuw9NPPaYzUXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/V92Za/dJMcagLQtwY/3tEPKB7VRDuw9NPPaYzUXk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/V92Za/dJMcagLQtwY/3tEPKB7VRDuw9NPPaYzUXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FV92Za%2FdJMcagLQtwY%2F3tEPKB7VRDuw9NPPaYzUXk%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;1280&quot; height=&quot;720&quot; data-filename=&quot;9-2.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;과제는 JWT 기반 인증 방식을 유지하기 때문에 세션은 STATELESS로 설정하고 CSRF는 비활성화했습니다. /auth/**와 /health는 permitAll(), /admin/**은 hasRole(&quot;ADMIN&quot;)으로 권한을 설정하고 JwtAuthenticationFilter를 Security 필터 체인에 등록했습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;9-3.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9X65g/dJMcahYgiLi/Dq3oCS0VOGsY7K7ZiIR37k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9X65g/dJMcahYgiLi/Dq3oCS0VOGsY7K7ZiIR37k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9X65g/dJMcahYgiLi/Dq3oCS0VOGsY7K7ZiIR37k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9X65g%2FdJMcahYgiLi%2FDq3oCS0VOGsY7K7ZiIR37k%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;1280&quot; height=&quot;720&quot; data-filename=&quot;9-3.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;OncePerRequestFilter를 상속받아 요청당 한 번만 실행되도록 하였습니다. JWT를 파싱해 AuthUser를 생성하고 SecurityContextHolder에 저장하며, 토큰이 유효하지 않으면 401을 반환히도록 설계하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;9-4.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mGHLM/dJMcacWWARw/PsEON3ur4WgmRWzwtYG121/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mGHLM/dJMcacWWARw/PsEON3ur4WgmRWzwtYG121/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mGHLM/dJMcacWWARw/PsEON3ur4WgmRWzwtYG121/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmGHLM%2FdJMcacWWARw%2FPsEON3ur4WgmRWzwtYG121%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;1280&quot; height=&quot;720&quot; data-filename=&quot;9-4.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;UserDetails를 구현하고 getAuthorities()에서 ROLE_ prefix를 붙여 Spring Security가 권한을 인식할 수 있도록 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;9-5.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bn5oeq/dJMcabcEC7E/qkYgL7d22y3shEqDY5V2wk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bn5oeq/dJMcabcEC7E/qkYgL7d22y3shEqDY5V2wk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bn5oeq/dJMcabcEC7E/qkYgL7d22y3shEqDY5V2wk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbn5oeq%2FdJMcabcEC7E%2FqkYgL7d22y3shEqDY5V2wk%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;1280&quot; height=&quot;720&quot; data-filename=&quot;9-5.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;기존 request.getAttribute() 방식에서 SecurityContextHolder.getContext().getAuthentication().getPrincipal()로 변경하여 AuthUser를 컨트롤러에 주입받도록 했습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>TIL &amp;amp; 트러블 슈팅</category>
      <author>N_HYUN</author>
      <guid isPermaLink="true">https://hyunspaceworkshop.tistory.com/34</guid>
      <comments>https://hyunspaceworkshop.tistory.com/34#entry34comment</comments>
      <pubDate>Mon, 6 Apr 2026 19:56:08 +0900</pubDate>
    </item>
    <item>
      <title>[내일배움캠프] - 2026.03.31(화)</title>
      <link>https://hyunspaceworkshop.tistory.com/33</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2026.03.31(화) TIL&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;오늘은 스프링 플러스 과제가 발제되었습니다. 챕터4 Index 강의를 시청하였고, Index는 면접에서 단골로 나오는 주제인 만큼 유튜브와 구글 검색을 통해 추가적으로 공부하였습니다. 이후 스프링 플러스 과제의 필수 Lv.1 1번, 3번 문제를 풀었습니다. 이번 과제는 사실 이전에 배웠던 내용들이었지만, 개념을 조금 더 이해한 상태에서 다시 풀어보니 새로운 느낌이었습니다. 이전에는 제대로 이해하지 못한 채로 사용했던 탓에 문제를 보았을 때 스스로 풀 수 없을 것 같다는 느낌에 집중이 잘 되지 않았습니다. 하지만 그 과정을 거치고 나서 해당 내용들을 조금이라도 알고 나니 손에 잡히는 문제가 되었고, 그 차이가 꽤 크게 느껴져서 좋았습니다. 내일은 캐싱에 대해 공부하면서 과제를 이어나갈 예정입니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt; &lt;span style=&quot;text-align: left;&quot;&gt;&amp;rarr; 인덱스(Index) 개념 정리: &lt;a href=&quot;https://hyunspaceworkshop.tistory.com/32&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://hyunspaceworkshop.tistory.com/32&lt;/a&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;</description>
      <category>TIL &amp;amp; 트러블 슈팅</category>
      <author>N_HYUN</author>
      <guid isPermaLink="true">https://hyunspaceworkshop.tistory.com/33</guid>
      <comments>https://hyunspaceworkshop.tistory.com/33#entry33comment</comments>
      <pubDate>Tue, 31 Mar 2026 21:54:38 +0900</pubDate>
    </item>
    <item>
      <title>인덱스(Index)</title>
      <link>https://hyunspaceworkshop.tistory.com/32</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;인덱스(Index)란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;인덱스(Index)는 데이터베이스 테이블에서 데이터를 더 빠르게 검색하기 위해 사용하는 &lt;b&gt;자료구조&lt;/b&gt;입니다. 마치 책의 목차처럼 원하는 데이터를 빠르게 찾을 수 있도록 도와주며, 데이터를 정렬된 구조로 유지하여 테이블 전체를 스캔하지 않고도 필요한 데이터에 빠르게 접근할 수 있도록 합니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;서점으로 이해하는 Index&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;인덱스가 없는 경우, 데이터베이스는 원하는 데이터를 찾기 위해 테이블의 모든 행을 처음부터 끝까지 하나씩 확인해야 합니다. 이를 &lt;b&gt;Full Table Scan &lt;/b&gt;이라고 합니다. 데이터가 10건이라면 금방 찾을 수 있지만, 1만 건, 10만 건이 넘어간다면 그만큼 조회 시간이 길어지게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt; 인덱스 없이 전체를 탐색하는 경우 &lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;교보문고에서 스프링 부트 관련 책을 찾는다고 가정해봅시다. 검색 기능 없이 넓은 매장을 직접 돌아다니며 책을 하나씩 확인한다면 상당한 시간이 걸립니다. 책이 100권이라면 어떻게든 찾겠지만, 매장에 10만 권이 진열되어 있다면 원하는 책을 찾기까지 사실상 불가능에 가까운 시간이 소요될 것입니다. 데이터베이스도 마찬가지입니다. 인덱스가 없는 테이블에서 특정 데이터를 조회하면, 데이터베이스는 조건에 맞는 행을 찾을 때까지 첫 번째 행부터 마지막 행까지 전부 확인해야 합니다. 데이터가 적을 때는 문제가 없지만, 데이터가 쌓일수록 조회 성능은 급격히 저하됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt; 인덱스 적용 후 탐색 방식&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;서점 책위치.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;1280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lmW6F/dJMcaiJwqzj/X3yadpxizTf7xGVfKFUkIk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lmW6F/dJMcaiJwqzj/X3yadpxizTf7xGVfKFUkIk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lmW6F/dJMcaiJwqzj/X3yadpxizTf7xGVfKFUkIk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlmW6F%2FdJMcaiJwqzj%2FX3yadpxizTf7xGVfKFUkIk%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;1280&quot; height=&quot;1280&quot; data-filename=&quot;서점 책위치.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;1280&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;교보문고에는 책 검색 기능이 있습니다. 도서 검색 전용 컴퓨터로 찾고자하는 책 제목을 입력하면 위 자료 처럼 책이 어느 구역 몇 번째 칸에 있는지 바로 표시됩니다. 책마다 고유한 ID가 존재하고, 그 ID를 기반으로 위치를 즉시 파악할 수 있기 때문에 매장 전체를 돌아다닐 필요가 없습니다. 데이터베이스의 인덱스도 동일한 방식으로 동작합니다. 인덱스에는 특정 열의 값과 해당 데이터가 실제로 저장된 &lt;b&gt;위치 정보(포인터)&lt;/b&gt;가 함께 저장되어 있습니다. 덕분에 전체 테이블을 스캔하지 않고도 원하는 데이터의 위치로 곧바로 이동할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;서점&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;데이터베이스&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;매장 전체 진열된 책&lt;/td&gt;
&lt;td&gt;테이블의 전체 데이터&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;책 검색 기능&lt;/td&gt;
&lt;td&gt;인덱스(Index)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;책의 고유 ID&lt;/td&gt;
&lt;td&gt;Primary Key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;구역 및 칸 번호&lt;/td&gt;
&lt;td&gt;데이터의 실제 저장 위치(포인터)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;책 제목으로 검색&lt;/td&gt;
&lt;td&gt;WHERE 조건으로 조회&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;인덱스의 단점&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;인덱스는 조회 성능을 높여주는 만큼 단점도 존재합니다. 데이터가 삽입, 수정, 삭제될 때마다 인덱스도 함께 갱신되어야 하기 때문에 쓰기 작업에서 추가적인 비용이 발생합니다. 조회가 적고 쓰기가 잦은 테이블에 인덱스를 무분별하게 적용하면 오히려 전체적인 성능이 떨어질 수 있습니다. 또한 인덱스는 테이블과 별도로 저장되는 자료구조이기 때문에 그만큼의 디스크 공간을 추가로 차지하며, 인덱스가 많아질수록 저장 공간 사용량도 함께 늘어납니다. 결국 인덱스를 지나치게 많이 생성하면 쓰기 작업 시 갱신해야 할 인덱스도 늘어나 오버헤드가 커지기 때문에, 자주 조회되는 열에 한해 꼭 필요한 경우에만 적용하는 것이 중요합니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;인덱스의 종류&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;table id=&quot;333a4e59-e604-803e-86b0-cbf2b3442324&quot; style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;종류&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;설명&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;333a4e59-e604-802c-a730-d61b35fd8eb8&quot;&gt;
&lt;td id=&quot;h_K:&quot;&gt;기본 인덱스 (B-Tree Index)&lt;/td&gt;
&lt;td id=&quot;k&amp;#96;Q\&quot;&gt;가장 일반적인 인덱스로, 대부분의 DBMS에서 기본으로 사용됩니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;333a4e59-e604-8015-98a5-fddc86e956d0&quot;&gt;
&lt;td id=&quot;h_K:&quot;&gt;해시 인덱스 (Hash Index)&lt;/td&gt;
&lt;td id=&quot;k&amp;#96;Q\&quot;&gt;해시 함수를 사용해 매우 빠른 검색을 제공하지만, 범위 검색에는 부적합합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;333a4e59-e604-80cc-8054-f7484ea22546&quot;&gt;
&lt;td id=&quot;h_K:&quot;&gt;비트맵 인덱스 (Bitmap Index)&lt;/td&gt;
&lt;td id=&quot;k&amp;#96;Q\&quot;&gt;값의 종류가 적은 열(성별, 상태값 등)에 적합하며, OR 조건 처리에 강합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;333a4e59-e604-800f-aebc-c0d2f661f5de&quot;&gt;
&lt;td id=&quot;h_K:&quot;&gt;복합 인덱스 (Composite Index)&lt;/td&gt;
&lt;td id=&quot;k&amp;#96;Q\&quot;&gt;두 개 이상의 열을 조합한 인덱스로, 복잡한 쿼리 조건에 유리합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;333a4e59-e604-8033-9392-d78bc9a5a773&quot;&gt;
&lt;td id=&quot;h_K:&quot;&gt;유일 인덱스 (UNIQUE Index)&lt;/td&gt;
&lt;td id=&quot;k&amp;#96;Q\&quot;&gt;중복된 값을 허용하지 않으며, 기본키에 자동으로 생성됩니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;333a4e59-e604-80ea-a8d2-d918cbdfee27&quot;&gt;
&lt;td id=&quot;h_K:&quot;&gt;클러스터형 인덱스 (Clustered Index)&lt;/td&gt;
&lt;td id=&quot;k&amp;#96;Q\&quot;&gt;실제 데이터가 인덱스 순서대로 저장되며, 테이블당 하나만 생성할 수 있습니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;333a4e59-e604-80e0-af22-f3426e2ee1a8&quot;&gt;
&lt;td id=&quot;h_K:&quot;&gt;비클러스터형 인덱스 (Non-clustered Index)&lt;/td&gt;
&lt;td id=&quot;k&amp;#96;Q\&quot;&gt;인덱스와 실제 데이터가 분리되어 있으며, 여러 개 생성이 가능합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt; 인덱스 사용 예시&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1774941647079&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SELECT * FROM Employee
WHERE Department = 'Sales';&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;Department&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;text-align: start;&quot;&gt;열에 인덱스가 있다면, 전체 테이블을 스캔하지 않고 인덱스를 통해&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;text-align: start;&quot;&gt;Sales&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;부서에 해당하는 데이터를 빠르게 찾을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;인덱스 삭제&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1774941745970&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;DROP INDEX 인덱스이름;&lt;/code&gt;&lt;/pre&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;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;B-Tree 구조(Binary Tree)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;인덱스의 동작 원리를 제대로 이해하려면 &lt;span data-token-index=&quot;1&quot;&gt;B-Tree(Balanced Tree)&lt;/span&gt; 구조를 알아야 합니다. B-Tree는 이름 그대로 &lt;span data-token-index=&quot;3&quot;&gt;균형 잡힌 트리 구조&lt;/span&gt;로, 대부분의 데이터베이스가 인덱스를 구현할 때 사용하는 핵심 자료구조입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt; B-Tree의 구성 요소&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;B-Tree는 크게 세 가지 요소로 구성됩니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;루트 노드(Root Node):&lt;/b&gt; 트리의 최상단에 위치한 시작점입니다. 데이터를 검색할 때 항상 루트 노드에서부터 탐색을 시작합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;브랜치 노드(Branch Node):&lt;/b&gt; 루트와 리프 사이에 위치한 중간 노드입니다. 데이터의 범위를 좁혀가며 탐색 방향을 안내하는 역할을 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;리프 노드(Leaf Node):&lt;/b&gt; 트리의 최하단에 위치하며, 실제 데이터의 위치 정보(포인터)를 담고 있습니다. 최종적으로 찾고자 하는 데이터는 리프 노드에서 발견됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt; B-Tree의 탐색 과정&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;예를 들어 1부터 7까지의 데이터가 저장된 B-Tree에서 숫자 6을 찾는다고 가정해봅시다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;B-tree.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cn01TH/dJMcag53y7b/nGlafqbDEk9gfq8YvnAdh1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cn01TH/dJMcag53y7b/nGlafqbDEk9gfq8YvnAdh1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cn01TH/dJMcag53y7b/nGlafqbDEk9gfq8YvnAdh1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcn01TH%2FdJMcag53y7b%2FnGlafqbDEk9gfq8YvnAdh1%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;1280&quot; height=&quot;720&quot; data-filename=&quot;B-tree.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;탐색 과정은 다음과 같습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;루트 노드(4)에서 시작합니다. 찾는 값 6은 4보다 크므로 오른쪽으로 이동합니다.&lt;/li&gt;
&lt;li&gt;브랜치 노드(6)에 도달합니다. 찾는 값과 일치하므로 탐색을 완료합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;전체 데이터를 하나씩 확인하지 않고, &lt;b&gt;두 단계 만에 원하는 데이터를 찾아낸 것&lt;/b&gt;입니다. 데이터가 수백만 건이 되더라도 트리의 깊이는 그에 비해 훨씬 작기 때문에 매우 빠른 탐색이 가능합니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;B-Tree가 균형을 유지하는 이유&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;B-Tree의 핵심은 항상 &lt;b&gt;균형(Balance)을 유지한다&lt;/b&gt;는 점입니다. 모든 리프 노드는 루트 노드로부터 동일한 깊이에 위치합니다. 이 덕분에 어떤 데이터를 찾더라도 탐색에 걸리는 시간이 일정하게 유지됩니다. 만약 균형이 깨진다면 특정 데이터를 찾을 때 더 많은 단계를 거쳐야 하므로 검색 성능이 떨어지게 됩니다. 그래서 데이터가 추가되거나 삭제될 때마다 B-Tree는 자동으로 구조를 재정렬하여 균형을 맞춥니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;데이터 추가 시 발생하는 일&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;새로운 데이터가 추가될 경우, B-Tree는 아래 순서로 동작합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;새 데이터가 들어갈 적절한 리프 노드를 탐색합니다.&lt;/li&gt;
&lt;li&gt;해당 노드에 데이터를 삽입합니다.&lt;/li&gt;
&lt;li&gt;노드가 가득 찼다면 노드를 분할(Split)하고 상위 노드로 값을 올립니다.&lt;/li&gt;
&lt;li&gt;트리 전체의 균형을 다시 맞춥니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이 과정 때문에 데이터를 &lt;b&gt;조회할 때는 빠르지만&lt;/b&gt;, 데이터를 &lt;b&gt;삽입, 수정, 삭제할 때는 인덱스 갱신 비용이 추가로 발생&lt;/b&gt;하게 됩니다. 앞서 인덱스의 단점으로 설명드린 쓰기 성능 저하가 바로 이 이유 때문입니다.&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;정리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;B-Tree는 데이터를 정렬된 상태로 유지하면서 균형 잡힌 트리 구조를 통해 빠른 탐색을 가능하게 하는 자료구조입니다. 전체 데이터를 처음부터 끝까지 뒤지는 것이 아니라, 트리의 분기를 따라 탐색 범위를 절반씩 줄여나가기 때문에 데이터가 아무리 많아도 적은 단계로 원하는 값을 찾을 수 있습니다. 다만 쓰기 작업마다 균형을 유지하는 비용이 발생하기 때문에, 인덱스는 &lt;b&gt;자주 조회되는 열&lt;/b&gt;에 한해 신중하게 적용하는 것이 중요합니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DataBase</category>
      <author>N_HYUN</author>
      <guid isPermaLink="true">https://hyunspaceworkshop.tistory.com/32</guid>
      <comments>https://hyunspaceworkshop.tistory.com/32#entry32comment</comments>
      <pubDate>Tue, 31 Mar 2026 15:50:22 +0900</pubDate>
    </item>
    <item>
      <title>[내일배움캠프] - 2026.03.30(월)</title>
      <link>https://hyunspaceworkshop.tistory.com/31</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;2026.03.30(월) TIL&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;길고 길었던 결제 시스템 프로젝트가 끝나고, 이번 주부터 새로운 발제가 시작되었습니다. 오늘은 지난 시간에 배웠지만 따로 정리하지 못했던 &lt;b&gt;Docker&lt;/b&gt;에 대해 다시 복습하며 주요 개념들을 정리해 보았습니다. Docker는 현대 개발 환경에서 빠질 수 없는 도구인 만큼, 단순히 명령어를 외우는 것에서 그치지 않고 &lt;b&gt;왜 필요한지&lt;/b&gt;, &lt;b&gt;어떤 원리로 동작하는지&lt;/b&gt;까지 깊이 이해하는 것이 중요하다고 생각합니다. 앞으로도 계속해서 공부하며 내용을 보완해 나갈 예정입니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&amp;rarr; 도커(Docker) 개념 정리:&lt;/b&gt; &lt;a href=&quot;https://hyunspaceworkshop.tistory.com/30&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://hyunspaceworkshop.tistory.com/30&lt;/a&gt;&lt;/p&gt;</description>
      <category>TIL &amp;amp; 트러블 슈팅</category>
      <author>N_HYUN</author>
      <guid isPermaLink="true">https://hyunspaceworkshop.tistory.com/31</guid>
      <comments>https://hyunspaceworkshop.tistory.com/31#entry31comment</comments>
      <pubDate>Mon, 30 Mar 2026 22:38:32 +0900</pubDate>
    </item>
    <item>
      <title>도커(Docker)</title>
      <link>https://hyunspaceworkshop.tistory.com/30</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;도커(Docker)란?&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img.png&quot; data-origin-width=&quot;3840&quot; data-origin-height=&quot;2160&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cdi5A6/dJMb99TmXAS/Ix4ezxegcIj3MYNs7TCICk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cdi5A6/dJMb99TmXAS/Ix4ezxegcIj3MYNs7TCICk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cdi5A6/dJMb99TmXAS/Ix4ezxegcIj3MYNs7TCICk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcdi5A6%2FdJMb99TmXAS%2FIx4ezxegcIj3MYNs7TCICk%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;3840&quot; height=&quot;2160&quot; data-filename=&quot;img.png&quot; data-origin-width=&quot;3840&quot; data-origin-height=&quot;2160&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;도커는 소프트웨어 개발과 배포를 도와주는 &lt;b&gt;컨테이너(Container) 기술&lt;/b&gt;입니다. 도커를 사용하면 애플리케이션을 빌드하고, 배포하고, 실행하는 전체 과정을 훨씬 쉽게 관리할 수 있습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;주요 개념&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Docker Image: &lt;/b&gt;애플리케이션과 그 실행에 필요한 모든 설정이 포함된 스냅샷입니다. 컨테이너를 만들기 위해 반드시 필요한 재료라고 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Docker Container:&lt;/b&gt;&amp;nbsp;이미지를 기반으로 실행되는 독립된 프로세스입니다. 독립된 환경에서 애플리케이션을 실행하기 때문에, 서로 다른 컨테이너는 서로 간섭하지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Docker Hub:&lt;/b&gt;&amp;nbsp;이미지를 공유하고 배포할 수 있는 중앙 저장소입니다. 다른 사람이 만들어 놓은 이미지를 가져다 쓸 수도 있고, 내가 만든 이미지를 올려서 공유할 수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Dockerfile: &lt;/b&gt;이미지를 만들기 위한 스크립트 파일입니다. 이미지를 빌드하는 과정과 필요한 명령어들을 순서대로 기술합니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt; ☕ 커피로 쉽게 이해하는 Docker &lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;개발자들의 수액이라고 할 수 있는 &lt;b&gt;커피&lt;/b&gt;를 예시로 들어보겠습니다. 제가 커피 가게를 하나 창업했는데 잘 되어서 프랜차이즈화하여 다른 지점을 낸다고 가정해봅시다. 재료가 있다 하더라도 커피를 만드는 과정이나 비율이 조금씩 다르면 맛이 달라질 수 있습니다. 그렇게 되면 안 되기 때문에, 본점에서 사용하는 재료들을 &lt;b&gt;밀키트&lt;/b&gt;로 만들어 다른 지점에 제공합니다. 그러면 다른 지점에서도 본점의 커피와 똑같은 맛을 낼 수 있습니다. 도커도 마찬가지입니다. 우리가 실행하는 프로그램은 환경이 다르면 결과도 달라질 수 있습니다. 데이터베이스 버전, 패키지 충돌, 경로 설정 문제 등 여러 가지 복합적인 요소들이 있기 때문입니다. 이것을 해결하기 위해 도커가 필요합니다. 도커는 &lt;b&gt;어떤 환경에서든 언제나 같은 결과를 보장&lt;/b&gt;하기 위해 존재하는 도구입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;커피 비유 Docker 개념&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 105px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;b&gt;비유&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;b&gt;Docker 개념&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;b&gt;밀키트&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;Docker Image&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;b&gt;밀키트로 만든 커피&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;Docker Container&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;b&gt;커피 제작 레시피&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;Dockerfile&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;b&gt;커피 프랜차이즈 본사 창고&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;Docker Hub&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;레시피(Dockerfile)&lt;/b&gt;와 &lt;b&gt;밀키트(Image)&lt;/b&gt;만 있다면, &lt;b&gt;어떤 컴퓨터에서든 똑같은 프로그램을 실행&lt;/b&gt;할 수 있습니다. 도커는 단순히 프로그램만 패키징하는 것이 아니라 &lt;b&gt;실행 환경까지 함께 패키징&lt;/b&gt;하기 때문에 실행을 보장할 수 있습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;도커의 필요성&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;개발자 A와 B가 함께 프로그램을 개발하고 배포한다고 가정해봅시다. 이때 아래와 같은 상황이 생길 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Java 버전이 서로 다른 경우&lt;/li&gt;
&lt;li&gt;사용하는 라이브러리 버전이 다른 경우&lt;/li&gt;
&lt;li&gt;실수로 특정 설정 파일이나 코드를 빠뜨린 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이런 상황에서는 분명히 문제가 생기게 됩니다. 이를 해결해 주는 것이 바로 도커입니다. 도커는 이 모든 것을 &lt;b&gt;이미지 하나에 담아&lt;/b&gt; 어떤 상황에서도 똑같이 동작하도록 만들어 줍니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;정리&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Docker Image&lt;/b&gt; : 실행에 필요한 모든 것을 담은 패키지입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Docker Container&lt;/b&gt; : 이미지를 실행한 인스턴스(프로그램)입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Dockerfile&lt;/b&gt; : 이미지를 어떻게 만들지 정의한 레시피 파일입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Docker Hub&lt;/b&gt; : 이미지를 저장하고 공유하는 중앙 저장소입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;도커 컨테이너를 공사장이나 항구의 컨테이너 박스로 떠올리기 쉽지만, Docker Container는 이미지를 실행한 프로그램이라고 이해하시는 것이 정확합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;포트 매핑&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;컨테이너는 자체 네트워크를 가지고 있기 때문에, 기본적으로 외부에서 접근할 수 없습니다. -p 옵션으로 호스트 포트와 컨테이너 포트를 연결해야 외부에서 접근이 가능합니다. 이것을 &lt;b&gt;포트 매핑&lt;/b&gt;이라고 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;포트 매핑.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdDp5X/dJMcabjnUBD/Swgnn8toeV04PurDkOUyEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdDp5X/dJMcabjnUBD/Swgnn8toeV04PurDkOUyEK/img.png&quot; data-alt=&quot;포트 매핑:외부 요청 &amp;amp;rarr; 호스트 포트 &amp;amp;rarr; 컨테이너 포트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdDp5X/dJMcabjnUBD/Swgnn8toeV04PurDkOUyEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdDp5X%2FdJMcabjnUBD%2FSwgnn8toeV04PurDkOUyEK%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;1280&quot; height=&quot;720&quot; data-filename=&quot;포트 매핑.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;포트 매핑:외부 요청 &amp;rarr; 호스트 포트 &amp;rarr; 컨테이너 포트&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #eaecf0;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 호스트 8080 -&amp;gt; 컨테이너 8080
docker run -p 8080:8080 example-health-app:v1.0&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;-p 8080:8080 은 &lt;b&gt;호스트의 8080번 포트로 요청이 들어오면, 컨테이너의 8080번 포트로 전달하라&lt;/b&gt; 는 의미입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;형식은 -p 호스트포트:컨테이너포트 순서입니다. 왼쪽이 내 컴퓨터(호스트), 오른쪽이 컨테이너라고 기억하시면 편합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;환경변수 주입&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;컨테이너 실행 시 -e 옵션을 사용하면 환경변수를 주입할 수 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;docker run -e SPRING_PROFILES_ACTIVE=local \
           -e SPRING_DATASOURCE_URL=jdbc:mysql://... \
           example-health-app:v1.0&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;위 명령어를 실행하면 아래와 같이 설정이 적용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;환경 변수&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;값&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SPRING_PROFILES_ACTIVE&lt;/td&gt;
&lt;td&gt;local&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SPRING_DATASOURCE_URL&lt;/td&gt;
&lt;td&gt;jdbc:mysql://...&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;데이터베이스 주소나 실행 환경(local, dev, prod 등)처럼 &lt;b&gt;상황에 따라 바뀌는 설정값&lt;/b&gt;을 이미지에 직접 넣지 않고, 실행 시점에 외부에서 주입할 수 있어서 유연하게 활용할 수 있습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;태그&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;태그는 도커 이미지를 &lt;b&gt;버전별로 구분&lt;/b&gt;하고 싶을 때 사용합니다. 이미지 빌드 시 태그를 따로 지정하지 않으면, 자동으로 &lt;b&gt;latest&lt;/b&gt; 태그가 붙게 됩니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #eaecf0;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 태그 지정 O
docker build -t example-health-app:v1.0 .

# 태그 지정 X &amp;rarr; latest 자동 적용
docker build -t example-health-app .&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;latest는 단순히 태그를 지정하지 않았을 때 붙는 기본값입니다. 실제로 가장 최신 버전임을 자동으로 보장하지는 않으므로, 운영 환경에서는 v1.0, v1.1 처럼 명시적인 태그를 사용하는 것을 권장합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Docker 빌드&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Docker 빌드를 하기 전에 먼저 &lt;b&gt;Dockerfile&lt;/b&gt;이 필요합니다. 앞서 커피 비유로 설명드렸지만 다시 정리하자면, Dockerfile은 &lt;b&gt;Docker 이미지 생성에 필요한 설정값을 담고 있는 스크립트 파일&lt;/b&gt;입니다. 내부에 명시된 옵션값에 따라 컨테이너의 런타임 환경, 의존성 패키지, 실행 명령어가 정의됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Dockerfile 옵션&lt;/b&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 122px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;b&gt;옵션&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;b&gt;설명&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;b&gt;FROM&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;컨테이너 런타임 환경을 지정합니다. 버전을 명시하지 않으면 최신 버전을 사용합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;b&gt;WORKDIR&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;컨테이너 내부의 작업 디렉토리입니다. 이후 명령어들이 이 경로를 기준으로 실행됩니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;b&gt;RUN&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;b&gt;이미지 빌드 시점&lt;/b&gt;에 실행할 명령어입니다. 패키지 설치 등에 사용합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;b&gt;EXPOSE&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;컨테이너 실행 시 외부에 열어줄 포트를 명시합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;b&gt;CMD&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;b&gt;컨테이너 실행 시점&lt;/b&gt;에 실행할 명령어입니다. RUN과 실행 시점이 다른 점을 주의해야 합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RUN과 CMD의 차이가 헷갈리기 쉽습니다. RUN은 이미지를 만들 때, CMD는 이미지를 실행할 때 동작한다고 기억하시면 됩니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Dockerfile 예시&lt;/b&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dockerfile&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# 런타임 환경: Node.js 14 버전
FROM node:14

# 작업 디렉토리 설정
WORKDIR /app

# 의존성 파일 복사 및 설치
COPY package*.json ./
RUN npm install

# 소스코드 전체 복사
COPY . .

# 외부에 열어줄 포트
EXPOSE 8080

# 컨테이너 실행 시 앱 시작
CMD [&quot;node&quot;, &quot;server.js&quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Docker 빌드 명령어&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Dockerfile 작성이 끝났다면, 터미널에서 아래 명령어를 입력하여 이미지를 빌드할 수 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;mipsasm&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;# 기본 빌드
docker build [Dockerfile 경로]

# 태그를 함께 지정하는 경우 (권장)
docker build -t example-health-app:v1.0 .&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dockerfile 경로나 파일 이름이 잘못된 경우 에러가 발생할 수 있습니다. 명령어 실행 위치와 경로를 꼭 확인해 주세요.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Docker 실행 (Docker Run) - 컨테이너 생성 및 실행&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이미지 빌드가 완료되었다면, 이제 해당 이미지를 실행할 차례입니다. &lt;b&gt;docker run 명령어&lt;/b&gt;는 이미지를 읽어 &lt;b&gt;컨테이너를 생성하고 실행&lt;/b&gt;하는 명령어입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;css&quot; style=&quot;color: #eaecf0;&quot;&gt;&lt;code&gt;docker run -p [호스트 포트]:[컨테이너 포트] [Image ID]

# 예시
docker run -p 8080:8080 example-health-app:v1.0&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  앞서 설명드린 포트 매핑(-p 옵션) 을 이 시점에 함께 지정해 주어야 외부에서 컨테이너에 접근할 수 있습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;도커(Docker) 전체 흐름 정리&lt;/b&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;단계&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;명령어&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;설명&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1단계&lt;/td&gt;
&lt;td&gt;Dockerfile 작성&lt;/td&gt;
&lt;td&gt;이미지 설정 정의&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2단계&lt;/td&gt;
&lt;td&gt;docker build&lt;/td&gt;
&lt;td&gt;이미지 생성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3단계&lt;/td&gt;
&lt;td&gt;docker run&lt;/td&gt;
&lt;td&gt;컨테이너 생성 및 실행&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Etc/Web &amp;amp; CS</category>
      <author>N_HYUN</author>
      <guid isPermaLink="true">https://hyunspaceworkshop.tistory.com/30</guid>
      <comments>https://hyunspaceworkshop.tistory.com/30#entry30comment</comments>
      <pubDate>Mon, 30 Mar 2026 19:47:29 +0900</pubDate>
    </item>
    <item>
      <title>프로그래밍 언어(Programming Language)</title>
      <link>https://hyunspaceworkshop.tistory.com/29</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;프로그래밍 언어&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;프로그래밍 언어는 두가지로, &lt;b&gt;저급언어&lt;/b&gt;와 &lt;b&gt;고급언어&lt;/b&gt;로 나뉩니다. 아래에서는 &lt;b&gt;저급언어&lt;/b&gt;와 &lt;b&gt;고급언어&lt;/b&gt;가 뭔지 또한 관련 언어들의 특징에 대해서 알아보겠습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;저급 언어&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;저급 언어는&amp;nbsp;&lt;b&gt;컴퓨터가 이해하기 쉬운 형태로 작성된 프로그래밍 언어&lt;/b&gt;를 말하며, 기계어와 어셈블리어가 이에 해당됩니다. 실행속도는 빠르지만 사람이 이해하기 어렵다는 단점이 있습니다. 아래에서 자세히 살펴보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;기계어&lt;/b&gt;&lt;/h4&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;0과 1의 2진수 형태로 표현되며 수행 시간이 빠릅니다.&lt;/li&gt;
&lt;li&gt;CPU에 내장된 명령들을 직접 사용하는 것으로, 프로그램을 작성하고 이해하기 어렵습니다.&lt;/li&gt;
&lt;li&gt;기종 마다 기계어가 다르므로 언어의 호환성이 없습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;어셈블리어&lt;/b&gt;&lt;/h4&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&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;어셈블리어.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Pikeh/dJMb99S90GO/7JAQnfKHgLyR9veo8AMVO1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Pikeh/dJMb99S90GO/7JAQnfKHgLyR9veo8AMVO1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Pikeh/dJMb99S90GO/7JAQnfKHgLyR9veo8AMVO1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPikeh%2FdJMb99S90GO%2F7JAQnfKHgLyR9veo8AMVO1%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;1280&quot; height=&quot;720&quot; data-filename=&quot;어셈블리어.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;위와 같이 &lt;b&gt;기계어&lt;/b&gt;는 컴퓨터가 직접 이해 할 수 있는 언어이며 사람이 이해하기는 힘든 언어 입니다. 그래서 나온 언어가 &lt;b&gt;어셈블리어&lt;/b&gt;인데 해당 언어도 사람 마다 받아들여지기 어렵겠지만 어려운 기계어 보다는 사람에게 그나마 최적화 된 언어입니다. 아쉽게도 &lt;b&gt;어셈블리어&lt;/b&gt;는 CPU가 이해하지 못하여 프로그래머가 &lt;b&gt;어셈블리어&lt;/b&gt;로 작성한 코드는 &lt;b&gt;어셈블러&lt;/b&gt;라는 프로그램을 사용해서 기계어로 번역해야지만 CPU가 이해할 수 있습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style5&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;고급 언어&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;고급언어.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcdD4l/dJMcajg8rzR/PjFyYWlcIMNoKKCIYaG531/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcdD4l/dJMcajg8rzR/PjFyYWlcIMNoKKCIYaG531/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcdD4l/dJMcajg8rzR/PjFyYWlcIMNoKKCIYaG531/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcdD4l%2FdJMcajg8rzR%2FPjFyYWlcIMNoKKCIYaG531%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;1280&quot; height=&quot;720&quot; data-filename=&quot;고급언어.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;고급 언어는 저급 언어와 다르게 인간이 이해하기 쉽도록 만들어진 프로그래밍 언어입니다. 아래에서 한번 고급언어의 특징을 알아봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&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;li&gt;컴퓨터가 이해할 수 있는 기계어로 번역하기 위해 컴파일러나 인터프리터가 사용됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;고급 언어는 우리가 살면서 한번쯤은(?) 들어봤던 &lt;b&gt;C언어, C++, JAVA, Python&lt;/b&gt; 등등 다양한 언어들이 속해 있습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style5&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;컴파일러와 인터프리터&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;컴퓨터는 기본적으로 기계어만 이해할 수 있기 때문에, 고급 언어로 작성된 프로그램은 반드시 기계어로 변환되는 과정을 거쳐야 합니다. 이때 사용되는 것이 바로 &lt;b&gt;컴파일러(Compiler)&lt;/b&gt;와 &lt;b&gt;인터프리터(Interpreter)&lt;/b&gt;입니다. 처음 접하는 사람에게는 다소 생소한 용어일 수 있지만, 두 프로그램 모두 고급 언어로 작성된 &lt;b&gt;원시 프로그램(Source Program)&lt;/b&gt;을 컴퓨터가 이해할 수 있는 &lt;b&gt;목적 프로그램(Object Program)&lt;/b&gt;으로 번역하는 역할을 합니다. 다만 프로그램을 번역하는 &lt;b&gt;방식의 차이&lt;/b&gt;에 따라 컴파일러와 인터프리터로 구분됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;184&quot; data-start=&quot;45&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;컴파일러(Compiler)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-end=&quot;184&quot; data-start=&quot;45&quot; data-ke-size=&quot;size18&quot;&gt;컴파일러는 프로그램 전체 코드를 한 번에 기계어로 번역하는 프로그램입니다. 즉, 사람이 작성한 고급 언어 코드를 컴퓨터가 이해할 수 있는 기계어로 변환한 뒤 실행 파일을 생성하는 방식이라고 생각하시면 됩니다.&lt;/p&gt;
&lt;p data-end=&quot;195&quot; data-start=&quot;189&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;195&quot; data-start=&quot;189&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;lt;예시&amp;gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;235&quot; data-start=&quot;198&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;203&quot; data-start=&quot;198&quot; data-section-id=&quot;1o4g6j&quot;&gt;C&lt;/li&gt;
&lt;li data-end=&quot;213&quot; data-start=&quot;206&quot; data-section-id=&quot;16yidor&quot;&gt;C++&lt;/li&gt;
&lt;li data-end=&quot;222&quot; data-start=&quot;216&quot; data-section-id=&quot;1j440ww&quot;&gt;Go&lt;/li&gt;
&lt;li data-end=&quot;233&quot; data-start=&quot;225&quot; data-section-id=&quot;6rhxgo&quot;&gt;Rust&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;319&quot; data-start=&quot;238&quot; data-ke-size=&quot;size18&quot;&gt;컴파일러 방식은 프로그램 전체를 미리 번역한 후 실행하기 때문에 &lt;b&gt;실행 속도가 빠르며, 실행 전에 오류를 확인할 수 있다는 특징&lt;/b&gt;이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-end=&quot;179&quot; data-start=&quot;43&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;인터프리터(Interpreter)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-end=&quot;179&quot; data-start=&quot;43&quot; data-ke-size=&quot;size18&quot;&gt;인터프리터는 프로그램의 코드를 한 줄씩 해석하면서 바로 실행하는 방식의 번역 프로그램입니다. 컴파일러처럼 전체 코드를 한 번에 번역하는 것이 아니라, 코드를 순서대로 읽으면서 그때그때 실행합니다.&lt;/p&gt;
&lt;p data-end=&quot;190&quot; data-start=&quot;184&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;190&quot; data-start=&quot;184&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;lt;예시&amp;gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;233&quot; data-start=&quot;193&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;203&quot; data-start=&quot;193&quot; data-section-id=&quot;1lju5j0&quot;&gt;Python&lt;/li&gt;
&lt;li data-end=&quot;220&quot; data-start=&quot;206&quot; data-section-id=&quot;1mnqnmj&quot;&gt;JavaScript&lt;/li&gt;
&lt;li data-end=&quot;231&quot; data-start=&quot;223&quot; data-section-id=&quot;6r5k0k&quot;&gt;Ruby&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;324&quot; data-start=&quot;236&quot; data-ke-size=&quot;size18&quot;&gt;인터프리터 방식은 코드를 한 줄씩 해석하며 실행하기 때문에 &lt;b&gt;실행 속도는 상대적으로 느리지만, 실행하면서 바로 결과를 확인할 수 있다는 특징&lt;/b&gt;이 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;324&quot; data-start=&quot;236&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 72px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;&lt;b&gt;구분&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;&lt;b&gt;컴파일러(Compiler)&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 21px;&quot;&gt;&lt;b&gt;인터프리터(Interpreter)&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px;&quot;&gt;&lt;b&gt;번역 방식&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px;&quot;&gt;전체 번역&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px;&quot;&gt;한 줄씩 번역&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px;&quot;&gt;&lt;b&gt;실행 속도&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px;&quot;&gt;빠름&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px;&quot;&gt;느림&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px;&quot;&gt;&lt;b&gt;오류 발견&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px;&quot;&gt;실행 전&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px;&quot;&gt;실행 중&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Etc/Web &amp;amp; CS</category>
      <author>N_HYUN</author>
      <guid isPermaLink="true">https://hyunspaceworkshop.tistory.com/29</guid>
      <comments>https://hyunspaceworkshop.tistory.com/29#entry29comment</comments>
      <pubDate>Sun, 15 Mar 2026 01:46:06 +0900</pubDate>
    </item>
    <item>
      <title>아키텍처(Architecture)</title>
      <link>https://hyunspaceworkshop.tistory.com/28</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;아키텍처란(Architecture)?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;아키텍처(Architecture)&lt;/b&gt;란? 시스템의 구조, 동작 등을 정의하는 개념적인 모형으로 시스템의 목적을 달성하기 위해 시스템의 각 컴포넌트가 무엇이며 어떻게 상호작용하는지, 정보가 어떻게 교환되는 지를 설명합니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;소프트웨어에서의 아키텍처&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;소프트웨어 아키텍처는 시스템을 구성하는 다양한 요소들이 어떻게 상호작용하고 배치될지 정의하는 &lt;b&gt;청사진&lt;/b&gt;입니다. 아키텍처는 시스템의 구조를 설계할 때 중요한 역할을 하며, &lt;b&gt;성능&lt;/b&gt;, &lt;b&gt;확장성&lt;/b&gt;, &lt;b&gt;유지보수성&lt;/b&gt; 등 여러 측면에서 시스템의 성공에 큰 영향을 미칩니다. 여기서는 주요 &lt;b&gt;소프트웨어 아키텍처 패턴&lt;/b&gt;과 &lt;b&gt;아키텍처 설계 시 고려할 점들&lt;/b&gt;을 설명하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;소프트웨어 아키텍처 패턴&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;레이어드 아키텍처 (Layered Architecture)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;가장 일반적이고 많이 사용되는 아키텍처 패턴으로, 시스템을 여러 계층(Layer)으로 나누어 각 계층이 특정 역할을 담당합니다. 계층 간의 의존 관계를 명확하게 정의함으로써 유지보수와 테스트가 용이합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;예시&lt;/b&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;b&gt;Presentation Layer (UI Layer)&lt;/b&gt;: 사용자 인터페이스와 상호작용.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Business Logic Layer (Service Layer)&lt;/b&gt;: 애플리케이션의 비즈니스 로직 처리.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Data Access Layer&lt;/b&gt;: 데이터베이스와의 상호작용.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Database Layer&lt;/b&gt;: 실제 데이터 저장소 (DB).&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;장점&lt;/b&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;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;단점&lt;/b&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;마이크로서비스 아키텍처 (Microservices Architecture)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;마이크로서비스아키텍처.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c0FtQx/dJMcahp8oN6/dObhEjnZPHGcgXydzxkghk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c0FtQx/dJMcahp8oN6/dObhEjnZPHGcgXydzxkghk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c0FtQx/dJMcahp8oN6/dObhEjnZPHGcgXydzxkghk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc0FtQx%2FdJMcahp8oN6%2FdObhEjnZPHGcgXydzxkghk%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;1280&quot; height=&quot;720&quot; data-filename=&quot;마이크로서비스아키텍처.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;시스템을 작은 서비스들로 나누고, 각 서비스가 독립적으로 배포되고 운영됩니다. 각 서비스는 &lt;b&gt;특정 비즈니스 기능&lt;/b&gt;을 담당하고, &lt;b&gt;자체 데이터베이스&lt;/b&gt;를 가질 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;특징&lt;/b&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;size18&quot;&gt;&lt;b&gt;장점&lt;/b&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;b&gt;스케일링&lt;/b&gt;과 &lt;b&gt;배포&lt;/b&gt;가 용이.&lt;/li&gt;
&lt;li&gt;개발 팀이 독립적으로 작업할 수 있어 개발 속도 향상.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;단점&lt;/b&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;b&gt;분산 시스템 관리&lt;/b&gt;가 필요.&lt;/li&gt;
&lt;li&gt;트랜잭션 관리가 어려울 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;클라이언트 서버 아키텍처 (Client-Server Architecture)&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;클라이언트서버 아키텍처.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0am7m/dJMcadHY0yV/DXwvn89GzGdBcb4rVoo6tk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0am7m/dJMcadHY0yV/DXwvn89GzGdBcb4rVoo6tk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0am7m/dJMcadHY0yV/DXwvn89GzGdBcb4rVoo6tk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0am7m%2FdJMcadHY0yV%2FDXwvn89GzGdBcb4rVoo6tk%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;1280&quot; height=&quot;720&quot; data-filename=&quot;클라이언트서버 아키텍처.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;클라이언트와 서버가 명확하게 분리되어, 클라이언트는 서버로 요청을 보내고, 서버는 클라이언트에게 응답을 반환하는 방식입니다. 주로 웹 애플리케이션에서 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;특징&lt;/b&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;b&gt;네트워크&lt;/b&gt;를 통해 서로 통신합니다.&lt;/li&gt;
&lt;li&gt;서버는 &lt;b&gt;데이터 저장&lt;/b&gt; 및 &lt;b&gt;로직 처리&lt;/b&gt;를 담당하고, 클라이언트는 &lt;b&gt;사용자 인터페이스&lt;/b&gt;를 담당합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;장점&lt;/b&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;b&gt;유지보수&lt;/b&gt;가 용이.&lt;/li&gt;
&lt;li&gt;서버 측에서 비즈니스 로직을 처리하므로 &lt;b&gt;보안&lt;/b&gt;을 강화할 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;단점&lt;/b&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;b&gt;성능 문제&lt;/b&gt; 발생 가능.&lt;/li&gt;
&lt;li&gt;클라이언트가 서버에 과도하게 의존할 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;이벤트 기반 아키텍처 (Event-Driven Architecture)&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;이벤트 기반 아키텍처.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HIRvP/dJMcabjarGu/CfolEqKfskthKPdrT2N5g1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HIRvP/dJMcabjarGu/CfolEqKfskthKPdrT2N5g1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HIRvP/dJMcabjarGu/CfolEqKfskthKPdrT2N5g1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHIRvP%2FdJMcabjarGu%2FCfolEqKfskthKPdrT2N5g1%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;1280&quot; height=&quot;720&quot; data-filename=&quot;이벤트 기반 아키텍처.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;시스템에서 발생하는 &lt;b&gt;이벤트&lt;/b&gt;에 따라 동작이 결정되는 아키텍처입니다. &lt;b&gt;이벤트&lt;/b&gt;는 사용자 행동, 시스템 상태 변화 등 다양한 원인에 의해 트리거됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;특징&lt;/b&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;b&gt;이벤트 프로듀서&lt;/b&gt;와 &lt;b&gt;이벤트 리스너&lt;/b&gt;가 존재.&lt;/li&gt;
&lt;li&gt;이벤트를 처리하는 컴포넌트들은 독립적으로 동작.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;장점&lt;/b&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;b&gt;실시간 처리&lt;/b&gt;에 유리.&lt;/li&gt;
&lt;li&gt;시스템 간의 결합도가 낮아 확장과 유연성이 뛰어남.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;단점&lt;/b&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;b&gt;디버깅&lt;/b&gt;과 &lt;b&gt;트랜잭션 관리&lt;/b&gt;가 어려울 수 있음.&lt;/li&gt;
&lt;li&gt;이벤트의 순서와 일관성 문제가 발생할 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;아키텍처 설계 시 고려해야 할 요소&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;성능 (Performance)&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;요구 사항&lt;/b&gt;에 따라 시스템의 처리 성능이 중요할 수 있습니다.&lt;/li&gt;
&lt;li&gt;지연 시간(Latency)을 줄이고, 처리량(Throughput)을 높이기 위해 효율적인 아키텍처 설계가 필요합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;확장성 (Scalability)&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시스템이 성장함에 따라 요구되는 처리 용량을 &lt;b&gt;수평 확장&lt;/b&gt;(서버 추가)이나 &lt;b&gt;수직 확장&lt;/b&gt;(서버 성능 향상)으로 해결할 수 있어야 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;클라우드 기반 아키텍처&lt;/b&gt;와 &lt;b&gt;컨테이너화&lt;/b&gt;가 확장성을 지원하는 주요 방법입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;가용성 (Availability)&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시스템이 언제든지 정상적으로 동작할 수 있도록 높은 &lt;b&gt;가용성&lt;/b&gt;을 보장해야 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;장애 복구&lt;/b&gt;(Failover)와 &lt;b&gt;분산 아키텍처&lt;/b&gt;를 통해 장애 발생 시에도 서비스를 지속할 수 있게 설계해야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;유지보수성 (Maintainability)&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시스템이 커질수록 &lt;b&gt;유지보수성&lt;/b&gt;이 중요한 요소로 작용합니다.&lt;/li&gt;
&lt;li&gt;각 모듈이나 서비스가 잘 분리되어 있고, &lt;b&gt;문서화&lt;/b&gt;가 잘 되어 있어야 효율적인 유지보수가 가능합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;보안 (Security)&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터와 시스템을 보호하기 위해 &lt;b&gt;인증&lt;/b&gt;, &lt;b&gt;인가&lt;/b&gt;, &lt;b&gt;암호화&lt;/b&gt;, &lt;b&gt;취약점 관리&lt;/b&gt; 등을 고려해야 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;분산 시스템&lt;/b&gt;에서는 &lt;b&gt;서비스 간 인증&lt;/b&gt;과 &lt;b&gt;데이터 보호&lt;/b&gt;를 신경 써야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;유연성 (Flexibility)&lt;/b&gt;&lt;/h4&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;b&gt;모듈화&lt;/b&gt;와 &lt;b&gt;플러그인 아키텍처&lt;/b&gt; 등을 사용하여 유연성을 높일 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;결론&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;소프트웨어 아키텍처는 시스템의 &lt;b&gt;성능&lt;/b&gt;, &lt;b&gt;확장성&lt;/b&gt;, &lt;b&gt;유지보수성&lt;/b&gt; 등을 보장하는 중요한 설계 단계입니다. 각 아키텍처 패턴은 특정한 요구 사항에 맞춰 설계되며, 프로젝트의 특성에 맞는 아키텍처를 선택하는 것이 매우 중요합니다. 아키텍처 설계 시에는 &lt;b&gt;기술적 선택&lt;/b&gt;뿐만 아니라, &lt;b&gt;비즈니스 요구&lt;/b&gt;와 &lt;b&gt;팀의 역량&lt;/b&gt;도 고려해야 합니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Etc/Web &amp;amp; CS</category>
      <author>N_HYUN</author>
      <guid isPermaLink="true">https://hyunspaceworkshop.tistory.com/28</guid>
      <comments>https://hyunspaceworkshop.tistory.com/28#entry28comment</comments>
      <pubDate>Fri, 13 Mar 2026 21:24:30 +0900</pubDate>
    </item>
    <item>
      <title>컴퓨터 구조(Computer architecture)</title>
      <link>https://hyunspaceworkshop.tistory.com/27</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;컴퓨터 구조&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;컴퓨터는 하드웨어(Hardware)&lt;/b&gt; 와 &lt;b&gt;소프트웨어(Software)&lt;/b&gt;가 결합된 시스템으로, 정보를 처리하고 다양한 작업을 수행할 수 있도록 설계되어 있습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;하드웨어(Hardware)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;하드웨어는 컴퓨터를 구성하는 &lt;b&gt;물리적인 장치&lt;/b&gt;들을 의미하며, 다음과 같은 주요 구성 요소로 이루어집니다.&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;중앙처리장치(CPU, Central Processing Unit)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;컴퓨터의 두뇌 역할을 하며, 연산 및 제어 기능을 수행합니다. &lt;b&gt;산술 논리 연산장치(ALU)&lt;/b&gt;와 &lt;b&gt;제어장치(Control Unit)&lt;/b&gt;로 구성됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;메모리(Memory)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;데이터를 저장하고 처리하는 공간입니다. RAM, ROM, 캐시, 레지스터 등이 있으며, 각각 속도와 용도에 따라 구분됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;입출력 장치(I/O Devices)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;사용자와 컴퓨터 간의 상호작용을 담당합니다. 예: 키보드, 마우스, 모니터, 프린터 등이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;보조기억장치(Storage)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;데이터를 장기적으로 저장하는 장치입니다. HDD, SSD, USB 등이 이에 해당됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;소프트웨어(Software)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;소프트웨어는 하드웨어를 제어하고, 사용자가 원하는 작업을 수행할 수 있도록 하는 &lt;b&gt;프로그램의 집합&lt;/b&gt;입니다. 크게 다음과 같이 나뉩니다.&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;운영체제(OS, Operating System)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;하드웨어와 소프트웨어를 중재하는 역할을 하며, 시스템 자원을 관리합니다. 예: Windows, Linux, macOS 등&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;응용 프로그램(Application Software)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;사용자가 직접 사용하는 소프트웨어로, 특정 작업을 수행합니다. 예: 웹 브라우저, 워드 프로세서, 게임 등&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;시스템 소프트웨어(System Software)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;하드웨어를 직접 제어하고 응용 소프트웨어가 원활히 작동할 수 있도록 지원합니다. 운영체제나 드라이버 등이 여기에 해당됩니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;CPU&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;컴퓨터 시스템은 기본적으로 &lt;b&gt;중앙 처리 장치(CPU)&lt;/b&gt;, &lt;b&gt;주기억장치(RAM)&lt;/b&gt;, &lt;b&gt;보조 기억 장치(디스크, CD 등)&lt;/b&gt;, 그리고 &lt;b&gt;입출력 장치(I/O Devices)&lt;/b&gt;로 구성됩니다. 이 구성 요소들은 &lt;b&gt;컴퓨터의 기본 골격&lt;/b&gt;을 형성하며, 이러한 구조를 &lt;b&gt;폰 노이만 구조(Von Neumann Architecture)&lt;/b&gt;라고 부릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;폰 노이만 구조란?&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;폰 노이만 구조는 존 폰 노이만(John von Neumann)이 1945년에 제안한 컴퓨터 구조로, 현재 대부분의 컴퓨터 시스템이 이 구조를 기반으로 하고 있습니다. 이 구조의 가장 큰 특징은 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;프로그램 내장 구조(Stored Program Concept)&lt;/b&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;CPU가 메모리에서 명령어를 순차적으로 읽고 실행함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;단일 버스 구조&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;명령어와 데이터가 하나의 버스를 통해 전달되어 병목 현상(Von Neumann Bottleneck)이 발생할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;CPU(Central Processing Unit)의 구조 및 역할&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;CPU는 &lt;b&gt;컴퓨터 시스템의 핵심 부품&lt;/b&gt;으로, 다음과 같은 역할을 합니다.&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;명령어 해석 및 실행&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;주기억장치에 저장된 명령어를 읽어 들여 해석하고 실행&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;산술 및 논리 연산 수행&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;계산 및 논리적인 판단 수행&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;제어 기능 수행&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;프로그램의 흐름을 제어하고, 다른 장치와의 통신을 조율&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;CPU의 주요 구성 요소&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;연산 논리 장치(ALU : Arithmetic Logic Unit)&lt;/b&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;캐시나 메모리로부터 읽어온 데이터는 레지스터(Register)라는 CPU 전용의 기억장소에 저장되며, ALU는 레지스터에 저장된 데이터를 이용하여 덧셈, 곱셈 등과 같은 산술 연산을 수행합니다.&lt;/li&gt;
&lt;li&gt;부동소숫연산장치(FPU)와 정수연산장치, 논리연산(AND, OR 등) 장치 등이 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt; 제어 장치(Control Unit)&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;제어장치는 CPU가 자신 및 주변기기들을 컨트롤하는 장치로, 프로그램의 수행 순서를 제어하는 프로그램 계수기(program counter), 현재 수행중인 명령어의 내용을 임시 기억하는 명령 레지스터(instruction register), 명령 레지스터에 수록된 명령을 해독하여 수행될 장치에 제어 신호를 보내는 명령해독기(instruction decoder)로 이루어져 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt;제어 장치 구현 방식&amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;table id=&quot;20ca4e59-e604-8043-b52a-cabe7e22ecf0&quot; style=&quot;border-collapse: collapse; width: 100%; height: 105px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px; width: 50.5814%;&quot;&gt;&lt;b&gt; 고정 배선 제어(Hardwired)Micro Program &lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 21px; width: 49.3023%;&quot;&gt;&lt;b&gt; &lt;span data-token-index=&quot;0&quot;&gt;Micro Program&lt;/span&gt; &lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;20ca4e59-e604-801c-8973-d4dc4d359157&quot; style=&quot;height: 42px;&quot;&gt;
&lt;td id=&quot;k@nn&quot; style=&quot;height: 42px; width: 50.5814%;&quot;&gt;제어신호가 Hardwired Circuit에 의해서 생성 되도록 하드웨어 구성하며 상태계수기와 PLA(Programmable Logic Array) 회로로 구성&lt;/td&gt;
&lt;td id=&quot;EL:N&quot; style=&quot;height: 42px; width: 49.3023%;&quot;&gt;발생 가능한 제어 신호들의 조합을 미리 구성하여 ROM에 저장했다가 필요 시 신호를 발생시키는 Software 방식&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;20ca4e59-e604-8083-a237-cce1d364055b&quot; style=&quot;height: 21px;&quot;&gt;
&lt;td id=&quot;k@nn&quot; style=&quot;height: 21px; width: 50.5814%;&quot;&gt;고속 처리, 고가&lt;/td&gt;
&lt;td id=&quot;EL:N&quot; style=&quot;height: 21px; width: 49.3023%;&quot;&gt;하드웨어 방식에 비해 속도도 낮고 가격도 저렴&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;20ca4e59-e604-80d5-a340-e4016a8feaa7&quot; style=&quot;height: 21px;&quot;&gt;
&lt;td id=&quot;k@nn&quot; style=&quot;height: 21px; width: 50.5814%;&quot;&gt;RISC 시스템에 적용&lt;/td&gt;
&lt;td id=&quot;EL:N&quot; style=&quot;height: 21px; width: 49.3023%;&quot;&gt;CISC에 적용&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;레지스터(Register)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;레지스터(Register)는 중앙처리장치(CPU) 내부에 있는 기억장치입니다.&lt;/li&gt;
&lt;li&gt;주로 산술 연산 논리장치에 의해 사용되는 범용 레지스터(General-Purpose Register)와 PC 등 특수 목적에 사용되는 전용 레지스터(Dedicated-Purpose Register)로 구분할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;버스(Bus)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CPU와 메모리 및 I/O 장치 간 데이터 전송 통로&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;CPU의 기능&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;CPU는 기억장치에 저장된 명령어를 인출하고 해독한 뒤, 명령어에 따라 필요한 경우에만 데이터 인출이나 연산, 결과 저장 등의 작업을 수행합니다. 명령어 처리 과정은 모든 명령어에서 공통적으로 인출과 해독을 거치며, 실행 단계에서는 명령어의 종류에 따라 동작이 달라지기 때문에 이는 CPU의 핵심 기능이자 컴퓨터 시스템의 작동 원리를 이루는 중요한 역할을 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;명령어&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;명령어는 시스템이 특정 동작을 수행시키는 작은 단위입니다. 명령어는 코드로 되어 있는데&amp;nbsp;&lt;b&gt;동작코드(Op-code: Operational Code)&lt;/b&gt;&amp;nbsp;와&amp;nbsp;&lt;b&gt;오퍼랜드(Operand)&lt;/b&gt;&amp;nbsp;로 구성되어 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;동작코드(Op-code):&lt;/b&gt; 각 명령어의 실행 동작을 구분하여 표현합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;오퍼랜드(Operand):&lt;/b&gt; 명령어의 실행에 필요한 자료나 실제 자료의 저장 위치를 의미합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&amp;lt;명령어 수행 과정&amp;gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biBsF2/dJMcabclwo2/hoOTWqYUEc2PeJA35S9w5K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biBsF2/dJMcabclwo2/hoOTWqYUEc2PeJA35S9w5K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biBsF2/dJMcabclwo2/hoOTWqYUEc2PeJA35S9w5K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiBsF2%2FdJMcabclwo2%2FhoOTWqYUEc2PeJA35S9w5K%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;1280&quot; height=&quot;720&quot; data-filename=&quot;1.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;읽기(Fetch Instruction, FI): 메모리에서 명령을 가져온다.&lt;/li&gt;
&lt;li&gt;해석(Decode Instruction, DI): 명령을 해석한다.&lt;/li&gt;
&lt;li&gt;실행(Execute Instruction, EI): 명령을 수행한다.&lt;/li&gt;
&lt;li&gt;기록(Write Back, WB): 수행한 결과를 기록한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;명령어 처리 방식&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;CISC(Complex Instruction Set Computer)&lt;/b&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;li&gt;파이프라이닝의 사용이 어렵다.&lt;/li&gt;
&lt;li&gt;복잡한 마이크로 프로그램 구조를 갖고있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;RISC(Reduced Instruction Set Computer)&lt;/b&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;메모리 Load / Store 명령만 처리하는 방식이다.&lt;/li&gt;
&lt;li&gt;파이프라이닝, 슈퍼스칼라의 사용이 가능하다.&lt;/li&gt;
&lt;li&gt;복잡한 컴파일러 구조를 갖고 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Memory&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;컴퓨터에서 말하는 메모리는 데이터를 저장하고 처리하는 장치로, 기본적으로 기억소자라 불리는 반도체로 구성되어 있습니다. 반도체는 전류를 흐르게 하거나 차단할 수 있는 특성을 가지며, 이러한 특성을 이용해 0과 1의 디지털 신호를 표현하고 임시적으로 정보를 저장할 수 있습니다. 메모리는 주로 RAM과 같이 전원이 꺼지면 데이터가 사라지는 휘발성 메모리와, ROM처럼 전원을 꺼도 내용이 유지되는 비휘발성 메모리로 나뉩니다. 이러한 메모리는 CPU가 명령어를 빠르게 처리할 수 있도록 데이터를 임시로 저장하거나 불러오는 역할을 하며, 컴퓨터 시스템의 성능에 큰 영향을 미칩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;메모리 분류별 특성&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;보조기억장치와 메모리의 차이는&amp;nbsp;&lt;b&gt;휘발성&lt;/b&gt;&amp;nbsp;입니다. 메모리는 시스템이 활성화 된 상태에서는 그 값을 기억하고 있지만 시스템이 꺼지게 되면 지워지게 됩니다. 그에 비해 보조 기억장치는 시스템이 꺼져도 기억하고 있는 값이 휘발되지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;제목 없2.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9D0bM/dJMcabi95c8/kTcd4ZwQ1HguMti4Haa8e0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9D0bM/dJMcabi95c8/kTcd4ZwQ1HguMti4Haa8e0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9D0bM/dJMcabi95c8/kTcd4ZwQ1HguMti4Haa8e0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9D0bM%2FdJMcabi95c8%2FkTcd4ZwQ1HguMti4Haa8e0%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;1280&quot; height=&quot;720&quot; data-filename=&quot;제목 없2.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;메모리 성능&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;메모리의 속도는 메모리가 CPU와 데이터를 주고받는 시간을 의미합니다. 이를 액세스라고 부르며, 단위는 ns(나노초, nano-second)로 10억 분의 1초를 나타내며 메모리 속도의 기준이 됩니다. 메모리의 속도는 빠를수록 성능이 좋다고 말할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;리프레시 시간&lt;/b&gt;이 일정 시간을 &lt;b&gt;&amp;ldquo;리프레시 시간&amp;rdquo;&lt;/b&gt;이라고 합니다. 이는 메모리에서 한 번 읽고 나서 다시 읽을 수 있기까지의 시간을 의미합니다.&lt;/li&gt;
&lt;li&gt;메모리는 일정 시간마다 재충전을 해줘야 하며, 그렇지 않으면 저장된 정보가 사라지게 됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;메모리 액세스 시간&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;메모리 액세스 시간은 데이터를 읽어오라는 명령을 받은 후, 실제로 데이터를 읽기 시작할 때까지 걸리는 시간을 말합니다. CPU가 명령어를 처리할 때 해당 명령어에 포함된 주소를 메모리에 전달하게 됩니다. 이후 메모리는 해당 주소에 저장된 값을 CPU로 전달하는데, 이 전체 과정에 걸리는 시간이 액세스 시간입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;사이클 시간 (리프레시 시간 + 메모리 액세스 시간)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;사이클 시간은 메모리 작업이 완료된 후, 다음 명령을 받을 준비가 되었다는 신호를 보낼 때까지의 시간을 의미합니다. 즉, 사이클 시간은 메모리 액세스 시간과 리프레시 시간을 더한 값입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;메모리 종류&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;주기억장치&lt;/b&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;RAM (Random Access Memory)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;RAM은 컴퓨터의 전원이 꺼지면 저장된 내용이 모두 사라지는 휘발성 메모리이기 때문에, 데이터를 영구적으로 저장하기 위해서는 보조 저장 장치가 반드시 필요합니다. RAM의 크기는 프로그램의 수행 속도에 직접적인 영향을 주며, CPU가 직접 접근할 수 있는 유일한 저장 장치입니다. RAM은 크게 SRAM과 DRAM으로 나뉘는데, SRAM은 리프레시가 필요 없고 전력 소모가 적지만 가격이 비싸며, DRAM은 리프레시가 필요하지만 저렴하고 일반적으로 더 널리 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;ROM (Read Only Memory)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;ROM은 대부분 읽기만 가능한 저장 장치로 구성되어 있으며, 전원이 꺼져도 저장된 내용이 유지되는 비휘발성 메모리입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;보조기억장치&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;자기 디스크&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;자기 디스크는 원판 표면에 있는 자성 물질의 입자 방향(북극과 남극)으로 0과 1을 표현하는 저장 매체입니다. 디스크 드라이브는 이러한 자기 디스크로부터 데이터를 읽거나 쓰는 주변 장치를 의미합니다. 자기 디스크에는 플로피 디스크(FDD)와 하드 디스크(HDD)가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;광 디스크&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;광 디스크(optical disc, OD)는 빛의 반사 특성을 이용해 데이터를 읽는 저장 매체입니다. 1세대인 CD를 시작으로, 2세대인 DVD, 3세대인 블루레이 디스크까지 발전해 왔습니다. 차세대 디스크로는 테라 디스크나 HVD 등이 존재합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;플래시 메모리&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;플래시 메모리는 전자적으로 데이터를 삭제하고 다시 쓸 수 있는 비휘발성 메모리입니다. 충격에 강하고 전력이 적게 들어 휴대용 기기에 널리 사용됩니다. 플래시 메모리에는 USB와 SSD가 있으며, SSD는 하드디스크처럼 기계적 부품이 없고 디스크나 헤더도 존재하지 않지만, 저전력, 저소음, 저중량이라는 특징을 가지고 있습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;캐시 메모리(Cache Memory)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;캐시 메모리는 CPU 내 또는 외에 존재하는 메모리로써, 메인 메모리와 CPU 간의 데이터 속도 향상을 위한 중간 버퍼 역할을 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Cache Hit&lt;/b&gt;&amp;nbsp;: CPU가 필요한 데이터가 Cache Memory 내에 들어와 있는 경우&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Cache Miss&lt;/b&gt;&amp;nbsp;: 접근하고자 하는 데이터가 없을 경우&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Hit Ratio&lt;/b&gt;&amp;nbsp;: 원하는 데이터가 Cache에 있을 확률&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 206px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;b&gt; &lt;b&gt;요소&lt;/b&gt; &lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 17px;&quot;&gt;&lt;b&gt;내용&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;b&gt;Cache 크기&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;Cache Memory의 Size의 크기가 크면 Hit Ratio율과 반비례 관계&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 42px;&quot;&gt;
&lt;td style=&quot;height: 42px;&quot;&gt;&lt;b&gt;인출 방식(Fetch Algorithm)&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 42px;&quot;&gt;&lt;b&gt;요구 인출(Demand Fetch)&lt;/b&gt;: 필요 시 요구하여 인출하는 방식&amp;nbsp;&lt;b&gt;선 인출(Pre-Fetch)&lt;/b&gt;: 예상되는 데이터를 미리 인출하는 방식&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 42px;&quot;&gt;
&lt;td style=&quot;height: 42px;&quot;&gt;&lt;b&gt;쓰기 정책(Write Policy)&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 42px;&quot;&gt;&lt;b&gt;Write-Through&lt;/b&gt;: 주기억 장치와 캐시에 동시에 쓰는 방식. Cache와 메모리의 내용이 항상 일치하며 구성 방법이 단순하다.&amp;nbsp;&lt;b&gt;Write-Back&lt;/b&gt;: 데이터 변경만 캐시에 기록하는 방식. 구성방법이 복잡하다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 42px;&quot;&gt;
&lt;td style=&quot;height: 42px;&quot;&gt;&lt;b&gt;교체(Replace) 알고리즘&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 42px;&quot;&gt;Cache Miss 발생시 기존 메모리와 교체하는 방식. FIFO, LRU, LFU, Random, Optimal Belady&amp;rsquo;s MIN(향후 가장 참조 되지 않을 블록을 교체) 등이 있다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 42px;&quot;&gt;
&lt;td style=&quot;height: 42px;&quot;&gt;&lt;b&gt;사상(Mapping) 기법&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 42px;&quot;&gt;주기억장치의 블록을 적재할 캐시 내의 위치를 지정하는 방법. 직접 매핑(direct mapping), 어소시에이티브 매핑(associative mapping), 셋 어소시에이티브 매핑(set associative mapping) 등이 있다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Etc/Theoretical Computer Science</category>
      <author>N_HYUN</author>
      <guid isPermaLink="true">https://hyunspaceworkshop.tistory.com/27</guid>
      <comments>https://hyunspaceworkshop.tistory.com/27#entry27comment</comments>
      <pubDate>Fri, 13 Mar 2026 17:17:10 +0900</pubDate>
    </item>
    <item>
      <title>[내일배움캠프] - DAY21 클라우드 아키텍처 설계 &amp;amp; 배포 프로젝트 트러블 슈팅</title>
      <link>https://hyunspaceworkshop.tistory.com/26</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;트러블 슈팅&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. &quot;/actuator/info&quot; 엔드포인트 미노출 문제&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;현상&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;문제 2-2의 &lt;b&gt;&lt;span data-token-index=&quot;0&quot;&gt;Actuator Info 확장&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;span data-token-index=&quot;0&quot;&gt;문제에서 애플리케이션 배포 후&amp;nbsp; &lt;b&gt;http://EC2_PUBLIC_IP:8080/actuator/info&lt;/b&gt; 로접속 하였지만 팀 info 엔드포인트 내용이 표시되지 않는 문제가 발생하였습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;647&quot; data-origin-height=&quot;365&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2MLmd/dJMcaaLhKJc/pPiQLp2WFLR4blVIlIxfGK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2MLmd/dJMcaaLhKJc/pPiQLp2WFLR4blVIlIxfGK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2MLmd/dJMcaaLhKJc/pPiQLp2WFLR4blVIlIxfGK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2MLmd%2FdJMcaaLhKJc%2FpPiQLp2WFLR4blVIlIxfGK%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;647&quot; height=&quot;365&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;647&quot; data-origin-height=&quot;365&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;원인&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Spring Boot 기본 설정&lt;/b&gt;에서는 &lt;b&gt;Actuator의 info 엔드포인트&lt;/b&gt;가 기본적으로 활성화되어 있지 않습니다. 따라서 애플리케이션에 &lt;b&gt;info&lt;/b&gt; 관련 정보를 application.yml에 추가하더라도, &lt;b&gt;별도의 활성화 설정이 없으면&lt;/b&gt; 해당 엔드포인트는 &lt;b&gt;외부에서&lt;/b&gt; &lt;b&gt;접근할 수 없습니다.&lt;/b&gt; 예를 들어, 팀 정보를 나타내는 team 파라미터를 설정 파일에 작성했더라도, &lt;b&gt;management.endpoint.info.enabled&lt;/b&gt; 또는 &lt;b&gt;info.env.enabled&lt;/b&gt; 옵션이 활성화되지 않으면 &lt;b&gt;/actuator/info&lt;/b&gt;에 해당 정보가 노출되지 않습니다. 이로 인해 &lt;b&gt;엔드포인트에 접근 시 글로벌 서버 오류가 발생&lt;/b&gt;하거나, &lt;b&gt;정보가 표시되지 않는 현상&lt;/b&gt;이 발생하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;해결&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;application.yml 에 아래 이미지와 같이 설정을 추가하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;888&quot; data-origin-height=&quot;447&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5Bc9g/dJMcaflwDT0/kGhZjXmZlKpyNUQR0unsLk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5Bc9g/dJMcaflwDT0/kGhZjXmZlKpyNUQR0unsLk/img.png&quot; data-alt=&quot;￼&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5Bc9g/dJMcaflwDT0/kGhZjXmZlKpyNUQR0unsLk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5Bc9g%2FdJMcaflwDT0%2FkGhZjXmZlKpyNUQR0unsLk%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;888&quot; height=&quot;447&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;888&quot; data-origin-height=&quot;447&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;￼&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;추가 후 아래와 같이 정상적으로 출력되는것을 확인할 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;661&quot; data-origin-height=&quot;536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BNefJ/dJMcacWCfAP/9JkTrc6X9RZFkd4VeOIdPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BNefJ/dJMcacWCfAP/9JkTrc6X9RZFkd4VeOIdPK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BNefJ/dJMcacWCfAP/9JkTrc6X9RZFkd4VeOIdPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBNefJ%2FdJMcacWCfAP%2F9JkTrc6X9RZFkd4VeOIdPK%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;661&quot; height=&quot;536&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;661&quot; data-origin-height=&quot;536&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. EC2에서 Spring Boot 프로덕션 프로퍼티 적용 실패로 인한 서버 시작 오류&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;현상&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1341&quot; data-origin-height=&quot;700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zXFDT/dJMcacI7BIC/Er9Ib0NgZDpQSaANyyRjyK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zXFDT/dJMcacI7BIC/Er9Ib0NgZDpQSaANyyRjyK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zXFDT/dJMcacI7BIC/Er9Ib0NgZDpQSaANyyRjyK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzXFDT%2FdJMcacI7BIC%2FEr9Ib0NgZDpQSaANyyRjyK%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;1341&quot; height=&quot;700&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1341&quot; data-origin-height=&quot;700&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;EC2&lt;/b&gt; 서버에서 Spring Boot 애플리케이션을 실행하고 &lt;b&gt;/actuator/info&lt;/b&gt; 엔드포인트에 접근할 때 서버 에러가 발생하였습니다. 로그를 확인한 결과, Parameter Store에 접근하는 과정에서 &lt;b&gt;AccessDeniedException&lt;/b&gt;이 발생하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;원인&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;application-prod.yml&lt;/b&gt;에는 Parameter Store에서 &lt;b&gt;DB 및 기타 민감 정보를 가져오도록 설정&lt;/b&gt;되어 있고, &lt;b&gt;application-local.yml&lt;/b&gt;에는 &lt;b&gt;H2 DB 설정과 &quot;optional:aws-parameterstore:&quot;만 지정&lt;/b&gt;되어 있습니다. EC2 서버 실행 시 환경 변수로 prod 프로필이 활성화되지 않으면 Spring Boot가 local 프로필을 로드하게 되며, 이 경우 실제 prod Parameter Store 경로&lt;b&gt;(/ca-project/prod/)&lt;/b&gt;에 &lt;b&gt;접근하지 못해 오류가 발생&lt;/b&gt;합니다. 즉, &lt;b&gt;프로파일을 지정하지 않아 잘못된 yml이 로드&lt;/b&gt;되는 것이 &lt;b&gt;문제&lt;/b&gt;였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;해결&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt; EC2&lt;/b&gt; 실행 시 &lt;b&gt;SPRING_PROFILES_ACTIVE&lt;/b&gt; 환경 변수를 명시적으로 prod로 지정하여 오류를 수정하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-03-13 011723.png&quot; data-origin-width=&quot;1360&quot; data-origin-height=&quot;441&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdm9Tb/dJMcajnQDfD/YOad44mlIvFsksJCEm79u0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdm9Tb/dJMcajnQDfD/YOad44mlIvFsksJCEm79u0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdm9Tb/dJMcajnQDfD/YOad44mlIvFsksJCEm79u0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbdm9Tb%2FdJMcajnQDfD%2FYOad44mlIvFsksJCEm79u0%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;1360&quot; height=&quot;441&quot; data-filename=&quot;스크린샷 2026-03-13 011723.png&quot; data-origin-width=&quot;1360&quot; data-origin-height=&quot;441&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1258&quot; data-origin-height=&quot;580&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbztV9/dJMcai3yN2C/XK0PqslPVsNzWdQc5HJpRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbztV9/dJMcai3yN2C/XK0PqslPVsNzWdQc5HJpRk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbztV9/dJMcai3yN2C/XK0PqslPVsNzWdQc5HJpRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbztV9%2FdJMcai3yN2C%2FXK0PqslPVsNzWdQc5HJpRk%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;1258&quot; height=&quot;580&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1258&quot; data-origin-height=&quot;580&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;정상적으로 팀 이름이 출력되는 것을 확인할 수 있었으며, application-prod.yml이 올바르게 적용되어 서버가 정상적으로 동작함을 검증했습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. 중첩 컨트롤러에서 @RequestMapping 누락으로 인한 엔드포인트 접근 오류 &lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;현상&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1268&quot; data-origin-height=&quot;788&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bB2gXJ/dJMcaaR4IOX/CmZZzaQ5dhpl48N2ONYCf0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bB2gXJ/dJMcaaR4IOX/CmZZzaQ5dhpl48N2ONYCf0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bB2gXJ/dJMcaaR4IOX/CmZZzaQ5dhpl48N2ONYCf0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbB2gXJ%2FdJMcaaR4IOX%2FCmZZzaQ5dhpl48N2ONYCf0%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;1268&quot; height=&quot;788&quot; data-origin-width=&quot;1268&quot; data-origin-height=&quot;788&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt; EC2&lt;/b&gt;에서 Spring Boot 애플리케이션을 실행하고 포스트맨으로 &lt;b&gt;/api/members/{id}/profile-image&lt;/b&gt; 엔드포인트에 파일 업로드 요청을 보냈을 때 요청 처리 오류가 발생하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;원인&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-03-13 020812.png&quot; data-origin-width=&quot;916&quot; data-origin-height=&quot;1186&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cju2BX/dJMcabckJ3N/jxPupqj0LT1MxS7Tw4AqdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cju2BX/dJMcabckJ3N/jxPupqj0LT1MxS7Tw4AqdK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cju2BX/dJMcabckJ3N/jxPupqj0LT1MxS7Tw4AqdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcju2BX%2FdJMcabckJ3N%2FjxPupqj0LT1MxS7Tw4AqdK%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;916&quot; height=&quot;1186&quot; data-filename=&quot;스크린샷 2026-03-13 020812.png&quot; data-origin-width=&quot;916&quot; data-origin-height=&quot;1186&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;클라우드 아키텍처 설계 및 배포에 중점을 두다 보니, &lt;b&gt;MemberController&lt;/b&gt;와 &lt;b&gt;FileController&lt;/b&gt;를 각각 분리하지 않고 하나의 클래스 안에서 &lt;b&gt;중첩 컨트롤러 형태로 관리하도록 설계&lt;/b&gt;하였습니다. 그러나 FileController에 별도로 &lt;b&gt;@RequestMapping(&quot;/api/members&quot;)&lt;/b&gt;를 선언하지 않아 &lt;b&gt;Spring이 해당 경로를 인식하지 못한 것이 문제&lt;/b&gt;였습니다. 이전 프로젝트에서는 각 컨트롤러를 분리하여 작성했지만, 이번 프로젝트에서는 &lt;b&gt;아키텍처 단순화와 배포 편의를 위해 중첩 컨트롤러 형태로 처리&lt;/b&gt;하다 보니 발생한 실수였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;해결&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-03-13 021049.png&quot; data-origin-width=&quot;935&quot; data-origin-height=&quot;563&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kCxQf/dJMcafTmPj3/QZcqKA3FQCKlyERR543EH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kCxQf/dJMcafTmPj3/QZcqKA3FQCKlyERR543EH1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kCxQf/dJMcafTmPj3/QZcqKA3FQCKlyERR543EH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkCxQf%2FdJMcafTmPj3%2FQZcqKA3FQCKlyERR543EH1%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;935&quot; height=&quot;563&quot; data-filename=&quot;스크린샷 2026-03-13 021049.png&quot; data-origin-width=&quot;935&quot; data-origin-height=&quot;563&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;FileController 클래스에도 &lt;b&gt;@RequestMapping(&quot;/api/members&quot;)&lt;/b&gt;를 명시적으로 선언하여 각 컨트롤러가 동일한 기본 경로를 올바르게 인식하도록 수정하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1262&quot; data-origin-height=&quot;757&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TocWd/dJMcafy4GoZ/HhvdsL3EIiFYdwg9QSFj1K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TocWd/dJMcafy4GoZ/HhvdsL3EIiFYdwg9QSFj1K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TocWd/dJMcafy4GoZ/HhvdsL3EIiFYdwg9QSFj1K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTocWd%2FdJMcafy4GoZ%2FHhvdsL3EIiFYdwg9QSFj1K%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;1262&quot; height=&quot;757&quot; data-origin-width=&quot;1262&quot; data-origin-height=&quot;757&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이후 &lt;b&gt;Postman으로 요청&lt;/b&gt;을 보내자 &lt;b&gt;정상적으로 key 값이 반환&lt;/b&gt;되었으며, &lt;b&gt;컨트롤러가 의도한 대로 동작&lt;/b&gt;함을 확인할 수 있었습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>TIL &amp;amp; 트러블 슈팅</category>
      <author>N_HYUN</author>
      <guid isPermaLink="true">https://hyunspaceworkshop.tistory.com/26</guid>
      <comments>https://hyunspaceworkshop.tistory.com/26#entry26comment</comments>
      <pubDate>Thu, 12 Mar 2026 00:12:14 +0900</pubDate>
    </item>
    <item>
      <title>[내일배움캠프] - DAY20 IP와 네트워크 통신에 대해 알아보자</title>
      <link>https://hyunspaceworkshop.tistory.com/25</link>
      <description>&lt;h2 data-end=&quot;474&quot; data-start=&quot;359&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;글을 시작하며..&lt;/b&gt;&lt;/h2&gt;
&lt;p data-end=&quot;474&quot; data-start=&quot;359&quot; data-ke-size=&quot;size18&quot;&gt;오늘은 &lt;b&gt;IP와 네트워크에 대해 알아보는 시간을 가져보겠습니다. &lt;/b&gt;IP는 네트워크에서 각 장치를 구분하기 위해 사용되는 중요한 개념이며, 우리가 인터넷을 통해 데이터를 주고받을 때 필수적으로 사용됩니다. 또한 이번 글에서는 &lt;b&gt;지난 시간에 공부했던 HTTP와 HTTPS의 개념도 함께 다시 정리해보려고 합니다.&lt;/b&gt; IP가 실제로 어떻게 사용되는지 이해하기 위해서는 HTTP와 HTTPS와 같은 통신 방식에 대한 이해도 함께 필요하기 때문입니다.&lt;/p&gt;
&lt;p data-end=&quot;474&quot; data-start=&quot;359&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;701&quot; data-start=&quot;626&quot; data-ke-size=&quot;size18&quot;&gt;이번 글에서는 &lt;b&gt;IP의 기본 개념을 먼저 살펴보고, 이어서 HTTP와 HTTPS의 차이점 및 네트워크&lt;/b&gt;에 대해서도 함께 정리해보겠습니다.&lt;/p&gt;
&lt;p data-end=&quot;701&quot; data-start=&quot;626&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;IP&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;IP 주소&lt;/b&gt;는 &lt;b&gt;인터넷에 연결된 각 장치(PC, 스마트폰, 서버 등)를 식별하기 위해 부여되는 고유한 숫자 주소&lt;/b&gt;입니다. 흔히 사람의 지문에 비유되지만, 사실상 &lt;b&gt;기기 자체의 고유 번호가 아니라, 기기가 접속한 네트워크(인터넷 접속 지점)의 주소&lt;/b&gt;를 나타냅니다. 예를 들어 동일한 노트북을 집&amp;middot;카페&amp;middot;회사에서 각각 다른 네트워크에 연결하면 IP 주소도 달라집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;IP 주소의 구조&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;집 주소가 &lt;b&gt;&amp;ldquo;서울/강남구/테헤란로/44길&amp;rdquo; &lt;/b&gt;처럼 계층적으로 구분되듯이, IP 주소도 일정한 형식을 갖습니다. 현재 가장 널리 쓰이는 IP 주소 체계는 &lt;b&gt;IPv4&lt;/b&gt;이며, 123.123.123.123 처럼 &lt;b&gt;0~255 범위의 숫자 4개(옥텟)를 점(.)으로 구분&lt;/b&gt;합니다. IPv4 주소는 0.0.0.0부터 255.255.255.255까지 존재하며, 약 &lt;b&gt;42억 개의 고유 주소&lt;/b&gt;를 제공할 수 있습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;IPv4의 한계와 IPv6&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;스마트폰, 태블릿, IoT(사물인터넷) 등 다양한 기기가 등장하면서 IPv4 주소가 빠르게 고갈되고 있습니다. 이를 해결하기 위해 등장한 것이 &lt;b&gt;IPv6&lt;/b&gt;입니다. IPv6 주소 1234:5678:9ABC:DEF0:1234:5678:9ABC:DEF0처럼 &lt;b&gt;16진수(0~F) 네 자리 블록을 8개, 콜론(:)으로 구분&lt;/b&gt;하는 형태를 사용합니다. IPv6는 사실상 거의 무한에 가까운 주소 공간을 제공해 향후 기기 증가에도 대응할 수 있습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;그 밖의 특징&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;공인(Public) IP / 사설(Private) IP:&lt;/b&gt; 가정&amp;middot;회사 내부 네트워크에서 쓰이는 IP(사설)와 인터넷에서 직접 식별되는 IP(공인)가 구분됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;고정(Static) IP / 동적(Dynamic) IP:&lt;/b&gt; 일부 서버는 변하지 않는 고정 IP를 사용하지만, 일반 사용자에게는 ISP가 주기적으로 바꾸는 동적 IP가 할당됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;NAT(Network Address Translation):&lt;/b&gt; IPv4 주소 부족 문제를 완화하기 위해, 여러 기기가 하나의 공인 IP를 공유하도록 해 주는 기술입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;쉽게 말해 IP 주소는 &lt;b&gt;&amp;ldquo;네트워크에서 기기(혹은 네트워크 종단)를 구분하는 집주소 같은 번호&amp;rdquo;&lt;/b&gt;이고, IPv6는 미래를 위한 새로운 주소 체계입니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;포트(Port)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-end=&quot;232&quot; data-start=&quot;40&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;포트(Port)&lt;/b&gt;는 컴퓨터 네트워크에서 데이터가 들어오고 나가는 &lt;b&gt;논리적인 통신 종단점&lt;/b&gt;을 의미하며, &lt;b&gt;0부터 65535까지의 번호 범위&lt;/b&gt;를 가집니다. 네트워크 통신에서 &lt;b&gt;IP 주소가 특정 컴퓨터(서버나 장치)를 식별한다면, 포트 번호는 그 컴퓨터 내부에서 실행 중인 특정 애플리케이션이나 서비스&lt;/b&gt;를 구분하는 역할을 합니다. 예를 들어 하나의 서버에는 웹 서버, 데이터베이스, 메일 서버 등 여러 서비스가 동시에 실행될 수 있는데, 이때 포트 번호를 통해 &lt;b&gt;어떤 서비스와 통신할지 구분&lt;/b&gt;하게 됩니다.&lt;/p&gt;
&lt;p data-end=&quot;232&quot; data-start=&quot;40&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;351&quot; data-start=&quot;335&quot; data-ke-size=&quot;size18&quot;&gt;일반적으로 웹 서비스에서는&amp;nbsp; 다음과 같이 잘 알려진 포트 번호를 사용하여 데이터를 주고받습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;449&quot; data-start=&quot;352&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;381&quot; data-start=&quot;352&quot; data-section-id=&quot;ei6mfl&quot;&gt;&lt;b&gt;80번 포트&lt;/b&gt;를 사용하는 &lt;b&gt;HTTP&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;449&quot; data-start=&quot;382&quot; data-section-id=&quot;4s8vob&quot;&gt;&lt;b&gt;443번 포트&lt;/b&gt;를 사용하는 &lt;b&gt;HTTPS&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;651&quot; data-start=&quot;451&quot; data-ke-size=&quot;size18&quot;&gt;쉽게 비유하면 &lt;b&gt;IP 주소는 &amp;ldquo;서울 / 강남구 / 테헤란로 / 44길&amp;rdquo;과 같은 건물의 주소&lt;/b&gt;라고 볼 수 있고, &lt;b&gt;포트 번호는 그 건물 안에 있는 특정 호수나 사무실 번호&lt;/b&gt;라고 생각할 수 있습니다. 즉, IP 주소가 &lt;b&gt;어떤 컴퓨터로 갈지&lt;/b&gt;를 결정한다면, 포트 번호는 &lt;b&gt;그 컴퓨터 안에서 어떤 프로그램과 통신할지&lt;/b&gt;를 결정한다고 볼 수 있습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;도메인과 DNS&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;도메인(Domain)과 IP 주소&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;IP 주소는 123.123.123.123 같은 숫자로 이루어진 인터넷상의 식별자입니다. 그러나 숫자만으로 된 주소는 사람이 기억하기 어렵기 때문에, 이를 대신할 수 있는 &lt;b&gt;도메인(Domain)&lt;/b&gt; 개념이 도입되었습니다. 예를 들어 naver.com, google.com과 같은 도메인은 해당 서비스의 이름을 반영하고 있어 훨씬 기억하기 쉽습니다. 도메인은 &lt;b&gt;도메인 등록 대행업체(Registrar)&lt;/b&gt; 를 통해 구매할 수 있으며, 국내에는 가비아&amp;middot;후이즈 등이 있고, 해외에는 GoDaddy 같은 업체가 있습니다. 다만 도메인은 그 자체가 웹사이트의 위치를 알려주는 것이 아니라, &lt;b&gt;사람이 쉽게 기억할 수 있는 이름&lt;/b&gt;을 제공하는 역할을 합니다. 실제 통신을 위해서는 여전히 IP 주소가 필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;DNS(Domain Name System)의 역할&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;도메인과 실제 IP 주소를 연결해 주는 시스템이 바로 &lt;b&gt;DNS&lt;/b&gt;입니다. DNS는 전 세계에 분산된 거대한 데이터베이스로, 도메인과 해당 도메인에 대응하는 IP 주소가 저장되어 있습니다. 사용자가 브라우저 주소창에 도메인을 입력하면, 브라우저는 다음과 같은 과정을 거쳐 실제 IP 주소를 알아냅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;사용자가 www.naver.com을 입력하면, 브라우저는 먼저 &lt;b&gt;로컬 캐시(브라우저&amp;middot;운영체제 캐시)&lt;/b&gt; 에 해당 IP 주소가 저장되어 있는지 확인합니다.&lt;/li&gt;
&lt;li&gt;캐시에 없으면, &lt;b&gt;리커시브 DNS 서버(ISP나 구글 DNS 같은 공용 DNS)&lt;/b&gt; 에 질의가 전달됩니다.&lt;/li&gt;
&lt;li&gt;리커시브 DNS는 순차적으로 &lt;b&gt;루트 네임서버 &amp;rarr; TLD(Top-Level Domain) 서버 &amp;rarr; 권한 네임서버(Authoritative Server)&lt;/b&gt; 를 거쳐 최종적으로 naver.com의 실제 IP 주소를 찾아옵니다.&lt;/li&gt;
&lt;li&gt;찾은 IP 주소를 브라우저에 전달하면, 브라우저는 해당 IP 주소의 웹 서버와 연결해 웹페이지를 가져옵니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;정리&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;도메인&lt;/b&gt;은 사람이 기억하기 쉬운 인터넷 주소(문자 형태)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;IP 주소&lt;/b&gt;는 실제 네트워크에서 기기를 식별하는 숫자 주소&lt;/li&gt;
&lt;li&gt;&lt;b&gt;DNS&lt;/b&gt;는 도메인을 IP 주소로 변환해 주는 시스템&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;즉, 사용자가 naver.com 같은 도메인을 입력하면, DNS가 이를 xxx.xxx.xxx.xxx 형태의 IP 주소로 바꿔 주고, 브라우저는 해당 서버에 접속해 웹사이트를 표시하게 되는 것입니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;HTTP와 HTTPS&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;HTTP&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;HTTP(HyperText Transfer Protocol)&lt;/b&gt; 는 웹에서 데이터를 주고받기 위해 사용되는 &lt;b&gt;애플리케이션 계층 프로토콜&lt;/b&gt;입니다. 쉽게 말해, 네트워크로 연결된 클라이언트(브라우저 등)와 서버가 &lt;b&gt;어떤 방식으로 대화할지 약속해 놓은 규칙&lt;/b&gt;입니다. 명함에서 전화번호 앞에 Tel:이나 Fax:를 붙여 연락 방법을 구분하듯, 인터넷에서는 http://라는 접두사를 붙여 &lt;b&gt;&amp;ldquo;이 주소는 HTTP 규칙으로 통신한다&amp;rdquo;&lt;/b&gt; 라고 알려줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;요청과 응답&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;HTTP는 기본적으로 &lt;b&gt;클라이언트의 요청(Request)&lt;/b&gt; 과 &lt;b&gt;서버의 응답(Response)&lt;/b&gt; 으로 이루어집니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클라이언트(브라우저)는 서버에 &amp;ldquo;편지&amp;rdquo;처럼 요청 메시지를 보냅니다. 이 안에는 &amp;ldquo;어떤 문서를 달라&amp;rdquo;, &amp;ldquo;어떤 작업을 처리해 달라&amp;rdquo; 같은 명령이 담깁니다.&lt;/li&gt;
&lt;li&gt;서버는 이 요청을 확인한 뒤, 허가된 요청이라면 결과(HTML, 이미지, JSON 데이터 등)를 담아 응답하고, 잘못된 요청이라면 오류 메시지를 반환합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;HTTP를 편지에 비유하는 이유는, &lt;b&gt;각각의 요청과 응답이 독립적이고 개별적으로 처리되기 때문&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;HTTP의 특징&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Stateless(무상태성)&lt;/b&gt;: HTTP는 이전 요청의 상태를 기억하지 않습니다. 즉, 매 요청은 서로 독립적입니다. (로그인 상태 유지 같은 기능은 쿠키&amp;middot;세션&amp;middot;토큰 같은 별도 기술이 필요합니다.)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;유연한 데이터 전송&lt;/b&gt;: HTML, 이미지, 동영상, JSON 등 다양한 형태의 데이터를 교환할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;확장성&lt;/b&gt;: HTTP 요청에는 GET, POST, PUT, DELETE 같은 메서드가 있고, 응답에는 200 OK, 404 Not Found, 500 Internal Server Error 같은 상태 코드가 포함되어 의미를 명확히 전달합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;정리&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;HTTP&lt;/b&gt;는 웹에서 클라이언트와 서버가 대화하는 규칙(프로토콜)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;요청과 응답&lt;/b&gt; 구조로 동작하며, 각 요청은 독립적&lt;/li&gt;
&lt;li&gt;&lt;b&gt;무상태(stateless)&lt;/b&gt; 특징을 가지며, 쿠키&amp;middot;세션&amp;middot;토큰으로 보완 가능&lt;/li&gt;
&lt;li&gt;HTTPS는 HTTP에 보안을 강화한 방식&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;HTTPS&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;HTTPS(HyperText Transfer Protocol Secure)&lt;/b&gt;는 기존의 &lt;b&gt;HTTP에 보안 계층(SSL/TLS)&lt;/b&gt; 을 덧붙인 프로토콜입니다. 즉, 클라이언트와 서버 간에 주고받는 데이터를 암호화하여 &lt;b&gt;도청, 위&amp;middot;변조, 피싱 공격&lt;/b&gt;으로부터 안전하게 보호합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;HTTPS의 동작 원리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;HTTPS는 &lt;b&gt;SSL/TLS 암호화 프로토콜&lt;/b&gt;을 사용합니다. 그 과정은 대략 다음과 같습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;클라이언트가 접속 요청&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;브라우저가 서버에 HTTPS 요청을 보냅니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;인증서 교환&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;서버는 자신의 &lt;b&gt;SSL/TLS 인증서(공개키 포함)&lt;/b&gt; 를 클라이언트에 전달합니다. 이 인증서는 신뢰할 수 있는 기관(CA, Certificate Authority)이 발급한 것입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;키 교환 및 암호화 채널 생성&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;클라이언트는 서버의 공개키를 사용해 세션 키(대칭키)를 안전하게 전달하고, 이후 모든 통신은 이 세션 키를 사용한 &lt;b&gt;대칭키 암호화&lt;/b&gt;로 이루어집니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;보안 통신 시작&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;클라이언트와 서버는 암호화된 채널을 통해 요청과 응답을 주고받습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;HTTPS의 특징&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;데이터 암호화&lt;/b&gt;: 제3자가 네트워크를 가로채더라도 내용을 읽을 수 없음.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;데이터 무결성 보장&lt;/b&gt;: 중간에 데이터가 변조되면 탐지 가능.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;인증(Authentication)&lt;/b&gt;: 인증서를 통해 클라이언트가 접속한 서버가 신뢰할 수 있는 서버임을 확인.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;HTTP vs HTTPS 비교&lt;/b&gt;&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 105px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 12.1705%; height: 21px;&quot;&gt;&lt;b&gt; &lt;span data-token-index=&quot;0&quot;&gt;구분&lt;/span&gt; &lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 41.7054%; height: 21px;&quot;&gt;&lt;b&gt; &lt;span data-token-index=&quot;0&quot;&gt;HTTP&lt;/span&gt; &lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 46.124%; height: 21px;&quot;&gt;&lt;b&gt; &lt;span data-token-index=&quot;0&quot;&gt;HTTPS&lt;/span&gt; &lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 12.1705%; height: 21px;&quot;&gt;&lt;b&gt; &lt;span data-token-index=&quot;0&quot;&gt;보안&lt;/span&gt; &lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 41.7054%; height: 21px;&quot;&gt;없음 (평문 전송)&lt;/td&gt;
&lt;td style=&quot;width: 46.124%; height: 21px;&quot;&gt;SSL/TLS 암호화로 안전한 통신 제공&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 12.1705%; height: 21px;&quot;&gt;&lt;b&gt; &lt;span data-token-index=&quot;0&quot;&gt;포트 번호&lt;/span&gt; &lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 41.7054%; height: 21px;&quot;&gt;80&lt;/td&gt;
&lt;td style=&quot;width: 46.124%; height: 21px;&quot;&gt;443&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 12.1705%; height: 21px;&quot;&gt;&lt;b&gt; &lt;span data-token-index=&quot;0&quot;&gt;속도&lt;/span&gt; &lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 41.7054%; height: 21px;&quot;&gt;빠름 (암호화 과정 없음)&lt;/td&gt;
&lt;td style=&quot;width: 46.124%; height: 21px;&quot;&gt;약간 느릴 수 있음 (암호화/복호화 과정 때문)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 12.1705%; height: 21px;&quot;&gt;&lt;b&gt; &lt;span data-token-index=&quot;0&quot;&gt;사용 예시&lt;/span&gt; &lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 41.7054%; height: 21px;&quot;&gt;단순한 웹 테스트, 내부망 용도&lt;/td&gt;
&lt;td style=&quot;width: 46.124%; height: 21px;&quot;&gt;온라인 쇼핑, 로그인, 결제, 민감 데이터 전송&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;정리&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;HTTPS = HTTP + SSL/TLS 보안 계층&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;데이터를 암호화하여 &lt;b&gt;기밀성, 무결성, 인증&lt;/b&gt;을 보장&lt;/li&gt;
&lt;li&gt;현대 웹 서비스에서는 보안을 위해 사실상 &lt;b&gt;모든 사이트가 HTTPS 사용&lt;/b&gt;을 기본으로 하고 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;네트워크(Network)란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;네트워크&lt;/b&gt;는 컴퓨터, 스마트폰, 태블릿, 서버 등 &lt;b&gt;여러 디지털 기기들이 서로 연결되어 데이터를 주고받는 통신 구조&lt;/b&gt;를 말합니다. 가장 대표적인 예가 &lt;b&gt;인터넷&lt;/b&gt;으로, 전 세계 수십억 개의 장치들이 연결되어 정보를 주고받는 &lt;b&gt;거대한 네트워크&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;네트워크의 목적&lt;/b&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;정보 공유&lt;/b&gt; &amp;ndash; 문서, 이미지, 영상 등 데이터를 서로 주고받음&lt;/li&gt;
&lt;li&gt;&lt;b&gt;자원 공유&lt;/b&gt; &amp;ndash; 프린터, 저장장치, 소프트웨어 등을 여러 기기가 함께 사용&lt;/li&gt;
&lt;li&gt;&lt;b&gt;통신&lt;/b&gt; &amp;ndash; 이메일, 채팅, 전화 등 실시간 의사소통&lt;/li&gt;
&lt;li&gt;&lt;b&gt;원격 접근&lt;/b&gt; &amp;ndash; 다른 컴퓨터나 서버에 접속해 작업 수행&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;네트워크의 기본 구성 요소&lt;/b&gt;&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 88.4882%; height: 266px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;b&gt;호스트(기기)&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;컴퓨터, 스마트폰, 태블릿, 서버 등 네트워크에 연결된 모든 장치&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;b&gt;라우터(Router)&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;여러 네트워크를 연결해주는 장치 (예: 집 와이파이 공유기)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;b&gt;스위치(Switch)&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;같은 네트워크 내 여러 기기를 효율적으로 연결해줌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;b&gt;모뎀(Modem)&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;인터넷 신호를 컴퓨터가 이해할 수 있도록 변환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;&lt;b&gt;전송 매체&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 21px;&quot;&gt;데이터를 전달하는 통로 (예: LAN 케이블, 와이파이 등)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;네트워크의 종류&lt;/b&gt;&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 88.9543%; height: 229px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 43px;&quot;&gt;
&lt;td style=&quot;height: 43px;&quot;&gt;&lt;b&gt;LAN (근거리 통신망)&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 43px;&quot;&gt;집, 학교, 사무실 등 좁은 범위 내 연결된 네트워크&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 43px;&quot;&gt;
&lt;td style=&quot;height: 43px;&quot;&gt;&lt;b&gt;WAN (광역 통신망)&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 43px;&quot;&gt;도시, 국가, 전 세계를 연결하는 네트워크 (인터넷 포함)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 43px;&quot;&gt;
&lt;td style=&quot;height: 43px;&quot;&gt;&lt;b&gt;WLAN (무선 LAN)&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 43px;&quot;&gt;와이파이를 이용한 무선 네트워크&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 43px;&quot;&gt;
&lt;td style=&quot;height: 43px;&quot;&gt;&lt;b&gt;PAN (개인 영역망)&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 43px;&quot;&gt;블루투스, 테더링 등 개인 기기 간 연결&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;네트워크의 작동 방식 (예시)&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;예: 사용자(수강생)가 내일배움캠프 웹에서 강의 영상을 시청할려고 할 때&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-section-id=&quot;cl0egd&quot; data-start=&quot;40&quot; data-end=&quot;73&quot;&gt;사용자가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;내일배움캠프 웹사이트에 접속합니다.&lt;/b&gt;&lt;/li&gt;
&lt;li data-section-id=&quot;1m5afsv&quot; data-start=&quot;74&quot; data-end=&quot;135&quot;&gt;강의 목록에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;원하는 강의를 클릭하여 &amp;ldquo;이 강의 영상을 보여줘!&amp;rdquo;라는 요청을 서버에 보냅니다.&lt;/b&gt;&lt;/li&gt;
&lt;li data-section-id=&quot;1efsri2&quot; data-start=&quot;136&quot; data-end=&quot;186&quot;&gt;요청은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;와이파이 &amp;rarr; 라우터 &amp;rarr; 인터넷망 &amp;rarr; 내일배움캠프 서버&lt;/b&gt;로 전달됩니다.&lt;/li&gt;
&lt;li data-section-id=&quot;13z3zam&quot; data-start=&quot;187&quot; data-end=&quot;234&quot;&gt;서버는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;요청된 강의 영상을 찾아 사용자에게 응답 데이터를 전송합니다.&lt;/b&gt;&lt;/li&gt;
&lt;li data-section-id=&quot;pybmqt&quot; data-start=&quot;235&quot; data-end=&quot;285&quot;&gt;전달된 데이터가 사용자 기기로 도착하면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;강의 영상이 화면에 나타나 재생됩니다.&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;b&gt;이 모든 과정이 네트워크를 통해 이루어집니다.&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;핵심 요약&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;네트워크는 &lt;b&gt;기기 간 데이터 통신 시스템&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;정보 공유&lt;/b&gt;와 &lt;b&gt;자원 활용&lt;/b&gt;, &lt;b&gt;실시간 통신&lt;/b&gt;을 가능하게 함&lt;/li&gt;
&lt;li&gt;유선 또는 무선으로 연결되며, 구성 요소와 통신 규칙(프로토콜)에 따라 작동&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>TIL &amp;amp; 트러블 슈팅</category>
      <author>N_HYUN</author>
      <guid isPermaLink="true">https://hyunspaceworkshop.tistory.com/25</guid>
      <comments>https://hyunspaceworkshop.tistory.com/25#entry25comment</comments>
      <pubDate>Tue, 10 Mar 2026 00:34:51 +0900</pubDate>
    </item>
  </channel>
</rss>