<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>하면 된다</title>
    <link>https://ssoonearth.tistory.com/</link>
    <description>궁금한 건 못 참아~
개발자 준비생의 삽질 기록장</description>
    <language>ko</language>
    <pubDate>Fri, 24 Jul 2026 18:41:12 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>ssoonearth</managingEditor>
    <item>
      <title>패스트캠퍼스 환급 챌린지 48일차 : 9개 도메인 프로젝트로 끝내는 백엔드 웹 개발 (Java/Spring) 초격차 패키지 Online 강의 후기</title>
      <link>https://ssoonearth.tistory.com/48</link>
      <description>&lt;p data-ke-size=&quot;size14&quot;&gt;본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성하였습니다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;a href=&quot;https://abit.ly/lisbva&quot;&gt;https://abit.ly/lisbva&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_3757.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DdLVA/btsN2RUiYl0/x6EzBZaJqgtvoWt8LMQK81/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DdLVA/btsN2RUiYl0/x6EzBZaJqgtvoWt8LMQK81/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DdLVA/btsN2RUiYl0/x6EzBZaJqgtvoWt8LMQK81/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDdLVA%2FbtsN2RUiYl0%2Fx6EzBZaJqgtvoWt8LMQK81%2Fimg.jpg&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;600&quot; height=&quot;800&quot; data-filename=&quot;IMG_3757.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_3758.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ns9IG/btsN0PDXxay/49kHoiQso3kC9Z9P9pfNDK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ns9IG/btsN0PDXxay/49kHoiQso3kC9Z9P9pfNDK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ns9IG/btsN0PDXxay/49kHoiQso3kC9Z9P9pfNDK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fns9IG%2FbtsN0PDXxay%2F49kHoiQso3kC9Z9P9pfNDK%2Fimg.jpg&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;600&quot; height=&quot;800&quot; data-filename=&quot;IMG_3758.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_3754.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;1468&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7xWUI/btsN1rCzLit/ALqZHhKoWzLYt5LiQw1690/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7xWUI/btsN1rCzLit/ALqZHhKoWzLYt5LiQw1690/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7xWUI/btsN1rCzLit/ALqZHhKoWzLYt5LiQw1690/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7xWUI%2FbtsN1rCzLit%2FALqZHhKoWzLYt5LiQw1690%2Fimg.jpg&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;600&quot; height=&quot;291&quot; data-filename=&quot;IMG_3754.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;1468&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-17 오전 10.20.54.png&quot; data-origin-width=&quot;336&quot; data-origin-height=&quot;130&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rssOt/btsN0LuHwyP/rh0RHS7B5IlqjJdqgF5W8K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rssOt/btsN0LuHwyP/rh0RHS7B5IlqjJdqgF5W8K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rssOt/btsN0LuHwyP/rh0RHS7B5IlqjJdqgF5W8K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrssOt%2FbtsN0LuHwyP%2Frh0RHS7B5IlqjJdqgF5W8K%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;336&quot; height=&quot;130&quot; data-filename=&quot;스크린샷 2025-05-17 오전 10.20.54.png&quot; data-origin-width=&quot;336&quot; data-origin-height=&quot;130&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;패스트캠퍼스의 '9개 도메인 프로젝트로 끝내는 백엔드 웹 개발 (Java/Spring) 초격차 패키지 Online' 강의 수강 48일차!&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;오늘은 Websocket을 활용한 실시간 메시징 도메인 서버의 회원가입 기능 구현을 위한 docker와 Spring Data JPA에 대한 개념 학습을 진행하였다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;카카오톡 인증을 통해 카카오톡으로부터 사용자 정보를 받아오고, 이 정보들을 이용해서 우리의 채팅 서비스에 회원 정보가 있는지 확인하여 (회원 정보가 없다면) 카카오톡에서 받아온 정보로 회원가입을 시키고, (회원 정보가 있다면) 로그인을 완료하도록 구현하는 작업을 진행하기로 했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;이번 강의에서는 구현에 들어가기 전, 사용할 기능들에 대한 개념 학습을 먼저 진행하였다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;Docker&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;: 컨테이너 기반의 오픈소스 가상화 플랫폼 (컨테이너: 프로세스를 격리시켜 동작할 수 있도록 표준화된 패키징)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;- 컨테이너 내에는 소프트웨어가 작동하는 데 필요한 라이브러리, 시스템 도구, 코드, 런타임 등을 모두 포함하고 있기 때문에, 환경에 구애받지 않고 어플리케이션을 배포 및 확장할 수 있다는 장점이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;- image라고 하는 어플리케이션 실행에 필요한 모든 것들을 포함하는 템플릿을 사용하여 실행된다.&lt;/span&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;- 기존의 가상화 기술은 OS부터 어플리케이션까지 모든 구성 요소를 가상화했다면, 도커는 호스트 OS는 컨테이너 간 커널을 공유하고, OS 위에서 작동하는 프로세스에 필요한 것들만 가상화한다. =&amp;gt; 가볍고 안정적&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;MySQL&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;: 대표적인 오픈소스 RDBMS&lt;/span&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;Spring Data JPA&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;: 스프링 프레임워크에서 데이터 접근 계층을 간편하게 구현할 수 있도록 도와주는 모듈&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;- Query Method: 메서드 이름을 기반으로 하여 JPA의 쿼리를 자동으로 생성해주는 기능&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;노트북을 바꾸기 전에 사용하던 기기에서는 MySQL을 직접 설치하여 사용한 적이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;도중에 충돌이 생겨 지웠다가 다시 설치해야 하는 상황이 생겼는데, 곳곳에 남아있는 설정들 때문에 꽤 고생을 했던 기억이 난다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;이번에는 깔끔하고 편하게 작업을 진행하고 싶어 사용해야 하는 것이 있다면 도커를 사용하고 있는데, 너무 만족스럽다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;로컬에서 사용하는 것만 아니라 배포 작업 등에도 도커를 사용해보고 싶다.&lt;/p&gt;</description>
      <category>패스트캠퍼스 챌린지</category>
      <category>습관형성</category>
      <category>오공완</category>
      <category>직장인자기계발</category>
      <category>패스트캠퍼스</category>
      <category>패스트캠퍼스후기</category>
      <category>환급챌린지</category>
      <author>ssoonearth</author>
      <guid isPermaLink="true">https://ssoonearth.tistory.com/48</guid>
      <comments>https://ssoonearth.tistory.com/48#entry48comment</comments>
      <pubDate>Sun, 18 May 2025 11:41:27 +0900</pubDate>
    </item>
    <item>
      <title>패스트캠퍼스 환급 챌린지 47일차 : 9개 도메인 프로젝트로 끝내는 백엔드 웹 개발 (Java/Spring) 초격차 패키지 Online 강의 후기</title>
      <link>https://ssoonearth.tistory.com/47</link>
      <description>&lt;p data-ke-size=&quot;size14&quot;&gt;본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성하였습니다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;a href=&quot;https://abit.ly/lisbva&quot;&gt;https://abit.ly/lisbva&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_3751.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cB6vDB/btsN1yOuCoA/wsDYncC4Wyqa3apR2VO010/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cB6vDB/btsN1yOuCoA/wsDYncC4Wyqa3apR2VO010/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cB6vDB/btsN1yOuCoA/wsDYncC4Wyqa3apR2VO010/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcB6vDB%2FbtsN1yOuCoA%2FwsDYncC4Wyqa3apR2VO010%2Fimg.jpg&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;600&quot; height=&quot;800&quot; data-filename=&quot;IMG_3751.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_3753.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qroLb/btsN1pj0S5j/AxA4ROrkGHZcV3CJTrcSE0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qroLb/btsN1pj0S5j/AxA4ROrkGHZcV3CJTrcSE0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qroLb/btsN1pj0S5j/AxA4ROrkGHZcV3CJTrcSE0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqroLb%2FbtsN1pj0S5j%2FAxA4ROrkGHZcV3CJTrcSE0%2Fimg.jpg&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;602&quot; height=&quot;803&quot; data-filename=&quot;IMG_3753.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_IMG_3752.jpg&quot; data-origin-width=&quot;3000&quot; data-origin-height=&quot;2415&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PTF2K/btsN0k41ZMC/QJmVBpsSUozJsR9LT6t8K0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PTF2K/btsN0k41ZMC/QJmVBpsSUozJsR9LT6t8K0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PTF2K/btsN0k41ZMC/QJmVBpsSUozJsR9LT6t8K0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPTF2K%2FbtsN0k41ZMC%2FQJmVBpsSUozJsR9LT6t8K0%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;600&quot; height=&quot;483&quot; data-filename=&quot;edited_IMG_3752.jpg&quot; data-origin-width=&quot;3000&quot; data-origin-height=&quot;2415&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-17 오전 12.39.52.png&quot; data-origin-width=&quot;337&quot; data-origin-height=&quot;51&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tyLGd/btsN1tfBLZr/y7GQpn9f5WkDt0B2Vnrvek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tyLGd/btsN1tfBLZr/y7GQpn9f5WkDt0B2Vnrvek/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tyLGd/btsN1tfBLZr/y7GQpn9f5WkDt0B2Vnrvek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtyLGd%2FbtsN1tfBLZr%2Fy7GQpn9f5WkDt0B2Vnrvek%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;383&quot; height=&quot;58&quot; data-filename=&quot;스크린샷 2025-05-17 오전 12.39.52.png&quot; data-origin-width=&quot;337&quot; data-origin-height=&quot;51&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;패스트캠퍼스의 '9개 도메인 프로젝트로 끝내는 백엔드 웹 개발 (Java/Spring) 초격차 패키지 Online' 강의 수강 47일차!&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;오늘은 Websocket을 활용한 실시간 메시징 도메인 서버의 OAuth2를 이용한 로그인 기능 고도화 작업을 진행하였다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;OAuth2&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;: 사용자의 아이디와 비밀번호를 공유하지 않고도 다른 서비스에서 제공하고 있는 정보에 사용자를 대신해서 접근할 수 있는 기능&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;OAuth2에서 정의하는 4개의 role&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;1. Resource Owner: 사용자&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;2. Client: 사용자의 인증을 통해 카카오톡 등의 서비스에 저장되어 있는 정보에 접근하고자 하는 어플리케이션 (현재의 경우, 채팅 서비스)&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;3. Authorization Server: 사용자의 인증을 받은 클라이언트에게 리소스 서버에 접근할 수 있는 access token을 발급해주는 서버&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;4. Resource Server: 사용자의 정보를 담고 있는 서버&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;이번 프로젝트에서는 Authorization Code Grant 방식을 사용하기로 했다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;1. Resource Owner가 클라이언트로 접근을 시도&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;2. Client는 Authorization 서버로 Resource Owner를 Redirect 시켜 인증을 하도록 함&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;3. Resource Owner가 Authorization 서버를 통해 로그인 -&amp;gt; Authorization 서버는 Authorization Code 발급해줌&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;4. Resource Owner가 위에서 발급받은 코드를 클라이언트에 전달 -&amp;gt; Authorization 서버로부터 리소스 서버에 접근할 수 있는 Access Token을 발급받음&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;5. 이후, 클라이언트는 필요 시 Access Token을 통해 리소스 서버로부터 리소스 오너(사용자)의 정보를 가져옴&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;스프링 시큐리티에서는 OAuth2 Client 라는 추가적인 모듈을 제공하고 있다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;이를 추가하면, 기본적으로 사용되던 form login 방식의 인증 흐름에 차이점이 생긴다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;UsernamePasswordAuthenticationFilter/Token, UserDetailsService, UserDetails가 사용되지 않고,&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;OAuth2 로그인을 위해 구현된 OAuth2LoginAuthenticationFilter, OAuth2AuthenticationProvider, OAuth2UserService, OAuth2User 인터페이스를 사용하여 인증이 진행된 후 Authentication 객체를 반환한다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1747408555303&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;build.gradle 파일에 의존성을 추가해주었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-17 오전 12.18.52.png&quot; data-origin-width=&quot;1866&quot; data-origin-height=&quot;480&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqo89p/btsN1forFAr/gXwlhL4ULkCW3rwXQnNy9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqo89p/btsN1forFAr/gXwlhL4ULkCW3rwXQnNy9k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqo89p/btsN1forFAr/gXwlhL4ULkCW3rwXQnNy9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbqo89p%2FbtsN1forFAr%2FgXwlhL4ULkCW3rwXQnNy9k%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;1866&quot; height=&quot;480&quot; data-filename=&quot;스크린샷 2025-05-17 오전 12.18.52.png&quot; data-origin-width=&quot;1866&quot; data-origin-height=&quot;480&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;카카오톡과 연동하기 위해, kakao developers에서 우리의 서비스를 등록해주었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #282c34; color: #bbbbbb;&quot;&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;security:
  oauth2:
    client:
      registration:
        kakao:
          client-id: 앱 키 &amp;gt; REST API 키
          client-secret: 카카오 로그인 &amp;gt; 보안 &amp;gt; Client Secret
          scope:
            - profile_nickname
          redirect-uri: &quot;http://localhost:8080/login/oauth2/code/kakao&quot;
          client-name: kakao
          authorization-grant-type: authorization_code
          client-authentication-method: client_secret_post
      provider:
        kakao:
          authorization-uri: https://kauth.kakao.com/oauth/authorize
          token-uri: https://kauth.kakao.com/oauth/token
          user-info-uri: https://kapi.kakao.com/v2/user/me
          user-name-attribute: id&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;이후, application.yml 파일에 OAuth2 클라이언트를 사용하기 위한 설정값들을 추가해 주었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-17 오전 12.34.17.png&quot; data-origin-width=&quot;1442&quot; data-origin-height=&quot;1500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/36cXF/btsN1SlBR1d/PDX8M7DvKYxSIzqUnwd5g1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/36cXF/btsN1SlBR1d/PDX8M7DvKYxSIzqUnwd5g1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/36cXF/btsN1SlBR1d/PDX8M7DvKYxSIzqUnwd5g1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F36cXF%2FbtsN1SlBR1d%2FPDX8M7DvKYxSIzqUnwd5g1%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;1442&quot; height=&quot;1500&quot; data-filename=&quot;스크린샷 2025-05-17 오전 12.34.17.png&quot; data-origin-width=&quot;1442&quot; data-origin-height=&quot;1500&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_스크린샷 2025-05-17 오전 12.30.21.png&quot; data-origin-width=&quot;1288&quot; data-origin-height=&quot;1560&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CDQRe/btsN10cTUAQ/LHO9yaCxKw7emcvAKLsTZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CDQRe/btsN10cTUAQ/LHO9yaCxKw7emcvAKLsTZk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CDQRe/btsN10cTUAQ/LHO9yaCxKw7emcvAKLsTZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCDQRe%2FbtsN10cTUAQ%2FLHO9yaCxKw7emcvAKLsTZk%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;1288&quot; height=&quot;1560&quot; data-filename=&quot;edited_스크린샷 2025-05-17 오전 12.30.21.png&quot; data-origin-width=&quot;1288&quot; data-origin-height=&quot;1560&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;어플리케이션을 실행하면 위와 같이 카카오톡 로그인 화면이 뜨고, 로그인을 하면 개인정보 이용 동의창이 뜨는 것을 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;스프링에서 oauth 설정이 이렇게 간단한지 처음 알았다..!&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;카카오 이외의 다른 서비스로 OAuth 기능 구현도 해보고 싶은 생각이 든다.&lt;/p&gt;</description>
      <category>패스트캠퍼스 챌린지</category>
      <category>습관형성</category>
      <category>오공완</category>
      <category>직장인자기계발</category>
      <category>패스트캠퍼스</category>
      <category>패스트캠퍼스후기</category>
      <category>환급챌린지</category>
      <author>ssoonearth</author>
      <guid isPermaLink="true">https://ssoonearth.tistory.com/47</guid>
      <comments>https://ssoonearth.tistory.com/47#entry47comment</comments>
      <pubDate>Sat, 17 May 2025 01:06:41 +0900</pubDate>
    </item>
    <item>
      <title>패스트캠퍼스 환급 챌린지 46일차 : 9개 도메인 프로젝트로 끝내는 백엔드 웹 개발 (Java/Spring) 초격차 패키지 Online 강의 후기</title>
      <link>https://ssoonearth.tistory.com/46</link>
      <description>&lt;p data-ke-size=&quot;size14&quot;&gt;본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성하였습니다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;a href=&quot;https://abit.ly/lisbva&quot;&gt;https://abit.ly/lisbva&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_3749.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0U8ti/btsN11izHuM/UHX3hRxr2QYeNAcTeMZBkk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0U8ti/btsN11izHuM/UHX3hRxr2QYeNAcTeMZBkk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0U8ti/btsN11izHuM/UHX3hRxr2QYeNAcTeMZBkk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0U8ti%2FbtsN11izHuM%2FUHX3hRxr2QYeNAcTeMZBkk%2Fimg.jpg&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;600&quot; height=&quot;800&quot; data-filename=&quot;IMG_3749.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_3750.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c0WFcu/btsN0ISa2FU/6KME8UIdvYHsxZCCxlxei0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c0WFcu/btsN0ISa2FU/6KME8UIdvYHsxZCCxlxei0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c0WFcu/btsN0ISa2FU/6KME8UIdvYHsxZCCxlxei0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc0WFcu%2FbtsN0ISa2FU%2F6KME8UIdvYHsxZCCxlxei0%2Fimg.jpg&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;600&quot; height=&quot;800&quot; data-filename=&quot;IMG_3750.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-15 오전 10.47.23.png&quot; data-origin-width=&quot;331&quot; data-origin-height=&quot;99&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xPdBK/btsNZfHlJAo/JEONCPeATKZdYKKVj7Nolk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xPdBK/btsNZfHlJAo/JEONCPeATKZdYKKVj7Nolk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xPdBK/btsNZfHlJAo/JEONCPeATKZdYKKVj7Nolk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxPdBK%2FbtsNZfHlJAo%2FJEONCPeATKZdYKKVj7Nolk%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;331&quot; height=&quot;99&quot; data-filename=&quot;스크린샷 2025-05-15 오전 10.47.23.png&quot; data-origin-width=&quot;331&quot; data-origin-height=&quot;99&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;패스트캠퍼스의 '9개 도메인 프로젝트로 끝내는 백엔드 웹 개발 (Java/Spring) 초격차 패키지 Online' 강의 수강 46일차!&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;오늘은 Websocket을 활용한 실시간 메시징 도메인 서버의 로그인 기능 적용 작업을 진행하였다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;지난 시간에는 주소만 입력한다면 누구나 접속할 수 있는 채팅 기능을 만들었다면, 이번에는 채팅 기능에 Spring Security를 이용한 로그인 기능을 적용시켜 로그인한 사용자만 채팅창에 접근할 수 있도록 구현하였다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;Spring Security란 인증 및 인가를 위한 스프링의 하위 프레임워크이다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;서블릿(Servlet)은 클라이언트의 http 요청을 처리하고 동적으로 응답을 생성하는 자바 기반의 웹 프로그래밍 기술로, 웹 서버 상에서 동작하는 자바 클래스이다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;스프링부트에서는 &lt;span&gt;기본적으로 &lt;/span&gt;&lt;span&gt;Tomcat&lt;/span&gt;&lt;span&gt;이라는 &lt;/span&gt;&lt;span&gt;내장 &lt;/span&gt;&lt;span&gt;웹 &lt;/span&gt;&lt;span&gt;서버를 &lt;/span&gt;&lt;span&gt;사용하며, &lt;/span&gt;&lt;span&gt;이는 &lt;/span&gt;&lt;span&gt;서블릿 &lt;/span&gt;&lt;span&gt;컨테이너 &lt;/span&gt;&lt;span&gt;역할을 &lt;/span&gt;&lt;span&gt;하여 &lt;/span&gt;&lt;span&gt;우리가 &lt;/span&gt;&lt;span&gt;작성한 &lt;/span&gt;&lt;span&gt;웹 &lt;/span&gt;&lt;span&gt;애플리케이션 &lt;/span&gt;&lt;span&gt;코드를 &lt;/span&gt;&lt;span&gt;실행하고 &lt;/span&gt;&lt;span&gt;HTTP &lt;/span&gt;&lt;span&gt;요청을 &lt;/span&gt;&lt;span&gt;처리한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;서버로 들어온 HTTP 요청은 여러 개의 서블릿 필터를 거쳐서 서블릿에 도달하게 된다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;이러한 &lt;/span&gt;&lt;span&gt;필터 &lt;/span&gt;&lt;span&gt;계층 &lt;/span&gt;&lt;span&gt;구조 &lt;/span&gt;&lt;span&gt;중 &lt;/span&gt;&lt;span&gt;하나로 스프링 시큐리티&lt;/span&gt;&lt;span&gt;의 &lt;/span&gt;FilterChainProxy&lt;span&gt;가 &lt;/span&gt;&lt;span&gt;삽입되어 &lt;/span&gt;&lt;span&gt;동작한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;FilterChainProxy&lt;span&gt;는 &lt;/span&gt;&lt;span&gt;하나의 &lt;/span&gt;&lt;span&gt;필터로 &lt;/span&gt;&lt;span&gt;보이지만, &lt;/span&gt;&lt;span&gt;내부적으로 &lt;/span&gt;&lt;span&gt;여러 &lt;/span&gt;&lt;span&gt;개의 &lt;/span&gt;SecurityFilterChain&lt;span&gt;을 &lt;/span&gt;&lt;span&gt;관리한다. &lt;/span&gt;&lt;span&gt;개발자는 &lt;/span&gt;&lt;span&gt;이 &lt;/span&gt;&lt;span&gt;체인을 &lt;/span&gt;&lt;span&gt;커스터마이징하여 &lt;/span&gt;&lt;span&gt;인증, &lt;/span&gt;&lt;span&gt;인가, &lt;/span&gt;&lt;span&gt;세션 &lt;/span&gt;&lt;span&gt;관리 &lt;/span&gt;&lt;span&gt;등 &lt;/span&gt;&lt;span&gt;보안 &lt;/span&gt;&lt;span&gt;기능을 &lt;/span&gt;&lt;span&gt;확장할 &lt;/span&gt;&lt;span&gt;수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #282c34; color: #bbbbbb;&quot;&gt;
&lt;pre class=&quot;sml&quot;&gt;&lt;code&gt;dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-websocket'
    implementation 'org.springframework.boot:spring-boot-starter-security'
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'org.springframework.security:spring-security-test'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;build.gradle 파일에 spring security 관련 의존성을 추가해 주었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-15 오전 10.39.55.png&quot; data-origin-width=&quot;1032&quot; data-origin-height=&quot;624&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJTpbe/btsNXnmDzar/JsKt1IAWZHWQ6Hn2tAxJA0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJTpbe/btsNXnmDzar/JsKt1IAWZHWQ6Hn2tAxJA0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJTpbe/btsNXnmDzar/JsKt1IAWZHWQ6Hn2tAxJA0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJTpbe%2FbtsNXnmDzar%2FJsKt1IAWZHWQ6Hn2tAxJA0%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;1032&quot; height=&quot;624&quot; data-filename=&quot;스크린샷 2025-05-15 오전 10.39.55.png&quot; data-origin-width=&quot;1032&quot; data-origin-height=&quot;624&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;어플리케이션을 실행시키고 localhost:8080으로 접속하니, index.html 화면이 바로 뜨는 것이 아니라 /login 경로의 로그인 화면으로 접속되는 것을 확인할 수 있다. 스프링 부트의 장점 중 하나인 auto configuration 덕분에 프로젝트의 classpath에 스프링 시큐리티가 있는 것을 확인하여 자동으로 기본 form login 기능이 적용된 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-15 오전 10.46.04.png&quot; data-origin-width=&quot;968&quot; data-origin-height=&quot;568&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3JvH7/btsNYt7obvn/r8Ecml7kNW76gkDh00BSZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3JvH7/btsNYt7obvn/r8Ecml7kNW76gkDh00BSZ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3JvH7/btsNYt7obvn/r8Ecml7kNW76gkDh00BSZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3JvH7%2FbtsNYt7obvn%2Fr8Ecml7kNW76gkDh00BSZ1%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;968&quot; height=&quot;568&quot; data-filename=&quot;스크린샷 2025-05-15 오전 10.46.04.png&quot; data-origin-width=&quot;968&quot; data-origin-height=&quot;568&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;username에는 'user'를, password에는 프로젝트 콘솔에 출력되는 Using generated security password 값을 복사하여 붙여넣고 sign in 버튼을 누르면 로그인이 되어 기존의 채팅창으로 넘어가게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;프로젝트를 진행하면서 스프링 시큐리티를 사용해 본 경험이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;매번 느끼지만 스프링에서 제공하는 하위 프레임워크를 잘 활용하면 개발 생산성에 정말 큰 도움이 되는 것 같다.&lt;/p&gt;</description>
      <category>패스트캠퍼스 챌린지</category>
      <category>습관형성</category>
      <category>오공완</category>
      <category>직장인자기계발</category>
      <category>패스트캠퍼스</category>
      <category>패스트캠퍼스후기</category>
      <category>환급챌린지</category>
      <author>ssoonearth</author>
      <guid isPermaLink="true">https://ssoonearth.tistory.com/46</guid>
      <comments>https://ssoonearth.tistory.com/46#entry46comment</comments>
      <pubDate>Fri, 16 May 2025 23:37:25 +0900</pubDate>
    </item>
    <item>
      <title>패스트캠퍼스 환급 챌린지 45일차 : 9개 도메인 프로젝트로 끝내는 백엔드 웹 개발 (Java/Spring) 초격차 패키지 Online 강의 후기</title>
      <link>https://ssoonearth.tistory.com/45</link>
      <description>&lt;p data-ke-size=&quot;size14&quot;&gt;본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성하였습니다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;a href=&quot;https://abit.ly/lisbva&quot;&gt;https://abit.ly/lisbva&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_3731.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/odcTp/btsNYoLRcy9/wQ58jNk0OKNlURW1LPlcn0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/odcTp/btsNYoLRcy9/wQ58jNk0OKNlURW1LPlcn0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/odcTp/btsNYoLRcy9/wQ58jNk0OKNlURW1LPlcn0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FodcTp%2FbtsNYoLRcy9%2FwQ58jNk0OKNlURW1LPlcn0%2Fimg.jpg&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;600&quot; height=&quot;800&quot; data-filename=&quot;IMG_3731.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_3732.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/K0e1R/btsNWQikGIJ/ItQsEGo4OvIqgGVxcb6xUK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/K0e1R/btsNWQikGIJ/ItQsEGo4OvIqgGVxcb6xUK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/K0e1R/btsNWQikGIJ/ItQsEGo4OvIqgGVxcb6xUK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FK0e1R%2FbtsNWQikGIJ%2FItQsEGo4OvIqgGVxcb6xUK%2Fimg.jpg&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;600&quot; height=&quot;800&quot; data-filename=&quot;IMG_3732.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-14 오후 10.11.13.png&quot; data-origin-width=&quot;1502&quot; data-origin-height=&quot;518&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/chS4AQ/btsNWIRYqje/hk7P7FmxsMSsCBKB9ukIrK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/chS4AQ/btsNWIRYqje/hk7P7FmxsMSsCBKB9ukIrK/img.png&quot; data-alt=&quot;실습 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/chS4AQ/btsNWIRYqje/hk7P7FmxsMSsCBKB9ukIrK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FchS4AQ%2FbtsNWIRYqje%2Fhk7P7FmxsMSsCBKB9ukIrK%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;602&quot; height=&quot;208&quot; data-filename=&quot;스크린샷 2025-05-14 오후 10.11.13.png&quot; data-origin-width=&quot;1502&quot; data-origin-height=&quot;518&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;실습 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-14 오후 9.50.34.png&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;116&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lh0du/btsNWGs2BtW/1LoWUKmm00eFzmvPehy6X0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lh0du/btsNWGs2BtW/1LoWUKmm00eFzmvPehy6X0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lh0du/btsNWGs2BtW/1LoWUKmm00eFzmvPehy6X0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Flh0du%2FbtsNWGs2BtW%2F1LoWUKmm00eFzmvPehy6X0%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;603&quot; height=&quot;105&quot; data-filename=&quot;스크린샷 2025-05-14 오후 9.50.34.png&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;116&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;패스트캠퍼스의 '9개 도메인 프로젝트로 끝내는 백엔드 웹 개발 (Java/Spring) 초격차 패키지 Online' 강의 수강 45일차!&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;오늘은 Websocket을 활용한 실시간 메시징 도메인 서버의 STOMP을 사용한 간단한 채팅 서비스 구현 작업을 진행하였다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #282c34; color: #bbbbbb;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Configuration
@EnableWebSocketMessageBroker // STOMP 기능 활성화
public class StompConfiguration implements WebSocketMessageBrokerConfigurer {

    // 클라이언트가 서버에 연결할 수 있도록 엔드포인트 지정
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint(&quot;/stomp/chats&quot;);
    }

    // 메세지 브로커로서의 역할을 하기 위해서 클라이언트에서 메세지를 발행하고, 클라이언트는 브로커로부터 전달되는 메세지를 받기 위해 구독을 해야 한다.
    // 그 경로들을 지정해주는 기능
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        // 메세지 발행 경로 (클라이언트 -&amp;gt; 서버로 메세지 보낼 때 사용할 prefix)
        registry.setApplicationDestinationPrefixes(&quot;/pub&quot;);

        // 메세지 구독 신청 경로 (서버 -&amp;gt; 클라이언트로 메세지 보낼 때 사용할 prefix)
        registry.enableSimpleBroker(&quot;/sub&quot;);
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;STOMP 사용을 위한 설정 파일을 생성하였다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;WebSocketMessageBrokerConfigurer 인터페이스를 구현하여 스톰프 기능을 설정할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;registerStompEndpoits(), configureMessageBroker()를 오버라이드하여 구현하였다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #282c34; color: #bbbbbb;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Slf4j
@Controller
public class StompChatController {

    @MessageMapping(&quot;/chats&quot;) // 어떤 경로로 발행된 메세지를 라우팅할 것인지 지정 (설정 파일에서 설정한 prefix(/pub)는 생략)
    @SendTo(&quot;/sub/chats&quot;) // 해당 경로를 구독하고 있는 모든 클라이언트에 메세지 전달
    public String handleMessage(@Payload String message) {
        log.info(&quot;{} Received&quot;, message);

        return message;
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;이후, 메세지 요청을 받는 컨트롤러를 생성했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;@MessageMapping 어노테이션을 통해 /pub/chats 경로로 발행된 메세지를 받아와 처리하고, 구독 중인 클라이언트들에게 메세지를 전달한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-14 오후 9.33.57.png&quot; data-origin-width=&quot;1416&quot; data-origin-height=&quot;82&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btRjbS/btsNXkQTSxu/apEvoHA9uEtNkbTKHubR80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btRjbS/btsNXkQTSxu/apEvoHA9uEtNkbTKHubR80/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btRjbS/btsNXkQTSxu/apEvoHA9uEtNkbTKHubR80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtRjbS%2FbtsNXkQTSxu%2FapEvoHA9uEtNkbTKHubR80%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;1416&quot; height=&quot;82&quot; data-filename=&quot;스크린샷 2025-05-14 오후 9.33.57.png&quot; data-origin-width=&quot;1416&quot; data-origin-height=&quot;82&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;어플리케이션을 실행하여 메세지를 보내면, 위 컨트롤러에서 작성한 포맷대로 log가 출력되는 것을 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;map 등의 자료구조에 직접 세션을 저장하고, 반복문을 수행하면서 메세지를 전송해야 했던 웹소켓과 달리 stomp는 경로 지정과 컨트롤러 구현만으로 메세지 전달이 가능해서 훨씬 빠르고 편리하게 개발을 할 수 있었다.&lt;/p&gt;</description>
      <category>패스트캠퍼스 챌린지</category>
      <category>습관형성</category>
      <category>오공완</category>
      <category>직장인자기계발</category>
      <category>패스트캠퍼스</category>
      <category>패스트캠퍼스후기</category>
      <category>환급챌린지</category>
      <author>ssoonearth</author>
      <guid isPermaLink="true">https://ssoonearth.tistory.com/45</guid>
      <comments>https://ssoonearth.tistory.com/45#entry45comment</comments>
      <pubDate>Thu, 15 May 2025 10:39:11 +0900</pubDate>
    </item>
    <item>
      <title>패스트캠퍼스 환급 챌린지 44일차 : 9개 도메인 프로젝트로 끝내는 백엔드 웹 개발 (Java/Spring) 초격차 패키지 Online 강의 후기</title>
      <link>https://ssoonearth.tistory.com/44</link>
      <description>&lt;p data-ke-size=&quot;size14&quot;&gt;본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성하였습니다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;a href=&quot;https://abit.ly/lisbva&quot;&gt;https://abit.ly/lisbva&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_3727.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mVB8n/btsNWhlKyAI/TtAC7033PN07n5CPI3Jc0k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mVB8n/btsNWhlKyAI/TtAC7033PN07n5CPI3Jc0k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mVB8n/btsNWhlKyAI/TtAC7033PN07n5CPI3Jc0k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmVB8n%2FbtsNWhlKyAI%2FTtAC7033PN07n5CPI3Jc0k%2Fimg.jpg&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;600&quot; height=&quot;800&quot; data-filename=&quot;IMG_3727.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_3729.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MyZw8/btsNUGUIr16/COBeHKAWwh3Pw1gx1DSMbk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MyZw8/btsNUGUIr16/COBeHKAWwh3Pw1gx1DSMbk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MyZw8/btsNUGUIr16/COBeHKAWwh3Pw1gx1DSMbk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMyZw8%2FbtsNUGUIr16%2FCOBeHKAWwh3Pw1gx1DSMbk%2Fimg.jpg&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;600&quot; height=&quot;800&quot; data-filename=&quot;IMG_3729.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-13 오후 3.38.52.png&quot; data-origin-width=&quot;1594&quot; data-origin-height=&quot;1106&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYSIt1/btsNVY06jtD/xe4cLqQ4ufxaEEa0w9KO71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYSIt1/btsNVY06jtD/xe4cLqQ4ufxaEEa0w9KO71/img.png&quot; data-alt=&quot;프로젝트 생성 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYSIt1/btsNVY06jtD/xe4cLqQ4ufxaEEa0w9KO71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYSIt1%2FbtsNVY06jtD%2Fxe4cLqQ4ufxaEEa0w9KO71%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;600&quot; height=&quot;416&quot; data-filename=&quot;스크린샷 2025-05-13 오후 3.38.52.png&quot; data-origin-width=&quot;1594&quot; data-origin-height=&quot;1106&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;프로젝트 생성 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-13 오후 11.57.31.png&quot; data-origin-width=&quot;664&quot; data-origin-height=&quot;296&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UybDq/btsNWsHlAUU/ALfoh0WRFqwcKMxoxNcQQ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UybDq/btsNWsHlAUU/ALfoh0WRFqwcKMxoxNcQQ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UybDq/btsNWsHlAUU/ALfoh0WRFqwcKMxoxNcQQ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUybDq%2FbtsNWsHlAUU%2FALfoh0WRFqwcKMxoxNcQQ0%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;601&quot; height=&quot;268&quot; data-filename=&quot;스크린샷 2025-05-13 오후 11.57.31.png&quot; data-origin-width=&quot;664&quot; data-origin-height=&quot;296&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;패스트캠퍼스의 '9개 도메인 프로젝트로 끝내는 백엔드 웹 개발 (Java/Spring) 초격차 패키지 Online' 강의 수강 44일차!&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;오늘은 Websocket을 활용한 실시간 메시징 도메인 서버의 프로젝트 생성, 웹소켓을 사용한 간단한 채팅 서비스 구현 작업을 진행하였다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;part4 강의에서는 채팅 상담 기능을 제공하는 백엔드 서비스를 만들 계획이다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;서버에 연결된 복수의 사용자들이 서로 메세지를 주고 받을 수 있는 간단한 채팅 기능을 WebSocket과 STOMP를 이용하여 각각 구현해보는 작업을 진행하기로 하였다. 먼저, 이번 강의에서는 웹소켓을 이용하여 개발을 진행하였다.&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #282c34; color: #bbbbbb;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Slf4j
@Component
public class WebSocketChatHandler extends TextWebSocketHandler {

	final Map&amp;lt;String, WebSocketSession&amp;gt; webSocketSessionMap = new ConcurrentHashMap&amp;lt;&amp;gt;();

	// 웹소켓 클라이언트가 서버로 연결을 한 이후에 실행되는 로직
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        log.info(&quot;{} connected&quot;, session.getId());
        this.webSocketSessionMap.put(session.getId(), session);
    }

	// 웹소켓 클라이언트에서 메세지가 왔을 때 처리하는 로직
    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage&amp;lt;?&amp;gt; message) throws Exception {
        log.info(&quot;{} sent {}&quot;, session.getId(), message.getPayload());

        this.webSocketSessionMap.values().forEach(
                webSocketSession -&amp;gt; {
                    try {
                        webSocketSession.sendMessage(message);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
        );
    }

	// 서버에 접속해 있던 웹소켓 클라이언트가 연결을 끊었을 때 처리하는 로직
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        log.info(&quot;{} disconnected&quot;, session.getId());
        this.webSocketSessionMap.remove(session.getId());
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;TextWebSocketHandler를 상속받고, 세 개의 메서드를 오버라이드하여 웹소켓 핸들러를 구현했다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;세션을 map 형태로 저장해둔 후, 연결된 모든 사용자에게 메세지를 전송하는 형식이다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #282c34; color: #bbbbbb;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@RequiredArgsConstructor
@EnableWebSocket
@Configuration
public class WebSocketConfiguration implements WebSocketConfigurer {

    final WebSocketChatHandler webSocketChatHandler;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(webSocketChatHandler, &quot;/ws/chats&quot;);
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;Spring에 웹소켓 서버 설정을 하기 위해 WebSocketConfigurer 인터페이스를 구현한 설정 파일을 생성하였다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;웹소켓 요청이 &quot;/ws/chats&quot; 경로로 들어오면 WebSocketHandler가 처리하도록 등록했다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-13 오후 11.43.06.png&quot; data-origin-width=&quot;1878&quot; data-origin-height=&quot;728&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mqC0I/btsNVewMgGY/57O91jv1UdFiAxpCf8BtA0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mqC0I/btsNVewMgGY/57O91jv1UdFiAxpCf8BtA0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mqC0I/btsNVewMgGY/57O91jv1UdFiAxpCf8BtA0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmqC0I%2FbtsNVewMgGY%2F57O91jv1UdFiAxpCf8BtA0%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;1878&quot; height=&quot;728&quot; data-filename=&quot;스크린샷 2025-05-13 오후 11.43.06.png&quot; data-origin-width=&quot;1878&quot; data-origin-height=&quot;728&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-13 오후 11.43.14.png&quot; data-origin-width=&quot;1498&quot; data-origin-height=&quot;800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cyefTZ/btsNV6ksC6f/kUkn6ky7UgjJE4oKiy1NC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cyefTZ/btsNV6ksC6f/kUkn6ky7UgjJE4oKiy1NC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cyefTZ/btsNV6ksC6f/kUkn6ky7UgjJE4oKiy1NC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcyefTZ%2FbtsNV6ksC6f%2FkUkn6ky7UgjJE4oKiy1NC0%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;1498&quot; height=&quot;800&quot; data-filename=&quot;스크린샷 2025-05-13 오후 11.43.14.png&quot; data-origin-width=&quot;1498&quot; data-origin-height=&quot;800&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;다른 브라우저에서 localhost에 접속한 후, 각각 connect하고 메세지를 send하면 두 개의 창에서 실시간으로 전송된 메세지가 출력되는 것을 확인할 수 있다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;웹소켓만 가지고 정말 간단한 채팅 기능을 구현해 보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;너무 신기하다! 다음 강의에서 STOMP로 구현할 때는 어떤 차이가 있을지 궁금하다.&lt;/p&gt;</description>
      <category>패스트캠퍼스 챌린지</category>
      <category>습관형성</category>
      <category>오공완</category>
      <category>직장인자기계발</category>
      <category>패스트캠퍼스</category>
      <category>패스트캠퍼스후기</category>
      <category>환급챌린지</category>
      <author>ssoonearth</author>
      <guid isPermaLink="true">https://ssoonearth.tistory.com/44</guid>
      <comments>https://ssoonearth.tistory.com/44#entry44comment</comments>
      <pubDate>Wed, 14 May 2025 01:26:40 +0900</pubDate>
    </item>
    <item>
      <title>패스트캠퍼스 환급 챌린지 43일차 : 9개 도메인 프로젝트로 끝내는 백엔드 웹 개발 (Java/Spring) 초격차 패키지 Online 강의 후기</title>
      <link>https://ssoonearth.tistory.com/43</link>
      <description>&lt;p data-ke-size=&quot;size14&quot;&gt;본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성하였습니다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;a href=&quot;https://abit.ly/lisbva&quot;&gt;https://abit.ly/lisbva&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_3722.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cSd40e/btsNUbN1huu/1D7rbjihJGOprvqG2Rvyl0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cSd40e/btsNUbN1huu/1D7rbjihJGOprvqG2Rvyl0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cSd40e/btsNUbN1huu/1D7rbjihJGOprvqG2Rvyl0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcSd40e%2FbtsNUbN1huu%2F1D7rbjihJGOprvqG2Rvyl0%2Fimg.jpg&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;600&quot; height=&quot;800&quot; data-filename=&quot;IMG_3722.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_3724.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0K7um/btsNULurhv4/Om54Kx2cMy4i2OzXBuFVQk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0K7um/btsNULurhv4/Om54Kx2cMy4i2OzXBuFVQk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0K7um/btsNULurhv4/Om54Kx2cMy4i2OzXBuFVQk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0K7um%2FbtsNULurhv4%2FOm54Kx2cMy4i2OzXBuFVQk%2Fimg.jpg&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;600&quot; height=&quot;800&quot; data-filename=&quot;IMG_3724.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_3723.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;801&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ckRP1F/btsNUOSfoXB/gIDU1pK7ySFKHizpAkT1C1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ckRP1F/btsNUOSfoXB/gIDU1pK7ySFKHizpAkT1C1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckRP1F/btsNUOSfoXB/gIDU1pK7ySFKHizpAkT1C1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FckRP1F%2FbtsNUOSfoXB%2FgIDU1pK7ySFKHizpAkT1C1%2Fimg.jpg&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;600&quot; height=&quot;159&quot; data-filename=&quot;IMG_3723.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;801&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-13 오후 3.49.06.png&quot; data-origin-width=&quot;334&quot; data-origin-height=&quot;43&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cRTOgx/btsNVaVaoEn/kZ1gboRL5d9kxI5uJ56Rz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cRTOgx/btsNVaVaoEn/kZ1gboRL5d9kxI5uJ56Rz0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cRTOgx/btsNVaVaoEn/kZ1gboRL5d9kxI5uJ56Rz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcRTOgx%2FbtsNVaVaoEn%2FkZ1gboRL5d9kxI5uJ56Rz0%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;334&quot; height=&quot;43&quot; data-filename=&quot;스크린샷 2025-05-13 오후 3.49.06.png&quot; data-origin-width=&quot;334&quot; data-origin-height=&quot;43&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;패스트캠퍼스의 '9개 도메인 프로젝트로 끝내는 백엔드 웹 개발 (Java/Spring) 초격차 패키지 Online' 강의 수강 43일차!&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;오늘은 Websocket을 활용한 실시간 메시징 도메인 서버 개발 강의의 웹소켓 이론에 대한 학습을 진행하였다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;Spring Framework의 WebSocket 지원&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;1. Web Socket API&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;: 웹소켓 메세지를 다룰 수 있는 api 제공&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;- WebSocketHandler: 이진 데이터 또는 텍스트 데이터를 다루기 위한 바이너르 웹소켓 핸들러 또는 텍스트 웹소켓 핸들러를 상속받아 구현하는 것만으로 간단한 웹소켓 서버를 만들 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;- WebSocket Handshake: 웹소켓의 http 핸드쉐이크를 커스터마이징할 수 있는 핸드쉐이크 인터셉터를 제공. 핸드쉐이크 인터페이스의 beforeHandshake, afterHandshake 메소드를 제공하는데, 이를 구현함으로써 핸드쉐이크 과정 중에 일어나는 인증, 서브 프로토콜 협상 등의 부가적인 작업들을 제어할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;- 웹소켓 서버 설정을 자바코드로 제어할 수 있는 기능을 제공한다. 이를 통해 웹소켓의 메세지 버퍼 사이즈, 타임아웃과 같은 설정을 제어할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;2. SockJS Fallback&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;: 웹소켓이 정상적으로 작동하지 않는 환경을 위한 SockJS 프로토콜 지원&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;- 브라우저상의 SockJS 클라이언트가 웹소켓, 스트리밍, 롱폴링 등의 통신 방법 중에서 적절한 방식을 선택하기 위해서는, 서버로 요청을 보내서 세션/쿠키의 사용 여부 등 여러가지 기본적인 정보들을 받아야 한다. 또한, 프록시에서 연결이 끊기는 것을 방지하기 위해서 서버에서는 프록시로 heartbeat 요청을 지속적으로 보내줘야 한다. 이렇게 SockJS가 작동하기 위한 서버 사이드의 역할들에 대한 지원을 해주는 기능을 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;3. STOMP&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;: STOMP 브로커 기능을 제공&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;- 웹소켓을 직접 사용하는 것보다 더 풍부한 기능을 제공한다. (메세지 포맷 정의 / 파싱 로직 구현 불필요, 하나의 웹소켓 핸들러에서 처리하던 것을 다수의 컨트롤러에서 처리 가능(&lt;span&gt;@&lt;/span&gt;&lt;span&gt;MessageMapping)&lt;/span&gt;, Spring Security 이용 가능 등)&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;- @Configuration, @EnableWebSocketMessageBroker 어노테이션을 선언하고, WebSocketMessageBrokerConfigurer 인터페이스를 구현하면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;저번 강의에서 웹소켓에 대한 개념만 학습했을 때는 너무 복잡해 보여서 이걸 어떻게 구현할 수 있을지 상상이 되지 않았는데, 스프링상에서 제공하는 웹소켓 관련 기능이 굉장히 많은 것을 알게 되어 다행이다~&lt;/span&gt;&lt;/p&gt;</description>
      <category>패스트캠퍼스 챌린지</category>
      <category>습관형성</category>
      <category>오공완</category>
      <category>직장인자기계발</category>
      <category>패스트캠퍼스</category>
      <category>패스트캠퍼스후기</category>
      <category>환급챌린지</category>
      <author>ssoonearth</author>
      <guid isPermaLink="true">https://ssoonearth.tistory.com/43</guid>
      <comments>https://ssoonearth.tistory.com/43#entry43comment</comments>
      <pubDate>Tue, 13 May 2025 15:52:00 +0900</pubDate>
    </item>
    <item>
      <title>패스트캠퍼스 환급 챌린지 42일차 : 9개 도메인 프로젝트로 끝내는 백엔드 웹 개발 (Java/Spring) 초격차 패키지 Online 강의 후기</title>
      <link>https://ssoonearth.tistory.com/42</link>
      <description>&lt;p data-ke-size=&quot;size14&quot;&gt;본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성하였습니다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;a href=&quot;https://abit.ly/lisbva&quot;&gt;https://abit.ly/lisbva&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_3710.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfTGth/btsNUxbdm2m/m1rT8l1SbyEeFPPmPPLs4k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfTGth/btsNUxbdm2m/m1rT8l1SbyEeFPPmPPLs4k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfTGth/btsNUxbdm2m/m1rT8l1SbyEeFPPmPPLs4k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfTGth%2FbtsNUxbdm2m%2Fm1rT8l1SbyEeFPPmPPLs4k%2Fimg.jpg&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;600&quot; height=&quot;800&quot; data-filename=&quot;IMG_3710.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_3713.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tydYA/btsNVe91HGM/J2UqPjnFurypvMgxEENKYK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tydYA/btsNVe91HGM/J2UqPjnFurypvMgxEENKYK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tydYA/btsNVe91HGM/J2UqPjnFurypvMgxEENKYK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtydYA%2FbtsNVe91HGM%2FJ2UqPjnFurypvMgxEENKYK%2Fimg.jpg&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;600&quot; height=&quot;800&quot; data-filename=&quot;IMG_3713.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_3711.jpg&quot; data-origin-width=&quot;2370&quot; data-origin-height=&quot;2587&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kFc4s/btsNUPJqp6S/YkjpB24N3yyVbXKoJKkXa1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kFc4s/btsNUPJqp6S/YkjpB24N3yyVbXKoJKkXa1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kFc4s/btsNUPJqp6S/YkjpB24N3yyVbXKoJKkXa1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkFc4s%2FbtsNUPJqp6S%2FYkjpB24N3yyVbXKoJKkXa1%2Fimg.jpg&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;600&quot; height=&quot;655&quot; data-filename=&quot;IMG_3711.jpg&quot; data-origin-width=&quot;2370&quot; data-origin-height=&quot;2587&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-12 오후 10.34.27.png&quot; data-origin-width=&quot;333&quot; data-origin-height=&quot;336&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Buit9/btsNUTdW9rn/MiSKtNkHCUBFkpR977EyT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Buit9/btsNUTdW9rn/MiSKtNkHCUBFkpR977EyT0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Buit9/btsNUTdW9rn/MiSKtNkHCUBFkpR977EyT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBuit9%2FbtsNUTdW9rn%2FMiSKtNkHCUBFkpR977EyT0%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;333&quot; height=&quot;336&quot; data-filename=&quot;스크린샷 2025-05-12 오후 10.34.27.png&quot; data-origin-width=&quot;333&quot; data-origin-height=&quot;336&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;패스트캠퍼스의 '9개 도메인 프로젝트로 끝내는 백엔드 웹 개발 (Java/Spring) 초격차 패키지 Online' 강의 수강 42일차!&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;오늘은 Websocket을 활용한 실시간 메시징 도메인 서버 개발 강의의 웹소켓 이론에 대한 학습을 진행하였다.&lt;/span&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;(새롭게 시작할 토이 프로젝트에서 웹소켓을 사용하게 될 것 같아서 갑작스럽게 수강하는 강의를 바꾸게 되었다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;기존에 수강 중이던 redis 강의는 추후에 꼭 완강하도록 해야겠다,, )&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;웹소켓&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;: TCP 기반의 연결을 통해 실시간 양방향 통신을 가능하게 해주는 통신 프로토콜&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;하나의 커넥션을 이용하여 실시간으로 효율적인 양방향 통신이 가능하다는 장점이 있다. (전이중 통신)&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;하지만 비교적 최신 기술이기 때문에 브라우저의 호환성이 떨어지고, stateful한 특징에 맞춰 연결의 상태에 따른 여러가지 상황들을 구현시 신경써야 하는 단점이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;웹소켓은 실시간성이 중요한 채팅, 인터넷 게임, 주식거래 사이트, 협업 툴 등의 서비스에 주로 사용된다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;웹소켓과 http의 비교&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;- http는 서버로부터 데이터를 받기 위해서 반드시 클라이언트의 요청이 있어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;한 번의 요청과 응답을 주고 받기 위해서는 3-way handshake 과정을 거쳐야 하기 때문에, 이로 인한 오버헤드가 발생할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;- 서버와 연결을 맺기 위한 최초의 handshake 과정 이후에는 클라이언트와 서버가 각자 원하는 시점에 원하는 데이터를 보낼 수 있다. 그렇기에, handshake로 인한 불필요한 오버헤드가 발생하지 않는다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;웹소켓 이전의 실시간 통신 방식&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;- Polling&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;: 서버로부터 원하는 데이터를 얻어오기 위해 일정한 간격으로 서버에 계속 요청을 보내는 방법&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;서버에 변경사항이 없는 경우에도 계속해서 요청을 보내는 상황이 발생할 수 있기 때문에 불필요한 트래픽 낭비가 많이 생긴다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;- Long Polling&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;: 한번의 요청을 보내고 서버에서 보내줄 데이터가 없다면, 그 데이터를 보낼 수 있는 상황이 될 때까지 연결을 끊지 않고 유지하는 방식&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;해당 요청에 대해 응답을 받으면, 클라이언트에서는 해당 데이터를 처리한 후에 바로 다시 서버로 요청을 보내서 다음 데이터를 대기한다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;폴링 방식보다는 불필요한 트래픽이 줄어들지만, 많은 요청을 보내야 하는 문제는 해결되지 않는다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;- 스트리밍&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;: 클라이언트에서 서버로 요청을 보내고 나면, 이에 대한 연결을 끊지 않은 상태로 서버에서 데이터를 보낼 수 있을 때마다 몇 번이고 응답을 내려주는 방식&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;빈번한 요청이라는 문제는 해결할 수 있지만, 클라이언트에서 서버로 데이터를 전송할 수 없다는 문제가 있다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;웹소켓은 하나의 연결을 이용해서 양방향 통신이 가능하기에 위의 문제들을 해결할 수 있다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;웹소켓 핸드쉐이크&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;: 최초의 요청은 http 프로토콜을 이용하여 이루어진다. get 메서드를 이용해 웹소켓 프로토콜로의 업그레이드 요청을 보냄.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;서버에서는 이에 대한 응답으로 200(일반적인 성공에 대한 응답)이 아닌, 100을 내려준다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;위 과정 이후부터는 웹소켓 프로토콜을 이용하여 서버와 연결을 맺고 데이터를 주고 받을 수 있게 된다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;웹소켓 프로토콜에서 사용하는 가장 작은 데이터 단위인 &lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;'Frame' 형식을 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;웹소켓 프로토콜상의 데이터 전송은 일련의 프레임을 사용한다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;프레임은 비트 단위로 세부적인 구조를 가지고 있으며, 크기 헤더와 페이로드로 구분된다.&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;0번 비트&lt;/td&gt;
&lt;td&gt;FIN&lt;/td&gt;
&lt;td&gt;메시지의 마지막 프레임 여부 (1이면 마지막)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1~3번 비트&lt;/td&gt;
&lt;td&gt;RSV1~RSV3&lt;/td&gt;
&lt;td&gt;웹소켓 확장용 필드. 특별한 확장 없으면 기본값은 0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4~7번 비트&lt;/td&gt;
&lt;td&gt;Opcode&lt;/td&gt;
&lt;td&gt;전송 데이터의 종류 (예: 텍스트, 바이너리 등)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8번 비트&lt;/td&gt;
&lt;td&gt;Mask&lt;/td&gt;
&lt;td&gt;마스킹 여부. 클라이언트 &amp;rarr; 서버 전송 시 항상 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9~15번 비트&lt;/td&gt;
&lt;td&gt;Payload Length&lt;/td&gt;
&lt;td&gt;페이로드 데이터 길이 표현&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;- 0 ~ 125: 최초의 7비트를 이용해 직접 길이 표현&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;- 126: 최초의 7비트를 126으로 고정, 그 이후에 2 바이트를 사용하여 16비트 unsigned int로 길이 표현&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;- 127: 최초의 7비트를 127으로 고정, 그 이후에 8바이트를 사용하여 64비트 unsigned int로 길이 표현&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;이후, mask 비트가 1일 경우에는 길이 필드 뒤에 4바이트 마스킹 키가 추가되고, 그 뒤에 실제 페이로드 데이터가 전송된다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;웹소켓 프로토콜은 어플리케이션 레벨의 프로토콜이 아니기 때문에 주고받는 메세지 성격에 대한 충분한 정보가 없기 때문에 프레임워크나 컨테이너가 메세지를 어떻게 처리해야 할지 알 수가 없다. 그렇기 때문에 웹소켓 프로토콜을 위해 작동하는 서브 프로토콜 중 하나인 stomp를 사용한다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;stomp는 클라이언트와 서버가 전송할 메세지의 유형, 형식, 내용 등을 정의한다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;전에 웹소켓을 이용한 프로젝트를 진행하려다가 사전 지식의 벽에 가로막혀 도전하지 못했던 기억이 난다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;아직 정확히 이해가 되지 않는 부분도 있지만, 네트워크 공부를 병행하면서 진행하면 될 것 같다!&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;http 이외의 프로토콜을 사용하는 것은 처음이라 기대된다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>패스트캠퍼스 챌린지</category>
      <category>습관형성</category>
      <category>오공완</category>
      <category>직장인자기계발</category>
      <category>패스트캠퍼스</category>
      <category>패스트캠퍼스후기</category>
      <category>환급챌린지</category>
      <author>ssoonearth</author>
      <guid isPermaLink="true">https://ssoonearth.tistory.com/42</guid>
      <comments>https://ssoonearth.tistory.com/42#entry42comment</comments>
      <pubDate>Mon, 12 May 2025 23:01:06 +0900</pubDate>
    </item>
    <item>
      <title>패스트캠퍼스 환급 챌린지 41일차 : 9개 도메인 프로젝트로 끝내는 백엔드 웹 개발 (Java/Spring) 초격차 패키지 Online 강의 후기</title>
      <link>https://ssoonearth.tistory.com/41</link>
      <description>&lt;p data-ke-size=&quot;size14&quot;&gt;본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성하였습니다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;a href=&quot;https://abit.ly/lisbva&quot;&gt;https://abit.ly/lisbva&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_3705.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Q4btD/btsNTkP5jjR/pi20yksZDGsjDAlyUPwxyK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Q4btD/btsNTkP5jjR/pi20yksZDGsjDAlyUPwxyK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Q4btD/btsNTkP5jjR/pi20yksZDGsjDAlyUPwxyK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQ4btD%2FbtsNTkP5jjR%2Fpi20yksZDGsjDAlyUPwxyK%2Fimg.jpg&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;600&quot; height=&quot;800&quot; data-filename=&quot;IMG_3705.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_3706.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blcGbD/btsNTxBHhvD/ZXkxphUhxzxcDKESyvdmhK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blcGbD/btsNTxBHhvD/ZXkxphUhxzxcDKESyvdmhK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blcGbD/btsNTxBHhvD/ZXkxphUhxzxcDKESyvdmhK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblcGbD%2FbtsNTxBHhvD%2FZXkxphUhxzxcDKESyvdmhK%2Fimg.jpg&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;600&quot; height=&quot;800&quot; data-filename=&quot;IMG_3706.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-11 오후 10.49.11.png&quot; data-origin-width=&quot;335&quot; data-origin-height=&quot;80&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGg6ho/btsNSA7aiT1/v5ZYcYHVKEsyyKZHqRqE7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGg6ho/btsNSA7aiT1/v5ZYcYHVKEsyyKZHqRqE7k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGg6ho/btsNSA7aiT1/v5ZYcYHVKEsyyKZHqRqE7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGg6ho%2FbtsNSA7aiT1%2Fv5ZYcYHVKEsyyKZHqRqE7k%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;335&quot; height=&quot;80&quot; data-filename=&quot;스크린샷 2025-05-11 오후 10.49.11.png&quot; data-origin-width=&quot;335&quot; data-origin-height=&quot;80&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;패스트캠퍼스의 '9개 도메인 프로젝트로 끝내는 백엔드 웹 개발 (Java/Spring) 초격차 패키지 Online' 강의 수강 41일차!&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;오늘은 동영상 컨텐츠 서비스 개발 강의의 프로젝트 구조 및 필요한 기술과 의존성에 대한 학습을 진행하였다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_3709.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;2043&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpgIoi/btsNSvYTKwU/KdwkKRQlfI0wIH6ZX5XqkK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpgIoi/btsNSvYTKwU/KdwkKRQlfI0wIH6ZX5XqkK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpgIoi/btsNSvYTKwU/KdwkKRQlfI0wIH6ZX5XqkK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpgIoi%2FbtsNSvYTKwU%2FKdwkKRQlfI0wIH6ZX5XqkK%2Fimg.jpg&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;3024&quot; height=&quot;2043&quot; data-filename=&quot;IMG_3709.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;2043&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;도메인 로직을 중심에 두고, 외부 의존성을 입출력 포트와 어댑터로 분리하는 헥사고날 아키텍처로 설계하였다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span&gt;외부 &lt;/span&gt;&lt;span&gt;요청(&lt;/span&gt;&lt;span&gt;API &lt;/span&gt;&lt;span&gt;등)&lt;/span&gt;&lt;span&gt;이 &lt;/span&gt;&lt;span&gt;어댑터(&lt;/span&gt;&lt;span&gt;컨트롤러)&lt;/span&gt;&lt;span&gt;를 &lt;/span&gt;&lt;span&gt;통해 &lt;/span&gt;&lt;span&gt;들어오고, &lt;/span&gt;&lt;span&gt;이 &lt;/span&gt;&lt;span&gt;어댑터는 &lt;/span&gt;&lt;span&gt;애플리케이션 &lt;/span&gt;&lt;span&gt;계층의 &lt;/span&gt;&lt;span&gt;유즈케이스를 &lt;/span&gt;&lt;span&gt;실행한다. &lt;/span&gt;&lt;span&gt;유즈케이스는 &lt;/span&gt;&lt;span&gt;도메인 &lt;/span&gt;&lt;span&gt;모델과 &lt;/span&gt;&lt;span&gt;협력하며 &lt;/span&gt;&lt;span&gt;필요한 &lt;/span&gt;&lt;span&gt;작업을 &lt;/span&gt;&lt;span&gt;처리하고, &lt;/span&gt;&lt;span&gt;데이터 &lt;/span&gt;&lt;span&gt;저장이나 &lt;/span&gt;&lt;span&gt;외부 &lt;/span&gt;&lt;span&gt;API &lt;/span&gt;&lt;span&gt;호출이 &lt;/span&gt;&lt;span&gt;필요한 &lt;/span&gt;&lt;span&gt;경우에는 &lt;/span&gt;&lt;span&gt;아웃포트 &lt;/span&gt;&lt;span&gt;인터페이스를 &lt;/span&gt;&lt;span&gt;통해 퍼시스턴스&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;어댑터(&lt;/span&gt;&lt;span&gt;JPA, &lt;/span&gt;&lt;span&gt;Redis, &lt;/span&gt;&lt;span&gt;Kafka &lt;/span&gt;&lt;span&gt;등)&lt;/span&gt;&lt;span&gt;를 &lt;/span&gt;&lt;span&gt;호출한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_IMG_3707.jpg&quot; data-origin-width=&quot;3000&quot; data-origin-height=&quot;1617&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kD6gC/btsNSMzj6Eq/rFakLUSkN3AQpRpKTxQQqk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kD6gC/btsNSMzj6Eq/rFakLUSkN3AQpRpKTxQQqk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kD6gC/btsNSMzj6Eq/rFakLUSkN3AQpRpKTxQQqk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkD6gC%2FbtsNSMzj6Eq%2FrFakLUSkN3AQpRpKTxQQqk%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;3000&quot; height=&quot;1617&quot; data-filename=&quot;edited_IMG_3707.jpg&quot; data-origin-width=&quot;3000&quot; data-origin-height=&quot;1617&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;프로세스 흐름&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;Redis에 먼저 요청을 보내어 데이터가 있으면 바로 반환하고, 캐시에 저장된 데이터가 없는 경우에는 RDBMS에서 조회하여 Redis에 저장을 시킨 후에 반환이 되도록 한다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;cache hit / miss에 대한 처리는 Spring에서 제공하는 Spring Cache를 이용하면 편리하게 구현할 수 있다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;이번 강의에서는 수동으로 캐시 처리를 구현하는 것과 스프링을 이용하는 것 두 가지 방법을 모두 사용할 예정이다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;주요 기술&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;Spring + Redis (&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;SpringDataRedis를 구현하여 사용)&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;- RedisTempate&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp; &amp;nbsp;: Redis Operation에 대응되는 method 제공&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;- RedisRepository&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp; &amp;nbsp;: Spring Data에서 제공하는 interface로 접근&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;- @RedisHash&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp; &amp;nbsp;: Spring Data에서 사용하는 Redis에 hash로 저장될 데이터 (JPA의 Entity와 비슷한 개념)&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;필요한 의존성&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;- web&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;- jpa&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;- redis&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;- mongodb&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;- mysql&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;- (test) test&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;- (test) h2&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;- (test) mongodb&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;- (test) redis&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;그동안 항상 급하게 시작해서 그런지(ㅎㅎ;;) 프로젝트를 시작하기 전에 이렇게 자세하게 기술과 의존성에 대해 알아보는 건 처음이다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;간단하게나마 배경지식을 깔고 시작하는 것이 좋은 것 같다.&lt;/p&gt;</description>
      <category>패스트캠퍼스 챌린지</category>
      <category>습관형성</category>
      <category>오공완</category>
      <category>직장인자기계발</category>
      <category>패스트캠퍼스</category>
      <category>패스트캠퍼스후기</category>
      <category>환급챌린지</category>
      <author>ssoonearth</author>
      <guid isPermaLink="true">https://ssoonearth.tistory.com/41</guid>
      <comments>https://ssoonearth.tistory.com/41#entry41comment</comments>
      <pubDate>Sun, 11 May 2025 23:07:06 +0900</pubDate>
    </item>
    <item>
      <title>패스트캠퍼스 환급 챌린지 40일차 : 9개 도메인 프로젝트로 끝내는 백엔드 웹 개발 (Java/Spring) 초격차 패키지 Online 강의 후기</title>
      <link>https://ssoonearth.tistory.com/40</link>
      <description>&lt;p data-ke-size=&quot;size14&quot;&gt;본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성하였습니다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;a href=&quot;https://abit.ly/lisbva&quot;&gt;https://abit.ly/lisbva&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_3702.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYfA8B/btsNRL2hnwR/ZvwBk0dnaR9sSZvKnFiI7k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYfA8B/btsNRL2hnwR/ZvwBk0dnaR9sSZvKnFiI7k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYfA8B/btsNRL2hnwR/ZvwBk0dnaR9sSZvKnFiI7k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYfA8B%2FbtsNRL2hnwR%2FZvwBk0dnaR9sSZvKnFiI7k%2Fimg.jpg&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;600&quot; height=&quot;800&quot; data-filename=&quot;IMG_3702.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_3704.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cPyPYa/btsNRKWBeCC/i7pWiwp0AkrEPrAQctVLEk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cPyPYa/btsNRKWBeCC/i7pWiwp0AkrEPrAQctVLEk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cPyPYa/btsNRKWBeCC/i7pWiwp0AkrEPrAQctVLEk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcPyPYa%2FbtsNRKWBeCC%2Fi7pWiwp0AkrEPrAQctVLEk%2Fimg.jpg&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;600&quot; height=&quot;800&quot; data-filename=&quot;IMG_3704.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_3703.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;2253&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blzZPF/btsNRejiEer/My79xLi5GBfabOkMxxoaX0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blzZPF/btsNRejiEer/My79xLi5GBfabOkMxxoaX0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blzZPF/btsNRejiEer/My79xLi5GBfabOkMxxoaX0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblzZPF%2FbtsNRejiEer%2FMy79xLi5GBfabOkMxxoaX0%2Fimg.jpg&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;600&quot; height=&quot;447&quot; data-filename=&quot;IMG_3703.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;2253&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-10 오후 11.02.57.png&quot; data-origin-width=&quot;337&quot; data-origin-height=&quot;308&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bldiHp/btsNSO4Izi5/MBoY9KLz94s03CSSlHQ1O0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bldiHp/btsNSO4Izi5/MBoY9KLz94s03CSSlHQ1O0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bldiHp/btsNSO4Izi5/MBoY9KLz94s03CSSlHQ1O0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbldiHp%2FbtsNSO4Izi5%2FMBoY9KLz94s03CSSlHQ1O0%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;337&quot; height=&quot;308&quot; data-filename=&quot;스크린샷 2025-05-10 오후 11.02.57.png&quot; data-origin-width=&quot;337&quot; data-origin-height=&quot;308&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;패스트캠퍼스의 '9개 도메인 프로젝트로 끝내는 백엔드 웹 개발 (Java/Spring) 초격차 패키지 Online' 강의 수강 40일차!&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;오늘은 동영상 컨텐츠 서비스 개발 강의의 커리큘럼 설명 및 개발 요구 사항 분석에 대한 학습을 진행하였다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;동영상 컨텐츠 서비스 구성&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;컨텐츠 서비스 (웹툰, 웹소설, 음악, 비디오 서비스 등)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;ㄴ 동영상 컨텐츠 서비스&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; ㄴ 동영상 정보 (제목, 설명, 업로드 일자, url, 썸네일, 영상 길이 등)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; ㄴ 사용자 액션 (구독(채널 단위), 좋아요(비디오 단위), 댓글(비디오 단위))&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;&amp;nbsp; &amp;nbsp; ㄴ 동영상 전송 (CDN)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;컨텐츠 서비스와 커뮤니티 서비스의 비교&lt;/span&gt;&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 style=&quot;width: 20%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;컨텐츠 생성&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;컨텐츠 조회&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;목록 기준&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;시간이 지난 컨텐츠 조회&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;컨텐츠 서비스&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;적음&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;생성되는 컨텐츠 대비 많음&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;연관성, 랜덤&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;장기간 지속됨&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;커뮤니티 서비스&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;많음&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;생성되는 컨텐츠 대비 적음&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;시간순&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;조회가 집중되는 시기가 짧음&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;Redis와 RDBMS의 비교&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 style=&quot;width: 20%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;데이터 저장소&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;데이터 저장 방식&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;장점&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;단점&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;Redis&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;Memory&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;Key-Value&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;빠른 조회 속도, 다양한 데이터 구조&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;비싼 메모리 가격, 휘발성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;RDBMS&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;Disk&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;SQL&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;무결성, 복잡한 관계 처리&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;고정된 스키마, 확장의 어려움&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;Redis는 메모리에 저장되기 때문에 조회 속도가 빠르지만 비용이 많이 지불된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;Key-Value 타입으로 저장되는데, value의 타입이 기본적인 타입 외에도 Hash, List, Set 등 다양하게 제공된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;하지만 데이터 간의 연관관계를 맺는 것에는 어려움이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;Redis와 RDBMS의 장점을 활용하여 RDBMS에서 조회에 시간이 많이 소요되는 데이터를 Redis가 중간에 가지고 있다가 빠르게 반환해주는 캐시 방식으로 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;Chche (캐시)&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;- 자주 사용하는 데이터나 값을 미리 복사해 놓는 임시 저장소&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;캐시를 사용하면 또 다른 인프라가 추가되는 것이기 때문에 인프라에 대한 관리 비용이 추가되게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;또한 캐시가 셧다운된 경우 복구 비용과 대체 시스템 구축, 셧다운 시에 DB로 몰리는 요청을 감당하게 되는 등 비용적인 문제가 커지게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;이러한 비용을 감수하면서도 캐시 사용을 고려해야 하는 상황은 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;- 접근 시간에 비해 원래 데이터에 접근하는 시간이 오래 걸리는 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;- 반복적으로 동일한 결과를 돌려주는 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;생성은 적지만 조회는 많고, 변경이 잘 일어나지 않고, 내부적인 계산을 반복할 필요가 없는 컨텐츠 서비스의 특성상 캐시를 사용하면 이득을 볼 수 있게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;전의 커뮤니티 서비스 강의 수강을 모두 끝내고, 이번에는 동영상 컨텐츠 서비스 강의 수강을 시작하게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;늘 RDBMS만 사용해보고 Redis 같은 NoSQL은 처음 사용해보는 거여서 굉장히 기대가 된다!&lt;/p&gt;</description>
      <category>패스트캠퍼스 챌린지</category>
      <category>습관형성</category>
      <category>오공완</category>
      <category>직장인자기계발</category>
      <category>패스트캠퍼스</category>
      <category>패스트캠퍼스후기</category>
      <category>환급챌린지</category>
      <author>ssoonearth</author>
      <guid isPermaLink="true">https://ssoonearth.tistory.com/40</guid>
      <comments>https://ssoonearth.tistory.com/40#entry40comment</comments>
      <pubDate>Sat, 10 May 2025 23:17:49 +0900</pubDate>
    </item>
    <item>
      <title>패스트캠퍼스 환급 챌린지 39일차 : 9개 도메인 프로젝트로 끝내는 백엔드 웹 개발 (Java/Spring) 초격차 패키지 Online 강의 후기</title>
      <link>https://ssoonearth.tistory.com/39</link>
      <description>&lt;p data-ke-size=&quot;size14&quot;&gt;본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성하였습니다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;a href=&quot;https://abit.ly/lisbva&quot;&gt;https://abit.ly/lisbva&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_3694.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0h0co/btsNPguAJ3m/AKVQvf2wG2CTOKyq5gBfJ0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0h0co/btsNPguAJ3m/AKVQvf2wG2CTOKyq5gBfJ0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0h0co/btsNPguAJ3m/AKVQvf2wG2CTOKyq5gBfJ0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0h0co%2FbtsNPguAJ3m%2FAKVQvf2wG2CTOKyq5gBfJ0%2Fimg.jpg&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;600&quot; height=&quot;800&quot; data-filename=&quot;IMG_3694.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_IMG_3695.jpg&quot; data-origin-width=&quot;2250&quot; data-origin-height=&quot;2707&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bf5dSo/btsNQPQbjLL/MMJ9jsvDdhWU9G88KRdA0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bf5dSo/btsNQPQbjLL/MMJ9jsvDdhWU9G88KRdA0K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bf5dSo/btsNQPQbjLL/MMJ9jsvDdhWU9G88KRdA0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbf5dSo%2FbtsNQPQbjLL%2FMMJ9jsvDdhWU9G88KRdA0K%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;600&quot; height=&quot;722&quot; data-filename=&quot;edited_IMG_3695.jpg&quot; data-origin-width=&quot;2250&quot; data-origin-height=&quot;2707&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-09 오전 10.17.56.png&quot; data-origin-width=&quot;1976&quot; data-origin-height=&quot;1500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QzxXD/btsNPIxzgBl/0AQDL9AjuaxYuKGskTapg0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QzxXD/btsNPIxzgBl/0AQDL9AjuaxYuKGskTapg0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QzxXD/btsNPIxzgBl/0AQDL9AjuaxYuKGskTapg0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQzxXD%2FbtsNPIxzgBl%2F0AQDL9AjuaxYuKGskTapg0%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;600&quot; height=&quot;455&quot; data-filename=&quot;스크린샷 2025-05-09 오전 10.17.56.png&quot; data-origin-width=&quot;1976&quot; data-origin-height=&quot;1500&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-09 오전 9.51.49.png&quot; data-origin-width=&quot;334&quot; data-origin-height=&quot;67&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cV7l6i/btsNOiTVnYU/W3ekiZPnrZNp2aN5Wx1Iik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cV7l6i/btsNOiTVnYU/W3ekiZPnrZNp2aN5Wx1Iik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cV7l6i/btsNOiTVnYU/W3ekiZPnrZNp2aN5Wx1Iik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcV7l6i%2FbtsNOiTVnYU%2FW3ekiZPnrZNp2aN5Wx1Iik%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;334&quot; height=&quot;67&quot; data-filename=&quot;스크린샷 2025-05-09 오전 9.51.49.png&quot; data-origin-width=&quot;334&quot; data-origin-height=&quot;67&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;패스트캠퍼스의 '9개 도메인 프로젝트로 끝내는 백엔드 웹 개발 (Java/Spring) 초격차 패키지 Online' 강의 수강 39일차!&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;오늘은 커뮤니티 피드 서비스의 알림 기능 구현 작업을 진행하였다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #282c34; color: #bbbbbb;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Repository
@RequiredArgsConstructor
public class FcmMessageRepositoryImpl implements MessageRepository {

    private final JpaFcmTokenRepository jpaFcmTokenRepository;

    private static final String LIKE_MESSAGE_TEMPLATE = &quot;%s님이 %s님의 글에 좋아요를 눌렀습니다.&quot;;
    private static final String MESSAGE_KEY = &quot;message&quot;;

    @Override
    public void sendLikeMessage(User sender, User targerUser) {
        Optional&amp;lt;FcmTokenEntity&amp;gt; tokenEntity = jpaFcmTokenRepository.findById(targerUser.getId());
        if (tokenEntity.isEmpty()) {
            return;
        }

        FcmTokenEntity token = tokenEntity.get();
        Message message = Message.builder()
                .putData(MESSAGE_KEY, LIKE_MESSAGE_TEMPLATE.formatted(sender.getName(), targerUser.getName()))
                .setToken(token.getFcmToken())
                .build();
        FirebaseMessaging.getInstance().sendAsync(message);
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;저장되어 있는 토큰 정보를 타켓 유저에 맞게 불러와주고, 그 값이 없다면 그냥 발송하지 않게 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;유저가 푸시 토큰을 받을 토큰이 저장되어있다면 파이어베이스에서 제공하는 메세지를 만들어서 비동기로 전달해준다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #282c34; color: #bbbbbb;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Override
@Transactional
public UserAuth loginUser(String email, String password, String fcmToken) {
    UserAuthEntity userAuthEntity = jpaUserAuthRepository.findById(email).orElseThrow();
    UserAuth userAuth = userAuthEntity.toUserAuth();

    if (!userAuth.matchPassword(password)) {
        throw new IllegalArgumentException(&quot;옳지 않은 비밀번호입니다.&quot;);
    }

    userAuthEntity.updateLastLoginAt();
    jpaFcmTokenRepository.save(new FcmTokenEntity(userAuth.getUserId(), fcmToken));
    return userAuth;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;이전에 구현했던 로그인 로직에 fcmToken을 파라미터로 추가하고, jpaFcmTokenRepository를 통해 저장하여 로그인할 때 토큰값도 같이 저장되게 하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #282c34; color: #bbbbbb;&quot;&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;@Override
@Transactional
public void like(Post post, User user) {
    LikeEntity likeEntity = new LikeEntity(post, user);
    entityManager.persist(likeEntity);
    jpaLikeRepository.save(likeEntity);
    jpaPostRepository.updateLikeCount(post.getId(), 1);
    messageRepository.sendLikeMessage(user, post.getAuthor());
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;기존의 like 로직에 messageRepository를 추가하여, 좋아요를 누를 때 저장되어 있는 토큰 기반으로 메세지가 전달되게 하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;어플리케이션을 실행시켜 user1과 user2 계정으로 로그인하여 fcmToken값을 저장시킨 후, postman에서 like 요청을 보내면 크롬에서 알림이 뜨는 것과 개발자 도구에서도 메세지 정보가 뜨는 것을 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;이렇게 커뮤니티 피드 서비스 강의가 모두 마무리되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;40일에 가까운 시간 동안 매일 해오던 것이 끝나서인지 뭔가 아쉽다ㅠㅠ&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;이번 part1, part2 강의를 들으며 객체지향적인 설계부터 jwt, 쿼리 튜닝, firebase 활용 등 많은 것을 배울 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;특히, 내가 어려워했던 테스트 코드 기반의 클린 아키텍처의 중요성과 본질 및 활용법 등에 대해 정말 많이 배운 것 같아 기쁘고 뿌듯하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;백엔드 개발자로서 갖추어야 할 기본적이지만 그만큼 중요한 것들에 대한 내용이 알차게 담겨있어서 매우 만족스럽게 수강할 수 있었다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;좋은 강의 만들어주신 강사님께도 감사한 마음을 전합니다.. &amp;zwj;♀️ &lt;/p&gt;</description>
      <category>패스트캠퍼스 챌린지</category>
      <category>습관형성</category>
      <category>오공완</category>
      <category>직장인자기계발</category>
      <category>패스트캠퍼스</category>
      <category>패스트캠퍼스후기</category>
      <category>환급챌린지</category>
      <author>ssoonearth</author>
      <guid isPermaLink="true">https://ssoonearth.tistory.com/39</guid>
      <comments>https://ssoonearth.tistory.com/39#entry39comment</comments>
      <pubDate>Fri, 9 May 2025 10:20:59 +0900</pubDate>
    </item>
  </channel>
</rss>