<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>kongbuhaneunJiye</title>
    <link>https://jjiye716.tistory.com/</link>
    <description>공부 블로그</description>
    <language>ko</language>
    <pubDate>Mon, 6 Apr 2026 02:46:05 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>ji._.ye</managingEditor>
    <item>
      <title>JPA(3) - 영속성 컨텍스트</title>
      <link>https://jjiye716.tistory.com/35</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;영속성 컨텍스트&amp;nbsp;&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;/li&gt;
&lt;li&gt;엔티티 매니저를 통해서 영속성 컨텍스트에 접근&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;EntityManager.persist(entity);&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; //엔티티를 DB에 저장하는 것이 아닌 엔티티 컨텍스트에 저장. 엔티티를 영속화한다는 뜻.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;294&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kQeg3/btsGTFAIWI4/V3PvTXc8ddvBvUz5HSWkGK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kQeg3/btsGTFAIWI4/V3PvTXc8ddvBvUz5HSWkGK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kQeg3/btsGTFAIWI4/V3PvTXc8ddvBvUz5HSWkGK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkQeg3%2FbtsGTFAIWI4%2FV3PvTXc8ddvBvUz5HSWkGK%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;500&quot; height=&quot;294&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;294&quot;/&gt;&lt;/span&gt;&lt;/figure&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;엔티티 매니저&amp;nbsp;&lt;/h3&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;엔티티 매니저와 영속성 컨텍스트는 1:1 또는 N:1 패밍&amp;nbsp;&lt;/li&gt;
&lt;li&gt;고객의 요청이 올때마다 EntityManager 생성&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mKTLf/btsGS75wUxn/mpNZnXnzdxCyNEd3jr66HK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mKTLf/btsGS75wUxn/mpNZnXnzdxCyNEd3jr66HK/img.png&quot; data-alt=&quot;J2SE 환경&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mKTLf/btsGS75wUxn/mpNZnXnzdxCyNEd3jr66HK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmKTLf%2FbtsGS75wUxn%2FmpNZnXnzdxCyNEd3jr66HK%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;500&quot; height=&quot;125&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;125&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;J2SE 환경&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;219&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9en9F/btsGT7Kv3FR/wbqSEk540JoSzxAhkK3C40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9en9F/btsGT7Kv3FR/wbqSEk540JoSzxAhkK3C40/img.png&quot; data-alt=&quot;J2EE&amp;amp;amp;nbsp; 환경&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9en9F/btsGT7Kv3FR/wbqSEk540JoSzxAhkK3C40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9en9F%2FbtsGT7Kv3FR%2FwbqSEk540JoSzxAhkK3C40%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;500&quot; height=&quot;219&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;219&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;J2EE&amp;amp;nbsp; 환경&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;엔티티의 생명주기&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;359&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oE5W2/btsGVw3PKXC/SwWWHHojKxSD84nPTL41mK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oE5W2/btsGVw3PKXC/SwWWHHojKxSD84nPTL41mK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oE5W2/btsGVw3PKXC/SwWWHHojKxSD84nPTL41mK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoE5W2%2FbtsGVw3PKXC%2FSwWWHHojKxSD84nPTL41mK%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;500&quot; height=&quot;359&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;359&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;비영속 (new/transient)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;영속성 컨텍스트와 전혀 관계가 없는 새로운 상태&lt;/li&gt;
&lt;li&gt;JPA와 전혀 관련이 없는 상태&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;영속 (managed)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;영속성 컨텍스트에 관리되는 상태&lt;/li&gt;
&lt;li&gt;영속 상태라고해서 바로 DB에 저장되는 것이 아님. DB는 이후에 커밋해야 저장됨.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;준영속 (detached)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;삭제(removed)
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;영구저장된 DB에서 삭제된 상태&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1713945139466&quot; class=&quot;fsharp&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;// 객체를 생성한 상태 (비영속)
Member member = new Member();
member.setId(&quot;member1&quot;);
member.setUsername(&quot;회원1&quot;);

EntityManager em = emf.createEntityManager();
em.getTransaction().begin();

//객체를 저장한 상태(영속)
em.persist(member)

//회원 엔티티를 영속성 컨텍스트에서 분리, 준영속 상태
em.detach(member);

//객체를 삭제한 상태(삭제)
em.remove(member);&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;영속성 컨텍스트의 이점&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 엔티티 조회, 1차 캐시&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;엔티티 메니저는 DB트랜잭션 단위로 실행됨.&lt;/li&gt;
&lt;li&gt;고객의 요청이 들어오고 이후 비즈니스가 종료되면, 영속성 컨텍스트도 종료되고 1차 캐시도 날라감.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;고객이 10명이면 10개의 1차 캐시 생성.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;ex) em.persist(entity)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;엔티티를 영속화하면 1차 캐시에 저장됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(바로 DB에 저장되는 것이 아님)&lt;/p&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/zFVzN/btsGTdxMViD/xIPx7LfDl8XDPq9tbgZX40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zFVzN/btsGTdxMViD/xIPx7LfDl8XDPq9tbgZX40/img.png&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;205&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;64.1&quot; data-filename=&quot;edited_edited_blob&quot; style=&quot;width: 63.3527%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zFVzN/btsGTdxMViD/xIPx7LfDl8XDPq9tbgZX40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzFVzN%2FbtsGTdxMViD%2FxIPx7LfDl8XDPq9tbgZX40%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;400&quot; height=&quot;205&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgBTpw/btsGTATLBI1/o1VqmcAl35wgD7jbmesne0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgBTpw/btsGTATLBI1/o1VqmcAl35wgD7jbmesne0/img.png&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;366&quot; data-is-animation=&quot;false&quot; width=&quot;497&quot; height=&quot;287&quot; data-filename=&quot;edited_blob&quot; data-widthpercent=&quot;35.9&quot; style=&quot;width: 35.4845%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgBTpw/btsGTATLBI1/o1VqmcAl35wgD7jbmesne0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgBTpw%2FbtsGTATLBI1%2Fo1VqmcAl35wgD7jbmesne0%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;400&quot; height=&quot;366&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) em.find()&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;조회 요청&lt;/span&gt;을 받으면 먼저 DB가 아닌 1차 캐시에 접근.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;1차 캐시에 해당 엔티티가 저장되어있는 경우&lt;/span&gt; DB에 접근할 필요 없이 바로 1차 캐시에서 엔티티를 반환.&amp;nbsp;&lt;/p&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/cyoO02/btsGVUQWth4/2LNfGMDRt5CwXBLIu9i7R1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cyoO02/btsGVUQWth4/2LNfGMDRt5CwXBLIu9i7R1/img.png&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;175&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;57.48&quot; data-filename=&quot;blob&quot; style=&quot;width: 56.8104%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cyoO02/btsGVUQWth4/2LNfGMDRt5CwXBLIu9i7R1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcyoO02%2FbtsGVUQWth4%2F2LNfGMDRt5CwXBLIu9i7R1%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;500&quot; height=&quot;175&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ctGLsN/btsGSjFgDtX/UXsoiQzd0lH3uhBSeFVSRK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ctGLsN/btsGSjFgDtX/UXsoiQzd0lH3uhBSeFVSRK/img.png&quot; data-origin-width=&quot;837&quot; data-origin-height=&quot;396&quot; data-is-animation=&quot;false&quot; style=&quot;width: 42.0268%;&quot; data-widthpercent=&quot;42.52&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ctGLsN/btsGSjFgDtX/UXsoiQzd0lH3uhBSeFVSRK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FctGLsN%2FbtsGSjFgDtX%2FUXsoiQzd0lH3uhBSeFVSRK%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;837&quot; height=&quot;396&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;1차 캐시에 저장된 엔티티를 조회하는 경우&amp;nbsp;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;1차 캐시에 해당 엔티티가 없을 경우 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; DB에 접근&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;rarr;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;DB에서 엔티티를 반환하여 1차 캐시에 저장&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;rarr;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;1차 캐시에 저장된 엔티티를 애플리케이션에 반환&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;28&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/r5U4R/btsGVTqXp9O/QTirOuzdL6eaheWmvcFKk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/r5U4R/btsGVTqXp9O/QTirOuzdL6eaheWmvcFKk0/img.png&quot; data-alt=&quot;memer2를 해당 트랜잭션 안에서 저장(영속), 조회한 적이 없으므로 1차 캐시에 저장되어있지 않음&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/r5U4R/btsGVTqXp9O/QTirOuzdL6eaheWmvcFKk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fr5U4R%2FbtsGVTqXp9O%2FQTirOuzdL6eaheWmvcFKk0%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;500&quot; height=&quot;28&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;28&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;memer2를 해당 트랜잭션 안에서 저장(영속), 조회한 적이 없으므로 1차 캐시에 저장되어있지 않음&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;216&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cdfnlu/btsGTaup3WG/fHAbMT1mbmGkZkl8rE7yzk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cdfnlu/btsGTaup3WG/fHAbMT1mbmGkZkl8rE7yzk/img.png&quot; data-alt=&quot;DB에 접근하여 엔티티를 반환&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cdfnlu/btsGTaup3WG/fHAbMT1mbmGkZkl8rE7yzk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcdfnlu%2FbtsGTaup3WG%2FfHAbMT1mbmGkZkl8rE7yzk%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;500&quot; height=&quot;216&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;216&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;DB에 접근하여 엔티티를 반환&lt;/figcaption&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;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;2. 영속 엔티티의 동일성 보장&amp;nbsp;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;자바 컬렉션에서 주소가 같은 객체를 두 번 조회하면 동일한 객체로 인식하는 것처럼&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;영속성 컨텍스트에서 하나의 객체를 두 번 조회하면 동일힌 객체로 인식&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1713947495552&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Member a = em.find(Member.class, &quot;member1&quot;);
Member b = em.find(Member.class, &quot;member1&quot;);

System.out.println(a == b); // true&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 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;3. 엔티티 등록&amp;nbsp; -&amp;nbsp; 쓰기 지연&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;엔티티를 등록하면 우선 1차 캐시에 저장했다가 이후 트랜잭션을 커밋하면 캐시에 저장된 엔티티가 한 번에 DB에 저장됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버퍼링 개념이라고 보면 됨.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1713947841348&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
//엔티티 매니저는 데이터 변경시 트랜잭션을 시작해야 한다.
transaction.begin(); // [트랜잭션] 시작

em.persist(memberA);
em.persist(memberB);
//여기까지 INSERT SQL을 데이터베이스에 보내지 않는다.

//커밋하는 순간 데이터베이스에 INSERT SQL을 보낸다.
transaction.commit(); // [트랜잭션] 커밋&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&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/beii9Z/btsGTBkHRAH/suugyl2eyaVa0A251QV7Zk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beii9Z/btsGTBkHRAH/suugyl2eyaVa0A251QV7Zk/img.png&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;280&quot; data-is-animation=&quot;false&quot; data-filename=&quot;blob&quot; style=&quot;width: 49.1524%; margin-right: 10px;&quot; data-widthpercent=&quot;49.73&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beii9Z/btsGTBkHRAH/suugyl2eyaVa0A251QV7Zk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbeii9Z%2FbtsGTBkHRAH%2Fsuugyl2eyaVa0A251QV7Zk%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;500&quot; height=&quot;280&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biLEmS/btsGR06Rw5W/4OkCk4eYHKMeanM1ZGHKA0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biLEmS/btsGR06Rw5W/4OkCk4eYHKMeanM1ZGHKA0/img.png&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;277&quot; data-is-animation=&quot;false&quot; data-filename=&quot;blob&quot; style=&quot;width: 49.6848%;&quot; data-widthpercent=&quot;50.27&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biLEmS/btsGR06Rw5W/4OkCk4eYHKMeanM1ZGHKA0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiLEmS%2FbtsGR06Rw5W%2F4OkCk4eYHKMeanM1ZGHKA0%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;500&quot; height=&quot;277&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;em.persist(memberA);&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; em.persist(memberB);&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;304&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/A18hT/btsGTfoFSfF/tHErggMraAQaJK9eNJZG01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/A18hT/btsGTfoFSfF/tHErggMraAQaJK9eNJZG01/img.png&quot; data-alt=&quot;transaction.commit();&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/A18hT/btsGTfoFSfF/tHErggMraAQaJK9eNJZG01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FA18hT%2FbtsGTfoFSfF%2FtHErggMraAQaJK9eNJZG01%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;500&quot; height=&quot;304&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;304&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;transaction.commit();&lt;/figcaption&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;4. 엔티티 수정 - 변경 감지&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JPA는 &lt;span style=&quot;color: #ee2323;&quot;&gt;dirty checking&lt;/span&gt; 기능이 있음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영속성 컨텍스트에서 자동으로 UPDATE쿼리문을 생성하기 때문에&amp;nbsp;&amp;nbsp;애플리케이션에서 엔티티 수정 후 추가로 em.update(member); 코드를 작성할 필요가 없음&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Dirty Checking&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애플리케이션에서 엔티티 수정 후 transaction.commmit() 코드 실행&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;rarr; DB에 commit하기 전 flush가 자동으로 실행(영속성 컨텍스트의 변경 내용을 데이터베이스에 반영)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; flush: 1차 캐시에서 엔티티와 스냅샷 비교&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; flush: 데이터가 바뀌었다면 (dirty == 1, 엔티티와 스냅샷이 다르다면)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;UPDATE쿼리문을 '쓰기 지연 SQL 저장소' 에 저장&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; flush:&amp;nbsp; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;'쓰기 지연 SQL 저장소'&lt;span&gt; 의 쿼리문을 DB에 flush&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt; &amp;rarr; DB에 커밋 &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1713948974979&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin(); // [트랜잭션] 시작

// 영속 엔티티 조회
//엔티티의 스냅샷이 1차 캐시에 저장됨
//스냅샷: 1차 캐시에 처음으로 저장된 시점의 엔티티
Member memberA = em.find(Member.class, &quot;memberA&quot;);

// 영속 엔티티 데이터 수정
memberA.setUsername(&quot;hi&quot;);
memberA.setAge(10);

//em.update(member) 이런 코드가 있어야 하지 않을까? 필요없음 

transaction.commit(); // [트랜잭션] 커밋&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-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;292&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b4jfKG/btsGT9OZmsp/4aZqHQ1YJCKZok7MawqvKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b4jfKG/btsGT9OZmsp/4aZqHQ1YJCKZok7MawqvKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b4jfKG/btsGT9OZmsp/4aZqHQ1YJCKZok7MawqvKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb4jfKG%2FbtsGT9OZmsp%2F4aZqHQ1YJCKZok7MawqvKk%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;500&quot; height=&quot;292&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;292&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;5. 지연 로딩&amp;nbsp;&lt;/h4&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;플러시
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;영속성 컨텍스트를 비우는 것이 아님&lt;/li&gt;
&lt;li&gt;영속성 컨테스트의 변경내용을 DB에 동기화 하는 것&amp;nbsp;&lt;/li&gt;
&lt;li&gt;트랜잭션이라는 작업 단위 안에서 커밋 직전에만 동기화 하면 됨&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;em.flush() 실행&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;rarr; 1차 캐시에서 엔티티와 스냅샷을 비교해 엔티티 변경 감지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;rarr;&amp;nbsp;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt; 수정된 엔티티를 쓰기 지연 SQL저장소에 등록&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;rarr;&amp;nbsp;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt; 쓰기 지연 SQL저장소의 쿼리를 데이터베이스에 전송(등록, 수정, 삭제 쿼리)&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;&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;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;em.flush() - 직접 호출&lt;/li&gt;
&lt;li&gt;트랜잭션 커밋 - 플러시 자동 호출&lt;/li&gt;
&lt;li&gt;JPQL 쿼리 실행 - 플러시 자동 호출&amp;nbsp;&amp;nbsp;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1713951951302&quot; class=&quot;gcode&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;em.persist(memberA);
em.persist(memberB);
em.persist(memberC);
//중간에 JPQL 실행
query = em.createQuery(&quot;select m from Member m&quot;, Member.class);
List&amp;lt;Member&amp;gt; members= query.getResultList();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp; &amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;JPQL 쿼리문은 영속성 컨텍스트가 아닌 DB에 접근. 따라서 JPQL 실행 전 flush를 자동으로 호출하여 DB를 update 해야됨&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;플러시 모드 옵션&amp;nbsp;&lt;br /&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;em.setFlushMode(FlushModeType.AUTO) : 커밋이나 쿼리를 실행할 때 플러시 (기본)&lt;/li&gt;
&lt;li&gt;em.setFlushMode(FlushModeType.COMMIT) : 커밋할 때만 플러시&amp;nbsp;&lt;/li&gt;
&lt;/ol&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;준영속 상태&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;영속 상태: em.persist(), em.find() 에 의해 엔티티가 영속성 컨텍스트의 1차 캐시에 올라온 상태&lt;/li&gt;
&lt;/ul&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;준영속 상태: 영속 상태의 엔티티가 영속성 컨텍스트에서 분리(detached) 된 상태&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;영속성 컨텍스트가 제공하는 기능을 사용 못함&lt;/li&gt;
&lt;/ul&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;준영속 상태로 만드는 방법&amp;nbsp;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;em.detach(entity) 특정 엔티티만 준영속 상태로 전환&lt;/li&gt;
&lt;li&gt;em.clear() 영속성 컨텍스트를 완전히 초기화&lt;/li&gt;
&lt;li&gt;em.close() 영속성 컨텍스트를 종료&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>백엔드/스프링</category>
      <author>ji._.ye</author>
      <guid isPermaLink="true">https://jjiye716.tistory.com/35</guid>
      <comments>https://jjiye716.tistory.com/35#entry35comment</comments>
      <pubDate>Wed, 24 Apr 2024 18:09:43 +0900</pubDate>
    </item>
    <item>
      <title>DFS / BFS</title>
      <link>https://jjiye716.tistory.com/32</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;DFS&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특징&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;모든 정점을 방문하고자 할 때 사용됨.&lt;/li&gt;
&lt;li&gt;재귀(Recursion) 혹은 스택(Stack)을 이용하여 구현.&lt;/li&gt;
&lt;li&gt;무방향 그래프나 방향 그래프 모두에 적용.&lt;/li&gt;
&lt;li&gt;모든 경로를 탐색하기 때문에 경로의 길이가 길어질 경우에는 BFS에 비해 시간이 오래 걸릴 수 있음.&lt;/li&gt;
&lt;li&gt;어떤 경로가 있는지를 확인할 때 사용.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장점&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;현재 경로 상의 노드들만 기억하면 되므로 메모리 사용량이 적음.&lt;/li&gt;
&lt;li&gt;목표 노드가 깊은 단계에 있을 경우 해를 빨리 찾을 수 있음.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단점&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;최단 경로를 보장하지 않음.&lt;/li&gt;
&lt;li&gt;무한 루프에 빠질 수 있음.&lt;/li&gt;
&lt;li&gt;그래프가 큰 경우에는 탐색 공간이 너무 커져서 메모리 문제가 발생할 수 있음.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre id=&quot;code_1713682669393&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.ArrayList;
import java.util.List;

public class Graph {
    private int V; // 그래프의 정점 개수
    private List&amp;lt;List&amp;lt;Integer&amp;gt;&amp;gt; adjList; // 인접 리스트

    public Graph(int vertices) {
        this.V = vertices;
        adjList = new ArrayList&amp;lt;&amp;gt;(V);
        for (int i = 0; i &amp;lt; V; i++) {
            adjList.add(new ArrayList&amp;lt;&amp;gt;());
        }
    }

    // 그래프에 간선 추가
    public void addEdge(int source, int destination) {
        adjList.get(source).add(destination);
    }

    // DFS 탐색 메서드
    public void dfs(int vertex, boolean[] visited) {
        visited[vertex] = true;
        System.out.print(vertex + &quot; &quot;); // 방문한 정점 출력

        // 현재 정점과 연결된 모든 정점을 탐색
        for (int neighbor : adjList.get(vertex)) {
            if (!visited[neighbor]) {
                dfs(neighbor, visited); // 재귀적으로 이웃 정점을 탐색
            }
        }
    }

    // DFS 탐색 시작
    public void dfsStart(int start) {
        boolean[] visited = new boolean[V]; // 방문 여부를 저장하는 배열
        dfs(start, visited); // 시작 정점부터 DFS 탐색 시작
    }

    public static void main(String[] args) {
        Graph graph = new Graph(5);
        graph.addEdge(0, 1);
        graph.addEdge(0, 2);
        graph.addEdge(1, 3);
        graph.addEdge(1, 4);

        System.out.println(&quot;DFS 탐색 결과:&quot;);
        graph.dfsStart(0); // 정점 0에서 시작하여 DFS 탐색 시작
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;BFS&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특징&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 가까운 정점부터 탐색해나가는 알고리즘&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 큐를 사용하여 구현&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: left;&quot;&gt;시작 정점을 큐에 넣음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;큐에서 정점을 하나 꺼내어 방문&lt;/li&gt;
&lt;li&gt;방문한 정점과 인접한 모든 정점들을 큐에 넣음&lt;/li&gt;
&lt;li&gt;큐가 빌 때까지 위 과정을 반복&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장점&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;시작 정점에서 목표 정점까지의 &lt;span style=&quot;color: #ee2323;&quot;&gt;최단 경로&lt;/span&gt;를 찾을 수 있음&amp;nbsp;&lt;/li&gt;
&lt;li&gt;그래프의 &lt;span style=&quot;color: #ee2323;&quot;&gt;모든 정점을 방문&lt;/span&gt;할 때 유용&lt;/li&gt;
&lt;li&gt;깊이가 같은 노드를 모두 방문한 후에 깊이를 증가시키기 때문에, 어떤 경로가 있는지를 확인할 때 사용&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단점&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;DFS보다 많은 메모리를 사용 (큐를 사용하기 때문에)&lt;/li&gt;
&lt;li&gt;BFS는 재귀적으로 구현할 수 없음.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre id=&quot;code_1713683355359&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;

public class Graph {
    private int V; // 그래프의 정점 개수
    private List&amp;lt;List&amp;lt;Integer&amp;gt;&amp;gt; adjList; // 인접 리스트

    public Graph(int vertices) {
        this.V = vertices;
        adjList = new ArrayList&amp;lt;&amp;gt;(V);
        for (int i = 0; i &amp;lt; V; i++) {
            adjList.add(new ArrayList&amp;lt;&amp;gt;());
        }
    }

    // 그래프에 간선 추가
    public void addEdge(int source, int destination) {
        adjList.get(source).add(destination);
    }

    // BFS 탐색 메서드
    public void bfs(int start) {
        boolean[] visited = new boolean[V]; // 방문 여부를 저장하는 배열
        Queue&amp;lt;Integer&amp;gt; queue = new LinkedList&amp;lt;&amp;gt;(); // BFS를 위한 큐

        visited[start] = true; // 시작 정점 방문 표시
        queue.offer(start); // 시작 정점을 큐에 삽입

        while (!queue.isEmpty()) {
            int vertex = queue.poll(); // 큐에서 정점을 하나 꺼냄
            System.out.print(vertex + &quot; &quot;); // 방문한 정점 출력

            // 현재 정점과 연결된 모든 정점을 탐색
            for (int neighbor : adjList.get(vertex)) {
                if (!visited[neighbor]) {
                    visited[neighbor] = true; // 방문한 정점 표시
                    queue.offer(neighbor); // 방문하지 않은 정점을 큐에 삽입
                }
            }
        }
    }

    public static void main(String[] args) {
        Graph graph = new Graph(5);
        graph.addEdge(0, 1);
        graph.addEdge(0, 2);
        graph.addEdge(1, 3);
        graph.addEdge(1, 4);

        System.out.println(&quot;BFS 탐색 결과:&quot;);
        graph.bfs(0); // 정점 0에서 시작하여 BFS 탐색 시작
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>알고리즘/자료구조</category>
      <author>ji._.ye</author>
      <guid isPermaLink="true">https://jjiye716.tistory.com/32</guid>
      <comments>https://jjiye716.tistory.com/32#entry32comment</comments>
      <pubDate>Sun, 21 Apr 2024 16:09:22 +0900</pubDate>
    </item>
    <item>
      <title>Java 라이브러리</title>
      <link>https://jjiye716.tistory.com/31</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. String&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1-1. 문자열 붙이기, 자르기&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1713439661341&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String N = &quot;abcd&quot;; 
Sring K = &quot;efgh&quot;;
String s = N + K; //O(N+K)
s.substring(5); //&quot;fgh&quot; //O(N)
s.substring(0,3); //&quot;abc&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;size18&quot;&gt;1-2. 입력&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BufferedReader - 입력 라이브러리, String 객체만 다룸&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;예1) 한 줄 입력, 한 줄에 한 단어&lt;/p&gt;
&lt;pre id=&quot;code_1713608408288&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public Class main{
	public static void main(String[] args) throws IOException {
    
     		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            String s = br.readLine();
            
            .
            .
            .&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;예2) 한 줄 입력, 한 줄에 단어 여러개&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1713607735279&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Main {
    
	public static void main(String[] args) throws IOException {
 
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	    String[] input = br.readLine().split(&quot; &quot;);
        .
        .
        .&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예3) Int 입력&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BufferedReader는 String 객체만 취급하기 때문에 먼저 String 변수로 문자열을 저장하고 추후에 Integer 객체로 변환해야 한다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1713609182707&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;        
public class Main {
	public static void main(String[] args) throws IOException {
 
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		int N = Integer.parseInt(br.readLine());
        .
        .
        .&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1-3. 출력&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;StringBuilder -&amp;nbsp; 출력을 담당하는 class, 버퍼를 활용하여 문자열을 문자 시퀀스로 관리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;String을 불변객체지만 StringBuilder는 가변객체.&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;예1) 문자열 하나 반환&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1713610373498&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.IOException;

public class Main {

	public static void main(String[] args) throws IOException{
		StringBuilder sb = new StringBuilder();
        
		//문자열 추가
		sb.append(&quot;ab&quot;); //ab
	
		//다음 줄 이동
		sb.append(&quot;ef\n&quot;); 
		/* 
		abef\n
        	------ 커서는 이 줄에 위치
		*/
		
       		sb.append(&quot;ij&quot;).append(&quot;\n&quot;);
		 /*
		 abef\n
        	ij\n
        	------ 커서는 이 줄에 위치
         	*/


		//문자열 삽입 
		sb.insert(2, &quot;2&quot;);
		/*
		 ab2ef\n
        	 ij\n
		  ------ 커서는 이 줄에 위치
        	 */

		sb.insert(5, 5);
		/*
		 ab2ef5\n
        	 ij\n
		  ------ 커서는 이 줄에 위치
        	 */
	
		sb.insert(7, 7);
		/*
		 ab2ef5\n
        	 7ij\n
		  ------ 커서는 이 줄에 위치
       	  	*/

		sb.insert(6,6); 
		/*
		 ab2ef56\n
         	7ij\n
		  ------ 커서는 이 줄에 위치
        	 */
		

		//문자 삭제   
		sb.deleteCharAt(7); 
		/*
		 ab2ef567ij\n
	    	------ 커서는 이 줄에 위치
		*/
	
		//문자열 삭제
		sb.delete(8,11); //ab2f567------ 커서는 이 줄에 위치

		//문자열 뒤집기
		sb.reverse(); // 765f2ba

		//문자 교체
		sb.setCharAt(1, 'g'); //7g5f2ba
		
		//문자열 교체
		sb.replace(1,4,&quot;change&quot;); //7change2ba

		//문자열 길이 조정	
		sb.setLength(2); //7c

       
		//문자열 변환
		sb.toString(); //7c

	}  
}&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;ArrayList&lt;/h3&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;pre id=&quot;code_1713676588145&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        // ArrayList 생성
        ArrayList&amp;lt;String&amp;gt; arrayList = new ArrayList&amp;lt;&amp;gt;();

        // 요소 추가
        arrayList.add(&quot;Apple&quot;);
        arrayList.add(&quot;Banana&quot;);
        arrayList.add(&quot;Orange&quot;);

        // 요소 가져오기
        String firstElement = arrayList.get(0); //Apple 반환 
        
        // 요소 수정
        arrayList.set(1, &quot;Grapes&quot;);

        // 요소 제거
        arrayList.remove(1); // 인덱스로 제거
        rrayList.remove(&quot;Orange&quot;); // 값으로 제거
        
        // 요소가 포함되어 있는지 확인
        boolean containsBanana = arrayList.contains(&quot;Banana&quot;);
        
        // 특정 값의 인덱스 확인
        int indexOfGrapes = arrayList.indexOf(&quot;Grapes&quot;);

        // 사이즈 확인
        int size = arrayList.size();

        // 모든 요소 출력
        for (String element : arrayList) {
            System.out.println(element);
        }

        // ArrayList 비우기
        arrayList.clear();

        // ArrayList가 비어 있는지 확인
        boolean isEmpty = arrayList.isEmpty(); //true반환 
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;LinkedList&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dluble linked list 형태로 구현되어있음&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;인덱스 기반 접근은 ArayList보다 성능이 좋지 않음. 대신, 요소를 순차적으로 접근하는데 적합&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메서드는 ArrayList와 동일&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HashMap&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;키-값 쌍을 저장하는 자료구조&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 키의 값을 검색하거나 저장하는데 사용됨&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해시테이블을 기반으로 구현됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해시 테이블: 키를 해시 함수를 사용해 해시 코드로 변환하고 이 해시 코드를 사용하여 값을 저장하거나 검색&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1713678188346&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.HashMap;

public class Main {
    public static void main(String[] args) {
        // HashMap 생성
        HashMap&amp;lt;String, Integer&amp;gt; hashMap = new HashMap&amp;lt;&amp;gt;();

        // 요소 추가
        hashMap.put(&quot;Apple&quot;, 10);
        hashMap.put(&quot;Banana&quot;, 20);
        hashMap.put(&quot;Orange&quot;, 30);

        // 요소 가져오기
        int appleQuantity = hashMap.get(&quot;Apple&quot;); //O(1)

        // 요소 수정
        hashMap.put(&quot;Banana&quot;, 25); // O(1)

        // 요소 제거
        hashMap.remove(&quot;Orange&quot;); 

        // 사이즈 확인
        int size = hashMap.size();

        // 모든 요소 출력
        System.out.println(&quot;HashMap의 모든 요소:&quot;);
        for (String key : hashMap.keySet()) {
            int value = hashMap.get(key);
            System.out.println(key + &quot;: &quot; + value);
        }

        // HashMap에 특정 키가 포함되어 있는지 확인
        boolean containsApple = hashMap.containsKey(&quot;Apple&quot;); //O(1)
        
        // HashMap의 모든 키(key) 가져오기
        Set&amp;lt;String&amp;gt; keySet = hashMap.keySet();
   
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HashSet&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Set 인터페이스를 구현&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중복 X, 순서 X&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해시 테이블을 기반으로 구현&lt;/p&gt;
&lt;pre id=&quot;code_1713678902839&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.HashSet;

public class Main {
    public static void main(String[] args) {
        // HashSet 생성
        HashSet&amp;lt;String&amp;gt; hashSet = new HashSet&amp;lt;&amp;gt;();

        // 요소 추가
        hashSet.add(&quot;Apple&quot;);
        hashSet.add(&quot;Banana&quot;);
        hashSet.add(&quot;Orange&quot;);

        // 중복된 요소 추가
        hashSet.add(&quot;Apple&quot;); //O(1)

        // 요소의 개수 확인
        int size = hashSet.size(); //3

        // 요소가 포함되어 있는지 확인 //O(1)
        boolean containsBanana = hashSet.contains(&quot;Banana&quot;); // 출력: true

        // 요소 제거
        hashSet.remove(&quot;Orange&quot;); //O(1)

        // HashSet이 비어 있는지 확인
        boolean isEmpty = hashSet.isEmpty(); //false

        // 모든 요소 출력
        System.out.println(&quot;HashSet의 모든 요소:&quot;);
        for (String element : hashSet) {
            System.out.println(element);
        }

        // HashSet 비우기
        hashSet.clear();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Stack&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LIFO - Lsat In first Out&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vector 클래스를 상속하여 구현&lt;/p&gt;
&lt;pre id=&quot;code_1713679981422&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.Stack;

public class Main {
    public static void main(String[] args) {
        // 스택 생성
        Stack&amp;lt;Integer&amp;gt; stack = new Stack&amp;lt;&amp;gt;();

        // 요소 추가 (push) O(1)
        stack.push(10); //index 1
        stack.push(20); //index 2
        stack.push(30); //index 3

        // 요소 확인 (peek)  O(1)
        int topElement = stack.peek(); //30
        
        // 요소의 인덱스 검색 (search) O(n)
        int index = stack.search(20); //2
        
        // 요소 제거 (pop) O(1)
        int removedElement = stack.pop(); // 30 제거
        
        stack.contains(10); //true, O(n)
        
        // 스택이 비어 있는지 확인 (empty) O(1)
        boolean isEmpty = stack.empty(); // false


        // 스택의 모든 요소 출력
        System.out.println(&quot;스택의 모든 요소:&quot;);
        while (!stack.empty()) {
            System.out.println(stack.pop());
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Queue&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FIFO - First In First Out&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전용 구조체가 존재하지 않음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 LinkedList 클래스를 활용해 Queue 인터페이스를 구현&lt;/p&gt;
&lt;pre id=&quot;code_1713680463315&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.Queue;
import java.util.LinkedList;

public class Main {
    public static void main(String[] args) {
        // Queue 생성 (LinkedList를 사용하여 구현)
        Queue&amp;lt;Integer&amp;gt; queue = new LinkedList&amp;lt;&amp;gt;();

        // 요소 추가 (offer) O(1)
        queue.offer(10);
        queue.offer(20);
        queue.offer(30);

        // 요소 확인 (peek) O(1)
        int frontElement = queue.peek(); // 10

        // 요소 제거 (poll) O(1)
        int removedElement = queue.poll(); // 10

        // Queue가 비어 있는지 확인 (isEmpty) O(1)
        boolean isEmpty = queue.isEmpty(); // false

        // Queue의 크기 확인 (size) O(1)
        int size = queue.size(); // 2

        // Queue의 모든 요소 출력
        System.out.println(&quot;Queue의 모든 요소:&quot;);
        for (int element : queue) {
            System.out.println(element);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PriorityQueue&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요소를 우선순위에 따라 저장하고 제거&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최소 힙을 사용하여 구현됨&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중복값 허용&lt;/p&gt;
&lt;pre id=&quot;code_1713680839985&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.PriorityQueue;

public class Main {
    public static void main(String[] args) {
        // PriorityQueue 생성
        PriorityQueue&amp;lt;Integer&amp;gt; priorityQueue = new PriorityQueue&amp;lt;&amp;gt;();

        // 요소 추가 (offer) O(log n)
        priorityQueue.offer(30);
        priorityQueue.offer(10);
        priorityQueue.offer(20);

        // 요소 확인 (peek) O(1)
        int topElement = priorityQueue.peek(); // 10

        // 요소 제거 (poll) O(log n)
        int removedElement = priorityQueue.poll(); // 10

        // PriorityQueue가 비어 있는지 확인 (isEmpty) O(1)
        boolean isEmpty = priorityQueue.isEmpty(); // false

        // PriorityQueue의 크기 확인 (size) O(1)
        int size = priorityQueue.size(); // 2

        // PriorityQueue의 모든 요소 출력
        System.out.println(&quot;PriorityQueue의 모든 요소:&quot;);
        while (!priorityQueue.isEmpty()) {
            System.out.println(priorityQueue.poll());
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Deque(Double-ended Queue)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;양쪽 끝에서 삽입과 삭제를 모두 수행할 수 있는 큐(queue)의 확장된 형태&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;큐(Queue)와 스택(Stack)의 기능을 모두 제공&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt; 양쪽에서 요소를 추가하거나 제거&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;양방향으로 데이터를 처리해야 하는 상황에 매우 유용&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt; ArrayDeque와 LinkedList를 이용하여 인터페이스 구현&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;addFirst(E e)&lt;/b&gt;: Deque의 맨 앞에 요소를 추가합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간 복잡도: O(1)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;addLast(E e)&lt;/b&gt;: Deque의 맨 뒤에 요소를 추가합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간 복잡도: O(1)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;offerFirst(E e)&lt;/b&gt;: Deque의 맨 앞에 요소를 추가하고 성공 여부를 반환합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간 복잡도: O(1)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;offerLast(E e)&lt;/b&gt;: Deque의 맨 뒤에 요소를 추가하고 성공 여부를 반환합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간 복잡도: O(1)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;removeFirst()&lt;/b&gt;: Deque의 맨 앞에 있는 요소를 제거하고 반환합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간 복잡도: O(1)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;removeLast()&lt;/b&gt;: Deque의 맨 뒤에 있는 요소를 제거하고 반환합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간 복잡도: O(1)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;pollFirst()&lt;/b&gt;: Deque의 맨 앞에 있는 요소를 제거하고 반환합니다. Deque가 비어 있는 경우 null을 반환합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간 복잡도: O(1)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;pollLast()&lt;/b&gt;: Deque의 맨 뒤에 있는 요소를 제거하고 반환합니다. Deque가 비어 있는 경우 null을 반환합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간 복잡도: O(1)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;getFirst()&lt;/b&gt;: Deque의 맨 앞에 있는 요소를 반환합니다. Deque가 비어 있는 경우 NoSuchElementException이 발생합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간 복잡도: O(1)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;getLast()&lt;/b&gt;: Deque의 맨 뒤에 있는 요소를 반환합니다. Deque가 비어 있는 경우 NoSuchElementException이 발생합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간 복잡도: O(1)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;peekFirst()&lt;/b&gt;: Deque의 맨 앞에 있는 요소를 반환합니다. Deque가 비어 있는 경우 null을 반환합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간 복잡도: O(1)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;peekLast()&lt;/b&gt;: Deque의 맨 뒤에 있는 요소를 반환합니다. Deque가 비어 있는 경우 null을 반환합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간 복잡도: O(1)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;isEmpty()&lt;/b&gt;: Deque가 비어 있는지 확인합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간 복잡도: O(1)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;size()&lt;/b&gt;: Deque의 크기를 반환합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간 복잡도: O(1)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;pre id=&quot;code_1713681406497&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.Deque;
import java.util.ArrayDeque;

public class Main {
    public static void main(String[] args) {
        // Deque 생성 (ArrayDeque를 사용하여 구현)
        Deque&amp;lt;Integer&amp;gt; deque = new ArrayDeque&amp;lt;&amp;gt;();

        // 요소 추가 (addFirst / addLast) O(1)
        deque.addFirst(10);
        deque.addLast(20);
        deque.addFirst(5);
        deque.addLast(30);

        // Deque의 모든 요소 출력 O(1)
        System.out.println(&quot;Deque의 모든 요소:&quot;);
        for (int element : deque) {
            System.out.println(element);
        }

        // 요소 제거 (removeFirst / removeLast) O(1)
        int removedFirst = deque.removeFirst();
        int removedLast = deque.removeLast();

        // Deque의 크기 확인 (size) O(1)
        int size = deque.size();

        // Deque의 모든 요소 출력
        System.out.println(&quot;Deque의 모든 요소:&quot;);
        while (!deque.isEmpty()) {
            System.out.println(deque.removeFirst());
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;BinarySearch&amp;nbsp;&lt;/h3&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: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;O(log n)&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1713681645640&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[] array = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19};

        // 이진 탐색을 위해 배열을 먼저 정렬해야 함
        Arrays.sort(array);

        int key = 13;
        int index = Arrays.binarySearch(array, key);

        if (index &amp;gt;= 0) {
            System.out.println(key + &quot;는 배열의 &quot; + index + &quot;번째 인덱스에 있습니다.&quot;);
        } else {
            System.out.println(key + &quot;는 배열에 존재하지 않습니다.&quot;);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘/자료구조</category>
      <author>ji._.ye</author>
      <guid isPermaLink="true">https://jjiye716.tistory.com/31</guid>
      <comments>https://jjiye716.tistory.com/31#entry31comment</comments>
      <pubDate>Sun, 21 Apr 2024 12:33:36 +0900</pubDate>
    </item>
    <item>
      <title>JPA - (1) JPA 소개</title>
      <link>https://jjiye716.tistory.com/30</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;JPA&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Java Pesistence API&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 자바 진영의 ORM 표준 기술&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;ORM&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 객체와 RDB를 연결하는 프레임워크&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Object-relational mapping(객체 관계 매핑)&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;- ORM 프레임워크가 중간에서 매핑&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 대중적인 언어에는 대부분 ORM 기술이 존재&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;JPA 동작 방식&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애플리케이션 입장에선 자바 컬렉션에 저장하듯이 JPA를 이용하면 됨&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;JPA의 논리적 구조는 다음과 같음&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;- 애플리케이션과 JDBC 사이에서 동작&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;618&quot; data-origin-height=&quot;300&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEQvRi/btsGKt1gA78/jvIJ5RlYKkoDb6TQjHS0Rk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEQvRi/btsGKt1gA78/jvIJ5RlYKkoDb6TQjHS0Rk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEQvRi/btsGKt1gA78/jvIJ5RlYKkoDb6TQjHS0Rk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEQvRi%2FbtsGKt1gA78%2FjvIJ5RlYKkoDb6TQjHS0Rk%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;618&quot; height=&quot;300&quot; data-origin-width=&quot;618&quot; data-origin-height=&quot;300&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 저장&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;644&quot; data-origin-height=&quot;350&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c8urLP/btsGJQJbGk7/Ye5VEk3LXnvd4fU7rvyfZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c8urLP/btsGJQJbGk7/Ye5VEk3LXnvd4fU7rvyfZK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c8urLP/btsGJQJbGk7/Ye5VEk3LXnvd4fU7rvyfZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc8urLP%2FbtsGJQJbGk7%2FYe5VEk3LXnvd4fU7rvyfZK%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;644&quot; height=&quot;350&quot; data-origin-width=&quot;644&quot; data-origin-height=&quot;350&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 조회&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;641&quot; data-origin-height=&quot;376&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/J7Gvv/btsGI51gK5v/VmAumHuWEfrM6LudKb1gu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/J7Gvv/btsGI51gK5v/VmAumHuWEfrM6LudKb1gu0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/J7Gvv/btsGI51gK5v/VmAumHuWEfrM6LudKb1gu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJ7Gvv%2FbtsGI51gK5v%2FVmAumHuWEfrM6LudKb1gu0%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;641&quot; height=&quot;376&quot; data-origin-width=&quot;641&quot; data-origin-height=&quot;376&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;JPA의 물리적 구조&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- JPA는 표준 명세서, 인터페이스의 모음&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- JPA의 구현체 : 하이버네이트, EclipseLink, DataNucleus&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;571&quot; data-origin-height=&quot;239&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/r4HDp/btsGKNSQPj6/NWREgj0GqubIlcQwhJO3gK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/r4HDp/btsGKNSQPj6/NWREgj0GqubIlcQwhJO3gK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/r4HDp/btsGKNSQPj6/NWREgj0GqubIlcQwhJO3gK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fr4HDp%2FbtsGKNSQPj6%2FNWREgj0GqubIlcQwhJO3gK%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;571&quot; height=&quot;239&quot; data-origin-width=&quot;571&quot; data-origin-height=&quot;239&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;JPA를 사용해야 하는 이유&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1. SQL 중심적인 개발에서 객체 중심으로 개발&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 애플리케이션 입장에선 자바 컬렉션에 저장하듯이 JPA를 이용하면 됨&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2. 생산성 -JPA와 CRUD&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;bull; 저장: jpa.persist(member)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;bull; 조회: Member member = jpa.find(memberId)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;bull; 수정: member.setName(&amp;ldquo;변경할 이름&amp;rdquo;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;bull; 삭제: jpa.remove(member)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;3. 유지보수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필드 변경시 ...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 기존: 애플리케이션에서 모든 sql 수정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- JPA: 애플리케이션에선 필드만 추가, sql은 JPA가 처리&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;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;a href=&quot;https://jjiye716.tistory.com/29&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2024.04.18 - [백엔드/스프링] - JPA - sql 중심적인 개발의 문제점&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;5. 성능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 1차 캐시와 동일성(identity) 보장&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 트랜잭션을 지원하는 쓰기 지연(transactional write-behind)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 지연 로딩(Lazy Loading)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>백엔드/스프링</category>
      <author>ji._.ye</author>
      <guid isPermaLink="true">https://jjiye716.tistory.com/30</guid>
      <comments>https://jjiye716.tistory.com/30#entry30comment</comments>
      <pubDate>Thu, 18 Apr 2024 20:08:45 +0900</pubDate>
    </item>
    <item>
      <title>JPA - (0) sql 중심적인 개발의 문제점</title>
      <link>https://jjiye716.tistory.com/29</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;객체의 인스턴스 저장소가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;DB&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;인 경우와&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;자바 컬렉션(list, set)&lt;/span&gt;인 경우 코드와 성능에서 크게 차이가 남&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;저장소가 DB인 경우&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;애플리케이션은 객체 지향 언어(Java...)를 사용하지만 데이터는 관계형DB에 보관.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;애플리케이션과 데이터가 상호작용하기 위해선 객체를 SQL로 변환해 쿼리문을 DB에 전달 해야됨.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;DB에 인스턴스를 보관하는 경우 애플리케이션 계층에서 객체답게 모델링 할수록 매핑 작업이 늘어남.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;DB와 객체의 패러다임이 불일치!!&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;저장소가 자바 컬렉션인 경우&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;애플리케이션의 객체를 별도의 변환 없이 저장할 수 있음&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체의 인스턴스 저장소가 &lt;span style=&quot;color: #f89009;&quot;&gt;DB&lt;/span&gt;인 경우와 &lt;span style=&quot;color: #f89009;&quot;&gt;자바 컬렉션(list, set)&lt;/span&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;1. 상속&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;833&quot; data-origin-height=&quot;361&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHHMqY/btsGJs9thFH/VUqLU1CTToP0X02cmF2Mv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHHMqY/btsGJs9thFH/VUqLU1CTToP0X02cmF2Mv1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHHMqY/btsGJs9thFH/VUqLU1CTToP0X02cmF2Mv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHHMqY%2FbtsGJs9thFH%2FVUqLU1CTToP0X02cmF2Mv1%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;833&quot; height=&quot;361&quot; data-origin-width=&quot;833&quot; data-origin-height=&quot;361&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DB 테이블은 '상속 관계' 개념을 갖고있지 않음&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관계형 DB에선 '슈퍼타입 서브타입'으로 이 개념을 대체함&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대체할 만한 개념은 있지만 완전히 같은 것이 아니기에 유지보수와 구현이 복잡해짐&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) DB 사용&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예1) Album 인스턴스를 저장할 때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인스턴스를 분해해 ITEM, ALBUM 테이블에 각각 INSERT 해야함&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 인스턴스 분해&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2.INSERT INTO ITEM....&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3.INSERT INTO ALBUM&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;예2) Album 조회&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 각각의 테이블에 따른 조인 sql 작성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2, 각각의 객체 생성&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) 자바 컬렉션에 인스턴스를 저장, 조회 한다면?&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;list,add(album);&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Album album = list.get(albumId);&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 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;2. 연관관계&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;537&quot; data-origin-height=&quot;299&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/84nH3/btsGJNeB2Fh/esEyLRi3LNRz3m8vBD7t61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/84nH3/btsGJNeB2Fh/esEyLRi3LNRz3m8vBD7t61/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/84nH3/btsGJNeB2Fh/esEyLRi3LNRz3m8vBD7t61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F84nH3%2FbtsGJNeB2Fh%2FesEyLRi3LNRz3m8vBD7t61%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;537&quot; height=&quot;299&quot; data-origin-width=&quot;537&quot; data-origin-height=&quot;299&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 객체가 연관관계를 맺을 때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체는 &lt;span style=&quot;color: #ee2323;&quot;&gt;참조&lt;/span&gt;를 사용: member.getTeam()&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테이블은 &lt;span style=&quot;color: #ee2323;&quot;&gt;외래키(join)&lt;/span&gt;를 사용: JOIN ON M.TEAM_ID = T.TEAM_ID&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) 객체다운 모델링 VS 테이블에 맞춘 객체 모델링&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유지보수를 위해선 전자의 경우를 택해야 하지만 코드와 동작 방식이 더욱 복잡해짐&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 객체를 등록하고 DB에 저장하는 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;예1) class 구현&amp;nbsp;&lt;/p&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/AtJtk/btsGIM8AwEQ/DwAe0cZK94xTdxuP1JEsvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AtJtk/btsGIM8AwEQ/DwAe0cZK94xTdxuP1JEsvK/img.png&quot; data-origin-width=&quot;568&quot; data-origin-height=&quot;342&quot; data-is-animation=&quot;false&quot; width=&quot;432&quot; data-widthpercent=&quot;44.78&quot; id=&quot;kEditorPhotosEditingImage-2&quot; style=&quot;width: 44.2624%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AtJtk/btsGIM8AwEQ/DwAe0cZK94xTdxuP1JEsvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAtJtk%2FbtsGIM8AwEQ%2FDwAe0cZK94xTdxuP1JEsvK%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;568&quot; height=&quot;342&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8yN5y/btsGKttkEGk/XUAFhx7cBtSWKulei6HmWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8yN5y/btsGKttkEGk/XUAFhx7cBtSWKulei6HmWk/img.png&quot; data-origin-width=&quot;686&quot; data-origin-height=&quot;335&quot; data-is-animation=&quot;false&quot; width=&quot;446&quot; data-widthpercent=&quot;55.22&quot; id=&quot;kEditorPhotosEditingImage-3&quot; style=&quot;width: 54.5748%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8yN5y/btsGKttkEGk/XUAFhx7cBtSWKulei6HmWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8yN5y%2FbtsGKttkEGk%2FXUAFhx7cBtSWKulei6HmWk%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;686&quot; height=&quot;335&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;객체다운 모델링&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 테이블에 맞춘 객체 모델링&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/figcaption&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;size14&quot;&gt;예2) DB에 저장&amp;nbsp;&lt;/p&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/deFn3X/btsGJc6VCcF/wIKrqkkT4uVvWou72obTwk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/deFn3X/btsGJc6VCcF/wIKrqkkT4uVvWou72obTwk/img.png&quot; data-origin-width=&quot;793&quot; data-origin-height=&quot;314&quot; data-is-animation=&quot;false&quot; width=&quot;519&quot; style=&quot;width: 50.1827%; margin-right: 10px;&quot; data-widthpercent=&quot;50.77&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/deFn3X/btsGJc6VCcF/wIKrqkkT4uVvWou72obTwk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdeFn3X%2FbtsGJc6VCcF%2FwIKrqkkT4uVvWou72obTwk%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;793&quot; height=&quot;314&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cnofE1/btsGKbM5gXL/0uZ920wtmq1dykLaQIKnM1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cnofE1/btsGKbM5gXL/0uZ920wtmq1dykLaQIKnM1/img.png&quot; data-origin-width=&quot;857&quot; data-origin-height=&quot;350&quot; data-is-animation=&quot;false&quot; width=&quot;438&quot; height=&quot;179&quot; style=&quot;width: 48.6545%;&quot; data-widthpercent=&quot;49.23&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cnofE1/btsGKbM5gXL/0uZ920wtmq1dykLaQIKnM1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcnofE1%2FbtsGKbM5gXL%2F0uZ920wtmq1dykLaQIKnM1%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;857&quot; height=&quot;350&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; 객체다운 모델링&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;테이블에 맞춘 객체 모델링&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 객체 모델링 조회&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;예) 특정 member&amp;nbsp; 조회&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Member를 조회하기 위해선 Member와 Team 모두 조회해야됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연관관계에 있는 객체를 조회하기 위해 JOIN 작업을 추가적으로 해야됨.&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;545&quot; data-origin-height=&quot;369&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LV4SS/btsGKttlOYy/8YHQjMkouPEtwcBoEZYCI1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LV4SS/btsGKttlOYy/8YHQjMkouPEtwcBoEZYCI1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LV4SS/btsGKttlOYy/8YHQjMkouPEtwcBoEZYCI1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLV4SS%2FbtsGKttlOYy%2F8YHQjMkouPEtwcBoEZYCI1%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;432&quot; height=&quot;292&quot; data-origin-width=&quot;545&quot; data-origin-height=&quot;369&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) 자바 컬렉션에 인스턴스를 저장, 조회 한다면? &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;list.add(member);&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Member member = list.get(memberId);&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Team team = member.getTeam();&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;3. 객체 그래프 탐색&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체는 자유롭게 그래프를 탐색할 수 있어야 함&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만! DB에 객체를 저장한다면 처음 실행하는 sql에 따라 탐색 범위가 제한되면서 엔티티 신뢰 문제가 발생함&amp;nbsp;&lt;/p&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/bordBM/btsGJNeFbIi/bXq3FKbx4mCqawGMANJjD0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bordBM/btsGJNeFbIi/bXq3FKbx4mCqawGMANJjD0/img.png&quot; data-origin-width=&quot;530&quot; data-origin-height=&quot;270&quot; data-is-animation=&quot;false&quot; width=&quot;332&quot; height=&quot;169&quot; style=&quot;width: 42.0833%; margin-right: 10px;&quot; data-widthpercent=&quot;42.58&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bordBM/btsGJNeFbIi/bXq3FKbx4mCqawGMANJjD0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbordBM%2FbtsGJNeFbIi%2FbXq3FKbx4mCqawGMANJjD0%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;530&quot; height=&quot;270&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ByG2g/btsGJQvB8uj/Bl1EUKmDsRMauZ5o34p2Fk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ByG2g/btsGJQvB8uj/Bl1EUKmDsRMauZ5o34p2Fk/img.png&quot; data-origin-width=&quot;728&quot; data-origin-height=&quot;275&quot; data-is-animation=&quot;false&quot; width=&quot;574&quot; height=&quot;217&quot; data-widthpercent=&quot;57.42&quot; style=&quot;width: 56.7539%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ByG2g/btsGJQvB8uj/Bl1EUKmDsRMauZ5o34p2Fk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FByG2g%2FbtsGJQvB8uj%2FBl1EUKmDsRMauZ5o34p2Fk%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;728&quot; height=&quot;275&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;엔티티 신뢰 문제&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계층형 아키텍쳐(MVC패턴)는 다음 계층을 믿고 사용할 수 있어야 하는데 쿼리에 따라 탐색할 수 있는 범위가 달라지기에 요청을 보낸 계층(상위 계층)이 요청을 받은 계층(하위 계층)을 신뢰하지 못함. 따라서 개발자는 상위 계층의 코드에&amp;nbsp; 하위 계층에서의 탐색 범위를 벗어난 접근이 있는지 확인해야됨&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;754&quot; data-origin-height=&quot;242&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sQNKO/btsGIX95qtx/zb7EWGf6T2CSyWLWW2qdR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sQNKO/btsGIX95qtx/zb7EWGf6T2CSyWLWW2qdR0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sQNKO/btsGIX95qtx/zb7EWGf6T2CSyWLWW2qdR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsQNKO%2FbtsGIX95qtx%2Fzb7EWGf6T2CSyWLWW2qdR0%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;710&quot; height=&quot;228&quot; data-origin-width=&quot;754&quot; data-origin-height=&quot;242&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;member.DAO.find 코드를 확인해야 Team, Order에 접근(탐색) 가능 여부를 알 수 있음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;service계층이(MemberService) repository 계층(memberDAO)을 신뢰하지 못함.&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;모든 객체를 미리 로딩하면 탐색 범위를 고려할 필요가 없지만 join으로 인해 성능이 낮아짐.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;탐색 범위에 따라 메서드를 여러 개 구현하는 방법도 있지만 코드가 길어짐.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;4. 비교하기&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) sql로 DB에 접근&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;686&quot; data-origin-height=&quot;345&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KjL5g/btsGK8CiSc7/Zt1Nfsg0FmR6hf8Qf6MssK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KjL5g/btsGK8CiSc7/Zt1Nfsg0FmR6hf8Qf6MssK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KjL5g/btsGK8CiSc7/Zt1Nfsg0FmR6hf8Qf6MssK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKjL5g%2FbtsGK8CiSc7%2FZt1Nfsg0FmR6hf8Qf6MssK%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;686&quot; height=&quot;345&quot; data-origin-width=&quot;686&quot; data-origin-height=&quot;345&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;memberDAO.getMember(): DB에서 인스턴스를 조회해 값이 세팅된 객체 인스턴스 생성 및 반환&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 같은 쿼리문을 날리면 data는 같지만 다른 객체 인스턴스가 생성됨&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) 자바 컬렉션으로 인스턴스에 접근&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;member1 == member2; // 두 인스턴스는 같음 &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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;결론&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체를 자바 컬렉션에 저장하듯이 DB에 저장할 순 없을까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; JPA(Java Persistence API) 등장&amp;nbsp;&lt;/p&gt;</description>
      <category>백엔드/스프링</category>
      <author>ji._.ye</author>
      <guid isPermaLink="true">https://jjiye716.tistory.com/29</guid>
      <comments>https://jjiye716.tistory.com/29#entry29comment</comments>
      <pubDate>Thu, 18 Apr 2024 19:26:50 +0900</pubDate>
    </item>
    <item>
      <title>110501</title>
      <link>https://jjiye716.tistory.com/23</link>
      <description>&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;769&quot; data-origin-height=&quot;337&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWdQGF/btsF6ecKsy4/VVuwSnXIA2k3U6Vukxd4Nk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWdQGF/btsF6ecKsy4/VVuwSnXIA2k3U6Vukxd4Nk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWdQGF/btsF6ecKsy4/VVuwSnXIA2k3U6Vukxd4Nk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWdQGF%2FbtsF6ecKsy4%2FVVuwSnXIA2k3U6Vukxd4Nk%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;662&quot; height=&quot;290&quot; data-origin-width=&quot;769&quot; data-origin-height=&quot;337&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1711455136872&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Main{
    public static void main(String[] args) throws Exception{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String [] input = br.readLine().split(&quot; &quot;);
        
        int N = Integer.parseInt(input[0]);
        int K = Integer.parseInt(input[1]);
        
        int D[][] = new int[N+1][N+1];
        for(int i = 0; i &amp;lt; N+1; i++){
            D[i][0] = 1; D[i][i] = 1;
            for(int j = 1; j &amp;lt; i; j++){
                D[i][j] = (D[i-1][j-1]+D[i-1][j])%10007;
            } 
        }
        
        System.out.println(D[N][K]);
    }
}&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;&lt;b&gt;문제 포인트&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 다이나믹 프로그래밍&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이항계수는 다이나믹 프로그래밍의 대표적인 예시이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;nCk = n! / {(n-k)! *k!} 공식을 사용하여 구할 수도 있지만 파스칼의 삼각형을 적용하여 다이나믹프로그래밍으로 계산하는 방법도 있다.&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;1.이차원 배열 D[n][k] 에 nCk의 값을 넣고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. for문을 돌며 nCk = n-1Ck-1 + n-1Ck 공식 적용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;와 같은 코드를 통해 쉽게 구할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제에서 후자의 방법이 사용된 이유는 뒤에 설명하겠다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;220&quot; data-origin-height=&quot;158&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cExcmk/btsF8nzLLS6/iS5VgQSN9c0k0T4EIpADFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cExcmk/btsF8nzLLS6/iS5VgQSN9c0k0T4EIpADFk/img.png&quot; data-alt=&quot;출처: 위키백과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cExcmk/btsF8nzLLS6/iS5VgQSN9c0k0T4EIpADFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcExcmk%2FbtsF8nzLLS6%2FiS5VgQSN9c0k0T4EIpADFk%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;220&quot; height=&quot;158&quot; data-origin-width=&quot;220&quot; data-origin-height=&quot;158&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: 위키백과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. Mod(나머지) 연산&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Mod연산은 대게 정답이 자료형의 범위를 넘어가는 경우 값의 크기를 줄이기 위해 사용된다. 여기서 주의해야 할 점은 답을 구하는 과정에서도 값이 범위를 넘어갈 수 있다는 것이다. 이를 해결하기 위한 방법은 간단하다. Mod연산을 답을 구하는 중간 단계에서도 실행하는 것이다.&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;(A + B) % C = {(A % C) + (A % B)} % C&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(A x B) % C = {(A % C) x (A % B)} % C&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(A - B) % C = {(A - C) + (A - B)} % C&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;Mod는 위와 같이 분배법칙(정확한 용어는 아니지만 편의상 이렇게 부르겠다) 이 성립하기 때문에&amp;nbsp; 반복되는 연산일 경우 각 단계마다 Mod연산을 실행해도 올바른 답을 도출할 수 있음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;오답 노트&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다이나믹프로그래밍이 아닌 nCk = n! / {(n-k)! *k!} 공식을 적용하여 문제를 풀었지만 오답이 나왔다.&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;nCk&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;= (n-0)x(n-1)x...x(n-k+1) / k!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;= &lt;span style=&quot;color: #ee2323;&quot;&gt;{(n-0)/(k-0)} x {(n-1)/k-1} x ...x {(n-k+1)/1}&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;for 문을 돌려 순차적으로 {(n-i)/(k-i)} % 10007 을 계산하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오답의 이유는 for문의 각 단계에서 {(n-i)/(k-i)} 값이 소수가 나올 수도 있다는게 원인이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다이나믹 프로그래밍을 적용한 경우 각 단계에선 무조건 정수가 나오기에 Mod연산을 해도 정수 값이 나온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711456897644&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//틀린 코드
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Main{
    public static void main(String[] args) throws Exception{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String [] input = br.readLine().split(&quot; &quot;);
        
        int N = Integer.parseInt(input[0]);
        int K = Integer.parseInt(input[1]);
    
        int a = 1;
        for(; K&amp;gt;0 ;){
           a =  (N/K % 10007) * a; 
           --N; --K;
        }
        System.out.println(a % 10007);
    }
}&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;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다이나믹프로그래밍(파스칼의 삼각형) 기법을 사용해 for문의 각 단계에서 정수 값을 구하고 Mod를 적용해 값이 커지는걸 방지한다.&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘/백준</category>
      <author>ji._.ye</author>
      <guid isPermaLink="true">https://jjiye716.tistory.com/23</guid>
      <comments>https://jjiye716.tistory.com/23#entry23comment</comments>
      <pubDate>Tue, 26 Mar 2024 22:29:40 +0900</pubDate>
    </item>
    <item>
      <title>스프링부트 환경설정</title>
      <link>https://jjiye716.tistory.com/22</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;1. 프로젝트 생성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dependencies: Spring Web, Thymeleaf&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;644&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dY3n4L/btsF91Er0hZ/0AXBwgJII5mX5l7IsDB0Uk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dY3n4L/btsF91Er0hZ/0AXBwgJII5mX5l7IsDB0Uk/img.png&quot; data-alt=&quot;https://start.spring.io/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dY3n4L/btsF91Er0hZ/0AXBwgJII5mX5l7IsDB0Uk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdY3n4L%2FbtsF91Er0hZ%2F0AXBwgJII5mX5l7IsDB0Uk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;644&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;644&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://start.spring.io/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Dependencies - 라이브러리 선택&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Spring Web - 웹 개발에 필요한 라이브러리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Thymeleaf - HTML을 생성하는 템플릿 엔진&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 프로젝트 생성 후 Intellij에서 hello-spring 폴더에 위치한 build.gardle 오픈&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Grale&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;라이브러리를 가져오고 빌드를 관리하는 툴&lt;/li&gt;
&lt;li&gt;CI/CD를 위해 여러 작업들(Compile, Test, Packaging, Deploy&amp;amp;Run)을 자동화 시켜줌&lt;/li&gt;
&lt;li&gt;Packaging - 스프링 코드를 패키징 해 .jar, .war 파일로 생성&lt;/li&gt;
&lt;li&gt;jar 파일 - 컴파일된 여러 .class 파일이 포함된 단일 파일어플리케이션을 서버에 배포할땐 Gradle에서 jar파일을 생성해야 함.&lt;/li&gt;
&lt;li&gt;빌드 도구 - 소스 코드를 샐행 가능한 어플리케이션으로 만들어주는 도구&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;pre id=&quot;code_1711355080303&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;plugins {
	id 'java'
	id 'org.springframework.boot' version '2.7.9'
	id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}

group = 'hello'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-thymeleaf:2.7.8'
	implementation 'org.springframework.boot:spring-boot-starter-web:2.7.8'
	testImplementation 'org.springframework.boot:spring-boot-starter-test:2.7.8'
	implementation 'org.springframework.boot:spring-boot-starter-jdbc'
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	runtimeOnly 'com.h2database:h2'
	testImplementation('org.springframework.boot:spring-boot-starter-test:'){
		exclude group: 'org.junit.vintage',module: 'junit-vintage-engine'
	}
}

test{
	useJUnitPlatform()
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 파일 설명&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;resources 폴더 - java를 제외한 나머지 코드, HTML 파일도 이 폴더에 들어감.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.gitignore - git에는 소스코드만 올라가야 됨. build된 결과물은 올라가면 안됨.&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;3.Run&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HelloSpringApplication class의 main 메서드 실행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; @SpringbootApplication 작동 : 톰캣 웹서버를 내장하고 있음&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;998&quot; data-origin-height=&quot;514&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nLoCQ/btsGa0dXSVO/QLYb4YOeKlHHvcNcPEbNoK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nLoCQ/btsGa0dXSVO/QLYb4YOeKlHHvcNcPEbNoK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nLoCQ/btsGa0dXSVO/QLYb4YOeKlHHvcNcPEbNoK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnLoCQ%2FbtsGa0dXSVO%2FQLYb4YOeKlHHvcNcPEbNoK%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;998&quot; height=&quot;514&quot; data-origin-width=&quot;998&quot; data-origin-height=&quot;514&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;284&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/z0ZUb/btsF9zVW54F/q25iXYh9oCs51TgKjU0oik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/z0ZUb/btsF9zVW54F/q25iXYh9oCs51TgKjU0oik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/z0ZUb/btsF9zVW54F/q25iXYh9oCs51TgKjU0oik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fz0ZUb%2FbtsF9zVW54F%2Fq25iXYh9oCs51TgKjU0oik%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;284&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;284&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Tomcat initialized with port(s): 8080 (http)&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;960&quot; data-origin-height=&quot;236&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvK0Aq/btsGholE9LA/23UINhIifcxv7AxfifP8jK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvK0Aq/btsGholE9LA/23UINhIifcxv7AxfifP8jK/img.png&quot; data-alt=&quot;브라우저 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvK0Aq/btsGholE9LA/23UINhIifcxv7AxfifP8jK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvK0Aq%2FbtsGholE9LA%2F23UINhIifcxv7AxfifP8jK%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;960&quot; height=&quot;236&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;236&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;브라우저 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;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;localhost:8080에 연결이 안된다면?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Settings &amp;gt; Build, Execution &amp;gt; Deployment &amp;gt; Deburgger &amp;gt; Built-in Server&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에서 port 가 8080으로 설정되어있는지 확인&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;593&quot; data-origin-height=&quot;669&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1v0fF/btsGeAU7IUL/5WIMdcptAhXIdKUfYeYeyK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1v0fF/btsGeAU7IUL/5WIMdcptAhXIdKUfYeYeyK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1v0fF/btsGeAU7IUL/5WIMdcptAhXIdKUfYeYeyK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1v0fF%2FbtsGeAU7IUL%2F5WIMdcptAhXIdKUfYeYeyK%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;593&quot; height=&quot;669&quot; data-origin-width=&quot;593&quot; data-origin-height=&quot;669&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;</description>
      <category>백엔드/스프링</category>
      <author>ji._.ye</author>
      <guid isPermaLink="true">https://jjiye716.tistory.com/22</guid>
      <comments>https://jjiye716.tistory.com/22#entry22comment</comments>
      <pubDate>Tue, 26 Mar 2024 17:51:07 +0900</pubDate>
    </item>
    <item>
      <title>스프링 활용 - 환경 설정</title>
      <link>https://jjiye716.tistory.com/20</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;@PersistenceContext&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;영속성 컨텍스트: 엔티티를 영구 저장하는 환경&lt;/li&gt;
&lt;li&gt;스프링에는 영속성 관리를 위해 EntityManager존재&lt;/li&gt;
&lt;li&gt;EntityManager를 빈으로 주입할 때 사용&lt;/li&gt;
&lt;li&gt;EntityManager는 영속성 컨텍스트에 엔티티를 보관하고 관리&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1694390962499&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//MemberRepository

@Repository
public class MemberRepository {
    @PersistenceContext
    private EntityManager em;
    public  Long save(Member member){
        em.persist(member);
        return member.getId();
    }

    public Member find(Long id){
        return em.find(Member.class, id);
    }//같은 영속성 context 안에서는 ID가 동일하면 같은 Entity로 식별

}&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;@Transactional&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;오류가 발생했을 때 모든 작업을 원상태로 되돌릴 수 있음&lt;/li&gt;
&lt;li&gt;데이터 추가, 갱신, 삭제 등으로 이루어진 작업에 오류가 발생했을 때 모든 작업들을 원상태로 되돌림&lt;/li&gt;
&lt;li&gt;DB와 관련된 클래스, 메서드에 어노테이션 적용&lt;/li&gt;
&lt;li&gt;테스트 메서드에 어노테이션을 적용하면 메서즈가 종료될 때 자동으로 롤백&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@RollBack(false)&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;pre id=&quot;code_1694390878479&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//MemberRepositoryTest
...
 @Test
    @Transactional
    @Rollback(false)
    public void testMember() throws Exception{
        //given
        Member member = new Member();
        member.setUsername(&quot;memberA&quot;);

        //when
        Long saveId = memberRepository.save(member);
        Member findMember = memberRepository.find(saveId);
...&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;</description>
      <category>백엔드</category>
      <author>ji._.ye</author>
      <guid isPermaLink="true">https://jjiye716.tistory.com/20</guid>
      <comments>https://jjiye716.tistory.com/20#entry20comment</comments>
      <pubDate>Mon, 11 Sep 2023 09:24:29 +0900</pubDate>
    </item>
    <item>
      <title>NCP 사용 후기</title>
      <link>https://jjiye716.tistory.com/17</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;네이버 Essential Hands-on 강의를 들으면서 VPC서비스 이용방법을 배워봤다.&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;1.&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;514&quot; data-origin-height=&quot;194&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/X7OMX/btsqKhb5IUc/uThzDGxg7pcmGxMVVqPgo0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/X7OMX/btsqKhb5IUc/uThzDGxg7pcmGxMVVqPgo0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/X7OMX/btsqKhb5IUc/uThzDGxg7pcmGxMVVqPgo0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FX7OMX%2FbtsqKhb5IUc%2FuThzDGxg7pcmGxMVVqPgo0%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;514&quot; height=&quot;194&quot; data-origin-width=&quot;514&quot; data-origin-height=&quot;194&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 IP주소를 할당 받고, 4개의 server를 생성하였다. 4개의 서버로 네트워크 트래픽을 분산시키기 위해 Load Balancer를 생성하였다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;865&quot; data-origin-height=&quot;105&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bb173N/btsqLwGcInx/uYRar3HabKYsrIOkknuyfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bb173N/btsqLwGcInx/uYRar3HabKYsrIOkknuyfK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bb173N/btsqLwGcInx/uYRar3HabKYsrIOkknuyfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbb173N%2FbtsqLwGcInx%2FuYRar3HabKYsrIOkknuyfK%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;865&quot; height=&quot;105&quot; data-origin-width=&quot;865&quot; data-origin-height=&quot;105&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;VPC이름을 test, lab1으로 설정하요 가상 private cloud를 생성하였다. private이기 떄문에 CIDR은 같을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;869&quot; data-origin-height=&quot;584&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dbtUEk/btsqMiHGbZg/NcbHgDDxl9lXP5v8rbwvw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dbtUEk/btsqMiHGbZg/NcbHgDDxl9lXP5v8rbwvw0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dbtUEk/btsqMiHGbZg/NcbHgDDxl9lXP5v8rbwvw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdbtUEk%2FbtsqMiHGbZg%2FNcbHgDDxl9lXP5v8rbwvw0%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;869&quot; height=&quot;584&quot; data-origin-width=&quot;869&quot; data-origin-height=&quot;584&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Load balancer는 애플리케이션 로드밸런서, 네트워크 로드밸런서, 네트워크 프록시 로드밸런서가 있는데 그 중에 가장 기본적인 애플리케이션 로드밸런서를 생성했다. load balance를 적용할 VPC로 lab1을 선택했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;857&quot; data-origin-height=&quot;576&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/n1mce/btsqSbOseGu/8tUlK4XWjISMEhCJKmSjo1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/n1mce/btsqSbOseGu/8tUlK4XWjISMEhCJKmSjo1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/n1mce/btsqSbOseGu/8tUlK4XWjISMEhCJKmSjo1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fn1mce%2FbtsqSbOseGu%2F8tUlK4XWjISMEhCJKmSjo1%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;857&quot; height=&quot;576&quot; data-origin-width=&quot;857&quot; data-origin-height=&quot;576&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버 수를 자동으로 변경해주는 Auto Scaling서비스도 이용했다. 최소 용량, 최대 용량, 기대 용량, 서버 수를 지정해주고 헬스 체크 유형을 선택하여 생성하면 된다. lab1-vpc를 서버로 설정하였고 로드밸런서를 통해 헬스 체크를 할 수 있도록 선택했다.&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;후기: Ncloud 서비스를 이용한 서버 생성에 대해 알아보았다. 버튼만 몇 번 클릭하면 서버가 생성돼서 매우 편리하고 대시보드에서 상황을 한 눈에 볼 수 있어서 서버 관리에 용이할 것 같다.&amp;nbsp;&lt;/p&gt;</description>
      <category>백엔드</category>
      <author>ji._.ye</author>
      <guid isPermaLink="true">https://jjiye716.tistory.com/17</guid>
      <comments>https://jjiye716.tistory.com/17#entry17comment</comments>
      <pubDate>Thu, 10 Aug 2023 16:45:22 +0900</pubDate>
    </item>
    <item>
      <title>딥페이크 기술 보고서</title>
      <link>https://jjiye716.tistory.com/9</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;2학년 2학기, 데이터 사이언스 개론 수업에 제출했던 보고서다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이론 보다는 사용 예시에 중점을 두어 작성했다. 100점 만점에 90점을 받았는데, 분량이 부족해서 점수가 깎인 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;논문을 읽어보며 기술적인 면을 더 공부해봐야겠다.&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;딥페이크 기술과 응용 사례&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;C111106 &lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span&gt;유지예&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;(&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span&gt;초록&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;고인이 되어 다시 볼 수 없을 거라 생각한 가수가 공연을 하고&lt;span&gt;, &lt;/span&gt;가상 인물이 실제 인물처럼 미디어에서 활동을 한다&lt;span&gt;. &lt;/span&gt;이는 모두 딥페이크로 구현한 것이다&lt;span&gt;. &lt;/span&gt;딥페이크란 딥러닝을 이용해 얼굴 이미지를 편집하는 기술이다&lt;span&gt;. &lt;/span&gt;본 글에서는 다양한 딥페이크 기술의 특징과 원리&lt;span&gt;, &lt;/span&gt;응용 사례에 대해 설명하고&lt;span&gt;, &lt;/span&gt;딥페이크 악용 사례와 이에 대응하는 딥페이크 탐지 기술에 대해 설명한다&lt;span&gt;. &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&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;b&gt;&lt;span&gt;(&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span&gt;서론&lt;span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;영원히 못 볼 줄 알았던 사람을 다시 만나게 된다면 어떤 기분일까&lt;span&gt;? &lt;/span&gt;음악 채널 &lt;span&gt;M-net&lt;/span&gt;은 &lt;span&gt;AI&lt;/span&gt;음악 프로젝트 &lt;span&gt;&amp;lsquo;&lt;/span&gt;다시 한번&lt;span&gt;&amp;rsquo;&lt;/span&gt;을 통해 거북이의 터틀맨을 홀로그램 형태로 무대에 불러냈다&lt;span&gt;. &lt;/span&gt;거북이의 리더 &lt;span&gt;&amp;lsquo;&lt;/span&gt;터틀맨&lt;span&gt;&amp;rsquo;&lt;/span&gt;은 &lt;span&gt;2008&lt;/span&gt;년 고인이 된 사람이다&lt;span&gt;. &lt;/span&gt;그런데 어떻게 무대에 설 수 있었을까&lt;span&gt;? &lt;/span&gt;그 방법은 바로 딥페이크 기술이다&lt;span&gt;. &lt;/span&gt;딥페이크는 &lt;span&gt;AI&lt;/span&gt;를 이용해 사람의 이미지를 합성하는 기술이다&lt;span&gt;. &amp;lsquo;&lt;/span&gt;딥페이크&lt;span&gt;&amp;rsquo;&lt;/span&gt;란 용어는 &lt;span&gt;2017&lt;/span&gt;년 미국의 온라인 커뮤니티 레딧에 할리우드 배우의 얼굴과 포르노를 합성한 편집물을 올린 네티즌의 아이디 &lt;span&gt;&amp;lsquo;Deepfakes&amp;rsquo;&lt;/span&gt;에서 유래했다&lt;span&gt;. &lt;/span&gt;가상 인물&lt;span&gt;, &lt;/span&gt;얼굴 보정 등 다양한 분야에 딥페이크가 사용되고 있다&lt;span&gt;. &lt;/span&gt;딥페이크는 &lt;span&gt;Face Synthesis, Facial attributes, facial expression, face swap 4&lt;/span&gt;종류가 있다&lt;span&gt;. &lt;/span&gt;각 기술의 특징에 대해 알아보자&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&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;b&gt;&lt;span&gt;(&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span&gt;본론&lt;span&gt;1) Face Synthesis&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Face Synthesis&lt;/span&gt;&lt;span&gt;란 실제론 존재하지 않는 가상의 인물의 얼굴을 만들어내는 기술이다&lt;span&gt;. &lt;/span&gt;여기서 &lt;span&gt;GAN(Generative Adversarial Networks)&lt;/span&gt;이 사용된다&lt;span&gt;. GAN&lt;/span&gt;은 생성자와 구분자로 이루어진 두 네트워크를 경쟁시켜 학습시키는 비지도 학습 모델이다&lt;span&gt;. &lt;/span&gt;생성자는 기존 인물 사진으로 학습을 하며 실제 얼굴처럼 보이는 이미지를 생성한다&lt;span&gt;. &lt;/span&gt;판별자는 생성된 이미지 속 얼굴이 실제인지 가짜인지 구분하며 학습한다&lt;span&gt;. &lt;/span&gt;판별자가 가짜 이미지를 진짜 이미지라고 판단하면 생성자는 잘 학습된 것이므로 학습을 종료하고 생성모델을 사용해 이미지를 만드는 작업을 한다&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;411&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bX8lwQ/btr0riF5UJl/MpvGUcwcJHg0WGKA24z2w0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bX8lwQ/btr0riF5UJl/MpvGUcwcJHg0WGKA24z2w0/img.png&quot; data-alt=&quot;&amp;amp;lt;그림&amp;amp;amp;nbsp;1&amp;amp;gt; GAN의 아키텍처 (출처: Hamed Alqahtani. 2019. An Analysis Of Evaluation Metric Of GANs)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bX8lwQ/btr0riF5UJl/MpvGUcwcJHg0WGKA24z2w0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbX8lwQ%2Fbtr0riF5UJl%2FMpvGUcwcJHg0WGKA24z2w0%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;472&quot; height=&quot;265&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;411&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;&amp;lt;그림&amp;amp;nbsp;1&amp;gt; GAN의 아키텍처 (출처: Hamed Alqahtani. 2019. An Analysis Of Evaluation Metric Of GANs)&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;펄스나인은 가상인물 사업에 중점을 둔 기업이다&lt;span&gt;. &lt;/span&gt;이 기업은 가상 인물로 이뤄진 걸그룹 이너니티를 만들었다&lt;span&gt;. &lt;/span&gt;가상 걸그룹 이너니티는 실제 걸그룹처럼 음원을 내거나 미디어에 노출된다&lt;span&gt;. &lt;/span&gt;이 기업에서 만든 가상 인물들은 걸그룹뿐만 아니라 인플루언서&lt;span&gt;, SNS &lt;/span&gt;광고 모델&lt;span&gt;, &lt;/span&gt;유튜버 등 여러 분야에서 활동하고 있다&lt;span&gt;. &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;(&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span&gt;본론&lt;span&gt;2) Facial attributes&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Facial attributes&lt;/span&gt;&lt;span&gt;란 얼굴의 특정한 속성을 바꾸는 기술이다&lt;span&gt;. &lt;/span&gt;속성을 추가하거나 삭제하는 등 임의로 조절할 수 있다&lt;span&gt;. &lt;/span&gt;예를 들어 피부 색이나 주름을 조절하고 앞머리를 생성할 수 있다&lt;span&gt;. GAN&lt;/span&gt;에 기능을 추가한 다양한 알고리즘이&lt;span&gt; Facial attribute&lt;/span&gt;을 구현하는데 이용된다&lt;span&gt;. cGAN(conditional-GAN)&lt;/span&gt;은 생성자와 판별자에 특정 속성을 나타내는 정보를 추가해준 것이다&lt;span&gt;. &lt;/span&gt;정보는 안경 유무&lt;span&gt;, &lt;/span&gt;빨강 머리 등 임의로 선택이 가능하다&lt;span&gt;. StarGAN&lt;/span&gt;은 &lt;span&gt;cGAN&lt;/span&gt;의 한 종류로&lt;span&gt;, &lt;/span&gt;단일 네트워크를 이용해 다중 도메인에서의 이미지 간의 변형을 효율적으로 수행할 수 있도록 하는 알고리즘이다&lt;span&gt;. StarGAN&lt;/span&gt;을 이용하면 눈 크기&lt;span&gt;, &lt;/span&gt;피부색 등 여러 특징을 한 번에 바꿀 수 있다&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;페이스북은 이미지 속 인물의 감은 눈을 뜨게 만드는 &lt;span&gt;ExGAN(Exemplar GAN)&lt;/span&gt;기술을 개발했다&lt;span&gt;. ExGAN&lt;/span&gt;은 &lt;span&gt;cGAN&lt;/span&gt;의 한 종류로&lt;span&gt;, &lt;/span&gt;추가 정보를 생성자와 판별자 외에도 손실함수 등 다양한 곳에 적용한다&lt;span&gt;. &lt;/span&gt;이렇게 학습된 &lt;span&gt;ExGAN&lt;/span&gt;은 단순히 눈을 붙이는 것에서 나아가 인물의 얼굴형이나 피부색에 어우러지도록 눈의 색과 모양을 구현한다&lt;span&gt;. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;ldquo;Toonify Yourself!&amp;rdquo;&lt;/span&gt;&lt;span&gt;라는 홈페이지는 얼굴 사진을 업로드하면 카툰 캐릭터처럼 만들어준다&lt;span&gt;. StyleGAN&lt;/span&gt;에 캐릭터 데이터를 학습시킨 알고리즘을 이용하였다&lt;span&gt;. &lt;/span&gt;사용자가 직접 나이&lt;span&gt;, &lt;/span&gt;미소&lt;span&gt;, &lt;/span&gt;남성&lt;span&gt;, &lt;/span&gt;안경 등 여러 도메인을 컨트롤 하여 원하는 모습의 캐릭터를 만들 수 있다&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;532&quot; data-origin-height=&quot;259&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zlxBr/btr0nT8Glfn/KL1yPlsBVTG3PrIUwOEdL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zlxBr/btr0nT8Glfn/KL1yPlsBVTG3PrIUwOEdL0/img.png&quot; data-alt=&quot;&amp;amp;lt;그림&amp;amp;amp;nbsp;2&amp;amp;gt; Toonify의&amp;amp;amp;nbsp;emoji기술 (출처: bizsquare.info)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zlxBr/btr0nT8Glfn/KL1yPlsBVTG3PrIUwOEdL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzlxBr%2Fbtr0nT8Glfn%2FKL1yPlsBVTG3PrIUwOEdL0%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;532&quot; height=&quot;259&quot; data-origin-width=&quot;532&quot; data-origin-height=&quot;259&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;&amp;lt;그림&amp;amp;nbsp;2&amp;gt; Toonify의&amp;amp;nbsp;emoji기술 (출처: bizsquare.info)&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;(&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span&gt;본론&lt;span&gt;3) Facial Expression&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Facial Expression&lt;/span&gt;&lt;span&gt;이란 얼굴의 표정이나 입모양 등을 변경하는 기법이다&lt;span&gt;. &lt;/span&gt;원본 영상에 해당하는 사람이 목표 영상에 해당하는 사람의 표정을 흉내 내도록 원본 영상을 변화시켜 새로운 이미지를 만들어낸다&lt;span&gt;. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;온라인 가계도 플랫폼인 마이헤리티지는 이 기술을 적용해 사진속 인물을 생동감 있게움직이는 영상으로 바꿔주는 &lt;span&gt;&amp;lsquo;&lt;/span&gt;딥 노스텔지어&lt;span&gt;&amp;rsquo; &lt;/span&gt;기능을 제공한다&lt;span&gt;. &lt;/span&gt;실제 사람이 촬영한 비디오를 바탕으로&lt;span&gt;, &lt;/span&gt;사진 속 인물이 어떻게 움직였는지 추정하는 원리로 기술을 구현했다&lt;span&gt;.&lt;span&gt;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;사용자는 먼저 떠나버린 가족&lt;span&gt;, &lt;/span&gt;이전에 만난 적 없는 조상이나 역사 속 인물의 생생한 모습을 볼 수 있다&lt;span&gt;. &lt;/span&gt;표정&lt;span&gt;, &lt;/span&gt;입모양&lt;span&gt;, &lt;/span&gt;그리고 얼굴 움직임에 따른 각도 변화까지 자연스럽게 구현 가능하다&lt;span&gt;. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;575&quot; data-origin-height=&quot;346&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UGrg9/btr0olw3AHF/UcNBPhLUsdyG864aFrKEU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UGrg9/btr0olw3AHF/UcNBPhLUsdyG864aFrKEU1/img.png&quot; data-alt=&quot;&amp;amp;lt;그림&amp;amp;amp;nbsp;3&amp;amp;gt;&amp;amp;amp;nbsp;딥 노스텔지어 (출처: MyHeritage.com)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UGrg9/btr0olw3AHF/UcNBPhLUsdyG864aFrKEU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUGrg9%2Fbtr0olw3AHF%2FUcNBPhLUsdyG864aFrKEU1%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;437&quot; height=&quot;263&quot; data-origin-width=&quot;575&quot; data-origin-height=&quot;346&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;&amp;lt;그림&amp;amp;nbsp;3&amp;gt;&amp;amp;nbsp;딥 노스텔지어 (출처: MyHeritage.com)&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;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;(&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span&gt;본론&lt;span&gt;4) Face Swap&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Face Swap &lt;/span&gt;&lt;span&gt;이란 서로 다른 얼굴을 가진 두 이미지에서 얼굴 부분만 교체하는 기술이다&lt;span&gt;. &lt;/span&gt;사람들이 일반적으로 생각하는 딥페이크가 바로 이것이다&lt;span&gt;. &lt;/span&gt;원리는 다음과 같다&lt;span&gt;. &lt;/span&gt;원본 이미지의 얼굴부분을 목표 이미지의 얼굴로 교체하여 원본 이미지를 변환&lt;/span&gt;&lt;span&gt;한다&lt;span&gt;. &lt;/span&gt;이 기술에는 심층 신경망의 한 유형인 오토인코더 방식이 사용되었다&lt;span&gt;. &lt;/span&gt;인코더는 이미지의 특징을 추출한다&lt;span&gt;. &lt;/span&gt;이때 원본 이미지와 목표 이미지의 인코더가 공유됨으로써 두 이미지의 공통된 특징&lt;span&gt;, &lt;/span&gt;예를 들어 눈&lt;span&gt;, &lt;/span&gt;코&lt;span&gt;, &lt;/span&gt;입의 위치가 학습된다&lt;span&gt;. &lt;/span&gt;디코더는 구별되어 있으므로 두 이미지 각각의 특성&lt;span&gt;, &lt;/span&gt;예를 들어 눈 모양&lt;span&gt;, &lt;/span&gt;입 크기 같은 정보가 학습된다&lt;span&gt;. &lt;/span&gt;이렇게 학습된 공유 인코더와 목표 이미지로 학습된 디코더를 이용해 얼굴을 바꿀 수 있다&lt;span&gt;. &lt;/span&gt;원본 이미지를 인코더를 거쳐 눈&lt;span&gt;, &lt;/span&gt;코&lt;span&gt;, &lt;/span&gt;입의 위치를 알아내고 디코더를 통해 그 위치에 목표 이미지의 이목구비를 삽입시킨다&lt;span&gt;. &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;626&quot; data-origin-height=&quot;483&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cgTuxo/btr0vcSTDty/HNRJZtlkMBuZPPMceIg0A1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cgTuxo/btr0vcSTDty/HNRJZtlkMBuZPPMceIg0A1/img.png&quot; data-alt=&quot;&amp;amp;lt;그림&amp;amp;amp;nbsp;4&amp;amp;gt;&amp;amp;amp;nbsp;오토인코더 (출처: Nguyen, Thanh Thi, et al.(2019), &amp;quot;Deep learning for deepfakes creation and detection.&amp;quot;)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cgTuxo/btr0vcSTDty/HNRJZtlkMBuZPPMceIg0A1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcgTuxo%2Fbtr0vcSTDty%2FHNRJZtlkMBuZPPMceIg0A1%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;442&quot; height=&quot;341&quot; data-origin-width=&quot;626&quot; data-origin-height=&quot;483&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;&amp;lt;그림&amp;amp;nbsp;4&amp;gt;&amp;amp;nbsp;오토인코더 (출처: Nguyen, Thanh Thi, et al.(2019), &quot;Deep learning for deepfakes creation and detection.&quot;)&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;과거엔 &lt;span&gt;Face Swap&lt;/span&gt;기술이 녹화를 마친 영상에 적용되었다&lt;span&gt;. &lt;/span&gt;하지만 기술이 발달함에 따라 얼굴 변환 속도가 빨라지면서 실시간으로 송출하는 영상에도 적용이 가능하게 됐다&lt;span&gt;. &lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;특히 이 기술에 가상인간을 접목시킨 산업이 활발히 이뤄지고 있다&lt;span&gt;. &lt;/span&gt;모니터속 가상인간이 사회를 보거나 뉴스 인터뷰이의 얼굴을 가상인물로 대체하는 등 생방송에서 이 기술이 적극적으로 활용되고 있다&lt;span&gt;. &lt;/span&gt;구체적인 사례를 보자&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;콘텐츠 마케팅 전시회 &lt;span&gt;&amp;lsquo;CMS 2022&amp;rsquo;&lt;/span&gt;에 가상인간 &lt;span&gt;&amp;lsquo;&lt;/span&gt;재인&lt;span&gt;&amp;rsquo;&lt;/span&gt;이 등장하였다&lt;span&gt;. &lt;/span&gt;재인은 앞서 소개한 기업 펄스나인이 만든 가상인물이다&lt;span&gt;. &lt;/span&gt;재인은 사회자 역할을 하며 위화감없이 매끄러운 진행을 이어나갔다&lt;span&gt;. &lt;/span&gt;행사장 맞은편 회의실에는 한 여성이 말을 하고 있고&lt;span&gt; face swap &lt;/span&gt;기술을 통해 실시간으로 여성의 얼굴이 재인의 얼굴로 바뀐다&lt;span&gt;. &lt;/span&gt;화면으로 봤을 땐 가상인간인지 실제 인간인지 분간이 어려울 정도로 자연스럽다&lt;span&gt;. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;505&quot; data-origin-height=&quot;456&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JVwnX/btr0nVk5KyL/dvpf8N3QB52zK1lDgGZ7fK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JVwnX/btr0nVk5KyL/dvpf8N3QB52zK1lDgGZ7fK/img.png&quot; data-alt=&quot;&amp;amp;lt;그림&amp;amp;amp;nbsp;5&amp;amp;gt;&amp;amp;amp;nbsp;가상인간 재인 (출처:&amp;amp;amp;nbsp;안하늘, 2022.09.08, m.hankookilbo.com)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JVwnX/btr0nVk5KyL/dvpf8N3QB52zK1lDgGZ7fK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJVwnX%2Fbtr0nVk5KyL%2Fdvpf8N3QB52zK1lDgGZ7fK%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;355&quot; height=&quot;321&quot; data-origin-width=&quot;505&quot; data-origin-height=&quot;456&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;&amp;lt;그림&amp;amp;nbsp;5&amp;gt;&amp;amp;nbsp;가상인간 재인 (출처:&amp;amp;nbsp;안하늘, 2022.09.08, m.hankookilbo.com)&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;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;(&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span&gt;본론&lt;span&gt;5) &lt;/span&gt;딥페이크 악용 사례&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;앞서 소개한 사례들을 보면 딥페이크는 여러 분야에 활용되고 있다&lt;span&gt;. &lt;/span&gt;하지만 모든 기술이 그러하듯 항상 좋은 목적으로 사용되는 건 아니다&lt;span&gt;. &lt;/span&gt;여러 딥페이크 기술 중에서도 특히 &lt;span&gt;Facial Expression&lt;/span&gt;과 &lt;span&gt;Face Swap&lt;/span&gt;에서 악용사례가 빈번히 발생하고 있다&lt;span&gt;. &lt;/span&gt;실제 하지 않은 말이나 행동을 한 것처럼 영상을 조작해 유포하거나 그것을 악용하는 범죄가 증가하고 있다&lt;span&gt;. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이제는 보이스 피싱이 아닌 딥페이크 피싱이 도래하고 있다&lt;span&gt;. &lt;/span&gt;딥페이크로 가족&lt;span&gt;, &lt;/span&gt;지인을 사칭하면 피해자는 완전히 속을 수밖에 없다&lt;span&gt;. 2019&lt;/span&gt;년 유럽의 한 기업 &lt;span&gt;CEO&lt;/span&gt;가 모 기업 회장을 딥페이크로 모방한 범죄자에게 속아 &lt;span&gt;22&lt;/span&gt;만 유로를 송금하는 피해를 입었다&lt;span&gt;. 2021&lt;/span&gt;년 &lt;span&gt;A&lt;/span&gt;국에서는 범죄조직이 정부에서 운영하는 안면 인식 시스템을 딥페이크 기술로 속이는 방식으로 가짜 세금계산서를 발행해 세금을 탈루하려다 적발되었다&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;딥페이크를 이용하여 대통령이나 유명 연예인 등 사회적 영향력이 큰 인물이 등장하는 가짜 뉴스 문제도 심각하다&lt;span&gt;. &lt;/span&gt;선거철에는 후보자들의 가짜 영상이 돌아다니며 대선판을 뒤흔들고 가짜 뉴스는 정치적&lt;span&gt;, &lt;/span&gt;사회적&lt;span&gt;, &lt;/span&gt;경제적으로 큰 혼란을 야기할 수 있다&lt;span&gt;. &lt;/span&gt;예시로 &lt;span&gt;2022&lt;/span&gt;년 &lt;span&gt;3&lt;/span&gt;월&lt;span&gt;, &lt;/span&gt;우크라이나 대통령이 항복을 선언하는 가짜 영상이 우크라이나 뉴스 사이트에 공개되어 국제적인 혼란을 일으켰다&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;음란물에 연예인 또는 아동&lt;span&gt;, &lt;/span&gt;청소년 얼굴을 합성한 &lt;span&gt;&amp;lsquo;&lt;/span&gt;딥페이크 성적 허위 영상물&lt;span&gt;&amp;rsquo; &lt;/span&gt;유포 문제도 심각하다&lt;span&gt;. &lt;/span&gt;네덜란드의 사이버 보안회사 센시티의 조사에 따르면 &lt;span&gt;2019&lt;/span&gt;년 기준 전 세계 딥페이크 영상 중 성인물이 &lt;span&gt;96%&lt;/span&gt;에 이른다는 통계가 나왔다&lt;span&gt;. &lt;/span&gt;국내에선 &lt;span&gt;2022&lt;/span&gt;년 딥페이크 음란물을 합성하고 텔레그램 채팅방을 통해 판매한 &lt;span&gt;30 &lt;/span&gt;대 남성 &lt;span&gt;A &lt;/span&gt;씨가 검찰에 송치됐다&lt;span&gt;. &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&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;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;(&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span&gt;본론&lt;span&gt;6) &lt;/span&gt;딥페이크 탐지 기술&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;딥페이크 악용을 막기 위해 여러 기관에서 딥페이크를 탐지하는 &lt;span&gt;AI&lt;/span&gt;에 대한 연구가 진행중이다&lt;span&gt;. UCR&lt;/span&gt;의 연구팀은 변경된 이미지 내의 특정 영역을 감지하고 지역화할 수 있는 얼굴 표정 조작 감지&lt;span&gt;(EMD) &lt;/span&gt;프레임워크를 구축했다&lt;span&gt;. &lt;/span&gt;인텔은 심장이 혈액을 내보낼 때 정맥의 색이 변하는 점을 이용하여&lt;span&gt;, &lt;/span&gt;원본 영상에서 얼굴의 혈류 신호를 수집하고 시공간 지도로 변환시켜 딥러닝을 통해 영상의 진위를 판단하는 탐지기를 개발하였다&lt;span&gt;. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&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;b&gt;&lt;span&gt;(&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span&gt;결론&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;딥페이크 기술에는 &lt;/span&gt;&lt;span&gt;Face Synthesis,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Facial attributes,&lt;/span&gt;&lt;span&gt; Facial Expression, Face Swap&lt;/span&gt;&lt;span&gt;가 있고 이들의 원리와 사례에 대해 알아봤다&lt;span&gt;. &lt;/span&gt;딥페이크는 눈을 감을 사진을 뜨게 할 수 있고 역사속 인물 사진에 생동감을 주는 등 여러 분야에 사용되고 있다&lt;span&gt;. &lt;/span&gt;이렇게 딥페이크는 새로운 산업을 열었지만 가짜 뉴스나 금융 사기 등 악용 사례가 발생하고 있다&lt;span&gt;. &lt;/span&gt;이 문제점을 해결하기 위해 여러 기관에서 딥페이크 탐지 기술을 연구하고 있다&lt;span&gt;. &lt;/span&gt;따라서 딥페이크 기술을 무작정 수용하는 것 보단&lt;span&gt;, &lt;/span&gt;그것의 양면성에 유의하며 비판적으로 받아들일 필요가 있다&lt;span&gt;. &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&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&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;(&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;참고문헌&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;강진규&lt;span&gt;(2021.11.29), &lt;/span&gt;커지는 딥페이크 보이스피싱 우려&lt;span&gt;...&lt;/span&gt;경고 잇따라&lt;span&gt;, &lt;/span&gt;디지털투데이&lt;span&gt;(digitaltoday.co.kr, 2022.11.18.&lt;/span&gt;오전 &lt;span&gt;2&lt;/span&gt;시 &lt;span&gt;39&lt;/span&gt;분 접속&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;공감언론 뉴시스&lt;span&gt;(2022.04.06), &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;a href=&quot;https://newsis.com/view/?id=NISX20220406_0001822765&amp;amp;cID=10101&amp;amp;pID=10100&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;친러&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;해커, '&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;젤렌스키&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;항복' &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;가짜&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;영상&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;송출&amp;hellip;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;우크라&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;언론&amp;middot;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;기관&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;신뢰&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;저하&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;의도&quot;, &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;공감언론&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;뉴시스통신사(newsis.com,2022.11.18.&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;오전&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt; 2&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;시&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt; 41&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;분&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;접속)&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;김전은&lt;span&gt;(2021.03.03), &quot;&lt;/span&gt;오래된 스틸 사진에 생동감을&lt;span&gt;&quot;....AI &lt;/span&gt;기술로 탄생&lt;span&gt;, &lt;/span&gt;인터넷신문위원회&lt;span&gt;(thedailypost.kr, 2022.11.18.&lt;/span&gt;오전 &lt;span&gt;2&lt;/span&gt;시 &lt;span&gt;37&lt;/span&gt;분 접속&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;김정완&lt;span&gt;(2022.11.17), &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;a href=&quot;https://view.asiae.co.kr/article/2022111609585983938&quot;&gt;&lt;span&gt;&amp;lsquo;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;남의&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;얼굴에&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;음란물을&amp;hellip;&amp;rsquo; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;딥페이크&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;피해&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;느는데, &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;아시아경제 (asiae.co.kr, 2022.11.18.&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;오전 2&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;시 43&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;분&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;접속)&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;김정호&lt;span&gt;, &lt;/span&gt;안재주&lt;span&gt;, &lt;/span&gt;양보성&lt;span&gt;, &lt;/span&gt;정주연&lt;span&gt;, &lt;/span&gt;우사이먼성일 &lt;span&gt;(2020), &lt;/span&gt;데이터 기반 딥페이크 탐지기법에 관한 최신 기술 동향 조사&lt;span&gt;, &lt;/span&gt;정보보호학회지&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;박찬&lt;span&gt;(2022.05.09), &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;a href=&quot;http://www.aitimes.com/news/articleView.html?idxno=144482&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;ldquo;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;다&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;걸렸어&amp;rdquo;...99% &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;딥페이크&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;탐지하는 AI &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;기술, AI&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;타임스 (aitimes.com, 2022.11.18.&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;오전 2&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;시 47&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;분&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;접속 )&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;u&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;안하늘&lt;span&gt;(2022.09.08), &lt;/span&gt;얼굴&lt;span&gt; 100&lt;/span&gt;만개&lt;span&gt;&amp;middot;&lt;/span&gt;표정&lt;span&gt; 1500&lt;/span&gt;장이 만든 가상인간&lt;span&gt;...&quot;Z&lt;/span&gt;세대 마음 얻어야 살아 남아&lt;span&gt;&quot;, &lt;/span&gt;한국일보&lt;span&gt;(hankookilbo.com, 2022.11.18.&lt;/span&gt;오전 &lt;span&gt;2&lt;/span&gt;시 &lt;span&gt;31&lt;/span&gt;분 접속&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;윤희일&lt;span&gt;(2022.05.09), &lt;/span&gt;실제같은 가짜&lt;span&gt; '&lt;/span&gt;딥페이크&lt;span&gt;'&lt;/span&gt;의 세계 완전해부&lt;span&gt;...AI &lt;/span&gt;세상의 새로운 게임체인저&lt;span&gt;?, &lt;/span&gt;경향신문&lt;span&gt; (khan.co.kr, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;a href=&quot;https://view.asiae.co.kr/article/2022111609585983938&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2022.11.18.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;오전 2&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;시 45&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;분&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;접속)&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;이동재&lt;span&gt;(2022.11.16), &lt;/span&gt;인텔&lt;span&gt;, &lt;/span&gt;딥페이트 가짜 동영상 탐지 기술 공개&lt;span&gt;...&lt;/span&gt;정확도&lt;span&gt; 96% &lt;/span&gt;기록&lt;span&gt;, &lt;/span&gt;헬로&lt;span&gt;T (hellot.net, 2022.11.18.&lt;/span&gt;오전&lt;span&gt; 2&lt;/span&gt;시&lt;span&gt; 49&lt;/span&gt;분 접속&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;장기헌&lt;span&gt;(2020), &lt;/span&gt;머신러닝 기반의 얼굴 변환 시스템 구현 및 연구&lt;span&gt;, p.6~9&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;-Brian Dolhansky, Cristian Canton Ferrer (2017), Eye In-Painting with Exemplar Generative Adversarial Networks, p.1~4&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;-Nguyen, Thanh Thi, et al (2019), Deep learning for deepfakes creation and detection, p. 3&lt;/span&gt;&lt;/a&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>AIML/배경지식</category>
      <author>ji._.ye</author>
      <guid isPermaLink="true">https://jjiye716.tistory.com/9</guid>
      <comments>https://jjiye716.tistory.com/9#entry9comment</comments>
      <pubDate>Thu, 23 Feb 2023 03:03:55 +0900</pubDate>
    </item>
  </channel>
</rss>