<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>별걸 다 좋아하는 사람</title>
    <link>https://like-it-too.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Tue, 14 Apr 2026 15:21:04 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>넓고얕은사람</managingEditor>
    <item>
      <title>2025년 공부 내용은 깃허브에 기록 중 입니다.</title>
      <link>https://like-it-too.tistory.com/160</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/dmlal/DevStudy_Summary&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/dmlal/DevStudy_Summary&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1760594091709&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - dmlal/DevStudy_Summary: 공부한 개발 컨텐츠 요약 정리 용 레포지토리&quot; data-og-description=&quot;공부한 개발 컨텐츠 요약 정리 용 레포지토리. Contribute to dmlal/DevStudy_Summary development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/dmlal/DevStudy_Summary&quot; data-og-url=&quot;https://github.com/dmlal/DevStudy_Summary&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cvw9yt/hyZLkjiSFx/92gOJA8PFV6tOAzWPRhSv1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/zpCUz/hyZJ8ktguG/KlOJfdFdVKAOFVwDrE7MIk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/dmlal/DevStudy_Summary&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/dmlal/DevStudy_Summary&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cvw9yt/hyZLkjiSFx/92gOJA8PFV6tOAzWPRhSv1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/zpCUz/hyZJ8ktguG/KlOJfdFdVKAOFVwDrE7MIk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - dmlal/DevStudy_Summary: 공부한 개발 컨텐츠 요약 정리 용 레포지토리&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;공부한 개발 컨텐츠 요약 정리 용 레포지토리. Contribute to dmlal/DevStudy_Summary development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 정리해야할 일이 많아 깃허브로 이전하였습니다.&lt;/p&gt;</description>
      <author>넓고얕은사람</author>
      <guid isPermaLink="true">https://like-it-too.tistory.com/160</guid>
      <comments>https://like-it-too.tistory.com/160#entry160comment</comments>
      <pubDate>Thu, 16 Oct 2025 14:55:37 +0900</pubDate>
    </item>
    <item>
      <title>개인적으로 공부한 내용은 깃허브에 기록 중 입니다.</title>
      <link>https://like-it-too.tistory.com/notice/159</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/dmlal/DevStudy_Summary&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/dmlal/DevStudy_Summary&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1760594017296&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - dmlal/DevStudy_Summary: 공부한 개발 컨텐츠 요약 정리 용 레포지토리&quot; data-og-description=&quot;공부한 개발 컨텐츠 요약 정리 용 레포지토리. Contribute to dmlal/DevStudy_Summary development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/dmlal/DevStudy_Summary&quot; data-og-url=&quot;https://github.com/dmlal/DevStudy_Summary&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cvw9yt/hyZLkjiSFx/92gOJA8PFV6tOAzWPRhSv1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/zpCUz/hyZJ8ktguG/KlOJfdFdVKAOFVwDrE7MIk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/dmlal/DevStudy_Summary&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/dmlal/DevStudy_Summary&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cvw9yt/hyZLkjiSFx/92gOJA8PFV6tOAzWPRhSv1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/zpCUz/hyZJ8ktguG/KlOJfdFdVKAOFVwDrE7MIk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - dmlal/DevStudy_Summary: 공부한 개발 컨텐츠 요약 정리 용 레포지토리&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;공부한 개발 컨텐츠 요약 정리 용 레포지토리. Contribute to dmlal/DevStudy_Summary development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 기록 해야할 일이 많아 깃허브로 이전하였습니다.&lt;/p&gt;</description>
      <author>넓고얕은사람</author>
      <guid isPermaLink="true">https://like-it-too.tistory.com/notice/159</guid>
      <pubDate>Thu, 16 Oct 2025 14:54:01 +0900</pubDate>
    </item>
    <item>
      <title>실전 카프카 개발부터 운영까지 2</title>
      <link>https://like-it-too.tistory.com/158</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;카프카 주요 구성요소&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 카프카(또는 카프카 클러스터)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 브로커&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 카프카가 설치된 서버 또는 노드&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 프로듀서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 카프카로 메세지를 보내는 역할을 하는 클라이언트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 컨슈머&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 카프카에서 메세지를 꺼내가는 역할을 하는 클라이언트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 컨슈머는 특정 컨슈머 그룹에 속하며, 같은 그룹에 속한 컨슈머들은 토픽의 파티션을 분산 처리함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 기본적으로 컨슈머는 스티키 파티셔닝(Sticky Partitioning)을 사용. &lt;br /&gt;&amp;nbsp; &amp;nbsp; 이는 특정 컨슈머가 특정 파티션에 붙어서 계속해서 데이터를 처리하는 방식으로, 데이터 지역성을 높여 &lt;br /&gt;&amp;nbsp; &amp;nbsp; 캐시 히트율을 증가시키고 전반적인 처리 성능을 향상시킴.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 토픽&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 메시지를 저장하는 장소&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. 파티션&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 병렬 처리 및 고성능을 위해 하나의 토픽을 여러개로 나눔&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 파티션은 토픽을 물리적으로 나눈 단위로, 각 파티션은 독립적으로 메시지를 저장하고 관리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 각 파티션은 메시지를 순서대로 저장하며, 파티션 내의 메시지는 고유한 오프셋으로 식별&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 파티션을 통해 데이터를 병렬로 처리할 수 있으며, 클러스터 내의 여러 브로커에 분산시켜 저장할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7. 세그먼트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 프로듀서가 전송한 실제 메세지가 브로커의 로컬 디스크에 저장되는 파일&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;replication을 하면 토픽이 replication 되는게 아니라 토픽의 파티션이 replication 된다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레플리케이션 팩터 수가 커지면 안정성은 높아지지만 리소스를 많이 사용하게 되므로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;복제에 대한 오버헤드를 줄이고 최대한 브로커를 효율적으로 사용해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기준을 세우자면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트나 개발환경에서는 팩터 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영환경에서 약간의 유실이 허용되는 경우&amp;nbsp; 팩터2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유실을 허용하지 않는 운영환경&amp;nbsp; 팩터3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;경험에 비춰보자면 팩터 3에서도 충분히 메세지 안정성을 보장하며, 디스크 공간을 효율적으로 사용할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 그 이상으로 올리는 것은 고려해봐야할 사항&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;파티션&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 토픽을 여러개로 나눠 병렬 처리가 가능하게 함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하나를 여러개로 나누면 분산처리도 가능하며,&amp;nbsp; 이렇게 나눈 파티션 수만큼 컨슈머를 연결할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파티션은 초기 생성 후에 얼마든지 늘릴 수 있지만, 늘린 파티션을 다시 줄일수는없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;줄이는게 가능 할 경우 기존 파티션에 저장된 데이터를 새 파티션으로 이동해야 하고,&amp;nbsp; 이때 데이터 순서와 파티션 키 무결성을 보장할 수 없기 때문에 제약을 걸어둔 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;줄이고 싶다면 기존 토픽 데이터를 새 토픽으로 이동하면서 새 토픽에서 파티션 수를 기존보다 적게 만들면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>isAlreadyRead</category>
      <author>넓고얕은사람</author>
      <guid isPermaLink="true">https://like-it-too.tistory.com/158</guid>
      <comments>https://like-it-too.tistory.com/158#entry158comment</comments>
      <pubDate>Sun, 5 Jan 2025 16:22:54 +0900</pubDate>
    </item>
    <item>
      <title>실전 카프카 개발부터 운영까지</title>
      <link>https://like-it-too.tistory.com/157</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;525&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dyawnS/btsLCKSoqTW/z36fDN4hr8DEbdAHTPjKx1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dyawnS/btsLCKSoqTW/z36fDN4hr8DEbdAHTPjKx1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dyawnS/btsLCKSoqTW/z36fDN4hr8DEbdAHTPjKx1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdyawnS%2FbtsLCKSoqTW%2Fz36fDN4hr8DEbdAHTPjKx1%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;400&quot; height=&quot;525&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;525&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트에 카프카를 적용해야하여 카프카를 학습하는 중이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;강의와 서적 모두 학습 중인데 서적은 요약이 필요할 것 같아 대략적인 내용과 필요한 부분을 기록해 두려 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 카프카 버전이 현재와 많이 차이나므로 대략적으로 참고만 하는 식으로 진행할 것이며,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용 중단된 기능(Deprecated)에 대해서는 기록하지 않거나, 현재와의 차이점을 기록할 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1장. 카프카 개요&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;기업의 카프카 도입 사례와 카프카의 장점&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;아파치 카프카와 인플루언트 카프카의 차이&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 아파치 카프카는 자동차의 엔진이라면 &lt;br /&gt;&amp;nbsp; &amp;nbsp; 인플루언트 카프카는 각종 편의기능(네비게이션, 조향장치 등)이 모두 탑재된 완성된 자동차&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Apache Kafka와 Confluent Kafka의 주요 차이점&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style13&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;기능&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;Apache Kafka&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;Confluent Kafka&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;배포&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;오픈소스, 직접 설정&lt;/td&gt;
&lt;td&gt;상업적 배포, 기본 기능 포함 + 확장&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;운영 도구&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;직접 도구 설치 필요&lt;/td&gt;
&lt;td&gt;Control Center 등 다양한 도구 제공&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;데이터 관리&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Schema Registry 없음&lt;/td&gt;
&lt;td&gt;Schema Registry 제공&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;커넥터&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;기본 커넥터만 제공&lt;/td&gt;
&lt;td&gt;다수의 사전 빌드된 커넥터 제공&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;스트리밍 처리&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Streams API 제공&lt;/td&gt;
&lt;td&gt;Streams API + KSQL 지원&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;보안 및 인증&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;기본 보안 기능 제공&lt;/td&gt;
&lt;td&gt;강화된 보안 옵션 제공&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;지원&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;커뮤니티 기반&lt;/td&gt;
&lt;td&gt;상업적 지원 제공&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;비용&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;무료&lt;/td&gt;
&lt;td&gt;커뮤니티 버전 무료, 엔터프라이즈 유료&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;클라우드 배포&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;별도 설정 필요&lt;/td&gt;
&lt;td&gt;Confluent Cloud로 완전 관리형 제공&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;이벤트 드리븐 시스템 구성에서 가장 중요한 사항은 인바운드 데이터와 아웃바운드 데이터가 동일해야한다.&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;카프카 장점&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 빠른 데이터 수집이 가능한 높은 처리량&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 순서 보장&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; 이벤트 처리 순서가 보장되면서, 엔티티 간의 유효성 검사나 동시 수정 같은 복잡성 제거&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 적어도 한번 전송&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 카프카 클라이언트는 pull 방식으로 동작&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; pull은 자기자신의 속도로 데이터 처리 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; push는 브로커가 보내주는 속도에 의존&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 강력한 파티셔닝&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 이를 통해 수평확장 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;카프카 주요 특징&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 높은 처리량과 낮은 지연시간&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; -&amp;gt; 처리량은 카프가가 가장 높고, 응답속도만 보면 RabbitMQ가 가장 빠르지만,&amp;nbsp; 둘 다 함께 고려할 경우 카프카가 압도적&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 높은 확장성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; -&amp;gt; 기초 설계부터 확장성 고려&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 고가용성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; -&amp;gt; replcation 기능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 내구성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;람다 아키텍처?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 처리 아키텍처 중 배치 파이프라인과 실시간 파이프라인이 있는 아키텍처&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빅데이터를 처리하는 방식의 일종으로 하이브리드 방식으로 배치 처리나 스트림 처리를 이용할 수 있게 해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빅데이터를 실시간으로 분석하기 어렵기 때문에 대용량 데이터와 실시간 데이터를 결합해서 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아키텍처는 3개의 계층 (Batch, Serving, Speed 레이어) 으로 이루어져있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실시간 및 배치 처리를 동시에 제공하여 대용량 데이터 처리를 가능하게 하지만&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구현의 복잡성과 동일 로직을 각각 구현해야하는 코드의 중복이 있다. 그래서 디버깅이 어려움.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;837&quot; data-origin-height=&quot;462&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCkAn7/btsLEN7WM9x/w4ssc5Y2o9M7PAdWl3DzDk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCkAn7/btsLEN7WM9x/w4ssc5Y2o9M7PAdWl3DzDk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCkAn7/btsLEN7WM9x/w4ssc5Y2o9M7PAdWl3DzDk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCkAn7%2FbtsLEN7WM9x%2Fw4ssc5Y2o9M7PAdWl3DzDk%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;837&quot; height=&quot;462&quot; data-origin-width=&quot;837&quot; data-origin-height=&quot;462&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;카파 아키텍처?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;람다 아키텍처의 복잡성을 줄이기 위해 제안된 아키텍처로, 실시간 스트림 처리 중심으로 설계된 아키텍처이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단일 데이터 처리 파이프라인을 통해 모든 데이터를 실시간으로 처리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 데이터를 실시간으로 처리하므로 배치 레이어가 필요하지 않다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설계와 유지보수가 간단하다는 장점이 있고, 배치 레이어를 사용하지 않음으로 인해 중복구현이 필요없어졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 모든 데이터를 스트림 처리 방식으로 처리하므로, 매우 큰 배치 작업에서는 성능이 떨어질 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style13&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;특징&lt;/td&gt;
&lt;td&gt;람다 아키텍처&lt;/td&gt;
&lt;td&gt;카파 아키텍처&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;구조&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;배치 레이어 + 실시간 레이어&lt;/td&gt;
&lt;td&gt;단일 스트림 처리 레이어&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;복잡성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;높음&lt;/td&gt;
&lt;td&gt;낮음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;중복 구현&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;있음&lt;/td&gt;
&lt;td&gt;없음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;재처리 지원&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;제한적&lt;/td&gt;
&lt;td&gt;로그 시스템에서 재처리 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;실시간 처리 능력&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;배치와 실시간 결합으로 처리&lt;/td&gt;
&lt;td&gt;실시간 처리에 최적화&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;적용 사례&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;복잡한 데이터 처리 환경&lt;/td&gt;
&lt;td&gt;스트림 중심의 실시간 처리 환경&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;실제 운영 환경에서는 서비스의 안정성이 최우선이므로 단독 서버 형태로 운영하는 경우는 거의 없다.&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 카프카 최소 3개 쓰자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>isAlreadyRead</category>
      <author>넓고얕은사람</author>
      <guid isPermaLink="true">https://like-it-too.tistory.com/157</guid>
      <comments>https://like-it-too.tistory.com/157#entry157comment</comments>
      <pubDate>Sun, 5 Jan 2025 04:34:35 +0900</pubDate>
    </item>
    <item>
      <title>동시성이 터졌다.</title>
      <link>https://like-it-too.tistory.com/155</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1734158905361&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): 
[com.sparta.msa_exam.order.entity.Order#2]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아주 멋진 에러가 터졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;another transaction&amp;nbsp; &amp;nbsp;바로 동시성 문제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 낙관적 락을 걸어주었다.&lt;/p&gt;
&lt;pre id=&quot;code_1734159016383&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;jpa:
  properties: 
    hibernate:   
      use_version_always: true
      
      
엔티티엔
@Version 추가&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1734159051783&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Detached entity with generated id '2' has an uninitialized version value 'null': 
com.sparta.msa_exam.order.entity.Order.version&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뭐라는거야&amp;nbsp; 왜 못가져오는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 flush를 명시적으로 해주었다.&lt;/p&gt;
&lt;pre id=&quot;code_1734159075289&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;entityManager.persist(order);
orderRepository.save(order);
orderRepository.flush();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이젠 그냥 막 NPE 에러가 뜬다&lt;/p&gt;
&lt;pre id=&quot;code_1734159524894&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Cannot invoke &quot;java.util.List.stream()&quot; because the return value of 
&quot;com.sparta.msa_exam.order.entity.Order.getOrderProductList()&quot; is null&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영속성에서 저장이 문제구나 하는 생각에&lt;/p&gt;
&lt;pre id=&quot;code_1734159675798&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;List&amp;lt;OrderProductDto&amp;gt; orderProductDtoList = 
		Optional.ofNullable(order.getOrderProductList())                
			.orElse(Collections.emptyList()).stream()        
			.map(orderProduct -&amp;gt; new OrderProductDto(
					orderProduct.getProductId(), 
					orderProduct.getQuantity().getQuantity())
					).toList();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1734159698521&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Transactional
    public CreateOrderResponseDto createOrder(Long userId, CreateOrderRequestDto requestDto) {
        Order order = Order.builder()
                .userId(userId)
                .orderProductList(new ArrayList&amp;lt;&amp;gt;())
                .build();

        order = orderRepository.saveAndFlush(order);    // 이게 답이었다.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막부분을&amp;nbsp; save 대신 saveAndFlush로 날리니 어찌 해결은 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 또 이어서 에러가 터진다.&lt;/p&gt;
&lt;pre id=&quot;code_1734159755637&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SimpleMessageConverter only supports String, byte[] and Serializable payloads, received:
com.sparta.msa_exam.order.event.OrderCreateEvent&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SimpleMessageConverter는 String, byte[], Serializable 인터페이스를 구현한 객체만 지원한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 해당 객체를 직렬화 해주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 잭슨 컨터버를 추가하였다.&lt;/p&gt;
&lt;pre id=&quot;code_1734159893443&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class OrderCreateEvent implements Serializable {
    private Long orderId;
    private Long userId;
    private List&amp;lt;OrderProductDto&amp;gt; orderProductDtoList;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1734160014479&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        template.setMessageConverter(jackson2JsonMessageConverter());
        return template;
    }

    @Bean
    public Jackson2JsonMessageConverter jackson2JsonMessageConverter() {
        return new Jackson2JsonMessageConverter();
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러고 실행하니&lt;/p&gt;
&lt;pre id=&quot;code_1734160027014&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
    &quot;orderId&quot;: 1,
    &quot;userId&quot;: 1,
    &quot;totalPrice&quot;: 0,
    &quot;failedProductList&quot;: [
        1,
        2,
        3
    ]
}

실패에 담겼다.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주문 생성 실패 리스트에 담겼다.&lt;/p&gt;
&lt;pre id=&quot;code_1734160047692&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;for (Long productId : requestDto.getProductIdList()) {
            try {
                GetProductInfoResponseDto responseDto = productClient.getProductInfo(productId);
                OrderProduct orderProduct = new OrderProduct(order, productId, Price.of(responseDto.getPrice()), Quantity.of(responseDto.getQuantity()));
                order.addOrderProduct(orderProduct);
            } catch (CustomException e) {
                failedProductList.add(productId);
            }
        }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 역직렬화를 통해 해결하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기까지 완벽한 트러블슈팅이었으나,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애플리케이션 실행 시에 강제로 메세지큐가 실행되어 에러가 계속 발생하는 문제가 생겼다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 시도 끝에 메세지큐에 남아있는 요청이 문제라는 것을 확인하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 메세지큐 도커 내부에서 메세지큐를 비워주었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;명령어&quot;로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1734160165890&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker exec -it rabbitmq /bin/bash

rabbitmqctl purge_queue order.created.queue

exit&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;래빗MQ 웹으로 들어가는 관리자페이지는 default&amp;nbsp; 아이디, 패스워드를 입력하니 권한이 없다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 잘 아는 도커로 해야겠다.&lt;/p&gt;</description>
      <category>스파르타 심화/MSA 개인프로젝트</category>
      <author>넓고얕은사람</author>
      <guid isPermaLink="true">https://like-it-too.tistory.com/155</guid>
      <comments>https://like-it-too.tistory.com/155#entry155comment</comments>
      <pubDate>Sat, 14 Dec 2024 16:10:47 +0900</pubDate>
    </item>
    <item>
      <title>프로젝트 시작 - 대략적인 구상</title>
      <link>https://like-it-too.tistory.com/154</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문서로 제공된 요구사항 외에 내가 어떻게 구현해야할지에 대해 며칠을 고민했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;거의 3일을 어떻게 해야할지에 대해 고민만 한 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;먼저 DB에 대한 고민&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1732955586320&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;DB 분리 스키마 vs 테이블&quot; data-og-description=&quot;MSA 환경에서 데이터베이스를 어떻게 할 지 고민&amp;nbsp;도커컴포즈로 mysql과 레디스를 묶어 사용하려 했다.&amp;nbsp;이 경우 레디스는 key-space를 도메인 별로 나누면 된다.&amp;nbsp;하지만 mysql은 각 도메인마다 독립적&quot; data-og-host=&quot;like-it-too.tistory.com&quot; data-og-source-url=&quot;https://like-it-too.tistory.com/152&quot; data-og-url=&quot;https://like-it-too.tistory.com/152&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/f2158/hyXDhwZiEy/x0rKifvoGCtugg1O5R4BeK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/Z7S2r/hyXDmyh7fT/pyopMHZllYa2kWGLaOltz0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800&quot;&gt;&lt;a href=&quot;https://like-it-too.tistory.com/152&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://like-it-too.tistory.com/152&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/f2158/hyXDhwZiEy/x0rKifvoGCtugg1O5R4BeK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/Z7S2r/hyXDmyh7fT/pyopMHZllYa2kWGLaOltz0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;DB 분리 스키마 vs 테이블&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;MSA 환경에서 데이터베이스를 어떻게 할 지 고민&amp;nbsp;도커컴포즈로 mysql과 레디스를 묶어 사용하려 했다.&amp;nbsp;이 경우 레디스는 key-space를 도메인 별로 나누면 된다.&amp;nbsp;하지만 mysql은 각 도메인마다 독립적&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;like-it-too.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떻게 해야할지에 대해 고민했던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;깃허브 레포 관리에 대한 고민&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1732955623272&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;마이크로서비스 깃허브 관리방식&quot; data-og-description=&quot;MSA 프로젝트를 하며 깃허브 레포지토리를 어떻게 관리해야할지많은 고민이 생겨 이것저것 알아보았다.&amp;nbsp;깃허브 관리 방식에는 3가지를 찾을 수 있었다.&amp;nbsp;1. 모노레포 (Monorepo)2. 서브모듈 (Submodule)&quot; data-og-host=&quot;like-it-too.tistory.com&quot; data-og-source-url=&quot;https://like-it-too.tistory.com/151&quot; data-og-url=&quot;https://like-it-too.tistory.com/151&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/beD6JW/hyXC9eFIQw/YkxosAl6llfTQkskuPtdg0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/jBy3n/hyXGOmpghP/PWzTK30H17BbFOqwFeUhKk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800&quot;&gt;&lt;a href=&quot;https://like-it-too.tistory.com/151&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://like-it-too.tistory.com/151&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/beD6JW/hyXC9eFIQw/YkxosAl6llfTQkskuPtdg0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/jBy3n/hyXGOmpghP/PWzTK30H17BbFOqwFeUhKk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;마이크로서비스 깃허브 관리방식&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;MSA 프로젝트를 하며 깃허브 레포지토리를 어떻게 관리해야할지많은 고민이 생겨 이것저것 알아보았다.&amp;nbsp;깃허브 관리 방식에는 3가지를 찾을 수 있었다.&amp;nbsp;1. 모노레포 (Monorepo)2. 서브모듈 (Submodule)&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;like-it-too.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 쉽게 결정했는데&amp;nbsp; 프로젝트의 git 설정이 생각보다 귀찮았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에 잘해뒀어야했는데&amp;nbsp; 프로젝트 골조를 미리 다 만들고 init commit을 날리면 msa에선 대참사가 난다는걸 알아버렸다.&lt;/p&gt;
&lt;figure id=&quot;og_1732958280527&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;개빡치는 깃 - 하위 모듈 push rejected 해결?&quot; data-og-description=&quot;결과 스포&amp;nbsp;프로젝트 전체 삭제 후 다시 만듦&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;하면 안되는 행동 목록&amp;nbsp;1.&amp;nbsp; 모듈 remote 금지처음엔 main -&amp;gt;&amp;nbsp; 이곳이 비어있어서 remote해줬는데 절대 이러면 안된다.&amp;nbsp;루트디렉토리만 push가 되&quot; data-og-host=&quot;like-it-too.tistory.com&quot; data-og-source-url=&quot;https://like-it-too.tistory.com/153&quot; data-og-url=&quot;https://like-it-too.tistory.com/153&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bkqi5V/hyXDjO7AMB/TGrJMmO9a95xtTJZzm2In0/img.png?width=315&amp;amp;height=117&amp;amp;face=0_0_315_117,https://scrap.kakaocdn.net/dn/bI7gFz/hyXGCM1AIq/51X8fEl9VRaTRAE1CaDMr1/img.png?width=315&amp;amp;height=117&amp;amp;face=0_0_315_117,https://scrap.kakaocdn.net/dn/VPhvr/hyXGC7ljkX/oQrOK9NxD0HqQkkp3vXzWk/img.png?width=606&amp;amp;height=372&amp;amp;face=0_0_606_372&quot;&gt;&lt;a href=&quot;https://like-it-too.tistory.com/153&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://like-it-too.tistory.com/153&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bkqi5V/hyXDjO7AMB/TGrJMmO9a95xtTJZzm2In0/img.png?width=315&amp;amp;height=117&amp;amp;face=0_0_315_117,https://scrap.kakaocdn.net/dn/bI7gFz/hyXGCM1AIq/51X8fEl9VRaTRAE1CaDMr1/img.png?width=315&amp;amp;height=117&amp;amp;face=0_0_315_117,https://scrap.kakaocdn.net/dn/VPhvr/hyXGC7ljkX/oQrOK9NxD0HqQkkp3vXzWk/img.png?width=606&amp;amp;height=372&amp;amp;face=0_0_606_372');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;개빡치는 깃 - 하위 모듈 push rejected 해결?&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;결과 스포&amp;nbsp;프로젝트 전체 삭제 후 다시 만듦&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;하면 안되는 행동 목록&amp;nbsp;1.&amp;nbsp; 모듈 remote 금지처음엔 main -&amp;gt;&amp;nbsp; 이곳이 비어있어서 remote해줬는데 절대 이러면 안된다.&amp;nbsp;루트디렉토리만 push가 되&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;like-it-too.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 개인적으로 넣어보려는 것들의 목록이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1.&lt;/b&gt; &lt;b&gt;유저 권한&amp;nbsp; user / admin&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; a. admin은 &quot;주문 전체 조회&quot; 와 &quot;상품 정보 추가&quot;, &quot;상품 정보 수정&quot;, &quot;상품 정보 삭제&quot;&amp;nbsp; 기능을 가진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; b.&lt;b&gt; admin이 로그인 이후 권한이 변경 된 경우를 생각해서 서비스 쪽에서 한번 더 검증해줘야한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 이를 어떻게 할지 고민했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 권한은 무조건 게이트웨이 필터에서 검증하는 것이었고&amp;nbsp; 추가검증을 서비스에서 각자 해결할지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;auth를 타게할지에 대한 고민이었는데 auth를 타는것에 대해 나는 항상 부정적이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;auth를 타지않는다면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 게이트웨이 - 주문 - 프로덕트로&amp;nbsp; 깔끔하게 끝나는 반면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; auth를 탄다면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 게이트웨이 - 주문 - auth - 주문 - 프로덕트로&amp;nbsp; &amp;nbsp;중간과정이 2개나 추가된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;각 서비스가 통신을 통해 연결되기 때문에 과정이 길어진다는건&amp;nbsp; 처리시간 증가 및 에러 발생확률 증가와&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 긴밀하게 연관된다고 생각하여 전자로 구현하기로 결정했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2.&lt;/b&gt; &lt;b&gt;ddd 맛보기&amp;nbsp; (값 객체, 애그리거트, 4 레이어드 아키텍처)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; msa에&amp;nbsp; ddd의 몇 가지 개념을 선별해서 적용해 보려했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ddd 를 접목하면 도메인의 경계를 명확히하여 각 서비스의 역할과 책임을 명확히 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 이는 서비스가 다른 서비스의 영향을 덜 받게되며 서비스의 독립성 강화로 이어질 수 있다고 보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 그래서 값객체와 애그리거트 2가지 개념을 사용해보기로 하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;값객체&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;각 서비스의 중요한 컬럼을 외부의 변경으로부터 막을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;이를 통해 데이터 일관성을 유지할 수 있음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;현재 고려중인 부분은&amp;nbsp; 유저 - 유저네임,&amp;nbsp; &amp;nbsp;오더 - 주문 금액, 주문 상태,&amp;nbsp; &amp;nbsp;프로덕트 - 상품 가격, 수량&amp;nbsp; &amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;정도에 적용할 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;애그리거트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;관련된 데이터를 묶어 루트 애그리거트로만 접근하게 만들기 때문에&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;애그리거트를 통해 서비스 경계를 명확히 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;주문 - 주문금액 + 주문상품(id 제품명 수량 가격) + 주문 상태,&amp;nbsp; &amp;nbsp;프로덕트 -&amp;nbsp; &amp;nbsp;id 제품명 가격 수량&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 으로 사용할 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 4 레이어드 아키텍처&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 이것도 고려해보았으나&amp;nbsp; 지금 사용하는 패키지 구성과 비교했을 때 들인 시간에 비해 얻는 효율이 떨어질 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 같아&amp;nbsp; 다른 곳에 투자하기로 하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3.&lt;/b&gt; &lt;b&gt;rabbitMQ 사용&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;오더 생성 시에만 적용해보기로 하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;주문 생성 -&amp;gt; 재고 감소 메세지&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;재고 부족 -&amp;gt; 주문 취소 메세지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. 보상트랜잭션&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 오더 생성에만 적용해보기로 하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 재고 부족 -&amp;gt; 주문취소 메세지 일때&amp;nbsp; 보상트랜잭션을 사용하여 주문 취소 처리를 하는 것까지를 목표로 설정하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 주문상태를 cancelled로 변경,&amp;nbsp; 주문 데이터를 취소상태로 업데이트,&amp;nbsp; 주문 관련 트랜잭션 롤백&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 할 수 있다면 낙관적락까지 하면 좋겠지만 구현하다보면 서킷브레이커까지 엮일 것 같아&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;관련 시간이 매우 많이 들 것 같았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 그래서 일단은 패스하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>스파르타 심화/MSA 개인프로젝트</category>
      <author>넓고얕은사람</author>
      <guid isPermaLink="true">https://like-it-too.tistory.com/154</guid>
      <comments>https://like-it-too.tistory.com/154#entry154comment</comments>
      <pubDate>Sat, 30 Nov 2024 18:17:31 +0900</pubDate>
    </item>
    <item>
      <title>매우 화나는 깃 - 하위 모듈 push rejected 해결?</title>
      <link>https://like-it-too.tistory.com/153</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;결과 스포&amp;nbsp;&lt;/b&gt;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;프로젝트 전체 삭제 후 다시 만듦&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;하면 안되는 행동 목록&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1.&amp;nbsp; 모듈 remote 금지&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;315&quot; data-origin-height=&quot;117&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rAXLk/btsK1K6o8GC/jVPZ7IqGLevyruZJMWGhak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rAXLk/btsK1K6o8GC/jVPZ7IqGLevyruZJMWGhak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rAXLk/btsK1K6o8GC/jVPZ7IqGLevyruZJMWGhak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrAXLk%2FbtsK1K6o8GC%2FjVPZ7IqGLevyruZJMWGhak%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;315&quot; height=&quot;117&quot; data-origin-width=&quot;315&quot; data-origin-height=&quot;117&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음엔&lt;b&gt; main -&amp;gt;&amp;nbsp; 이곳이 비어있어서 remote해줬는데 절대 이러면 안된다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;루트디렉토리만 push가 되고 하위 모듈들은 푸시를 거절당하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;695&quot; data-origin-height=&quot;140&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9zJLA/btsK1pBqkhm/ftWMlVKgVWQUSNxBnfLWN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9zJLA/btsK1pBqkhm/ftWMlVKgVWQUSNxBnfLWN1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9zJLA/btsK1pBqkhm/ftWMlVKgVWQUSNxBnfLWN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9zJLA%2FbtsK1pBqkhm%2FftWMlVKgVWQUSNxBnfLWN1%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;695&quot; height=&quot;140&quot; data-origin-width=&quot;695&quot; data-origin-height=&quot;140&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;나처럼 이런 실수를 저질렀다면 위와 같이 해당 디렉토리로 이동해 명령어를 실행하면된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;인텔리제이 파워쉘 명령어이기 때문에 본인의 설정에 맞춰 진행하면 된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아무것도 안뜨면 성공한 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Get 하기 귀찮으면 폴더에서 .git 파일을 찾아보면 된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그 다음으로 진행한 해결방식들&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;608&quot; data-origin-height=&quot;154&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DMsiC/btsK25gXEEx/YtLXk41pvBjvbDpkXKkLn1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DMsiC/btsK25gXEEx/YtLXk41pvBjvbDpkXKkLn1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DMsiC/btsK25gXEEx/YtLXk41pvBjvbDpkXKkLn1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDMsiC%2FbtsK25gXEEx%2FYtLXk41pvBjvbDpkXKkLn1%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;608&quot; height=&quot;154&quot; data-origin-width=&quot;608&quot; data-origin-height=&quot;154&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대체 왜..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;rebase로 양쪽을 맞춰보기도 했지만 결과는 같았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여전히 커밋만 되고 깃허브에 푸시는 안되는 상태&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;633&quot; data-origin-height=&quot;225&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ceOCCZ/btsK2v8k2Cx/b2WCT9baytKxp7hy5ZLbCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ceOCCZ/btsK2v8k2Cx/b2WCT9baytKxp7hy5ZLbCK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ceOCCZ/btsK2v8k2Cx/b2WCT9baytKxp7hy5ZLbCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FceOCCZ%2FbtsK2v8k2Cx%2Fb2WCT9baytKxp7hy5ZLbCK%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;633&quot; height=&quot;225&quot; data-origin-width=&quot;633&quot; data-origin-height=&quot;225&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;git status로 상태를 보니&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;order와 product에 대해 git 이 아직 추적을 하고 있지 않았다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2&amp;nbsp; &amp;nbsp;add 생각없이 쓰기 금지&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;543&quot; data-origin-height=&quot;206&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHgA6r/btsK3j62yMX/n9ashv19Kin0dg0DQpL8uK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHgA6r/btsK3j62yMX/n9ashv19Kin0dg0DQpL8uK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHgA6r/btsK3j62yMX/n9ashv19Kin0dg0DQpL8uK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHgA6r%2FbtsK3j62yMX%2Fn9ashv19Kin0dg0DQpL8uK%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;543&quot; height=&quot;206&quot; data-origin-width=&quot;543&quot; data-origin-height=&quot;206&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;order와 product의 remote를 제거하고 (두번째 사진)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;add 명령어를 날려 추적을 하도록 하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 푸시하니&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;161&quot; data-origin-height=&quot;63&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bL13vj/btsK1YpOCuN/i7gNA73lTs7O5iwlFGU4x1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bL13vj/btsK1YpOCuN/i7gNA73lTs7O5iwlFGU4x1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bL13vj/btsK1YpOCuN/i7gNA73lTs7O5iwlFGU4x1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbL13vj%2FbtsK1YpOCuN%2Fi7gNA73lTs7O5iwlFGU4x1%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;161&quot; height=&quot;63&quot; data-origin-width=&quot;161&quot; data-origin-height=&quot;63&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;???&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;너무 멋있어서 박수 쳐주고싶고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빡쳐서 모듈을 싹 다 지운 다음 다시 등록하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;606&quot; data-origin-height=&quot;372&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dDNXqn/btsK1IgukU4/zB1hoUWuQLo07rOdkkwDJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dDNXqn/btsK1IgukU4/zB1hoUWuQLo07rOdkkwDJK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dDNXqn/btsK1IgukU4/zB1hoUWuQLo07rOdkkwDJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdDNXqn%2FbtsK1IgukU4%2FzB1hoUWuQLo07rOdkkwDJK%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;606&quot; height=&quot;372&quot; data-origin-width=&quot;606&quot; data-origin-height=&quot;372&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미 git init을 한 적이 있어서 깃이 이를 서브모듈로 인식한다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더이상 참지 못했다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;삭제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;삭제 후엔 침착하게&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유레카만 생성한 후 init commit을 날리고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;order와 product 모듈을 생성 후 다시 .git을 삭제해주고 init commit을 날리니 끝이 났다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인텔리제이 재실행시 매핑에 문제가 있다고하는데 무시하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인텔리제이 말 믿고 건드렸다간 push를 gui로 할 수 없게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;나도 알고 싶지 않았다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>오늘/Error</category>
      <author>넓고얕은사람</author>
      <guid isPermaLink="true">https://like-it-too.tistory.com/153</guid>
      <comments>https://like-it-too.tistory.com/153#entry153comment</comments>
      <pubDate>Fri, 29 Nov 2024 20:39:22 +0900</pubDate>
    </item>
    <item>
      <title>DB 분리 스키마 vs 테이블</title>
      <link>https://like-it-too.tistory.com/152</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MSA 환경에서 데이터베이스를 어떻게 할 지 고민&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도커컴포즈로 mysql과 레디스를 묶어 사용하려 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 경우 레디스는 key-space를 도메인 별로 나누면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 mysql은 각 도메인마다 독립적인 데이터베이스를 가져야하는데 어떻게 구현해야하나 고민이 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;방식은 두가지가 있다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 각 도메인이 다른 스키마를 사용&lt;/b&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 같은 스키마를 공유하되, 도메인 별로 테이블을 분리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 각 도메인이 다른 스키마를 사용&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Order는 order_db,&amp;nbsp; Product는 product_db,&amp;nbsp; Auth는 auth_db&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로 스키마를 분리할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 경우 각 도메인은 url이 분리되어 각자 독립적인 db를 보유한 것처럼 사용할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1732779325380&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;jdbc:mysql://mysql:3306/product_db
jdbc:mysql://mysql:3306/order_db
jdbc:mysql://mysql:3306/auth_db&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장점으로는 각 도메인이 물리적으로 다른 공간을 사용하기 때문에 충돌 가능성이 없으며,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터베이스 수준의 독립성을 가질 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 개별 스키마를 사용하므로 권한 제어 및 데이터 관리가 쉽다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제 발생 시 해당 스키마만 백업 또는 복구 할 수 있기 때문에 문제 해결이 쉽다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 MSA 확장 시 물리적으로 DB를 분리하기 쉽다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 같은 스키마를 공유하되, 도메인 별로 테이블을 분리&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;msa_example 이라는 스키마 아래에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;product, order, auth 테이블이 존재한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 경우엔 같은 도메인을 쓰고 내부에서 테이블이 독립적이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테이블끼리 직접 의존하지 않고 http 통신을 통해 데이터가 교환되기 때문에 논리적 독립성을 유지한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 구성이 쉬우며, 설정이 간편하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;결론&lt;/b&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;도커를 사용하는 기준에서는 스키마분리가 더 쉽다고 생각한다.&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도커컴포즈 yml에서 각 스키마를 작성해야하므로 코드가 길어진다는 것이 단점인데&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;yml파일을 단 한번만 작성하면 되므로 큰 문제는 아니라고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>프로그래밍/MSA</category>
      <author>넓고얕은사람</author>
      <guid isPermaLink="true">https://like-it-too.tistory.com/152</guid>
      <comments>https://like-it-too.tistory.com/152#entry152comment</comments>
      <pubDate>Thu, 28 Nov 2024 16:53:21 +0900</pubDate>
    </item>
    <item>
      <title>마이크로서비스 깃허브 관리방식</title>
      <link>https://like-it-too.tistory.com/151</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MSA 프로젝트를 하며 깃허브 레포지토리를 어떻게 관리해야할지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많은 고민이 생겨 이것저것 알아보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;깃허브 관리 방식에는 3가지를 찾을 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 모노레포 (Monorepo)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 서브모듈 (Submodule)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 다중 레포지토리 (Multi-repo)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 방식에 대해 간략히 설명해보자면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 모노레포 (Monorepo)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모노레포란 하나의 깃 레포지토리에서 여러 프로젝트 또는 서비스를 통합 관리하는 방식&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 서비스와 코드를 하나의 레포지토리에서 관리하는 것이 특징&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장점&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. CICD 파이프라인 설정과 코드 공유가 쉽다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 서비스 간 의존성 문제를 해결하기 쉽다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 같은 레포지토리에서 작업하므로 변경사항 추적이 쉬우며, 협업이 쉽다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 관련된 모든 변경사항을 한번의 커밋으로 관리할 수 있기 때문에 원자적으로 관리 가능하다. All or Nothing&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단점&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. msa지만 각 서비스의 독립적을 강조하기가 어렵다.&lt;br /&gt;&amp;nbsp; &amp;nbsp;특정 서비스만 배포하기 위해선 다른 관리방식보다 더 많은 설정이 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 프로젝트가 커질수록 작업에 애로사항이 많다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 서브모듈 (Submodule)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서브모듈은 하나의 깃 레포지토리에 다른 깃 레포지토리를 포함하여 관리할 수 있도록 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 사용하여 프로젝트 내에서 특정 서비스를 별도의 깃 레포지토리로 관리하면서도 메인 프로젝트와 연동할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;독립적인 저장소이므로 메인의 일부이지만, 별도의 커밋 히스토리와 브랜치를 가진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장점&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 버전관리를 독립적으로 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 공통 코드의 경우 여러 프로젝트에서 서브모듈로 추가하여 코드의 중복을 제거할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 그래서 msa에서 dto, 유틸리티 메서드, 글로벌 예외처리로직을 별도의 저장소로 관리하고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 각 서비스의 서브모듈로 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 서브모듈만 독립적으로 빌드하고 배포할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단점&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 서브모듈의 버전 동기화가 까다롭다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 메인 레포지토리에서 서브모듈의 버전을 명시적으로 업데이트 해주어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 메인과 서브모듈 간 의존성이 생기면 두 레포지토리의 변경사항을 동시에 관리해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 서브모듈의 변경사항을 메인에 제때 반영하지않으면 버전차이가 발생할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 팀원들이 모두 서브모듈 사용법을 숙지하고 있어야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 독립적으로 배포가능하다는 장점이 있으나, CICD 파이프라인 설정이 까다롭다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. 다중 레포지토리&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 프로젝트나 서비스를 독립된 깃 레포지토리로 관리하는 방식.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 서비스가 완전한 독립성을 가질 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장점&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 완전히 독립적이기 때문에 다른 서비스의 영향을 받지 않고&amp;nbsp; 개발 및 배포가 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 레포지토리의 크기가 작기 때문에 깃 속도가 빠름&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 서비스 별로 CICD 파이프라인을 각각 설정할 수 있어 커스텀이 쉽다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단점&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 의존성 관리가 어렵다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 글로벌로 사용되는 공통 코드 관리에 추가적인 작업이 필요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 변경 사항 추적이 어렵다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 여러 레포지토리에 영향을 미치는 커밋의 경우 추적이 쉽지 않다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 방식을 알아보며 위와 같이 정리할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 프로젝트는 규모가 크지 않으며, MSA에 대한 이해도가 낮으므로&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모노레포가 가장 적합하다고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서브모듈의 경우 혼자서는 학습 후 적용할 수 있지만, 팀의 모든 인원이 서브모듈에 대한 이해도가 필요하기 때문에 힘들 것 같고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다중 레포지토리는 서비스의 규모가 작기 때문에 적용하기엔 과하다고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;결국 모노레포&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>프로그래밍/MSA</category>
      <author>넓고얕은사람</author>
      <guid isPermaLink="true">https://like-it-too.tistory.com/151</guid>
      <comments>https://like-it-too.tistory.com/151#entry151comment</comments>
      <pubDate>Thu, 28 Nov 2024 02:18:16 +0900</pubDate>
    </item>
    <item>
      <title>Commit Count 확장  -  로그(TIL) 카운트  EventListener Error</title>
      <link>https://like-it-too.tistory.com/150</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커밋카운트 로직을 바탕으로 알고리즘 카운트, 로그(TIL) 카운트 를 만들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1732611525475&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    @EventListener
    @Async
    public void handleLogSubmitEvent(LogSubmitEvent event) {
        logCountService.updateLogCountOnSubmit(event.getUserId());
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 곳에는 비동기를 적용하여&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 제출한 이후 카운트를 따로 처리하게 함으로써&amp;nbsp; 제출 이후 바로 다른 작업을 할 수 있도록 하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;922&quot; data-origin-height=&quot;622&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVlpTq/btsKXi2vAeS/CCoLuBfsIoL2nKIauHKk11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVlpTq/btsKXi2vAeS/CCoLuBfsIoL2nKIauHKk11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVlpTq/btsKXi2vAeS/CCoLuBfsIoL2nKIauHKk11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVlpTq%2FbtsKXi2vAeS%2FCCoLuBfsIoL2nKIauHKk11%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;922&quot; height=&quot;622&quot; data-origin-width=&quot;922&quot; data-origin-height=&quot;622&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트코드를 작성하여&amp;nbsp; 간단히 로그 제출 -&amp;gt; 제출하며 카운트 이벤트 호출 로직으로 구성하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 테스트에서 문제가 발생하였고,&amp;nbsp; 비동기가 제대로 적용되지 않은것이라 생각해&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1732613714500&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; Awaitility.await()
                .atMost(5, TimeUnit.SECONDS)
                .untilAsserted(() -&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기에 5초를 주고 다음엔 30초씩 줘가며 확인을 하였지만 실패하였고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션이 제대로 돌아가지 않는게 문제인가 해서 트랜잭션을 삭제하고 afterEach로 레포지토리를 비워주었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 테스트는 성공하였으나 테스트 내부에서 에러가 발생하였고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;깔끔한 테스트 성공을 위해 testConfig를 하나 더 만들어서 적용하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1732613804437&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;org.springframework.transaction.UnexpectedRollbackException: 
Transaction silently rolled back because it has been marked as rollback-only&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트 코드에서 트랜잭션을 없앴지만 서비스코드에 남아있어서 이런 에러가 발생한다고 판단하였고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1732613865191&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Transactional(propagation = Propagation.REQUIRES_NEW)

public void updateLogCountOnSubmit(Long userId)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션의 전파 속성을 변경해보았지만 결과는 같았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 다시 일반 트랜잭션으로 되돌리고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1732613931805&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    @EventListener
    @Async
    public void handleLogSubmitEvent(LogSubmitEvent event) {
        logCountService.updateLogCountOnSubmit(event.getUserId());
    }
}

    @TransactionalEventListener
    @Async
    public void handleLogSubmitEvent(LogSubmitEvent event) {
        logCountService.updateLogCountOnSubmit(event.getUserId());
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이벤트에서 이벤트리스너를 트랜잭션이벤트리스너로 변경하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로직 상 제출이 완료 된 후 카운트를 체크하는 것이 맞기에 제출 트랜잭션이 끝난 후 카운트 트랜잭션이 실행되도록&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 트랜잭션을 두 개로 분리하였다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;277&quot; data-origin-height=&quot;97&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lqXNN/btsKXKj5kuv/F2PCgKbJmGz3FQFQdITFmk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lqXNN/btsKXKj5kuv/F2PCgKbJmGz3FQFQdITFmk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lqXNN/btsKXKj5kuv/F2PCgKbJmGz3FQFQdITFmk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlqXNN%2FbtsKXKj5kuv%2FF2PCgKbJmGz3FQFQdITFmk%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;277&quot; height=&quot;97&quot; data-origin-width=&quot;277&quot; data-origin-height=&quot;97&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존에는 submitLog 테스트는 성공했으나&lt;/p&gt;
&lt;pre id=&quot;code_1732614122869&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Log saveLog = logRepository.findByAddressAndUserId(submitLogDto.getAddress(), user.getId())
.orElseThrow(() -&amp;gt; new AssertionError(&quot;로그 못찾음&quot;));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 에러가 계속 발생하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 비동기쪽 문제라고 생각하여 이것저것 건드려보았는데 이벤트 관련 트랜잭션을 나누는 것이 정답이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;요약&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 @Async와 @EventListener 를 조합해서 이벤트리스너가 비동기적으로 동작하도록 설정했는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게하면 로그 제출작업이 완료되기 전에 로그 카운트 증가작업이 시작될 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 로그 제출 트랜잭션이 아직 완료되지 않아 DB에 저장되지 않은 상태에서 이벤트가 실행될 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카운트 증가를 위해 로그를 조회할 때 해당로그를 찾기 못했던 것이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 애너테이션을 변경하여 제출 트랜잭션이 커밋된 이후에 실행되도록 하였고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 통해 로그가 성공적으로 제출된 이후에 이벤트 리스너가 실행되므로 계속해서 발생하던 에러를 해결할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 성공 이후 위의 config를 삭제한 후 실행했음에도 문제가 발생하지 않았고, 성공적으로 실행되는 것으로 보아&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜잭션 분리가 답이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비동기 이벤트 처리와 트랜잭션 타이밍이 불일치하는 것이 원인이었고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애너테이션 변경을 통해 이벤트 실행 시점을 트랜잭션 완료 후로 조정하여 문제를 해결하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>devRace</category>
      <author>넓고얕은사람</author>
      <guid isPermaLink="true">https://like-it-too.tistory.com/150</guid>
      <comments>https://like-it-too.tistory.com/150#entry150comment</comments>
      <pubDate>Tue, 26 Nov 2024 18:46:51 +0900</pubDate>
    </item>
  </channel>
</rss>