<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>부동산 공부하는 개발자</title>
    <link>https://munu8989.tistory.com/</link>
    <description>부동산, IT, 육아 관련 경험을 공유합니다.</description>
    <language>ko</language>
    <pubDate>Fri, 10 Apr 2026 22:43:16 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>쏘롱마니</managingEditor>
    <image>
      <title>부동산 공부하는 개발자</title>
      <url>https://tistory1.daumcdn.net/tistory/3710758/attach/17112a36949c403fadeff3fa620f28a4</url>
      <link>https://munu8989.tistory.com</link>
    </image>
    <item>
      <title>immutable하고 빈이 아닌 맴버필드 DI하기(feat. @value)</title>
      <link>https://munu8989.tistory.com/13</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;문제상황&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;b&gt; &lt;span&gt;서비스에 멤버필드를 넣었고 해당 필드를 immutable 하게 만들기위해 final로 선언했고, @value로 값을 주입했다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;아래 그림처럼-&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cxPhXd/btqFXJERjpo/ftENU61yfK5GS497kmlh2k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cxPhXd/btqFXJERjpo/ftENU61yfK5GS497kmlh2k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cxPhXd/btqFXJERjpo/ftENU61yfK5GS497kmlh2k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcxPhXd%2FbtqFXJERjpo%2FftENU61yfK5GS497kmlh2k%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;아래그림처럼 바로 &quot;String이라는 빈이 없는데?&quot; 라며 에러가 터져버린다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/E66rd/btqFZM8sTJq/wYD3PU7Mc4adOy8pMHBCk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/E66rd/btqFZM8sTJq/wYD3PU7Mc4adOy8pMHBCk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/E66rd/btqFZM8sTJq/wYD3PU7Mc4adOy8pMHBCk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FE66rd%2FbtqFZM8sTJq%2FwYD3PU7Mc4adOy8pMHBCk0%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;음... @RequiredArgsConstructor를 통해서 생성자를 만들때 final이 잘 초기화 될거라 생각했는데.. 갑자기 String을 빈으로 인식해버리네..?&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;그럼 직접 생성자를 만들어서, 초기화를 시켜주는 방법을 고안해보았다. 먼저 아래그림처럼 생성자를 만들었다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PbC3X/btqFZxRfxgG/4WLyZjqTSM0ioYe9kY6rqk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PbC3X/btqFZxRfxgG/4WLyZjqTSM0ioYe9kY6rqk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PbC3X/btqFZxRfxgG/4WLyZjqTSM0ioYe9kY6rqk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPbC3X%2FbtqFZxRfxgG%2F4WLyZjqTSM0ioYe9kY6rqk%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;생성자만 만들면 @&lt;span style=&quot;color: #333333;&quot;&gt;RequiredArgsConstructor 때와 동일하게 String을 빈으로 인식해서 빈객체로 만들려한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;그럼 결론적으로 &lt;b&gt;&lt;span&gt;&lt;span&gt;빈이 아닌 멤버필드&lt;/span&gt;를&amp;nbsp;&lt;span&gt;@value를 사용해서&lt;/span&gt; &lt;span&gt;immutable 하게&amp;nbsp;&lt;/span&gt;&amp;nbsp;어떻게 쓸수있을까!?&lt;/span&gt; &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;아래그림처럼 선언하면 가능해진다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZEJkG/btqFZ4A3olF/vLJIzXKiQabgHcvU5EFS1K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZEJkG/btqFZ4A3olF/vLJIzXKiQabgHcvU5EFS1K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZEJkG/btqFZ4A3olF/vLJIzXKiQabgHcvU5EFS1K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZEJkG%2FbtqFZ4A3olF%2FvLJIzXKiQabgHcvU5EFS1K%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;정리&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;&lt;span&gt;1. @RequiredArgsConstructor 는 생성자 파라미터가 무조건 빈이라고 보기때문에 생성자를 통해 객체를 만들때 에러가 나는거라 유추된다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;span&gt;&lt;span&gt;2. 직접 생성자를 만들어서 생성자를 통해 객체를 만들때 @Value를 통하여 이 파라미터가 빈이 아니라는걸 명시 가능!&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;</description>
      <category>개발/문제해결</category>
      <category>@vALUE</category>
      <category>bean</category>
      <category>DI</category>
      <category>final</category>
      <category>immutable</category>
      <author>쏘롱마니</author>
      <guid isPermaLink="true">https://munu8989.tistory.com/13</guid>
      <comments>https://munu8989.tistory.com/13#entry13comment</comments>
      <pubDate>Fri, 24 Jul 2020 11:24:21 +0900</pubDate>
    </item>
    <item>
      <title>About Generic Wildcard</title>
      <link>https://munu8989.tistory.com/12</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;와일드 카드 &lt;b&gt;제네릭이&lt;/b&gt;란?&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;b&gt;레퍼런스 타입의 제네릭을 좀더 넓게! 제한 하는것.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;제한을 런타임 시점에 강제하는것.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이 두가지가 키포인트라 생각된다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&quot;레퍼런스 타입의 제네릭을 좀더 넓게! 제한하는것&quot; 의미&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;일반적으로 List&amp;lt;Number&amp;gt; 이 되면 &lt;span style=&quot;color: #333333;&quot;&gt;Number&lt;/span&gt;타입에 정확히 맞춰야한다.(자바의 강력한 타입 체킹)&lt;/p&gt;
&lt;p&gt;그러나 제네릭 와일드 카드를 사용하게 되면 List&amp;lt;? extends &lt;span style=&quot;color: #333333;&quot;&gt;Number&lt;/span&gt;&amp;gt; 처럼 쓸수 있고&lt;/p&gt;
&lt;p&gt;이는 String 을 상속받는 하위 클래스들을 모두~유연~하게 사용할수 있다는 장점을 갖게 된다.!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&quot;제한을 런타임 시점에 강제하는것&quot; 의미&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;일반 제네릭은 &amp;lt;T extends Number&amp;gt; 처럼 제한을 무엇으로 할지를 &lt;b&gt;컴파일 타임&lt;/b&gt;에 강제한다&lt;/p&gt;
&lt;p&gt;그러나, 와일드카드 제네릭은 &amp;lt;? extends T&amp;gt; 처럼&amp;nbsp; 제한을 &lt;b&gt;런타임 시점&lt;/b&gt;에 강제한다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;결론&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;제네릭의 제한을 넓게, 런타임시점에 입맛에 맞게 하고 싶을때 쓰면 좋을듯 하다.&lt;/p&gt;
&lt;p&gt;그런데 제네릭이란 본래 타입제한을 통한 에러를 걸러내는 역할도 하느것인데,, 너무 넓게 제한을 잡아버리면&lt;/p&gt;
&lt;p&gt;그 본래 기능이 퇴색? 될수있기때문에 상황에 따라 잘써야겠다..!&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/자바</category>
      <category>generic</category>
      <category>Wildcard</category>
      <author>쏘롱마니</author>
      <guid isPermaLink="true">https://munu8989.tistory.com/12</guid>
      <comments>https://munu8989.tistory.com/12#entry12comment</comments>
      <pubDate>Wed, 15 Jul 2020 11:14:10 +0900</pubDate>
    </item>
    <item>
      <title>분산 transaction 해결방법</title>
      <link>https://munu8989.tistory.com/11</link>
      <description>&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;SAGA&amp;nbsp; 패턴 : 보상 트랜잭션을 사용한 해결방법&lt;/b&gt;&lt;/li&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;
&lt;p&gt;이벤트 드리븐 방식 :&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;각 서비스의 트랜잭션에서 이벤트를 발생시킴.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;이벤트가 성공이면&amp;nbsp; 다른 서비스의 트랜잭션을 수행시킨다. .&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;이벤트가 실패면 다른 서비스에게 보상 트랜잭션을 수행시킨다.&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;각 서비스들은 어떤 이벤트를 받아야하는지 알기가 쉽지않아..&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Orderchestration 방식&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;하나의 Orchstration 서비스에서 트랜잭션을 관리한다.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;결제 완료 프로세스 ( pg사 결제완료(pay) -&amp;gt; 포인트/쿠폰 소멸(member))&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;이 결제 완료 서비스를 총괄하는 하나의 서비스가 있어야함. 그 어느 한서비스에서 뻑나면 롤백 프로세스를 태우면됨&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;서비스간 종속이 없어져서 좋긴한데, orchestration 서비스 생성 리소스가 크게듬&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;TCC( Try-cancle-comfirm ) : rest호출로 해결방법&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;staging repository와 실제 repository를 나눠 놓는것이 핵심 포인트!&lt;/li&gt;
&lt;li&gt;try 단계에서는 staging repository에 작업을 함.&lt;/li&gt;
&lt;li&gt;한 프로세스가 문제없이 끝나면 그제서야, 실제 repository에 작업을함.&lt;/li&gt;
&lt;li&gt;한 프로세스에서 문제가 생기면 cancle api를 호출하여 staging repository에 저장된 data 상태를 &quot;cancle&quot;이나 지워놓으면 그만&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.popit.kr/rest-%EA%B8%B0%EB%B0%98%EC%9D%98-%EA%B0%84%EB%8B%A8%ED%95%9C-%EB%B6%84%EC%82%B0-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98-%EA%B5%AC%ED%98%84-1%ED%8E%B8/&quot;&gt;참고 사이트 &lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;figure id=&quot;og_1594104192390&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;website&quot; data-og-title=&quot;REST 기반의 간단한 분산 트랜잭션 구현 - 1편 | Popit&quot; data-og-description=&quot;REST 기반의 간단한 분산 트랜잭션 구현 -1편 TCC 개관 REST 기반의 간단한 분산 트랜잭션 구현 - 2편 TCC Cancel, Timeout REST 기반의 간단한 분산 트랜잭션 구현 - 3편 TCC Confirm(Eventual Consistency) REST 기반의 &quot; data-og-host=&quot;www.popit.kr&quot; data-og-source-url=&quot;https://www.popit.kr/rest-%EA%B8%B0%EB%B0%98%EC%9D%98-%EA%B0%84%EB%8B%A8%ED%95%9C-%EB%B6%84%EC%82%B0-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98-%EA%B5%AC%ED%98%84-1%ED%8E%B8/&quot; data-og-url=&quot;http://www.popit.kr/rest-기반의-간단한-분산-트랜잭션-구현-1편/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/U7G5n/hyGHoqKDLB/ok13oOdrIqGMm4Ya15ybd1/img.png?width=884&amp;amp;height=458&amp;amp;face=0_0_884_458,https://scrap.kakaocdn.net/dn/CcZJH/hyGFZsBBgV/ZDnYbkGZ5gSfAyuBzbWJ2k/img.png?width=884&amp;amp;height=458&amp;amp;face=0_0_884_458,https://scrap.kakaocdn.net/dn/bsC0lA/hyGFJ4nk7S/EBx5rWB36bduE8Quix06CK/img.png?width=950&amp;amp;height=692&amp;amp;face=0_0_950_692&quot;&gt;&lt;a href=&quot;https://www.popit.kr/rest-%EA%B8%B0%EB%B0%98%EC%9D%98-%EA%B0%84%EB%8B%A8%ED%95%9C-%EB%B6%84%EC%82%B0-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98-%EA%B5%AC%ED%98%84-1%ED%8E%B8/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.popit.kr/rest-%EA%B8%B0%EB%B0%98%EC%9D%98-%EA%B0%84%EB%8B%A8%ED%95%9C-%EB%B6%84%EC%82%B0-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98-%EA%B5%AC%ED%98%84-1%ED%8E%B8/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/U7G5n/hyGHoqKDLB/ok13oOdrIqGMm4Ya15ybd1/img.png?width=884&amp;amp;height=458&amp;amp;face=0_0_884_458,https://scrap.kakaocdn.net/dn/CcZJH/hyGFZsBBgV/ZDnYbkGZ5gSfAyuBzbWJ2k/img.png?width=884&amp;amp;height=458&amp;amp;face=0_0_884_458,https://scrap.kakaocdn.net/dn/bsC0lA/hyGFJ4nk7S/EBx5rWB36bduE8Quix06CK/img.png?width=950&amp;amp;height=692&amp;amp;face=0_0_950_692');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot;&gt;REST 기반의 간단한 분산 트랜잭션 구현 - 1편 | Popit&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;REST 기반의 간단한 분산 트랜잭션 구현 -1편 TCC 개관 REST 기반의 간단한 분산 트랜잭션 구현 - 2편 TCC Cancel, Timeout REST 기반의 간단한 분산 트랜잭션 구현 - 3편 TCC Confirm(Eventual Consistency) REST 기반의&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;www.popit.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/MSA</category>
      <category>MSA</category>
      <category>분산 transaction</category>
      <author>쏘롱마니</author>
      <guid isPermaLink="true">https://munu8989.tistory.com/11</guid>
      <comments>https://munu8989.tistory.com/11#entry11comment</comments>
      <pubDate>Tue, 7 Jul 2020 15:47:04 +0900</pubDate>
    </item>
    <item>
      <title>옵저버 패턴 정리</title>
      <link>https://munu8989.tistory.com/10</link>
      <description>&lt;p style=&quot;text-align: justify;&quot;&gt;두가지 책으로 간단하게 정리했다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot;&gt;&lt;b&gt;- 디자인패턴입문 핵심내용&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;
&lt;p&gt;observer 패턴은 subject(피 관찰자)와 observer(관찰자)로 나뉜다&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;observer는 실제로 관찰자라는 의미지만 실제로 observer 패턴에서는 &lt;span&gt;능동적인 관찰이라기 보다는 &lt;/span&gt;subject 로부터 상태가 바뀜?을 전달되는것을 기다립니다.&amp;nbsp; &lt;span&gt;즉 Publish-Subscribe 패턴이라하는게 더 적당함.&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;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;- 헤드퍼스트 핵심내용&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;subject:obsever가 다대다가 될수 있음.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;
&lt;p&gt;예를들면 subject에 서울기상청, 부산기상청, 대전기상청은&amp;nbsp; 한국기상청꺼를 사용하여 implement함,,&amp;nbsp; 근데 나는 현재 서울기상청한테 publishing을 받아서 서울기상어플을만들었는데, 이제 부산기상어플로 바꾸려할때&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;subject가 observer에게 전달할때 본 객체자체를 넘기도록 하는게 좋다(푸시방식이 아닌 풀방식)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;옵저버들은 각자가 필요한 데이터들이 다를수있다. subject가 그 모두 다른 옵저버의 입맛을 챙겨주기엔 무리다.&lt;/li&gt;
&lt;li&gt;만약 subject가 확장되면서 정보들이 늘었다고치자, 그럼 퍼블릭 게터하나만 뚫어주면된다.&amp;nbsp; &amp;nbsp;안그러면 메소드를 수정하는일이 생길거다.
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>개발/디자인패턴</category>
      <category>observer</category>
      <category>옵저버</category>
      <author>쏘롱마니</author>
      <guid isPermaLink="true">https://munu8989.tistory.com/10</guid>
      <comments>https://munu8989.tistory.com/10#entry10comment</comments>
      <pubDate>Fri, 3 Jul 2020 18:56:00 +0900</pubDate>
    </item>
    <item>
      <title>프록시 패턴 정리</title>
      <link>https://munu8989.tistory.com/9</link>
      <description>&lt;p&gt;두가지 책에서 프록시 패턴을 정리해보았다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;- java 언어로 배우는 디자인 패턴 입문&lt;/b&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;
&lt;p&gt;Proxy의 뜻 &quot;대리인&quot;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;대리인이 본인을 대신해 대부분의 업무를 하다가, 중요하거나, 무거운 업무만 본인이 하게끔 하는 방식&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;가상 프록시 패턴을 쓰는이유?&lt;/p&gt;
&lt;/li&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;
&lt;p&gt;속도 올리기: 인스턴스 생성이 불필요한 작업을 할때는 인스턴스를 초기화 안함으로써 그 리소스를 절약한다. lazy init!(가상프록시)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;
&lt;p&gt;등장주제는 주체 클래스, 프록시 클래스, 본인과 프록시가 구현하는 인터페이스 정도로 나뉨&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;프록시 클래스, 본인 클래스는 강한결합이다.&lt;/p&gt;
&lt;/li&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;
&lt;p&gt;왜냐면 프록시 클래스가 본인클래스 필드 자체를 들고있기 떄문에..&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;그런데 (Prinatable) Class.forName(className).newInstance() 처럼 리플렉션을 사용하면 Pritanble 구현한 본인 객체가 무엇이던간에&amp;nbsp; 프록시 클래스는 영향을 안받을수있다..!&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;- 헤드퍼스트&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;
&lt;p&gt;프록시 패턴이란?&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;
&lt;p&gt;어떤 객체에 대한 접근을 제어하기 위한 용도로 대리인에게 해당하는 객체를 제공하는 패턴&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;프록시 패턴의 종류! 주요 3가지&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;
&lt;p&gt;원격 프록시&amp;nbsp; : 원격객체에 대한 프록시, 원격객체에 대한 접근을 마치 로컬에서 하듯이 한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;
&lt;p&gt;예 : 구글 docs..&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;가상 프록시 :&amp;nbsp; 생성하는데 비용이 많이드는 객체에 대한 프록시. 생성비용이 많이드는 객체대신에 라이트한 프록시 객체가 대부분의 일을 대신하다가, 직접적 업무는 주체클래스가.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;예 : 배틀그라운드 초기 그래픽 초기화가 오래걸린다. 그렇기 때문에 프록시를 이용해서 게임이 시작되기전(비행기가 착륙하기전)까지 한정된공간에서 놀수있게했는데, 그게 프록시 패턴이다.&lt;/li&gt;
&lt;li&gt;예 : 여러명이 협업하는 상황에서 어떤 객체에 대한 구현이 완벽하게 되지않았다. 근데 해당 객체는 프로세스상 호출은 하니깐 일단은 프록시 객체를 호출하게 해놓고, 주체 객체가 구현이 완료되면 주체객체로 대체하는 방법도 있다. 실제 객체를 붙여보기전에 미리 프로세스를 진행할수있다는 장점이 있겠다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;보호 프록시 :&amp;nbsp; 접근에 제한이 필요한 객체에 대한 프록시&lt;img src=&quot;https://k.kakaocdn.net/dn/psXGv/btqFnjfqSgD/LTjcIpzwmJV2k6DoKQA4K1/img.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-image-src=&quot;https://k.kakaocdn.net/dn/psXGv/btqFnjfqSgD/LTjcIpzwmJV2k6DoKQA4K1/img.png&quot; /&gt;출처: https://ko.wikipedia.org/wiki/%ED%94%84%EB%A1%9D%EC%8B%9C_%ED%8C%A8%ED%84%B4#/media/%ED%8C%8C%EC%9D%BC:Proxy_pattern_diagram.svg&lt;/li&gt;
&lt;/ol&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/디자인패턴</category>
      <category>proxy</category>
      <category>프록시</category>
      <author>쏘롱마니</author>
      <guid isPermaLink="true">https://munu8989.tistory.com/9</guid>
      <comments>https://munu8989.tistory.com/9#entry9comment</comments>
      <pubDate>Fri, 3 Jul 2020 18:46:32 +0900</pubDate>
    </item>
    <item>
      <title>테스트 코드에서의 org.hibernate.LazyInitializationException</title>
      <link>https://munu8989.tistory.com/8</link>
      <description>&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;두개의 entity(ordergood, order_refund_detail)가 oneToMany 관계로 걸려있었다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;엔드포인트를 테스트 코드에서 똑같이 재구현해서 테스트를 해봤는데,&lt;/span&gt;&amp;nbsp;layzyInitialLazyInitializationException 이 발생을했다. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;테스트 코드는 아래 그림과 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cDcGbY/btqFhMbkOGD/Dc4vcvTVj5GWyEFeXNLoOk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cDcGbY/btqFhMbkOGD/Dc4vcvTVj5GWyEFeXNLoOk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cDcGbY/btqFhMbkOGD/Dc4vcvTVj5GWyEFeXNLoOk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcDcGbY%2FbtqFhMbkOGD%2FDc4vcvTVj5GWyEFeXNLoOk%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;원인은!&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;테스트코드는 시작시 영속성컨텍스트 안만들어준다..&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;지금의 스프링 OSIV에서는 필터단 부터 영속성컨텍스트가 시작되기때문에 그 하위 메소드들은 영속성 컨텍스트가 유지된다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;테스트코드에서는 필터,인터셉터를 지나치지 않았기때문에 영속성 컨텍스트를 안만들어 주는것이다. 후 삽질..&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;br /&gt;아래그림과같이 @Transactional을 테스트메소드에 추가해주면 해결 끝!&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/E2rZo/btqFknuoYe6/5OtdvNyLKQ43CMbgyVOzz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/E2rZo/btqFknuoYe6/5OtdvNyLKQ43CMbgyVOzz0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/E2rZo/btqFknuoYe6/5OtdvNyLKQ43CMbgyVOzz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FE2rZo%2FbtqFknuoYe6%2F5OtdvNyLKQ43CMbgyVOzz0%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>개발/문제해결</category>
      <category>java test</category>
      <category>LazyInitializationException</category>
      <author>쏘롱마니</author>
      <guid isPermaLink="true">https://munu8989.tistory.com/8</guid>
      <comments>https://munu8989.tistory.com/8#entry8comment</comments>
      <pubDate>Thu, 2 Jul 2020 12:23:08 +0900</pubDate>
    </item>
    <item>
      <title>JPA Repository의 D.I 과정</title>
      <link>https://munu8989.tistory.com/7</link>
      <description>&lt;p&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cDoshI/btqE82EdW1k/unO77AnoDmFfAaRUNLup1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cDoshI/btqE82EdW1k/unO77AnoDmFfAaRUNLup1k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cDoshI/btqE82EdW1k/unO77AnoDmFfAaRUNLup1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcDoshI%2FbtqE82EdW1k%2FunO77AnoDmFfAaRUNLup1k%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;위 그림처럼 JPA Repository는 분명 interface만 정의해줬다. 구현체를 내가 따로 만든게 없다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzfqHA/btqE8wZRpO8/HTY6Bl012hGjbtgv7UWKSK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzfqHA/btqE8wZRpO8/HTY6Bl012hGjbtgv7UWKSK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzfqHA/btqE8wZRpO8/HTY6Bl012hGjbtgv7UWKSK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzfqHA%2FbtqE8wZRpO8%2FHTY6Bl012hGjbtgv7UWKSK%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;그런데 위 그림처럼 사용하는쪽에서 해당 Repository를 D.I를해서 사용할 수 있다. 구현체를 알아서 스프링에서 만들어주니, 쓸수 있는거일텐데..&lt;/p&gt;
&lt;p&gt;도대체 Repository 구현체는 어떤과정에 의해서 만들어지는것인가..?&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;디버깅을 통한 결과이다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;JpaRepositoryFactoryBean -&amp;gt; JpaRepositoryFactory -&amp;gt; interface (ex.PaymentRepository)를 가지고 reflection implement를 실행 -&amp;gt; SimpleJpaRepositoryImpl&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BgBtM/btqE82sgw0o/0mFPm3x1tbBfQqHjrj18wk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BgBtM/btqE82sgw0o/0mFPm3x1tbBfQqHjrj18wk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BgBtM/btqE82sgw0o/0mFPm3x1tbBfQqHjrj18wk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBgBtM%2FbtqE82sgw0o%2F0mFPm3x1tbBfQqHjrj18wk%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;그리고 Repository가 저렇게 JpaRepositoryFactory에서 생성이 되는 전제조건은 Repository를 스캔하는 base package를 설정해놔야 한다.&lt;br /&gt;이전에 @Component, @Service , @Bean 들은 두개의 스캔과정을 가지고 있다는것을 알게 됐다.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;1) @ComponentScan 2) EnableAutoConfigureScan&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;@Repository는 위 2가지 스캔 과정과 별개로 다른 스캔 과정, 어노테이션이 필요하다!&amp;nbsp;&lt;/p&gt;
&lt;p&gt;@SpringBootApplication이 붙은 메인클래스에 Repository는 @&lt;span&gt;&lt;b&gt;EnableJpaRepositories&lt;/b&gt; 어노테이션으로 설정이 가능하다. 저렇게 하면 basepackage가 com.waug.auth.common.rememberme.repository가 된다. 설정을 안하면 디폴트로 main 아래 java 패키지이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bktC7o/btqE9Kj5uid/DwrJ7p3yRkAR0BrfalD200/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bktC7o/btqE9Kj5uid/DwrJ7p3yRkAR0BrfalD200/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bktC7o/btqE9Kj5uid/DwrJ7p3yRkAR0BrfalD200/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbktC7o%2FbtqE9Kj5uid%2FDwrJ7p3yRkAR0BrfalD200%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/Spring</category>
      <author>쏘롱마니</author>
      <guid isPermaLink="true">https://munu8989.tistory.com/7</guid>
      <comments>https://munu8989.tistory.com/7#entry7comment</comments>
      <pubDate>Thu, 25 Jun 2020 14:44:25 +0900</pubDate>
    </item>
    <item>
      <title>스프링 Exception 처리 방안(@HandlerException, BasicErrorController)</title>
      <link>https://munu8989.tistory.com/6</link>
      <description>&lt;p&gt;일단 크게 2가지가 있다.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;1. @HandlerException, @ControllerAdvice를 이용하는 방안&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;2. BasicErrorController를 이용하는 방안&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이 두 사용방안은 실행되는 위치가 다르다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;1은 Interceptor, 2는 Filter&lt;/p&gt;
&lt;p&gt;그림으로 보면,&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8VXkL/btqE6xEP649/r8hZXLfO7dbdtKHPOYTAE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8VXkL/btqE6xEP649/r8hZXLfO7dbdtKHPOYTAE1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8VXkL/btqE6xEP649/r8hZXLfO7dbdtKHPOYTAE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8VXkL%2FbtqE6xEP649%2Fr8hZXLfO7dbdtKHPOYTAE1%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;1 에서 처리된 exception은 2까지 전파되지 않는다. 그래서 중복설정하게되면 basicErrorController가 왜 먹히지?하는 상황이 올수있다. 1과 2의 공통기능은 결국 Exception을 핸들링해주는 것이기 때문에 각 특징을 알고 써먹으면 될거같다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;@HandlerException와 BasicErrorController의 각각의 특징을 정리해보면,,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;- HandlerException&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;nbsp;Exception을 미리 메소드별로 나눠서 처리가능하다. 반대로 말하면 BasicErrorController는 모든 exception을 메소드별로 나눠서 처리하는게 불가능(error(), errorHtml()이란 메소드로만 분리됨)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;- BasicErrorController&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Exception을 html로 주는 경우(errorHtml), 그 외의 경우로 나눌수(error) 있음&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/Spring</category>
      <category>BasicErrorController</category>
      <category>spring</category>
      <category>spring exception</category>
      <author>쏘롱마니</author>
      <guid isPermaLink="true">https://munu8989.tistory.com/6</guid>
      <comments>https://munu8989.tistory.com/6#entry6comment</comments>
      <pubDate>Wed, 24 Jun 2020 15:22:48 +0900</pubDate>
    </item>
    <item>
      <title>Transaction 제대로 걸리지 않았던 문제</title>
      <link>https://munu8989.tistory.com/5</link>
      <description>&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문제상황&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;Controller -&amp;gt; Service -&amp;gt; Service(@Transactional)&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;문제이유
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;컨트롤러에 디폴트로 Transaction이 걸려있다고 생각했다.(예전 osiv를 생각했던것임)&lt;/li&gt;
&lt;li&gt;그렇지만 현재의 스프링 osiv는 서비스단에 직접 트랜잭션을 명시해야 트랜잭션이 시작됨.&lt;/li&gt;
&lt;li&gt;최종적으로 호출되는 Service에는 @Transactional을 명시했는데? 왜 안된거지?
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;같은 서비스 클래스 내에서의 호출(Service-&amp;gt;Service(@Transactional)을 했기때문에 transaction이 전파? 되지않았다..&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;문제해결
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;controller단에만 @transactional 명시
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;예전 transaction 적용방법. 컨트롤러단에서 데이터를 변경하면 의도치않은 데이터 변경값이 뷰에 전달될가능성이 커서&lt;u&gt;&lt;b&gt; 안좋은 방법이다!! PASS!!&lt;/b&gt;&lt;/u&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;service단에 @transactional 명시
&lt;ul style=&quot;list-style-type: disc;&quot;&gt;
&lt;li&gt;&lt;b&gt;외부에서 쓰일 메소드는 transactional 명시&lt;/b&gt;해놓음&lt;/li&gt;
&lt;li&gt;&lt;b&gt;내부에서만 쓰일 메소드는 private로 명시&lt;/b&gt;함으로써 &quot;이 메소드는 내부에서만 쓰일거고, 내부에서 호출은 transaction이 적용이 안돼!&quot; 라는 것을 인지할수 있다. @Transactional 붙여보면 컴파일시점에서부터 에러가 남을 알수있음!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/문제해결</category>
      <author>쏘롱마니</author>
      <guid isPermaLink="true">https://munu8989.tistory.com/5</guid>
      <comments>https://munu8989.tistory.com/5#entry5comment</comments>
      <pubDate>Tue, 23 Jun 2020 12:05:17 +0900</pubDate>
    </item>
    <item>
      <title>Transaction &amp;amp; 영속성 컨텍스트 이야기</title>
      <link>https://munu8989.tistory.com/4</link>
      <description>&lt;ul style=&quot;list-style-type: square;&quot; data-ke-list-type=&quot;square&quot;&gt;
&lt;li&gt;
&lt;p&gt;&lt;span&gt;트랜잭션 범위의 영속성 컨텍스트 전략이 기본이다&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;트랜잭션범위(=영속성 컨텍스트 범)에 있지않는 뷰 레벨(컨트롤러 등)에서 엔티티에 접근을 하다가&amp;nbsp;LazyInitailize Exception 이 발생!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;원인 사례 :&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;
&lt;ul style=&quot;list-style-type: square;&quot; data-ke-list-type=&quot;square&quot;&gt;
&lt;li&gt;
&lt;p&gt;&quot; 어 나는 뷰에는 이 엔티티의 필드를 좀 암호화해서 넘기구싶어&quot; 것을 원할수가 있음&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&quot; 뷰 레벨에서 나중에 (Lazy) 꺼내 써야지~ 지금은 당장 필요없으니깐~&quot;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;
&lt;p&gt;Lazy InitializeException을 해결하는 방법이 뭐가 있을까?&lt;/p&gt;
&lt;/li&gt;
&lt;ul style=&quot;list-style-type: square;&quot; data-ke-list-type=&quot;square&quot;&gt;
&lt;li&gt;
&lt;p&gt;뷰 레벨전에 엔티티를 미리 초기화하는 방법이 있겠네&lt;/p&gt;
&lt;/li&gt;
&lt;ul style=&quot;list-style-type: square;&quot; data-ke-list-type=&quot;square&quot;&gt;
&lt;li&gt;
&lt;p&gt;그럼 뷰 레벨전에 엔티티를 초기화하는 방법엔 뭐가있을까?&lt;/p&gt;
&lt;/li&gt;
&lt;ul style=&quot;list-style-type: square;&quot; data-ke-list-type=&quot;square&quot;&gt;
&lt;li&gt;
&lt;p&gt;글로벌 페치 전략 수정&lt;/p&gt;
&lt;/li&gt;
&lt;ul style=&quot;list-style-type: square;&quot; data-ke-list-type=&quot;square&quot;&gt;
&lt;li&gt;
&lt;p&gt;Entity에 fetchType &lt;span&gt;Eager&lt;/span&gt;로 지정&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;사용하지 않을수도있는 엔티티 까지도 로딩해서 메모리 문제.. 여기까진 OK&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;일반 JPA 메소드로 조회했을떄는 이너조인해서 잘 가져온다 문제가없다.. 근데? JPQL을 사용하게 되면 &lt;span&gt;N+1 문제&lt;/span&gt;가 발생한다&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;
&lt;p&gt;JPQL 페치 조인&lt;/p&gt;
&lt;/li&gt;
&lt;ul style=&quot;list-style-type: square;&quot; data-ke-list-type=&quot;square&quot;&gt;
&lt;li&gt;
&lt;p&gt;위의 N+1문제를 해결하기 위해 JPQL을 쓸때는 페치 조인을 쓴다.&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;
&lt;p&gt;강제로 초기화(Facade)&lt;/p&gt;
&lt;/li&gt;
&lt;ul style=&quot;list-style-type: square;&quot; data-ke-list-type=&quot;square&quot;&gt;
&lt;li&gt;
&lt;p&gt;이것도 아니면 Lazy 로딩인걸 무조건 initialize하는 계층인 facade 계층을 하나 만든다.(Controller &amp;lt;-&amp;gt; facade &amp;lt;-&amp;gt; service)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;li&gt;
&lt;p&gt;뷰 레벨전에 엔티티를 미리 초기화의 문제점&lt;/p&gt;
&lt;/li&gt;
&lt;ul style=&quot;list-style-type: square;&quot; data-ke-list-type=&quot;square&quot;&gt;
&lt;li&gt;
&lt;p&gt;누가 뷰 만들때 이 엔티티가 초기화 잘됐는지까지 확인해.. 그냥 뷰만 딱 만들지..너무 모델뷰간의 의존성이 높아진다..&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;
&lt;p&gt;그러면 Lazy InitializeException 가장 좋은방법은 OSIV 적용!&lt;/p&gt;
&lt;/li&gt;
&lt;ul style=&quot;list-style-type: square;&quot; data-ke-list-type=&quot;square&quot;&gt;
&lt;li&gt;
&lt;p&gt;스프링의 예전 OSIV&lt;/p&gt;
&lt;/li&gt;
&lt;ul style=&quot;list-style-type: square;&quot; data-ke-list-type=&quot;square&quot;&gt;
&lt;li&gt;
&lt;p&gt;요청당 트랜잭션 방식의 OSIV , 즉 요청이 들어오는 즉시(필터/인터셉터부터) 트랜잭션 시작!&amp;nbsp; 영속성컨텍스트도 똑같이 시작!&lt;/p&gt;
&lt;/li&gt;
&lt;ul style=&quot;list-style-type: square;&quot; data-ke-list-type=&quot;square&quot;&gt;
&lt;li&gt;
&lt;p&gt;문제점 : 뷰레벨에서 모델에 셋을할수있음. 즉 데이터가 바뀔수있음 뷰레벨에서.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9w3WN/btqE3dGYLnX/6NSYFLncosIUF2TiuwD46K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9w3WN/btqE3dGYLnX/6NSYFLncosIUF2TiuwD46K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9w3WN/btqE3dGYLnX/6NSYFLncosIUF2TiuwD46K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9w3WN%2FbtqE3dGYLnX%2F6NSYFLncosIUF2TiuwD46K%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;li&gt;
&lt;p&gt;지금의 스프링 OSIV&lt;/p&gt;
&lt;/li&gt;
&lt;ul style=&quot;list-style-type: square;&quot; data-ke-list-type=&quot;square&quot;&gt;
&lt;li&gt;
&lt;p&gt;서비스단에서 트랜잭션 시작!&amp;nbsp; 영속성컨텍스트는 필터/인터셉터부터 시작&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7b6kX/btqE2k7y0hZ/cqbJ0be9ymKWS7LUKkHY4k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7b6kX/btqE2k7y0hZ/cqbJ0be9ymKWS7LUKkHY4k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7b6kX/btqE2k7y0hZ/cqbJ0be9ymKWS7LUKkHY4k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7b6kX%2FbtqE2k7y0hZ%2FcqbJ0be9ymKWS7LUKkHY4k%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/ul&gt;</description>
      <category>개발/Spring</category>
      <author>쏘롱마니</author>
      <guid isPermaLink="true">https://munu8989.tistory.com/4</guid>
      <comments>https://munu8989.tistory.com/4#entry4comment</comments>
      <pubDate>Tue, 23 Jun 2020 11:19:08 +0900</pubDate>
    </item>
  </channel>
</rss>