<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Dawon ⌨️</title>
    <link>https://devlopsquare.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Tue, 4 Aug 2026 08:36:28 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>I'mDawon</managingEditor>
    <image>
      <title>Dawon ⌨️</title>
      <url>https://tistory1.daumcdn.net/tistory/3181683/attach/06a9e41889ad4fbc8425882273785877</url>
      <link>https://devlopsquare.tistory.com</link>
    </image>
    <item>
      <title>Spring에서  X-Forwarded-For 값을 가져오는 2가지 방법</title>
      <link>https://devlopsquare.tistory.com/251</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;결론부터 말하면 두가지 방법이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. X-Forwarded-For헤더에 직접 접근하여 가져오는 방법&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. &lt;span style=&quot;background-color: #fefefe; color: #000c34;&quot;&gt;HttpServletRequest의 getAddr()이 클라이언트 IP를 전달하도록 스프링 설정을 하는 방법&lt;/span&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;API를 호출한 사용자의 IP를 얻기 위해서 &lt;span style=&quot;background-color: #fefefe; color: #000c34;&quot;&gt;HttpServletRequest의 getAddr() 함수를 사용한다. 그러나 API요청이 Forward Proxy에 의해 전달 될 경우 &lt;span style=&quot;background-color: #fefefe; color: #000c34;&quot;&gt;HttpServletRequest의 getAddr() 호출 시&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #fefefe; color: #000c34;&quot;&gt;Forward Proxy의 IP가 찍히게 된다.&lt;/span&gt;&lt;/span&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;span style=&quot;background-color: #fefefe; color: #000c34;&quot;&gt;&lt;span style=&quot;background-color: #fefefe; color: #000c34;&quot;&gt;이런 경우 X-Forwarded-For라는 HTTP 헤더를 통해 프록시 서버를 통해 요청을 전달 받더라도, 진짜 Client IP를 전달 받을 수 있다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(proxy에서 X-Forwarded-For에 클라이언트 IP를 넣어주겠다는 설정이 있어야 한다. Nginx의 경우 &lt;span style=&quot;background-color: #242424; color: #e6e6e6;&quot;&gt;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;&lt;/span&gt;)&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;X-Forwarded-For는 HTTP proxy등을 통해 웹 서버에 접속하는 클라이언트의 IP 주소를 식별하기 위한 표준헤더이다.&lt;br /&gt;문법 : X-Forward-For: &amp;lt;client&amp;gt;, &amp;lt;proxy1&amp;gt;, &amp;lt;proxy2&amp;gt;&amp;nbsp;&lt;br /&gt;- 여러 프록시들을 거칠 때 IP주소들이 차례대로 열거된다. 가장 오른쪽에 있는 IP가 마지막으로 거친 proxy의 IP 주소이다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기 까지 되면, X-Forward-For 헤더 값에 접근해서 클라이언트의 IP를 가져올 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1653204564235&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String ip = request.getHeader(&quot;x-forwarded-for&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;그런데, 스프링 설정으로&amp;nbsp;&lt;span style=&quot;background-color: #fefefe; color: #000c34;&quot;&gt;HttpServletRequest의 getAddr()가 호출 되었을때, X-Forwarded-For값이 전달되도록 할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1653204649742&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;server.forward-headers-strategy=NATIVE&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스프링에서 제공하는 ForwardedHeaderFilter를 사용하려면 server.forward-headers-strategy=FRAMEWORK 속성을 사용하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>study</category>
      <author>I'mDawon</author>
      <guid isPermaLink="true">https://devlopsquare.tistory.com/251</guid>
      <comments>https://devlopsquare.tistory.com/251#entry251comment</comments>
      <pubDate>Sun, 22 May 2022 16:33:08 +0900</pubDate>
    </item>
    <item>
      <title>서킷브레이커</title>
      <link>https://devlopsquare.tistory.com/250</link>
      <description>&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;h3 data-ke-size=&quot;size23&quot;&gt;서킷 브레이커 왜 사용 할까?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Circuit Breaker 직역하자면 회로 차단기라는 뜻을 가지고 있습니다.&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;서비스 A가 서비스 B를 호출 했을 때, 서비스 B의 상태가 비정상적이라 응답을 해줄 수 없는 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스 A는 서비스 B의 응답을 계속해서 기다리는 상태가 됩니다.&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;서비스 B의 장애가 서비스 A까지 전파될 수 있습니다. 이를 방지하기 위해서 서킷 브레이커를 사용합니다.&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;대표적인 서킷브레이커 라이브러리로는 Resilience4J가 있습니다. 요청 서비스와 제공 서비스사이에 Resilice4J를 두고 통신합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;서킷브레이커 패턴&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서킷브레이커 패턴은 서비스 A와 서비스 B사이에 서킷브레이커를 두어 서비스 B로 전달되는 요청이 서킷브레이커를 통해 전달되도록 하는 패턴 입니다.&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;1234&quot; data-origin-height=&quot;560&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/datoMW/btrzjnAZKjM/sstTO6B2hqxMhWlCkLGDi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/datoMW/btrzjnAZKjM/sstTO6B2hqxMhWlCkLGDi1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/datoMW/btrzjnAZKjM/sstTO6B2hqxMhWlCkLGDi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdatoMW%2FbtrzjnAZKjM%2FsstTO6B2hqxMhWlCkLGDi1%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;572&quot; height=&quot;260&quot; data-origin-width=&quot;1234&quot; data-origin-height=&quot;560&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;서비스 B가 정상적이라면 서킷브레이커는 서비스 A의 요청을&amp;nbsp; 바이패스하여 서비스 B로 전달해 줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스 B가 비정상적이라면 이를 서킷브레이커가 감지하여 서킷브레이커에서 서비스 A의 호출을 끊습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 경우 서비스 A로 서비스 B의 장애가 전파 되지는 않지만, 정상적인 응답값을 받지 못하게 됩니다.&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;이러한 처리를 하기 위해 사용되는 것이 Fallback Messaging 입니다. 서비스 B가 정상적으로 응답을 할 수 없는 경우 서킷 브레이커에서 Fallback Messaging을 통해 정해진 룰대로 값을 응답합니다.&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;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MSA에서 모듈간의 장애전파를 막기 위해 서킷브레이커 패턴이 사용된다.&lt;/li&gt;
&lt;li&gt;장애 발생시 처리를 위해 FallbackMessaging이 사용되고, 서킷브레이커에서 장애 시 정해진 값을 응답 해 줄 수 있다.&lt;/li&gt;
&lt;li&gt;자바의 대표적인 서킷브레이커 라이브러리로는 Resilience4J가 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>study</category>
      <author>I'mDawon</author>
      <guid isPermaLink="true">https://devlopsquare.tistory.com/250</guid>
      <comments>https://devlopsquare.tistory.com/250#entry250comment</comments>
      <pubDate>Wed, 13 Apr 2022 23:42:14 +0900</pubDate>
    </item>
    <item>
      <title>Spring AOP - Transactional, Async</title>
      <link>https://devlopsquare.tistory.com/249</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Transactional 전파레벨 관련 실험&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;실험 환경&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;로컬에서 docker를 띄워 Slave, Master DB를 구성하였다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;961&quot; data-origin-height=&quot;230&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMd12f/btrxiwf2lFb/qQKXA5ufRRtd5hT8COzSUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMd12f/btrxiwf2lFb/qQKXA5ufRRtd5hT8COzSUK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMd12f/btrxiwf2lFb/qQKXA5ufRRtd5hT8COzSUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMd12f%2Fbtrxiwf2lFb%2FqQKXA5ufRRtd5hT8COzSUK%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;961&quot; height=&quot;230&quot; data-origin-width=&quot;961&quot; data-origin-height=&quot;230&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Read-Only True시 Slave DB와 연결, Read-Only False시 Master DB와 연결 하도록 구성&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1504&quot; data-origin-height=&quot;766&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2W4v8/btrxkKYyFCg/Of7bllZlGFwSRezSCOZvK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2W4v8/btrxkKYyFCg/Of7bllZlGFwSRezSCOZvK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2W4v8/btrxkKYyFCg/Of7bllZlGFwSRezSCOZvK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2W4v8%2FbtrxkKYyFCg%2FOf7bllZlGFwSRezSCOZvK1%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;1504&quot; height=&quot;766&quot; data-origin-width=&quot;1504&quot; data-origin-height=&quot;766&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;h4 data-ke-size=&quot;size20&quot;&gt;Transactional Read-Only False 메소드 안에서 Read-Only True인 메소드가 실행된다면?&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdSOQb/btrxj7fpjrv/naTh3mmF7Vq85DLq3edEGk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdSOQb/btrxj7fpjrv/naTh3mmF7Vq85DLq3edEGk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdSOQb/btrxj7fpjrv/naTh3mmF7Vq85DLq3edEGk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdSOQb%2Fbtrxj7fpjrv%2FnaTh3mmF7Vq85DLq3edEGk%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;768&quot; height=&quot;400&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;400&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;호출 한 메소드 (Read-Only False)에서 연결 된 Master DB와의 Connection을 사용한다.&lt;/li&gt;
&lt;li&gt;즉, 조회 쿼리 (Read-Only True)도 Slave를 찌르지 않고, Master DB와의 커넥션을 통해 가져오게 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1577&quot; data-origin-height=&quot;612&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c5ltbL/btrxkfSaQtP/l8l4wne4autivyjGMAeep1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c5ltbL/btrxkfSaQtP/l8l4wne4autivyjGMAeep1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c5ltbL/btrxkfSaQtP/l8l4wne4autivyjGMAeep1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc5ltbL%2FbtrxkfSaQtP%2Fl8l4wne4autivyjGMAeep1%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;1577&quot; height=&quot;612&quot; data-origin-width=&quot;1577&quot; data-origin-height=&quot;612&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;h4 data-ke-size=&quot;size20&quot;&gt;Transactional Read-Only True 메소드 안에서 Read-Only False인 메소드가 실행된다면?&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Connection is read-only. Queries leading to data modification are not allowed. 에러 발생&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3100&quot; data-origin-height=&quot;722&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ermASA/btrxjIf0j6g/42nKOT9o285hv06oEtQjH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ermASA/btrxjIf0j6g/42nKOT9o285hv06oEtQjH1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ermASA/btrxjIf0j6g/42nKOT9o285hv06oEtQjH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FermASA%2FbtrxjIf0j6g%2F42nKOT9o285hv06oEtQjH1%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;3100&quot; height=&quot;722&quot; data-origin-width=&quot;3100&quot; data-origin-height=&quot;722&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;h4 data-ke-size=&quot;size20&quot;&gt;Transaction 전파 레벨&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Propagation.REQUIRED
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스프링의 기본 전파 레벨&lt;/li&gt;
&lt;li&gt;해당 전파레벨의 메소드를 호출한 곳에서 별도의 트랜잭션이 설정되어 있지 않았다면 트랜잭션을 새로 시작&lt;/li&gt;
&lt;li&gt;호출한 곳에서 이미 트랜잭션이 설정되어 있다면 기존의 트랜잭션 내에서 로직을 실행&lt;/li&gt;
&lt;li&gt;예외가 발생하면 롤백이 되고 호출한 곳에도 롤백이 전파&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지는 Propagation.REQUIRED로 실행이 되어왔기 때문에, 부모의 트랜잭션 내에서 로직을 실행하였다.&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;REQUIRED_NEW로 전파레벨을 바꾸어본다면?&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1556&quot; data-origin-height=&quot;612&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vaK3Y/btrxhSXUCNU/Ok2I4kZHRSeZ3K7DVw5cFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vaK3Y/btrxhSXUCNU/Ok2I4kZHRSeZ3K7DVw5cFk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vaK3Y/btrxhSXUCNU/Ok2I4kZHRSeZ3K7DVw5cFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvaK3Y%2FbtrxhSXUCNU%2FOk2I4kZHRSeZ3K7DVw5cFk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1556&quot; height=&quot;612&quot; data-origin-width=&quot;1556&quot; data-origin-height=&quot;612&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;예외가 발생하지 않고 별개의 커넥션이 생성되었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2230&quot; data-origin-height=&quot;852&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cGGLLR/btrxkgXQztX/isxOzjgtROC4ECvU3a6SC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cGGLLR/btrxkgXQztX/isxOzjgtROC4ECvU3a6SC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cGGLLR/btrxkgXQztX/isxOzjgtROC4ECvU3a6SC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcGGLLR%2FbtrxkgXQztX%2FisxOzjgtROC4ECvU3a6SC0%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;2230&quot; height=&quot;852&quot; data-origin-width=&quot;2230&quot; data-origin-height=&quot;852&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Propagation.REQUIRED_NEW
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;매번 새로운 트랜잭션을 시작&lt;/li&gt;
&lt;li&gt;새로운 트랜잭션 안에서 예외가 발생해도 호출한 곳에는 롤백이 전파되지 않음&lt;/li&gt;
&lt;li&gt;생성된 트랜잭션들은 완전히 독립된 별개의 단위로 작동&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Spring AOP - Transactional&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;@Transactional이 없는 메소드에서 자신의 @Transactional이 붙은 메서드를 실행&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1300&quot; data-origin-height=&quot;512&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYdcyr/btrxlp7RSwl/K9tgQOXn6PGB9CskzYaVkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYdcyr/btrxlp7RSwl/K9tgQOXn6PGB9CskzYaVkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYdcyr/btrxlp7RSwl/K9tgQOXn6PGB9CskzYaVkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYdcyr%2Fbtrxlp7RSwl%2FK9tgQOXn6PGB9CskzYaVkK%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;1300&quot; height=&quot;512&quot; data-origin-width=&quot;1300&quot; data-origin-height=&quot;512&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JPA의 변경감지가 일어나지 않았다.&lt;/li&gt;
&lt;li&gt;변경감지
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Transaction을 Commit하는 순간 영속성 컨텍스트에 있는 엔티티의 변경을 감지&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Transaction이 걸리지 않았다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;948&quot; data-origin-height=&quot;433&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dpSQ59/btrxiuP6aNj/V60gGtg4ISdkVmlCK0dc9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dpSQ59/btrxiuP6aNj/V60gGtg4ISdkVmlCK0dc9k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dpSQ59/btrxiuP6aNj/V60gGtg4ISdkVmlCK0dc9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdpSQ59%2FbtrxiuP6aNj%2FV60gGtg4ISdkVmlCK0dc9k%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;948&quot; height=&quot;433&quot; data-origin-width=&quot;948&quot; data-origin-height=&quot;433&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;@Transactional이 없는 메소드에서 외부 @Transactional이 붙은 메서드를 실행&lt;/h4&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;1068&quot; data-origin-height=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMA0EZ/btrxj7sXhIz/yYuLuNYSjzBiTKmgUmcO1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMA0EZ/btrxj7sXhIz/yYuLuNYSjzBiTKmgUmcO1k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMA0EZ/btrxj7sXhIz/yYuLuNYSjzBiTKmgUmcO1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMA0EZ%2Fbtrxj7sXhIz%2FyYuLuNYSjzBiTKmgUmcO1k%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;1068&quot; height=&quot;500&quot; data-origin-width=&quot;1068&quot; data-origin-height=&quot;500&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JPA의 변경감지가 일어났다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1068&quot; data-origin-height=&quot;569&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/t80YH/btrxj8k5lsO/rhnGwNhymkVOqVoPu9MtKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/t80YH/btrxj8k5lsO/rhnGwNhymkVOqVoPu9MtKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/t80YH/btrxj8k5lsO/rhnGwNhymkVOqVoPu9MtKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ft80YH%2Fbtrxj8k5lsO%2FrhnGwNhymkVOqVoPu9MtKk%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;1068&quot; height=&quot;569&quot; data-origin-width=&quot;1068&quot; data-origin-height=&quot;569&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;h4 data-ke-size=&quot;size20&quot;&gt;트랜잭션의 동작 원리&amp;nbsp;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스프링 @Transactional은 Proxy를 통해 처리 된다.&lt;/li&gt;
&lt;li&gt;트랜잭션 어노테이션이 걸려있는 메소드의 클래스의 프록시 객체가 만들어진다.&lt;/li&gt;
&lt;li&gt;프록시 객체의 update에서 트랜잭션 비긴, 커밋, 롤백과 같은 작업이 이루어진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1473&quot; data-origin-height=&quot;452&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bRXdJ8/btrxmAac8g8/fuaLJH9UFqCdowLKPFQBsk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bRXdJ8/btrxmAac8g8/fuaLJH9UFqCdowLKPFQBsk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bRXdJ8/btrxmAac8g8/fuaLJH9UFqCdowLKPFQBsk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbRXdJ8%2FbtrxmAac8g8%2FfuaLJH9UFqCdowLKPFQBsk%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;1473&quot; height=&quot;452&quot; data-origin-width=&quot;1473&quot; data-origin-height=&quot;452&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;같은 클래스 내의 메소드를 호출 한 경우 &quot;프록시객체&quot;를 타지 않는다.&lt;/li&gt;
&lt;li&gt;자신의 클래스에 있는 update 메소드를 호출한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1491&quot; data-origin-height=&quot;682&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cGtcgS/btrxkfSbqVM/hU536ZnIbRCOM3xL1fYSek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cGtcgS/btrxkfSbqVM/hU536ZnIbRCOM3xL1fYSek/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cGtcgS/btrxkfSbqVM/hU536ZnIbRCOM3xL1fYSek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcGtcgS%2FbtrxkfSbqVM%2FhU536ZnIbRCOM3xL1fYSek%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;1491&quot; height=&quot;682&quot; data-origin-width=&quot;1491&quot; data-origin-height=&quot;682&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;반면 외부에 있는 메소드를 호출했을 때는 프록시 객체를 타게된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1516&quot; data-origin-height=&quot;682&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DpcrH/btrxkNnAvT5/d7FOIqOqlK1fvWxRDTaO11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DpcrH/btrxkNnAvT5/d7FOIqOqlK1fvWxRDTaO11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DpcrH/btrxkNnAvT5/d7FOIqOqlK1fvWxRDTaO11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDpcrH%2FbtrxkNnAvT5%2Fd7FOIqOqlK1fvWxRDTaO11%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;1516&quot; height=&quot;682&quot; data-origin-width=&quot;1516&quot; data-origin-height=&quot;682&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;h2 data-ke-size=&quot;size26&quot;&gt;Async 관련 실험&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Read-Only False 메소드에서 @Async로 Read-Only True 메소드를 실행 할 경우&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;756&quot; data-origin-height=&quot;475&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bT1prq/btrxivanZpK/21vYfWH3xYckBwaNYKbwVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bT1prq/btrxivanZpK/21vYfWH3xYckBwaNYKbwVk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bT1prq/btrxivanZpK/21vYfWH3xYckBwaNYKbwVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbT1prq%2FbtrxivanZpK%2F21vYfWH3xYckBwaNYKbwVk%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;756&quot; height=&quot;475&quot; data-origin-width=&quot;756&quot; data-origin-height=&quot;475&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;http-nio-8080-exec-1 쓰레드와, task-1 (@Async)쓰레드가 생성되었다.&lt;/li&gt;
&lt;li&gt;그리고 각 쓰레드마다 커넥션이 새로 생성되었으며 Transactional Read-Only 설정에 따라 Master, Slave로 연결이 되었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1359&quot; data-origin-height=&quot;484&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MAtXe/btrxeIVKgl4/JvfUVIRYMmNBFv6h1ZEpl0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MAtXe/btrxeIVKgl4/JvfUVIRYMmNBFv6h1ZEpl0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MAtXe/btrxeIVKgl4/JvfUVIRYMmNBFv6h1ZEpl0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMAtXe%2FbtrxeIVKgl4%2FJvfUVIRYMmNBFv6h1ZEpl0%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;1359&quot; height=&quot;484&quot; data-origin-width=&quot;1359&quot; data-origin-height=&quot;484&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;h4 data-ke-size=&quot;size20&quot;&gt;@Async Read-Only False 메소드에서 Read-Only True 메소드를 실행&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;947&quot; data-origin-height=&quot;416&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2jYfI/btrxgGKw4nA/cTfLG6E1eE0AT2flbPlOwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2jYfI/btrxgGKw4nA/cTfLG6E1eE0AT2flbPlOwK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2jYfI/btrxgGKw4nA/cTfLG6E1eE0AT2flbPlOwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2jYfI%2FbtrxgGKw4nA%2FcTfLG6E1eE0AT2flbPlOwK%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;947&quot; height=&quot;416&quot; data-origin-width=&quot;947&quot; data-origin-height=&quot;416&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;task-1 쓰레드가 생성되었다.&lt;/li&gt;
&lt;li&gt;해당 쓰레드에서 가져온 커넥션 (Read-Only False 이기 때문에 Master)로 Read-Only True 메소드인 getUser()가 실행되었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2766&quot; data-origin-height=&quot;534&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/obBCl/btrxjnpfYeN/x0zGeK8KGB8H4UVVyf5QR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/obBCl/btrxjnpfYeN/x0zGeK8KGB8H4UVVyf5QR0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/obBCl/btrxjnpfYeN/x0zGeK8KGB8H4UVVyf5QR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FobBCl%2FbtrxjnpfYeN%2Fx0zGeK8KGB8H4UVVyf5QR0%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;2766&quot; height=&quot;534&quot; data-origin-width=&quot;2766&quot; data-origin-height=&quot;534&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;h2 data-ke-size=&quot;size26&quot;&gt;Read-Only True에서 @Async Read-Only Ture 메소드 실행&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;947&quot; data-origin-height=&quot;416&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQKuzG/btrxiGo47zB/klYW63MB0AxkZ9aT9RFkXK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQKuzG/btrxiGo47zB/klYW63MB0AxkZ9aT9RFkXK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQKuzG/btrxiGo47zB/klYW63MB0AxkZ9aT9RFkXK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQKuzG%2FbtrxiGo47zB%2FklYW63MB0AxkZ9aT9RFkXK%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;947&quot; height=&quot;416&quot; data-origin-width=&quot;947&quot; data-origin-height=&quot;416&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기존 쓰레드 http-nio-8080-exec-2의 커넥션과 task-2의 커넥션이 별도로 생성된다.&lt;/li&gt;
&lt;li&gt;둘 다 Read-Only True여서 Slave DB와 연결되었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3014&quot; data-origin-height=&quot;1018&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/epyR2M/btrxgFkv5Sa/x7HI0EtHwJC8LFp8gabD81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/epyR2M/btrxgFkv5Sa/x7HI0EtHwJC8LFp8gabD81/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/epyR2M/btrxgFkv5Sa/x7HI0EtHwJC8LFp8gabD81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FepyR2M%2FbtrxgFkv5Sa%2Fx7HI0EtHwJC8LFp8gabD81%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;3014&quot; height=&quot;1018&quot; data-origin-width=&quot;3014&quot; data-origin-height=&quot;1018&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;h2 data-ke-size=&quot;size26&quot;&gt;Spring AOP -  Async&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;일반 메소드에서 @Async 붙은 메소드를 실행 (같은 클래스)&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;651&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bchN0m/btrxeIBu9JI/ePV4c84hqu0yr0pix5mOo1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bchN0m/btrxeIBu9JI/ePV4c84hqu0yr0pix5mOo1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bchN0m/btrxeIBu9JI/ePV4c84hqu0yr0pix5mOo1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbchN0m%2FbtrxeIBu9JI%2FePV4c84hqu0yr0pix5mOo1%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;1400&quot; height=&quot;651&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;651&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;세 메소드가 전부 http-nio-8080-exec6 스레드에서 실행된다.&lt;/li&gt;
&lt;li&gt;같은 클래스 내에서 실행한 @Async가 무시되었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3014&quot; data-origin-height=&quot;1510&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tfL8b/btrxhMKuxBB/5ZRj8bZzQy1QagOUocbJZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tfL8b/btrxhMKuxBB/5ZRj8bZzQy1QagOUocbJZk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tfL8b/btrxhMKuxBB/5ZRj8bZzQy1QagOUocbJZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtfL8b%2FbtrxhMKuxBB%2F5ZRj8bZzQy1QagOUocbJZk%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;3014&quot; height=&quot;1510&quot; data-origin-width=&quot;3014&quot; data-origin-height=&quot;1510&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;h4 data-ke-size=&quot;size20&quot;&gt;@Async 붙은 메소드에서 @Async 붙은 메소드를 실행 (같은 클래스)&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;651&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdC6Ah/btrxkK5loaz/x6Ix4JTFKRUbyvuAhp7PX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdC6Ah/btrxkK5loaz/x6Ix4JTFKRUbyvuAhp7PX0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdC6Ah/btrxkK5loaz/x6Ix4JTFKRUbyvuAhp7PX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdC6Ah%2FbtrxkK5loaz%2Fx6Ix4JTFKRUbyvuAhp7PX0%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;1400&quot; height=&quot;651&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;651&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;세 메소드가 전부 task-3 스레드에서 실행된다.&lt;/li&gt;
&lt;li&gt;같은 클래스 내에서 실행한 @Async들이 무시가 되었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3014&quot; data-origin-height=&quot;1510&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/D34C2/btrxlpGLCci/c6Lrr3Jtu0u9VAYMiYgk21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/D34C2/btrxlpGLCci/c6Lrr3Jtu0u9VAYMiYgk21/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/D34C2/btrxlpGLCci/c6Lrr3Jtu0u9VAYMiYgk21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FD34C2%2FbtrxlpGLCci%2Fc6Lrr3Jtu0u9VAYMiYgk21%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;3014&quot; height=&quot;1510&quot; data-origin-width=&quot;3014&quot; data-origin-height=&quot;1510&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;h2 data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;같은 클래스 내에서 AOP로 동작하는 어노테이션들 (Transactional, Async)의 호출을 주의하자&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>study</category>
      <author>I'mDawon</author>
      <guid isPermaLink="true">https://devlopsquare.tistory.com/249</guid>
      <comments>https://devlopsquare.tistory.com/249#entry249comment</comments>
      <pubDate>Fri, 25 Mar 2022 22:55:50 +0900</pubDate>
    </item>
    <item>
      <title>[Java]LocalDateTime, OffsetDateTime, ZonedDateTime, Instant</title>
      <link>https://devlopsquare.tistory.com/248</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;타임스탬프를 RFC 3339의 형태로 보내 달라는 요구사항을 받았다. 그리고 어떤 값은 밀리세컨드 단위까지, 어떤 값은 세컨드 값 까지만 전달해 달라는 요구사항을 받았다. 어카지?&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;ISO 8601&lt;/h3&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;a href=&quot;https://ko.wikipedia.org/wiki/ISO_8601&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://ko.wikipedia.org/wiki/ISO_8601&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;RFC 3339&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ISO 8601을 인터넷 프로토콜로 어떻게 다룰지 규정한 RFC&lt;/li&gt;
&lt;li&gt;RFC 3339에서는 'T'의 생략을 허용하지 않고, 날짜와 시간 사이의 공백을 허용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://ijmacd.github.io/rfc3339-iso8601/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ISO 8601과 RFC 3339의 차이&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UTC 시간대를 기준으로 여러 포맷이 사용 될 수 있지만 대부분 아래와 같은 형태 일 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2020&amp;ndash;08&amp;ndash;28T09:20:26.187+09:00&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;LocalDateTime(LocalDate, LocalTime)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;현재 로컬의 시간 정보&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/U4UK6/btrv7Q0EFLn/OAPlfYiXym9okAZghIEkdk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/U4UK6/btrv7Q0EFLn/OAPlfYiXym9okAZghIEkdk/img.png&quot; data-origin-width=&quot;1302&quot; data-origin-height=&quot;970&quot; width=&quot;492&quot; height=&quot;366&quot; style=&quot;width: 49.4186%; margin-right: 10px;&quot; data-widthpercent=&quot;50&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/U4UK6/btrv7Q0EFLn/OAPlfYiXym9okAZghIEkdk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FU4UK6%2Fbtrv7Q0EFLn%2FOAPlfYiXym9okAZghIEkdk%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;1302&quot; height=&quot;970&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ei4itj/btrv8ETPmW3/nnYXrcYqwi7Bc3c8V5Mdy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ei4itj/btrv8ETPmW3/nnYXrcYqwi7Bc3c8V5Mdy1/img.png&quot; data-origin-width=&quot;1302&quot; data-origin-height=&quot;970&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;50&quot; style=&quot;width: 49.4186%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ei4itj/btrv8ETPmW3/nnYXrcYqwi7Bc3c8V5Mdy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fei4itj%2Fbtrv8ETPmW3%2FnnYXrcYqwi7Bc3c8V5Mdy1%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;1302&quot; height=&quot;970&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1647433662948&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//서울
System.out.println(LocalDateTime.now());
2022-03-16T21:26:25.495803&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1647433450485&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//몬트리올
System.out.println(LocalDateTime.now());
2022-03-16T08:23:38.556553&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컴퓨터의 시간을 그대로 나타내주고 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;OffestDateTime&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;타임존에 대한 정보를 가지고 있다...!&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1647433766830&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;System.out.println(OffsetDateTime.now());
2022-03-16T21:29:11.227296+09:00&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;ZonedDateTime&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;OffestDateTime에서 ZoneRegion에 대한 정보까지 포함&lt;/li&gt;
&lt;li&gt;+09:00 시간대에 서울특별시-대한민국 말고도, 중국 칭다오나 일본 후쿠오카 같은 지역도 포함된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1302&quot; data-origin-height=&quot;970&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dwKYPV/btrv6WOaEmX/zTzNI2r8FliV9z3oo4vwy0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dwKYPV/btrv6WOaEmX/zTzNI2r8FliV9z3oo4vwy0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dwKYPV/btrv6WOaEmX/zTzNI2r8FliV9z3oo4vwy0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdwKYPV%2Fbtrv6WOaEmX%2FzTzNI2r8FliV9z3oo4vwy0%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;567&quot; height=&quot;423&quot; data-origin-width=&quot;1302&quot; data-origin-height=&quot;970&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1647434466886&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;System.out.println(ZonedDateTime.now());
2022-03-16T21:39:36.821077+09:00[Asia/Seoul]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Instant&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;유닉스 시간 : POSIX 시간이나 Eporch 시간이라 부르기도 한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1970년 1월 1일 00:00:00 협정 세계시 (UTC)로 부터의 경과 시간을 초로 환산하여 표현한 것 이다.&lt;/li&gt;
&lt;li&gt;자바의 System.currentTimeMillis() 현재의 유닉스 시간을 밀리초로 반환한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1647794050857&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;System.out.println(Instant.now());
System.out.println(Instant.ofEpochMilli(System.currentTimeMillis()));
//2022-03-20T16:32:04.204752Z
//2022-03-20T16:32:04.204Z
//현재 한국은 2022-03-21 01:32&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;now()로 하면 나노초 단위까지 계산 밀리초 단위 까지 계산하려면 ofEpochMili()를 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;초 단위 까지만 표기하기&lt;/h3&gt;
&lt;pre id=&quot;code_1647794243042&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;System.out.println(OffsetDateTime.now().withNano(0));
//2022-03-21T01:32:04+09:00&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;withNano(0)시 밀리세컨드 또한 사라진다.&lt;/li&gt;
&lt;li&gt;OffsetDateTime은 밀리초단위는 컨트롤을 못한다...;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;밀리 세컨드 단위 까지 표현하기&lt;/h3&gt;
&lt;pre id=&quot;code_1647794376584&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;System.out.println(OffsetDateTime.ofInstant(Instant.ofEpochMilli(Instant.now().toEpochMilli()), ZoneId.systemDefault()));
System.out.println(OffsetDateTime.ofInstant(new Date().toInstant(), ZoneId.systemDefault()));
//2022-03-21T01:32:04.204+09:00
//2022-03-21T01:32:04.204+09:00&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Date도 시간을 currentTimeMillis로 가지고 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1647794493202&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    public Date() {
        this(System.currentTimeMillis());
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기존 LocalDateTime을 OffsetDateTime으로 변경하기&lt;/h3&gt;
&lt;pre id=&quot;code_1647794715119&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;System.out.println(localdateTime);
System.out.println(localdateTime.atOffset(OffsetDateTime.now().getOffset()));

//2022-03-21T01:44:52.083033
//2022-03-21T01:44:52.083033+09:00&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;atOffset을 활용해서 offset을 붙혀 줄 수 있다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>study</category>
      <author>I'mDawon</author>
      <guid isPermaLink="true">https://devlopsquare.tistory.com/248</guid>
      <comments>https://devlopsquare.tistory.com/248#entry248comment</comments>
      <pubDate>Wed, 16 Mar 2022 21:41:16 +0900</pubDate>
    </item>
    <item>
      <title>[Java]컬렉션(Collections) 정리</title>
      <link>https://devlopsquare.tistory.com/239</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;컬렉션 프레임워크 란?&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다수의 데이터를 쉽고 효과적으로 처리할 수 있는 표준화된 방법을 제공하는 클래스의 집합을 의미한다.&lt;/li&gt;
&lt;li&gt;자료구조와 알고리즘을 구조화 하여 클래스로 구현해 놓은 것&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;695&quot; data-origin-height=&quot;459&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHy37n/btrmRSlLoWf/Wyv1h7dV9Jkiw6k4ePS0ak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHy37n/btrmRSlLoWf/Wyv1h7dV9Jkiw6k4ePS0ak/img.png&quot; data-alt=&quot;https://techvidvan.com/tutorials/java-collection-framework/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHy37n/btrmRSlLoWf/Wyv1h7dV9Jkiw6k4ePS0ak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHy37n%2FbtrmRSlLoWf%2FWyv1h7dV9Jkiw6k4ePS0ak%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;459&quot; data-origin-width=&quot;695&quot; data-origin-height=&quot;459&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://techvidvan.com/tutorials/java-collection-framework/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 200px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style9&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 16.6667%; height: 20px; text-align: center;&quot;&gt;구분&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 20px; text-align: center;&quot;&gt;종류&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 20px; text-align: center;&quot;&gt;중복 허용&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 20px; text-align: center;&quot;&gt;순서 존재&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 20px; text-align: center;&quot;&gt;정렬 여부&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 20px; text-align: center;&quot;&gt;THREAD-SAFE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 16.6667%; height: 54px; text-align: center;&quot; rowspan=&quot;3&quot;&gt;LIST&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;ArrayList&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;O&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9;&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;LinkedList&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9;&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9;&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;Vector&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9;&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9;&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9;&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 16.6667%; height: 54px; text-align: center;&quot; rowspan=&quot;3&quot;&gt;SET&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;HashSet&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;Linked&lt;br /&gt;HashSet&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9;&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;TreeSet&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9;&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 16.6667%; height: 72px; text-align: center;&quot; rowspan=&quot;4&quot;&gt;MAP&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;HashMap&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;Linked&lt;br /&gt;HashMap&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9;&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;Hashtable&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9;&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;TreeMap&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9;&quot;&gt;O&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; height: 18px; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9;&quot;&gt;X&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;List는 중복이 가능하고, 순서가 있는 데이터의 집합이다.&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;ArrayList - 특정 원소 조회가 많은 경우 사용하는 것이 좋다.&lt;/span&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;기본 크기는 10이지만 원소가 늘어나면 더 큰 배열에 옮긴다.&lt;/li&gt;
&lt;li&gt;인덱스로 조회가 가능하므로, 인덱스만 알면 해당 데이터를 빠르게 조회 할 수 있다.&lt;/li&gt;
&lt;li&gt;삽입, 삭제를 하면 그 뒤에 있는 데이터를 뒤로 밀거나 앞으로 당겨야 하기 때문에 느리다. (O(N))&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;LinkedList - 조회보다 삽입/삭제가 많은 경우에 사용하는 것이 좋다.&lt;/span&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;특정 원소를 조회하는 경우 첫 노드 부터 순회해야 하기 때문에 ArrayList에 비해 느리다.&lt;/li&gt;
&lt;li&gt;포인터로 각각 노드들을 연결하고 있어서, 삽입/삭제가 빠르다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;단순히 기존 포인터를 끊고 새로운 노드에 연결하면 되기 때문이다.&lt;/li&gt;
&lt;li&gt;그러나 중간에 데이터를 삽입, 삭제 할 경우 그 데이터까지 순차적으로 조회해야 하기 때문에 O(N)의 시간복잡도를 가진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;Vector - ArrayList와 비슷하게 배열로 만들어진 리스트지만, thread-safe하다.&lt;/span&gt;&amp;nbsp;
&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;get, put에 모두 syncronized가 걸려있어서 스레드마다 lock이 걸리게 되고, 성능이 ArrayList보다 좋지 않다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;Stack - LIFO(Last-In-First-Out)특성을 가지는 자료구조이다.&lt;/span&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;들어올 때는 push, 나갈때는 pop이라는 용어를 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Set은 중복이 불가능하고, 순서가 없는 데이터의 집합이다.&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;HashSet - 중복을 허용하지 않고, 순서를 가지지 않는다&lt;/span&gt;.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HashSet이 판단하는 동일한 객체란 꼭 같은 인스턴스를 뜻하지 않는다. (동일성)&lt;/li&gt;
&lt;li&gt;HashSet은 객체를 저장하기 전에 먼저 객체의 hashCode() 메소드를 호출한다. 그리고 같다면 equals()로 두 객체리를 비교해서 동등성을 판단한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1639064792825&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    @Test
    public void hashSetTest() {
        Set&amp;lt;String&amp;gt; hashSet = new HashSet&amp;lt;&amp;gt;();
        hashSet.add(&quot;하나&quot;);
        hashSet.add(&quot;둘&quot;);
        hashSet.add(&quot;셋&quot;);

        System.out.println(hashSet);

        hashSet.add(&quot;넷&quot;);
        hashSet.add(&quot;다섯&quot;);

        System.out.println(hashSet);

    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;47&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQc3pz/btrnqxpm8bv/XzFc3P6BwKKfs1KBsFlmdk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQc3pz/btrnqxpm8bv/XzFc3P6BwKKfs1KBsFlmdk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQc3pz/btrnqxpm8bv/XzFc3P6BwKKfs1KBsFlmdk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQc3pz%2Fbtrnqxpm8bv%2FXzFc3P6BwKKfs1KBsFlmdk%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;540&quot; height=&quot;47&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;47&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;LinkedHashSet - 중복은 허용하지 않지만, 순서를 가진다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1639064820033&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    @Test
    public void linkedHashSetTest() {
        Set&amp;lt;String&amp;gt; hashSet = new LinkedHashSet&amp;lt;&amp;gt;();
        hashSet.add(&quot;하나&quot;);
        hashSet.add(&quot;둘&quot;);
        hashSet.add(&quot;셋&quot;);

        System.out.println(hashSet);

        hashSet.add(&quot;넷&quot;);
        hashSet.add(&quot;다섯&quot;);

        System.out.println(hashSet);

    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;47&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhOn1j/btrnuWPqSHP/Qb4EthKkbV9Nv5DspNq7Hk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhOn1j/btrnuWPqSHP/Qb4EthKkbV9Nv5DspNq7Hk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhOn1j/btrnuWPqSHP/Qb4EthKkbV9Nv5DspNq7Hk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbhOn1j%2FbtrnuWPqSHP%2FQb4EthKkbV9Nv5DspNq7Hk%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;540&quot; height=&quot;47&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;47&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;TreeSet - 중복은 허용하지않고, 순서를 가지지 않는다. 그러나 정렬이 되어있다.&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이진트리를 기반으로 한 Set컬렉션이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1639064870298&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    @Test
    public void treeSetTest() {
        Set&amp;lt;String&amp;gt; hashSet = new TreeSet&amp;lt;&amp;gt;();
        hashSet.add(&quot;하나&quot;);
        hashSet.add(&quot;둘&quot;);
        hashSet.add(&quot;셋&quot;);

        System.out.println(hashSet);

        hashSet.add(&quot;넷&quot;);
        hashSet.add(&quot;다섯&quot;);

        System.out.println(hashSet);
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;47&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cjv56Q/btrnuXHCfk2/MAtuAkVEzgzKcmu1eZJ2D1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cjv56Q/btrnuXHCfk2/MAtuAkVEzgzKcmu1eZJ2D1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cjv56Q/btrnuXHCfk2/MAtuAkVEzgzKcmu1eZJ2D1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcjv56Q%2FbtrnuXHCfk2%2FMAtuAkVEzgzKcmu1eZJ2D1%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;540&quot; height=&quot;47&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;47&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Queue는 FIFO(First-In-First-Out)구조를 가진다.&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;처음 들어온 원소가 처음으로 나간다는 특징이 있다.&lt;/li&gt;
&lt;li&gt;들어올때는 enqueue, 나갈때는 dequeue라고 한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PriorityQueue&lt;/b&gt;는 우선순위를 가지는 큐로 원소에 우선순위를 부여하여 높은 순으로 먼저 반환한다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Dequeue&lt;/b&gt;는 양쪽으로 넣고 빼는 것이 가능한 큐 자료구조 이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Map은 키와 값을 가지고 순서는 기억하지 않으며 키는 중복이 불가능하고, 값은 중복이 가능한 데이터 집합이다.&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;HashMap은 키와 값을 가지고, 순서는 기억하지 않으며 키는 중복이 불가능하고, 값은 중복이 가능하다.&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;key와 value에 null을 허용한다.&lt;/li&gt;
&lt;li&gt;동기화를 보장하지 않는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1639065155864&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    @Test
    public void hashMapTest() {
        Map&amp;lt;String, String&amp;gt; hashMap = new HashMap();
        hashMap.put(&quot;사과&quot;, &quot;apple&quot;);
        hashMap.put(&quot;포도&quot;, &quot;grape&quot;);
        hashMap.put(&quot;수박&quot;, &quot;watermelon&quot;);
        hashMap.put(&quot;배&quot;, &quot;pear&quot;);

        System.out.println(hashMap);
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;25&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yXR16/btrnxkO5rwm/t6W7BBtu52jL4a8plKMP3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yXR16/btrnxkO5rwm/t6W7BBtu52jL4a8plKMP3K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yXR16/btrnxkO5rwm/t6W7BBtu52jL4a8plKMP3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyXR16%2FbtrnxkO5rwm%2Ft6W7BBtu52jL4a8plKMP3K%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;540&quot; height=&quot;25&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;25&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;HashTable은 HashMap과 동일한 특징을 가지지만 Thread-Safe하여 동기화를 지원한다.&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;key와 value에 null을 허용하지 않는다.&lt;/li&gt;
&lt;li&gt;동기화를 보장한다.&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;get(), put(), remove() 등에 syncronized 키워드가 붙어있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;LinkedHashMap은 들어온 순서대로 순서를 가지는 Map이다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1639065209073&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    @Test
    public void linkedHashMapTest() {
        Map&amp;lt;String, String&amp;gt; hashMap = new LinkedHashMap&amp;lt;&amp;gt;();
        hashMap.put(&quot;사과&quot;, &quot;apple&quot;);
        hashMap.put(&quot;포도&quot;, &quot;grape&quot;);
        hashMap.put(&quot;수박&quot;, &quot;watermelon&quot;);
        hashMap.put(&quot;배&quot;, &quot;pear&quot;);

        System.out.println(hashMap);
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;25&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Qtmo4/btrnv2g4W7h/ERHwbRIKe5bHsl6kLGYzL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Qtmo4/btrnv2g4W7h/ERHwbRIKe5bHsl6kLGYzL1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Qtmo4/btrnv2g4W7h/ERHwbRIKe5bHsl6kLGYzL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQtmo4%2Fbtrnv2g4W7h%2FERHwbRIKe5bHsl6kLGYzL1%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;540&quot; height=&quot;25&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;25&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;TreeMap은 key를 기준으로 정렬이 되어 저장되는 Map이다.&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이진트리를 기반으로한 Map이다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;부모 키값을 비교하여 낮은 건 왼쪽에 높은건 오른쪽에 Map.Entry를 저장한다.&lt;/li&gt;
&lt;li&gt;그래서 저장시간이 다른 자료구조에 비해 오래 걸린다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1639065256082&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    @Test
    public void treeMapTest() {
        Map&amp;lt;String, String&amp;gt; hashMap = new TreeMap&amp;lt;&amp;gt;();
        hashMap.put(&quot;사과&quot;, &quot;apple&quot;);
        hashMap.put(&quot;포도&quot;, &quot;grape&quot;);
        hashMap.put(&quot;수박&quot;, &quot;watermelon&quot;);
        hashMap.put(&quot;배&quot;, &quot;pear&quot;);

        System.out.println(hashMap);
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;25&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RbsaU/btrnwo5hUvM/e4nHpNHkxyjhd6R2Yr6TIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RbsaU/btrnwo5hUvM/e4nHpNHkxyjhd6R2Yr6TIK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RbsaU/btrnwo5hUvM/e4nHpNHkxyjhd6R2Yr6TIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRbsaU%2Fbtrnwo5hUvM%2Fe4nHpNHkxyjhd6R2Yr6TIK%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;540&quot; height=&quot;25&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;25&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>study</category>
      <author>I'mDawon</author>
      <guid isPermaLink="true">https://devlopsquare.tistory.com/239</guid>
      <comments>https://devlopsquare.tistory.com/239#entry239comment</comments>
      <pubDate>Thu, 2 Dec 2021 20:56:42 +0900</pubDate>
    </item>
    <item>
      <title>[Spring]프로토타입과 스코프</title>
      <link>https://devlopsquare.tistory.com/238</link>
      <description>&lt;blockquote data-ke-style=&quot;style3&quot;&gt;토비의 스프링 vol2 챕터 1.3 프로토타입과 스코프를 읽고 정리한 글 입니다.&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;스코프&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;존재할 수 있는 범위&lt;/li&gt;
&lt;li&gt;빈 오브젝트가 만들어져 존재할 수 있는 범위이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;스프링 빈은 기본적으로 싱글톤으로 만들어 진다.&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;애플리케이션 컨텍스트마다 빈의 오브젝트는 한 개만 만들어진다.&lt;/li&gt;
&lt;li&gt;요청이 있을 때마다 매번 애플리케이션 로직을 담은 오브젝트를 새로 만드는 건 비효율적이기 때문이다.&lt;/li&gt;
&lt;li&gt;하나의 빈 오브젝트에 동시에 여러 스레드가 접근하기 때문에 상태 값을 인스턴스 변수에 저장해 두고 사용할 수 없다.&lt;/li&gt;
&lt;li&gt;싱글톤으로 설정된 빈은 DI, DL시 항상 같은 오브젝트가 리턴됨이 보장된다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DL (Dependency Lookup) : 컨테이너에서 getBean()을 통해 조회하는 것,&lt;/li&gt;
&lt;li&gt;주입 받는 것이 아니라 직접 필요한 의존관계를 찾는 것.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;프로토타입 스코프는 컨테이너에게 빈을 요청할 때마다 매번 새로운 오브젝트를 생성해준다.&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로토타입 빈은 IoC의 기본 원칙을 따르지 않는다.&lt;/li&gt;
&lt;li&gt;프로토타입 스코프를 갖는 빈은 요청이 있을 때마다 컨테이너가 생성하고 초기화하고 DI까지 해주기도 하지만 일단 빈을 제공하고 나면 컨테이너는 더 이상 빈 오브젝트를 관리하지 않는다.&lt;/li&gt;
&lt;li&gt;프로토타입 빈은 생성 후 관리는 전적으로 DI 받은 오브젝트에 달려있다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로토타입빈을 주입받은 빈이 싱글톤이라면, 이 빈에 주입된 프로토타입 빈도 역시 싱클톤 생명 주기를 따름&lt;/li&gt;
&lt;li&gt;그러나 주입받은 빈의 스코프가 더 작다면, 프로토타입 빈도 해당 빈과 함께 제거&lt;/li&gt;
&lt;li&gt;메소드 안에서 사용하고 따로 저장해 두지 않는다면, 메소드가 끝나고 프로토타입 빈도 제거&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;IoC의 기본 개념은 애플리케이션을 구성하는 핵심 오브젝트를 코드가 아니라 컨테이너가 관리한다는 것이다. 그래서 스프링이 관리하는 오브젝트인 빈은 그 생성과 다른 빈에 대한 의존관계 주입, 초기화(메소드 호출), DI, DL을 통한 사용, 제거에 이르기까지 모든 오브젝트의 생명주기를 컨테이너가 관리한다. 빈에 대한 정보와 오브젝트에 대한 레퍼런스는 컨테이너가 계속 갖고 있고, 필요할&amp;nbsp;&lt;br /&gt;때마다 요청해서 빈 오브젝트를 얻을 수 있다.&lt;/blockquote&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;span style=&quot;background-color: #ffc9af;&quot;&gt;프로토타입 빈은 내부에서 스프링의 DI를 통해 빈을 주입받아야 할 경우 사용한다.&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로토타입 빈은 코드에서 new로 오브젝트를 생성하는 것을 대신하기 위해 사용된다.&lt;/li&gt;
&lt;li&gt;사용자 요청별로 독립적인 정보나 작업 상태를 저장해둘 오브젝트를 만들 필요가 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이 경우 new로도 충분한데, 왜 프로토 타입 빈을 사용할까?&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;사용자 요청에 따라 매번 독립적인 오브젝트를 만들어야 하는데, 매번 새롭게 만들어지는 오브젝트가 컨테이너 내의 빈을 사용해야 하는 경우 즉, 프로토타입 빈안에서 DI가 필요한 경우 사용한다.&lt;/li&gt;
&lt;li&gt;코드에서 일일이 수동으로 DI를 해줄 것이 아니라면 프로토타입빈으로 생성하는 것이 좋다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;매번 새로운 오브젝트가 필요하면서 DI를 통해 다른 빈을 사용할 수 있어야 한다면? -&amp;gt; 프로토타입빈 사용&lt;/b&gt;&lt;/li&gt;
&lt;/ul&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;span style=&quot;background-color: #ffc9af;&quot;&gt;요청 스코프 빈은 하나의 웹 요청 안에서 만들어지고 해당 요청이 끝날 때 제거된다.&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 요청별로 독립적인 빈이 만들어지기 때문에 빈 오브젝트 내에 상태 값을 저장해 둬도 안전하다.&lt;/li&gt;
&lt;li&gt;하나의 웹 요청을 처리하는 동안 참조하는 요청 스코프 빈은 항상 동일한 오브젝트임이 보장된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;세션 스코프는 HTTP 세션과 같은 존재 범위를 갖는 빈이다.&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HTTP 세션은 사용자별로 만들어지고 브라우저를 닫거나 세션 타임이 종료될 때까지 유지되기 때문에 로그인 정보나 사용자별 선택옵션을 저장해두기에 유용하다.&lt;/li&gt;
&lt;li&gt;웹 환경에종속적인 HttpSession을 다른 계층으로 넘겨서 사용하게 하는 건 좋지 않다. -&amp;gt; &lt;b&gt;HTTP 세션에 저장되는 정보를 웹 기술에 종속적이지 않은 오브젝트에 담아서 (ex. DTO(?)) HTTP 세션에 직접 접근이 가능한 프레젠테이션과 서비스 계층사이에 주고받아야 한다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;세션 스코프를 이용하면 이런 번거로움 없이도 HTTP 세션에 저장되는 정보를 모든 계층에서 안전하게 이용할 수 있다.&lt;/li&gt;
&lt;/ul&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;span style=&quot;background-color: #ffc9af;&quot;&gt;애플리케이션 스코프는 서블릿 컨텍스트에 저장되는 빈 오브젝트이다.&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서블릿 컨텍스트는 웹 애플리케이션마다 만들어진다.&lt;/li&gt;
&lt;li&gt;웹 애플리케이션마다 스프링의 애플리케이션 컨텍스트도 만들어진다.&lt;/li&gt;
&lt;li&gt;드물지만 웹 애플리케이션과 싱글톤 스코프가 다른 경우가 있다.&lt;/li&gt;
&lt;li&gt;애플리케이션 스코프도 싱글톤 스코프와 마찬가지로 상태를 갖지 않거나, 상태가 있다고 하더라도 읽기전용으로 만들거나, 멀티스레드 환경에서 안전하도록 만들어야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;스프링 빈 생명주기 메소드로 초기화 메소드와 소멸메서드가 있다.&lt;/span&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;해당 부분은 초보 웹 개발자를 위한 스프링5 프로그래밍 입문의 내용을 정리하였습니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨테이너가 관리하는 빈 객체의 라이프사이클은 &lt;b&gt;객체 생성 -&amp;gt; 의존 설정 -&amp;gt; 초기화 -&amp;gt; 소멸&lt;/b&gt;의 라이프 사이클을 가진다. 스프링 컨테이너는 빈 객체를 초기화하고 소멸하기 위해 빈 객체의 지정한 메서드를 호출한다. 스프링은 다음의 두 인터페이스에 이 메서드를 정의하고 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;InitializingBean&lt;/li&gt;
&lt;li&gt;DisposableBean&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 클래스가 위의&amp;nbsp; 인터페이스를 구현하여 사용할 수 있는 것이 아니다. 외부에서 제공받은 클래스에서 사용하고 싶은 경우에는 스프링 설정에서 직접 초기화, 소멸 메서드를 지정할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1638437218806&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Bean(initMethod=&quot;connect&quot;, destroyMethod=&quot;close&quot;)
public Client2 client2() {
    Client2 client = new Client2();
    client.setHost(&quot;Host&quot;);
    return client;
}&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;b&gt;@PostConstruct, @PreDestory&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;스프링은 왜 싱글톤을 기본 스코프로 사용할까?&lt;/span&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서버 성능에 좋기 때문이다.&lt;/li&gt;
&lt;li&gt;IoC컨테이너를 통해 주입받는 싱글톤 스코프 빈은 &lt;b&gt;'동일성'&lt;/b&gt;을 보장한다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;스프링이 주로 적용되는 대상은 자바 엔터프라이즈 기술을 사용하는 서버환경이다. 초 당 많은 요청을 받아내야 하고, 요청을 처리하기 위해 컨트롤러 단, 서비스 단, 레포지토리 단으로 많은 계층으로 구성되어있다. 그리고 이 계층 마다 다양한 객체들이 참여하여 협력한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;그런데 요청이 들어올 때 마다 비즈니스 로직 처리를 위한 객체를 새로 생성한다면? -&amp;gt; 힙 메모리가 꽉 찰 것이다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&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;span style=&quot;background-color: #ffc9af;&quot;&gt;멀티 스레드 환경에서 싱글톤은 무상태성으로 만들어져야 한다.&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;싱글톤은 멀티스레드 환경이라면 여러 스레드가 동시에 접근해서 사용할 수 있다.&lt;/li&gt;
&lt;li&gt;다중 사용자의 요청을 한꺼번에 처리하는 스레드들이 동시에 싱글톤 오브젝트의 인스턴스 변수를 수정하는 것은 매우 위험하다.&lt;/li&gt;
&lt;li&gt;저장할 공간이 하나 뿐이니 서로 값을 덮어쓰고, 자신이 저장하지 않은 값을 읽어올 수 있기 때문이다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>study</category>
      <author>I'mDawon</author>
      <guid isPermaLink="true">https://devlopsquare.tistory.com/238</guid>
      <comments>https://devlopsquare.tistory.com/238#entry238comment</comments>
      <pubDate>Thu, 2 Dec 2021 17:02:53 +0900</pubDate>
    </item>
    <item>
      <title>[DB]트랜잭션 정리</title>
      <link>https://devlopsquare.tistory.com/237</link>
      <description>&lt;blockquote data-ke-style=&quot;style3&quot;&gt;에이든의 트랜잭션 매커니즘, 샐리, 예지니어스의 트랜잭션 테코톡을 듣고 정리한 글 입니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;트랜잭션&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;여러 쿼리를 논리적으로 하나의 작업으로 묶어주는 것&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;하나의 트랜잭션은 커밋 혹은 롤백된다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;데이터베이스에 저장된 데이터베이스의 무결성과 동시성의 성능을 지키기위해 트랜잭션의 설정이 중요 &lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;ACID&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;트랜잭션이 안전하게 수행된다는 것을 보장하기 위한 성질&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;Atomicity&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;트랜잭션은 DB에 모두 반영되거나, 전혀 반영되지 않아야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;완료되지 않은 트랜잭션의 중간 상태를 DB에 반영해서는 안 된다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;Consistency&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;트랜잭션 작업처리결과는 항상 일관성 있어야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;데이터베이스는 항상 일관된 상태로 유지되어야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;Isolation&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;둘 이상의 트랜잭션이 동시 실행되고 있을 때, 어떤 트랜잭션도 다른 트랜잭션 연산에 끼어들 수 없다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;Durability&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;트랜잭션이 성공적으로 완료되었으면 결과는 영구히 반영되어야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;커밋이 되었다면, 정전과 같이 예상치 못한 문제가 발생 되었더라도 데이터는 반영된 그대로 남아있어야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;트랜잭션 격리 수준&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;동시에 DB 접근할 때 그 접근을 어떻게 제어할지에 대한 설정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;격리 수준이 높아 질 수록 데이터 정합성은 좋아지나 동시성 성능이 떨어진다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;격리수준&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;READ-UNCOMMITTED&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;커밋 전의 트랜잭션의 데이터 변경 내용을 다른 트랜잭션이 읽는 것을 허용&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;READ-COMITTED&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;커밋이 완료된 데이터만 다른 트랜잭션에서 조회가능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;트랜잭션이 이루어지는 동안 다른 사용자는 해당 데이터에 접근이 불가능하다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;REPEATABLE-READ&lt;/span&gt;&lt;span&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;트랜잭션 범위 내에서 조회한 내용이 항상 동일함을 보장&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;SERIALIZABLE&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;한 트랜잭션에서 사용하는 데이터를 다른 트랜잭션에서 접근 불가&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&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;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;DIRTY READ&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;NON-REPEATABLE READ&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;PHANTOM READ&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;READ UNCOMMITTED&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;발생&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;발생&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;발생&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;READ COMMITED&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;없음&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;발생&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;발생&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;REPEATABLE READ&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;발생&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;발생&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;발생&lt;br /&gt;(InnoDB는 없음)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;SERIALIZABLE&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;없음&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;없음&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;DIRTY READ&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;더티페이지(메모리에는 변경이 되었지만 디스크에는 아직 변경이 되지 않은 데이터)에 있는 데이터를 검색한다. 커밋되지 않은 데이터를 리드하기 때문에 더티리드 후 더티페이지가 롤백이 되면 잘못된 데이터를 읽어온 경우가 되어버린다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;아래 예시에서 트랜잭션 A가 트랜잭션을 끝마치지 못하고 롤백한다면 트랜잭션 B는 무효가 된 값을 읽고 처리한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;447&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Qim76/btrmMfPqbTk/NCGKCF27RWg2N7lD8XMv91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Qim76/btrmMfPqbTk/NCGKCF27RWg2N7lD8XMv91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Qim76/btrmMfPqbTk/NCGKCF27RWg2N7lD8XMv91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQim76%2FbtrmMfPqbTk%2FNCGKCF27RWg2N7lD8XMv91%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;940&quot; height=&quot;447&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;447&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;NON-REPEATABLE READ&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;같은 트랜잭션 내에서 READ시 값이 다르게 나오는 &lt;b&gt;데이터 불일치 문제 &lt;/b&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;하나의 트랜잭션에서 같은 쿼리를 두번 이상 수행할 때, 똑같은 쿼리임에도 다른 결과를 볼 수 있게 되는 현상&lt;/li&gt;
&lt;li&gt;트랜잭션 중 데이터가 변경되면 문제가 발생할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;951&quot; data-origin-height=&quot;447&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9qIa4/btrmK0eb0yG/pfQ5bVIY1nTFbQiNDjqi5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9qIa4/btrmK0eb0yG/pfQ5bVIY1nTFbQiNDjqi5k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9qIa4/btrmK0eb0yG/pfQ5bVIY1nTFbQiNDjqi5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9qIa4%2FbtrmK0eb0yG%2FpfQ5bVIY1nTFbQiNDjqi5k%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;951&quot; height=&quot;447&quot; data-origin-width=&quot;951&quot; data-origin-height=&quot;447&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;Phantom Read&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;NON-REPREATABLE READ의 한 종류&lt;/li&gt;
&lt;li&gt;하나의 트랜잭셩네서 일정 범위의 레코드를 두번이상 읽을 때, 똑같은 쿼리임에도 첫번째 쿼리에서 없던 레코드가 두번째 쿼리에서 나타나는 현상&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;447&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdf8if/btrmQ4zDjGl/s3SWp9WhJZlBCuBAiptyHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdf8if/btrmQ4zDjGl/s3SWp9WhJZlBCuBAiptyHk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdf8if/btrmQ4zDjGl/s3SWp9WhJZlBCuBAiptyHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbdf8if%2FbtrmQ4zDjGl%2Fs3SWp9WhJZlBCuBAiptyHk%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;940&quot; height=&quot;447&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;447&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;트랜잭션 전파 타입&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;트랜잭션 경계에서 이미 진행중인 트랜잭션이 있을 어떻게 동작할지 결정하는 것&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;전파타입&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;REQUIRED&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;현재 진행중인 트랜잭션이 존재하면 해당 트랜잭션을 사용한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;존재하지 않으면 새로운 트랜잭션을 생성한다.&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;두 메서드가 하나의 트랜잭션으로 실행되기 때문에 어느 메서드에서 문제가 발생해도 실행했던 모든 쿼리가 롤백된다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;374&quot; data-origin-height=&quot;391&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cnKa2u/btrmQrnE1fc/HVouKDVokikukGuPxSqQV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cnKa2u/btrmQrnE1fc/HVouKDVokikukGuPxSqQV0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cnKa2u/btrmQrnE1fc/HVouKDVokikukGuPxSqQV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcnKa2u%2FbtrmQrnE1fc%2FHVouKDVokikukGuPxSqQV0%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;265&quot; height=&quot;277&quot; data-origin-width=&quot;374&quot; data-origin-height=&quot;391&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;SUPPORTS&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;진행중인 트랜잭션이 있다면 트랜잭션을 사용한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;진행중인 트랜잭션이 없다면 트랜잭션 없이 메서드가 정상동작한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;MANDATORY&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;REQUIRED와 달리 진행 중인 트랜잭션이 존재하지 않을 경우 예외가 발생한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;REQUIRES_NEW&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;항상 새로운 트랜잭션을 시작한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;진행 중인 트랜잭션이 존재하면 기존 트랜잭션을 일시 중지하고 새로운 트랜잭션을 시작한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;새로운 트랜잭션이 종료된 뒤에 기존 트랜잭션이 계속된다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;NOT_SUPPORTED&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;SUPPORT와 달리 진행 중인 트랜잭션이 존재할 경우 메서드가 실행되는 동안 트랜잭션을 일시 중지 되고 메서드 실행이 종료된 후에 트랜잭션을 계속 진행한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;트랜잭션을 사용하지 않는 설정&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;NEVER&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;메서드가 트랜잭션을 필요로 하지 않는다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;만약 진행 중인 트랜잭션이 존재하면 예외 발생&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;NESTED&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;진행 중인 트랜잭션이 존재하면 그 안에 새로운 트랜잭션을 만드는 설정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;중첩된 트랜잭션 2는 부모인 트랜잭션1의 커밋, 롤백에는 영향을 받는다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;트랜잭션2의 커밋 롤백에는 트랜잭션1이 영향을 받지 않는다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;374&quot; data-origin-height=&quot;391&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oOvmX/btrmLBq8R9H/2J1K1pqZ8vnMPkWDCfbiFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oOvmX/btrmLBq8R9H/2J1K1pqZ8vnMPkWDCfbiFK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oOvmX/btrmLBq8R9H/2J1K1pqZ8vnMPkWDCfbiFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoOvmX%2FbtrmLBq8R9H%2F2J1K1pqZ8vnMPkWDCfbiFK%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;265&quot; height=&quot;277&quot; data-origin-width=&quot;374&quot; data-origin-height=&quot;391&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;Timeout&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1638417700792&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Transactional(timeout=10)&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;초 단위로 트랜잭션 제한시간을 설정할 수 있는 속성&lt;/li&gt;
&lt;li&gt;설정된 시간이 지나면 예외가 발생하며 롤백&lt;/li&gt;
&lt;li&gt;따로 설정하지 않으면 timeout 속성은 지정되어 있지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;readOnly&lt;/h3&gt;
&lt;pre id=&quot;code_1638417772007&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Transactional(readOnly=true)&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;트랜잭션 작업 안에서 update, insert, delete 작업이 일어나는 것을 방지&lt;/li&gt;
&lt;li&gt;해당 옵션을 적용하면 flush 모드가 manual로 설정되어 jpa의 더티체킹 기능 무시 하여 성능향상에 도움을 줌&lt;/li&gt;
&lt;/ul&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;span&gt;rollbackFor&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1638417938488&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Transactional(rollbackFor=NoSuchElementException.class)&lt;/code&gt;&lt;/pre&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;기본적으로 트랜잭션은 런타임 예외와 Error가 발생했을 때만 롤백&lt;/li&gt;
&lt;li&gt;체크예외나 예외가 발생하지 않으면 커밋하도록 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;noRollbackFor&lt;/h3&gt;
&lt;pre id=&quot;code_1638418065856&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Transactional(noRollbackFor={IOException.class, SqlException.class})&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;롤백 대상인 지정된 런타임 예외를 롤백하지 않고 커밋하도록 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;트랜잭션 메커니즘&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;624&quot; data-origin-height=&quot;438&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dhB5Kx/btrmKA0C10b/r9rK9yZcntkaepcRAs8itk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dhB5Kx/btrmKA0C10b/r9rK9yZcntkaepcRAs8itk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dhB5Kx/btrmKA0C10b/r9rK9yZcntkaepcRAs8itk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdhB5Kx%2FbtrmKA0C10b%2Fr9rK9yZcntkaepcRAs8itk%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;624&quot; height=&quot;438&quot; data-origin-width=&quot;624&quot; data-origin-height=&quot;438&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;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;BEGIN TRAN
UPDATE accounts
SET balance = balance - 10000
WHERE user = '구매자'
SET balance = balance + 10000
WHERE user = '판매자'
COMMIT TRAN&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;UPDATE accounts SET balance = balance - 10000 WHERE user = '구매자'&lt;/b&gt; 쿼리 실행&lt;/li&gt;
&lt;li&gt;업데이트에 필요한 데이터를 데이터 캐시에 요청을 하는데, 데이터 캐시에 해당 데이터가 없다.&lt;/li&gt;
&lt;li&gt;데이터 파일에서 데이터를 가져와야 한다.&lt;/li&gt;
&lt;li&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;style1&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;User&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;Balance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;구매자&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;10,000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;li&gt;데이터가 로드 된 후, 업데이트를 하면 되는데 &lt;b&gt;그 전에 로그 캐시에 로그를 기록해야 한다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;ReDo로그와 UnDo로그에 기록을 한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ReDo 로그
&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;pre id=&quot;code_1638418776928&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;트랜잭션_1 START
트랜잭션_1 UPDATE accounts 구매자.balance 0&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;UnDo 로그
&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;pre id=&quot;code_1638418795780&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;로그_1 accounts 구매자.balance 10000&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&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;style1&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;User&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;Balance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;구매자&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;UPDATE accounts SET balance = balance + 10000 WHERE user = '판매자'&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;쿼리 실행&lt;/li&gt;
&lt;li&gt;판매자의 데이터가 없으므로 데이터 파일에서 데이터 캐시로 로드
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 75px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 25px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 25px;&quot;&gt;User&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 25px;&quot;&gt;Balance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 25px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 25px;&quot;&gt;구매자&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 25px;&quot;&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 25px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 25px;&quot;&gt;판매자&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 25px;&quot;&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;li&gt;ReDo로그와 UnDo로그에 기록을 한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;nbsp;ReDo로그
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1638419241187&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;트랜잭션_1 START
트랜잭션_1 UPDATE accounts 구매자.balance 0
트랜잭션_2 UPDATE accounts 판재마.balance 10000&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;UnDo로그
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1638419250084&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;로그_1 accounts 구매자.balance 10000
로그_2 accounts 판매자.balance 0&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;데이터 캐시의 데이터 업데이트
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 75px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 25px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 25px; text-align: center;&quot;&gt;User&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 25px; text-align: center;&quot;&gt;Balance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 25px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 25px; text-align: center;&quot;&gt;구매자&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 25px; text-align: center;&quot;&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 25px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 25px; text-align: center;&quot;&gt;판매자&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 25px; text-align: center;&quot;&gt;10000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;li&gt;트랜잭션의 한 단위가 끝났다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;데이터 롤백 시 UnDo로그를 통해 롤백한다.&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;UnDo를 통해서 &lt;b&gt;역순&lt;/b&gt;으로 기록을하게 되면 데이터가 이전 상태로 원복 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1638419378063&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;로그_1 accounts 구매자.balance 10000
로그_2 accounts 판매자.balance 0&lt;/code&gt;&lt;/pre&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 75px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 25px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 25px; text-align: center;&quot;&gt;User&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 25px; text-align: center;&quot;&gt;Balance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 25px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 25px; text-align: center;&quot;&gt;구매자&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 25px; text-align: center;&quot;&gt;10000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 25px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 25px; text-align: center;&quot;&gt;판매자&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 25px; text-align: center;&quot;&gt;0&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;h4 data-ke-size=&quot;size20&quot;&gt;예상치 못한 오류 발생 시 ReDo로그와 UnDo로그를 통해 복구한다.&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ReDo로그를 순차적으로 실행 해서 데이터들을 다시 일관성 있게 만들어 준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1638419498437&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;트랜잭션_1 START
트랜잭션_1 UPDATE accounts 구매자.balance 0
트랜잭션_2 UPDATE accounts 판재마.balance 10000&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Undo로그를 역순으로 실행하여 다시 커밋이 되지 않은 것들을 다시 이전 상태로 돌려준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1638419619919&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;로그_1 accounts 구매자.balance 10000
로그_2 accounts 판매자.balance 0&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;h4 data-ke-size=&quot;size20&quot;&gt;참고&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=aX9c7z9l_u8&amp;amp;t=22s&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;  샐리의 트랜잭션&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=ImvYNlF_saE&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;  에이든의 트랜잭션 메커니즘&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=e9PC0sroCzc&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;  예지니어스의 트랜잭션&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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>study</category>
      <author>I'mDawon</author>
      <guid isPermaLink="true">https://devlopsquare.tistory.com/237</guid>
      <comments>https://devlopsquare.tistory.com/237#entry237comment</comments>
      <pubDate>Thu, 2 Dec 2021 12:57:10 +0900</pubDate>
    </item>
    <item>
      <title>우아한테크코스 글쓰기 아카이브</title>
      <link>https://devlopsquare.tistory.com/234</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;logo_thumnail_bg.jpeg&quot; data-origin-width=&quot;270&quot; data-origin-height=&quot;270&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QNT0s/btrlIdqDzjK/jj3ehzwr8RB9HyJGUmioSk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QNT0s/btrlIdqDzjK/jj3ehzwr8RB9HyJGUmioSk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QNT0s/btrlIdqDzjK/jj3ehzwr8RB9HyJGUmioSk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQNT0s%2FbtrlIdqDzjK%2Fjj3ehzwr8RB9HyJGUmioSk%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;270&quot; height=&quot;270&quot; data-filename=&quot;logo_thumnail_bg.jpeg&quot; data-origin-width=&quot;270&quot; data-origin-height=&quot;270&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;[LV.1]우아한테크코스 한달 생활기&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;a id=&quot;user-content-매일-만나는-데일리-미팅&quot; href=&quot;https://github.com/DWL5/woowa-writing-3/blob/main/%EC%88%98%EB%A6%AC_%EC%9A%B0%EC%95%84%ED%95%9C%ED%85%8C%ED%81%AC%EC%BD%94%EC%8A%A4_%ED%95%9C%EB%8B%AC_%EC%83%9D%ED%99%9C%EA%B8%B0.md#%EB%A7%A4%EC%9D%BC-%EB%A7%8C%EB%82%98%EB%8A%94-%EB%8D%B0%EC%9D%BC%EB%A6%AC-%EB%AF%B8%ED%8C%85&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;매일 만나는 데일리 미팅&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우아한테크코스는 한 명의 코치와 13~14명 정도의 크루들이 함께 데일리 미팅을 진행한다. 내가 속한 데일리 조는 매일 마스터가 정해진다. 마스터들이 대화 할 주제를 마련해 온다. 코로나때문에 온라인으로 크루들을 만나야 했다. Gather라는 가상공간과 아바타를 이용한 화상 미팅 서비스를 알게 되었다. 그렇게 우리의 모임은 Gather안에서 진행 되었다. 그곳에서 크루들이 만들어 놓은 해변가도 같이 거닐고 OX게임도 진행하였다. 첫 시작 부터 크루들을 못만나는 것이 아쉬웠었다. 그러나 Gather 덕분에 매일 아침을 즐겁게 시작할 수 있었다. 나름 대로 코로나 시국을 잘 헤쳐나가고 있었다!&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;a id=&quot;user-content-연극-대신-보라&quot; href=&quot;https://github.com/DWL5/woowa-writing-3/blob/main/%EC%88%98%EB%A6%AC_%EC%9A%B0%EC%95%84%ED%95%9C%ED%85%8C%ED%81%AC%EC%BD%94%EC%8A%A4_%ED%95%9C%EB%8B%AC_%EC%83%9D%ED%99%9C%EA%B8%B0.md#%EC%97%B0%EA%B7%B9-%EB%8C%80%EC%8B%A0-%EB%B3%B4%EB%9D%BC&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;연극 대신 보라&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우아한 테크코스 3기에서는 &quot;연극&quot; 대신 &quot;보이는 라디오&quot;를 하게 되었다. 누구나 한번 쯤 해보지 않을 일을 앞에 두고 겁을 먹은 적이 있을 것이다. 보이는 라디오 미션을 받은 내가 그랬다. 어떻게 해야 할지 모르는 요구사항도 주어졌다. 줌에서 한 사람당 배경을 4번씩 바꾸면서 라디오를 진행해야 한다. 난 줌을 우테코와서 거의 처음 써봤다. 그리고 만난지 일주일 정도 지난 크루들과 보이는 라디오를 준비해야 해야 했다. '잘 할 수 있을까?' 걱정이 앞섰다.&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;a id=&quot;user-content-페어-프로그래밍&quot; href=&quot;https://github.com/DWL5/woowa-writing-3/blob/main/%EC%88%98%EB%A6%AC_%EC%9A%B0%EC%95%84%ED%95%9C%ED%85%8C%ED%81%AC%EC%BD%94%EC%8A%A4_%ED%95%9C%EB%8B%AC_%EC%83%9D%ED%99%9C%EA%B8%B0.md#%ED%8E%98%EC%96%B4-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&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;처음에는 사실 장점이 무엇인지 잘 알지 못했다. 지금까지 총 4번의 페어 프로그래밍을 진행했다. 일단 페어 프로그래밍을 하면 평소보다 말을 5배정도 많이 하게 된다. 그 만큼 상대방과 의사소통을 많이 할 수 있다. 확률적으로(?) 영양가 있는 커뮤니케이션이 발생할 확률도 높다! 그래서 이전 보다 페어 프로그래밍에 대해 긍정적으로 생각하게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혼자가 아니라 둘이 미션을 진행하다 보니 의견이 부딪힐 때가 있다. 그 때마다 내 생각을 페어에게 잘 전달해야 한다. 페어 프로그래밍을 하면서 의사소통의 중요성을 정말 많이 깨닫게 되었다. 페어와 대화하면서 논리정연하지 못한 나에게 답답함을 느꼈다. 앞으로 더욱 더 커뮤니케이션을 잘하고 싶다는 생각이 들었다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;a id=&quot;user-content-제가-책을-읽어요&quot; href=&quot;https://github.com/DWL5/woowa-writing-3/blob/main/%EC%88%98%EB%A6%AC_%EC%9A%B0%EC%95%84%ED%95%9C%ED%85%8C%ED%81%AC%EC%BD%94%EC%8A%A4_%ED%95%9C%EB%8B%AC_%EC%83%9D%ED%99%9C%EA%B8%B0.md#%EC%A0%9C%EA%B0%80-%EC%B1%85%EC%9D%84-%EC%9D%BD%EC%96%B4%EC%9A%94&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;제가.. 책을 읽어요&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전에 &quot;개발관련 책을 한권 다 읽은 적이 있는가?&quot;에 대한 질문에 자신있게 답을 못했을 것이다. 시험공부를 위해 급하게 읽었다. 시험을 위해서 빨리 머리속에 지식을 넣어야 했다. 또한 눈앞의 이슈를 해결하기 위해서 슬쩍 찾아본 것이 다였다. 내 것으로 만들기 보다는 휘발성이 짙은 공부를 많이 했었다. 나중에 가면 내가 뭘 공부했는지 설명을 못했다.&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;우테코에서 떠먹여 주는 것 보다 공부에 집중 할 수 있는 환경을 제공해 주겠다고 했다. 이러한 환경조성을 위해 크루들에게 많은 경험을 하게 해주었다. 나는 특히 학습로그와 필독서를 정해 준 것이 많은 도움이 되었다. 우테코를 통해 내 학습 방식이 건강하지 못했음을 깨달았다. 내 학습방식에 많은 변화를 줄 수 있어서 기쁘다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;[LV.2] 우테코에서 찾은 나만의 효과적인 공부법&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;제가 2021년에 우테코에 있었을 때...&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 무언가를 끝냈을 때, &quot;어땠어?&quot; 라는 질문을 받는다. 과거의 나는 갑자기 머리속이 뒤엉키면서 &quot;음.. 재미있었어&quot;와 같은 형식적인 대답을 하곤 했다. 우테코를 시작하고나서 &quot;우테코 어때?&quot;라는 질문을 많이 받았다 . 그때도 &quot;좋아&quot;, &quot;많이 배우고 있어&quot;와 같이 짤막한 대답을 했었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레벨 1 두번째 미션 부터 학습로그를 작성해야 한다. 학습로그 작성 가이드에서 &quot;메타인지&quot;라는 단어가 자주 나온다. 메타인지란 자신의 생각에 대해 판단하는 능력을 말한다. 나는 학습로그를 어떤 개념에 대해 공부를 했고, 이번 미션에서 어떻게 적용했는지 작성하고 있다. 학습로그를 작성 할 때마다 스스로를 되돌아 봐야 한다. 돌아보는 과정에서 과거의 나에 대한 정리가 되는 동시에 미래의 내가 어떠한 방향으로 나아가야 하는지 생각하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;학습로그 작성에서 더 나아가 3명의 크루들이 뭉쳐 학습로그 토론을 해야 한다. 토론 시작 전에는 늘 무엇을 말해야 하나 걱정이 앞선다. 앞에서 언급한 것처럼 당황해서 아무 말도 못할 것 같다. 그러나 걱정과 달리 나는 학습로그 토론에서 생각보다 말을 잘했다! 스스로 한번 정리해 본 것에 대해서는 말이 술술 잘 나온다. 여기서 &quot;되돌아 본다&quot;라는 것의 중요성을 다시 한번 깨닫는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우테코를 진행하면서 &quot;회고&quot;에 대한 얘기를 많이 듣는다. 어떤 크루는 미션이 끝날 때마다 페어와 회고를 한다고 한다. 어떤 크루는 매일 자기가 배운 것을 정리하는 TIL을 작성한다고 한다. 이제 나도 &quot;회고&quot;라는 것을 자주 하고 있다. 여기에는 꼭 내가 무엇을 느꼈는지가 들어가야 한다. 흘러가는 것들을 그냥 두지 않고 의미있게 붙잡아 두는 연습을 하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우테코 레벨 1, 레벨2를 거치면서 많은 미션들을 수행했고, 수행하고 있다. 코드리뷰를 받는다. 그리고 많은 수업들이 진행되었고 수업마다 영양가 있는 질문들이 많이 나온다. 그리고 스터디를 진행한다. 테코톡를 듣는다.... 이렇게 우테코 과정 속에서 나는 많은 지식들을 얻는다. 내가 생각하는 공부 방법은 이렇게 지나쳐 가는 것들을 순간에 기록하는 것이다. 그리고 한 번 다시 되돌아 보는 것이다. 그리고 여기서 내가 몰랐던 게 무엇인지, 앞으로 어떤 것을 공부하는지 추려낸다. 매일 양질의 지식을 얻을 수 있는 우테코는 이러한 공부 방법을 진행하기에 최적의 환경이다. 나는 이러한 것들을 놓치지 않고 기록 하고, 다시 되돌아 보고 내 것으로 만들고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 모의 면접에서 받은 인상깊은 피드백이 있다.&lt;/p&gt;
&lt;div&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;&quot;잘 알고 있는 것을 설명할 때와 잘 모르는 것을 설명 할 때 확연히 티가 난다.&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 사람은 어떨지 몰라도 나는 정리되지 않은 것에 대해 말하는 게 어렵다. 보완할 방법은 계속해서 스스로를 회고하는 것이라는 걸 깨달았다. 앞으로 누군가 나에게 &quot;우테코 어땠어?&quot; 라는 질문을 한다면, 예전과 같이 당황하며 짤막한 대답을 하지 않을 것이다. &quot;제가 2021년에 우테코에 있었을 때...&quot; 로 시작하는 투머치 토커가 될 수 있을 정도로 회고를 해야 겠다!&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;a id=&quot;user-content-의식적인-연습-근데-이제-페어를-곁들인&quot; href=&quot;https://github.com/DWL5/woowa-writing-3/blob/main/%EC%88%98%EB%A6%AC_%EC%9A%B0%ED%85%8C%EC%BD%94%EC%97%90%EC%84%9C_%EC%B0%BE%EC%9D%80_%EB%82%98%EB%A7%8C%EC%9D%98_%ED%9A%A8%EA%B3%BC%EC%A0%81%EC%9D%B8_%EA%B3%B5%EB%B6%80%EB%B2%95.md#%EC%9D%98%EC%8B%9D%EC%A0%81%EC%9D%B8-%EC%97%B0%EC%8A%B5-%EA%B7%BC%EB%8D%B0-%EC%9D%B4%EC%A0%9C-%ED%8E%98%EC%96%B4%EB%A5%BC-%EA%B3%81%EB%93%A4%EC%9D%B8&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&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;페어 프로그래밍을 진행하면서 &quot;단축키 쓰기&quot;에 대한 의식적인 연습을 강제로 하게 되었다. 예전에 단축키를 잘 사용하지 않았던 터라 처음에는 불편했다. 점차 익숙해지면서 이것만큼 편한게 없구나 라는 걸 알게 되었다. 이제는 단축키를 사용하지 않으면 바로 &quot;아 맞다&quot;를 시전한다. 이제는 단축키를 사용하는 걸 의식하게 되었다! 앞으로는 좀 더 현란하게 단축키를 사용하는 개발자가 되어야 겠다고 다짐 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TDD로 개발하기 또한 페어 프로그래밍을 통해 확실하게 연습할 수 있었다. TDD는 계속 해서 연습해 왔던 부분이긴 하지만, 가끔 나도 모르게 구현부터 시작 할 때가 있다. 그럼 옆에서 페어가 말해준다. &quot;안돼 테스트 코드 먼저 짜야지.&quot; 만약 혼자 했었다면 구현을 먼저 하고 있었을 지도 모른다. 페어와 함께해서 기분 좋은 제약이 생기고, 이를 통해 의식적인 연습을 할 수 있었다. 이러한 연습을 마치고 나면 더 나아가고 싶다는 생각이 든다. 그래서 이번 지하철 노선도 미션에서는 &quot;테스트 코드가 다 통과 될 때까지 웹으로 확인하지 않기&quot; 라는 셀프 퀘스트를 만들었다. 이를 통해 이전보다 기능목록 작성을 꼼꼼히 할 수 있었다.&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;h2 data-ke-size=&quot;size26&quot;&gt;[LV.3]팀 프로젝트가 나에게 남긴 것&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;a id=&quot;user-content-어떠한-마음가짐으로-팀프로젝트에-임했는가&quot; href=&quot;https://github.com/DWL5/woowa-writing-3/blob/main/%EC%88%98%EB%A6%AC_%ED%8C%80%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EA%B0%80_%EB%82%A8%EA%B8%B4%EA%B2%83.md#%EC%96%B4%EB%96%A0%ED%95%9C-%EB%A7%88%EC%9D%8C%EA%B0%80%EC%A7%90%EC%9C%BC%EB%A1%9C-%ED%8C%80%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90-%EC%9E%84%ED%96%88%EB%8A%94%EA%B0%80&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;어떠한 마음가짐으로 팀프로젝트에 임했는가&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레벨 3이 시작되고 나서 &quot;함께자라기&quot;라는 책을 읽었다. 전문가일수록 사회적 기술과 사회적 인프라를 중요하게 생각한다는 것이다. 그 중 굉장히 인상깊은 부분이 있었다. 조직 내에서 새로운 기술을 도입하고자 노력하였는데, 조직원들이 수동적이고 보수적이어서 실패하였다는 청중이 있었다. 저자는 그 청중에게 &quot;그 조직원들이 선생님을 좋아하나요?&quot;라는 질문을 했다고 한다. 이 단락을 읽고 머리를 한 대 맞은 듯 멍해졌다. (왜 상처는 나도 받는가.. &lt;span&gt;&amp;nbsp;&lt;/span&gt;) 많은 심리학 책에서 나를 싫어하는 사람은 어디에나 있고 신경쓰지 말라고 한다. 그러나 조직관계에서는 다른 사람들이 나를 좋아하게 하기 위해서 노력해야 하는 것도 현실이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팀 프로젝트를 시작 하기 전에는 내가 아직 부족하다는 생각이 많이 들었다. 그래서 &quot;어떻게든 팀에 도움이 되는 사람이 되자&quot;라는 마음가짐이 컸다. 그 중 가장 기본적인 것이 적극적으로 참여하는 것이라고 생각했다. 적극적이려면 지식이 있어야 했다. 그래서 Oauth2, S3등 새로운 기술을 도입하려고 했을 때 미리 한번 연습삼아 구현을 해보고 참여하였다. 또한 서비스 적으로도 의견을 활발하게 내려고 하였다. '이번에 낸 배너 문구를 각자 생각해 보는 건 어때' 라는 의견이 받아 들여져서 기분이 좋았다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 이번 스프린트에 '약관'작성을 팀끼리 같이 해야하는 일이 있었다. 처음에 나는 약관을 한번도 작성해 보지 않아서 부담스러웠었다. 막상 참여하고 보니 약관을 작성하면서 도메인에 대한 이해도 명확해지고 결제, 환불에 대한 플로우를 명확하게 잡을 수 있었다. 어디에서나 배울 것이 있었다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;a id=&quot;user-content-집단이-팀은-아니다&quot; href=&quot;https://github.com/DWL5/woowa-writing-3/blob/main/%EC%88%98%EB%A6%AC_%ED%8C%80%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EA%B0%80_%EB%82%A8%EA%B8%B4%EA%B2%83.md#%EC%A7%91%EB%8B%A8%EC%9D%B4-%ED%8C%80%EC%9D%80-%EC%95%84%EB%8B%88%EB%8B%A4&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;집단이 팀은 아니다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 3번째 데모데이를 하기 전날 거의 새벽 3시까지 팀프로젝트를 하였다. 줌으로 진행되어 목소리가 끊길 때도 많고, 밤이라 피곤하고, 게다가 열대야 까지 있었다. 짜증날 법한 상황이다. 그러나 이상하게도 화가 나지 않았다. 왜 그런걸까? 이 모든 건 우테코에서 받은 회식 쿠폰으로 부터 비롯된 것 같다. 아니면 팀문화로 정한 반말모드의 힘인가? 혹은 우리 팀 모두 즐기게된 게임인 브롤스타즈 덕분 일지도 모르겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 처음 딱 모였을 때는 집단이 었을지도 모른다. 그러나 같이 팀 문화를 고민하고, 서비스에 대해 토론한다. 소소하게는 데일리에서 오늘 먹을 점심을 공유하고 서로가 어떤 MBTI인지 말한다. 이렇게 점차 우리는 팀이 되어가고 있었다. 처음 시작때보다 단톡방이 훨씬 활발해졌다. 메시지로 대화하다가 잘 안풀리면 바로 줌 ㄱㄱ를 외친다. 이러한 것들만 봐도 팀이 되어가고 있는 증거인 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;[LV.4]내가 꿈꾸는 프로그래머로서의 삶&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;a id=&quot;user-content-나는-왜-프로그래머로-일하고-싶을까&quot; href=&quot;https://github.com/DWL5/woowa-writing-3/blob/main/%EC%88%98%EB%A6%AC_%EB%82%B4%EA%B0%80%EA%BF%88%EA%BE%B8%EB%8A%94%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A1%9C%EC%8D%A8%EC%9D%98%EC%82%B6.md#%EB%82%98%EB%8A%94-%EC%99%9C-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A1%9C-%EC%9D%BC%ED%95%98%EA%B3%A0-%EC%8B%B6%EC%9D%84%EA%B9%8C&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;나는 왜 프로그래머로 일하고 싶을까.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 다녔던 학과에서는 2학년 때부터 수업이 영어로 진행된다. 안타깝게도 운영체제, 네트워크, 데이터베이스같이 이해가 중요한 CS 수업들도 영어로 진행되었다. 나는 영어를 잘 못했기 때문에 지식을 어떻게 영어로 잘 서술할 것인지 암기하는 식으로 공부했다. 그때는 따라가기 바빠 공부에 재미를 느끼지 못했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러던 도중 PHP와 데이터베이스를 사용해서 웹페이지를 만드는 수업을 듣게 되었다. 동아리 모집을 하는 웹페이지를 만들었다. 프로젝트를 하는 동안은 시간이 정말 순식간에 사라졌다. 생각대로 잘 안 될 때는 스트레스도 받았지만, 해결되었을 때는 그런 스트레스도 다 날아가 버렸다. 그리고 그때 문득 하루 8시간 정도 일을 하는데 내 삶을 투자해야 한다면 프로그래밍을 직업으로 삼아야겠다는 생각이 들었다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;a id=&quot;user-content-프로그래머로서-내-목표&quot; href=&quot;https://github.com/DWL5/woowa-writing-3/blob/main/%EC%88%98%EB%A6%AC_%EB%82%B4%EA%B0%80%EA%BF%88%EA%BE%B8%EB%8A%94%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A1%9C%EC%8D%A8%EC%9D%98%EC%82%B6.md#%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A1%9C%EC%84%9C-%EB%82%B4-%EB%AA%A9%ED%91%9C&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&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;우아한테크코스 이전에 나는 안드로이드 개발을 했었다. 그리고 안드로이드 공부에서 배운 내용을 적용하기 위해 앱을 만들어서 출시해보았다. 내가 좋아하는 게임인 리그 오브 레전드 관련 앱이었다. 두 앱 모두 활성 기기가 800대 정도로 생각보다 많이 사용주셔서 놀랐다. 그리고 누군가 내가 만든 것을 사용해주는 데에서 오는 기쁨이 매우 컸다. 이 이후에 서버까지 연동해서 서비스를 만들어보고 싶은 욕심이 생겼다. 그러나 서버 구현은 둘째치고, 배포를 어떻게 해야 하는지 방법만 찾아보다가 그렇게 시간이 흘러갔었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러던 도중 우아한테크코스에서 공부를 시작하였다. 우테코 3기 막바지에 온 지금 나는 서버 배포를 할 수 있게 되었다! 예전에 막막했던 것들을 여기서 차근차근 배울 수 있었다. 앞으로 늘 생각만 하고 있던 나만의 서비스 개발을 시작 할 일만 남은건가!&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;a id=&quot;user-content-앞으로&quot; href=&quot;https://github.com/DWL5/woowa-writing-3/blob/main/%EC%88%98%EB%A6%AC_%EB%82%B4%EA%B0%80%EA%BF%88%EA%BE%B8%EB%8A%94%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%A1%9C%EC%8D%A8%EC%9D%98%EC%82%B6.md#%EC%95%9E%EC%9C%BC%EB%A1%9C&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;앞으로&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우아한테크코스 이전에 나는 무언가를 만드는 데에만 집중했었다. 결과물의 질보다 결과물을 만드는 것에 더 관심이 있었던 것 같다. 우아한테크코스에서 보낸 10개월 동안 '잘' 만든 서비스란 무엇인가에 대해 많은 공부를 하였다. 그런 지식이 이번 팀 프로젝트에 드러나 있고, 앞으로 내가 개발자로서 성장하는 데 많은 도움이 될 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 앞으로 나는 회사에 들어가 개발자로서 일을 하게 될 텐데 여기서 내가 어떤 사람이 되고 싶은지 조금 적어보겠다. 팀 프로젝트를 하면서 느낀 것은 결과물에 내 생각, 노력이 많이 반영될수록 적극성이 높아진다는 것이었다. 회사의 서비스에 주인의식을 가지고 적극 의견을 내는 개발자가 되고 싶다. 영양가 있는 의견을 내기 위해서 공부를 꾸준히 해야지..&lt;/p&gt;</description>
      <category>우아한테크코스</category>
      <author>I'mDawon</author>
      <guid isPermaLink="true">https://devlopsquare.tistory.com/234</guid>
      <comments>https://devlopsquare.tistory.com/234#entry234comment</comments>
      <pubDate>Sat, 20 Nov 2021 16:43:48 +0900</pubDate>
    </item>
    <item>
      <title>[테코톡]TCP/IP</title>
      <link>https://devlopsquare.tistory.com/233</link>
      <description>&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;TCP/IP를 주제로 테코톡을 준비하였다.&lt;/li&gt;
&lt;li&gt;네트워크를 공부할 때 각각의 계층을 따로따로 공부하는 것 보다 하나의 흐름을 통해 공부를 하면 이해가 쉬웠다.&lt;/li&gt;
&lt;li&gt;테코톡에서도 과정을 중심으로 발표를 구성하였다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=BEK354TRgZ8&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/b4D805/hyMh9oKEln/1cPpZzM818f965stsripGK/img.jpg?width=640&amp;amp;height=480&amp;amp;face=408_156_441_192&quot; data-video-width=&quot;640&quot; data-video-height=&quot;480&quot; data-video-origin-width=&quot;640&quot; data-video-origin-height=&quot;480&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/BEK354TRgZ8&quot; width=&quot;640&quot; height=&quot;480&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption&gt;&lt;/figcaption&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&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/GStRK/btrkjaKLoXW/HE3JQlDrfWtbKqpXuFul7K/TCP%20%E1%84%87%E1%85%A1%E1%86%AF%E1%84%91%E1%85%AD%E1%84%8C%E1%85%A1%E1%84%85%E1%85%AD.pdf?attach=1&amp;amp;knm=tfile.pdf&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;TCP 발표자료.pdf&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;1.51MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>우아한테크코스</category>
      <author>I'mDawon</author>
      <guid isPermaLink="true">https://devlopsquare.tistory.com/233</guid>
      <comments>https://devlopsquare.tistory.com/233#entry233comment</comments>
      <pubDate>Tue, 9 Nov 2021 19:07:10 +0900</pubDate>
    </item>
    <item>
      <title>[Spring] Scheduling - CronTask</title>
      <link>https://devlopsquare.tistory.com/229</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;@EnableScheduling&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Scheduling 관련 Bean들을 등록해 준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1633174496942&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Configuration
@EnableScheduling
public class ScheduledConfig {
}&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;h2 data-ke-size=&quot;size26&quot;&gt;@Scheduled&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메서드 위에 @Schedule 어노테이션을 붙혀 해당 로직을 스케줄링 할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1633174733382&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Scheduled(cron = &quot;0 45 20 2 * *&quot;)
public String executeWithScheduled() {
    log.info(&quot;executeWithScheduled : 매달 2일 저녁 8시 45분&quot;);
    return &quot;execute&quot;;
}&lt;/code&gt;&lt;/pre&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-origin-width=&quot;1524&quot; data-origin-height=&quot;940&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wc4WA/btrgHEfxTTq/SKCFKWE18GqlGxFK10Wfb0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wc4WA/btrgHEfxTTq/SKCFKWE18GqlGxFK10Wfb0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wc4WA/btrgHEfxTTq/SKCFKWE18GqlGxFK10Wfb0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fwc4WA%2FbtrgHEfxTTq%2FSKCFKWE18GqlGxFK10Wfb0%2Fimg.png&quot; data-origin-width=&quot;1524&quot; data-origin-height=&quot;940&quot; data-ke-mobilestyle=&quot;widthOrigin&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 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;h2 data-ke-size=&quot;size26&quot;&gt;Cron표기법&lt;/h2&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;초&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;분&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;시&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;일&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;월&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;요일&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;연도&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;0 ~ 59&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;0 ~ 59&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;0~23&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;1~31&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;1~12&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;0~6&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;요일의 경우 0이 일요일이며 6이 토요일이다.&lt;/li&gt;
&lt;li&gt;* 는 모든 조건을 뜻한다.&lt;/li&gt;
&lt;li&gt;?는 설정값이 없을 때 쓰이며 일, 요일에서만 사용가능하다.&lt;/li&gt;
&lt;li&gt;L - 마지막 - 일, 요일에서만 사용가능&lt;/li&gt;
&lt;li&gt;W - 가장 가까운 평일을 찾는다. - 일 에서만 사용가능
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;10W
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;10일이 평일이면 : 10일에 수행&lt;/li&gt;
&lt;li&gt;10일이 토요일이면 : 가장 가운 평일인 금요일 9일에 수행&lt;/li&gt;
&lt;li&gt;10일이 일요일일때 가장 가까운 평일인 월요일 11일에 수행&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;# - 몇주 째인지 찾는다. - 요일에서만 사용가능
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;3#2 : 2째주 수요일에 수행&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&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;특정 시간에 스케줄을 걸고 동작하는지 테스트 하는 것은 너무 어렵다..ㅜ @Schedule를 걸면 ScheduleTaskHolder에 Task가 등록되는데, 이 Task에 설정된 값을 비교하는 식으로 테스트를 해야 할 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1633176229104&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@SpringBootTest
class TestServiceTest {
    @Autowired
    private ScheduledTaskHolder scheduledTaskHolder;

    @Test
    public void testExecuteWithScheduled() {
        String methodName = TestService.class.getName() + &quot;.executeWithScheduled&quot;;
        String cron =  &quot;0 45 20 2 * *&quot;;

        long count = scheduledTaskHolder.getScheduledTasks().stream()
                .filter(scheduledTask -&amp;gt; scheduledTask.getTask() instanceof CronTask)
                .map(scheduledTask -&amp;gt; (CronTask) scheduledTask.getTask())
                .filter(cronTask -&amp;gt; cronTask.getExpression().equals(cron) &amp;amp;&amp;amp; cronTask.toString().equals(methodName))
                .count();


        Assertions.assertThat(count).isEqualTo(1L);
    }
}&lt;/code&gt;&lt;/pre&gt;

&lt;a href=&quot;https://thankyou-for.com/creator/suri&quot; target=&quot;_blank&quot;&gt;&lt;img height=&quot;40&quot; style=&quot;border:0px;height:40px;&quot; src=&quot;https://de56jrhz7aye2.cloudfront.net/banner/yellow.svg&quot; border=&quot;0&quot; alt=&quot;thank you for button&quot; /&gt;&lt;/a&gt;</description>
      <category>study</category>
      <author>I'mDawon</author>
      <guid isPermaLink="true">https://devlopsquare.tistory.com/229</guid>
      <comments>https://devlopsquare.tistory.com/229#entry229comment</comments>
      <pubDate>Sat, 2 Oct 2021 16:04:24 +0900</pubDate>
    </item>
  </channel>
</rss>