<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.0">Jekyll</generator><link href="https://hwanjong.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://hwanjong.github.io/" rel="alternate" type="text/html" /><updated>2022-02-07T18:54:10+00:00</updated><id>https://hwanjong.github.io/feed.xml</id><title type="html">HJ Software Co.</title><subtitle>An amazing website.</subtitle><author><name>Hwanjong(Leader)</name></author><entry><title type="html">Welcome to Hwanjong Blog!</title><link href="https://hwanjong.github.io/jekyll/first-post/" rel="alternate" type="text/html" title="Welcome to Hwanjong Blog!" /><published>2021-10-19T12:26:28+00:00</published><updated>2021-10-19T12:26:28+00:00</updated><id>https://hwanjong.github.io/jekyll/first-post</id><content type="html" xml:base="https://hwanjong.github.io/jekyll/first-post/">&lt;p&gt;You’ll find this post in your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_posts&lt;/code&gt; directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jekyll serve&lt;/code&gt;, which launches a web server and auto-regenerates your site when a file is updated.&lt;/p&gt;

&lt;p&gt;To add new posts, simply add a file in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_posts&lt;/code&gt; directory that follows the convention &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;YYYY-MM-DD-name-of-post.ext&lt;/code&gt; and includes the necessary front matter. Take a look at the source for this post to get an idea about how it works.&lt;/p&gt;

&lt;p&gt;Jekyll also offers powerful support for code snippets:&lt;/p&gt;

&lt;p&gt;​&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python
def print_hi(name):
  print(&quot;hello&quot;, name)
print_hi('Tom')
​&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Check out the &lt;a href=&quot;https://jekyllrb.com/docs/home&quot;&gt;Jekyll docs&lt;/a&gt; for more info on how to get the most out of Jekyll. File all bugs/feature requests at &lt;a href=&quot;https://github.com/jekyll/jekyll&quot;&gt;Jekyll’s GitHub repo&lt;/a&gt;. If you have questions, you can ask them on &lt;a href=&quot;https://talk.jekyllrb.com/&quot;&gt;Jekyll Talk&lt;/a&gt;.&lt;/p&gt;</content><author><name>Hwanjong(Leader)</name></author><category term="jekyll" /><category term="blog" /><summary type="html">You’ll find this post in your _posts directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run jekyll serve, which launches a web server and auto-regenerates your site when a file is updated.</summary></entry><entry><title type="html">JPA vs Mybatis</title><link href="https://hwanjong.github.io/backend/JPA/" rel="alternate" type="text/html" title="JPA vs Mybatis" /><published>2021-10-19T04:26:28+00:00</published><updated>2021-10-19T04:26:28+00:00</updated><id>https://hwanjong.github.io/backend/JPA</id><content type="html" xml:base="https://hwanjong.github.io/backend/JPA/">&lt;h1 id=&quot;jpa-java-persistence-api&quot;&gt;JPA (Java Persistence API)&lt;/h1&gt;
&lt;h2 id=&quot;1-jpa-란&quot;&gt;1. JPA 란?&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;JPA는 DB 작업을 객체 기반으로 다루는 &lt;strong&gt;&lt;em&gt;인터페이스 표준&lt;/em&gt;&lt;/strong&gt; 으로 관계형 데이터 베이스를 어떻게 사용해야하는지를 정의&lt;br /&gt;
  - Hibernate : JPA를 준수하여 구현한 JPA 구현체 라이브러리 (&lt;em&gt;by Hibernate 개발자&lt;/em&gt;)&lt;/p&gt;

    &lt;p&gt;- Spring Data JPA : Hibernate, JPA와 달리 Spring에서 제공하는 JPA 모듈이다.&lt;/p&gt;
    &lt;blockquote&gt;
      &lt;p&gt;&lt;em&gt;API&lt;/em&gt; : https://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/repository/JpaRepository.html&lt;/p&gt;
    &lt;/blockquote&gt;

    &lt;blockquote&gt;
      &lt;p&gt;&lt;em&gt;구현체&lt;/em&gt; : https://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/repository/support/SimpleJpaRepository.html&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;개념적으로 JPA는 JDBC와 Application 사이에 위치한다.&lt;br /&gt;
  JDBC - ORM - &lt;strong&gt;JPA&lt;/strong&gt; - Application&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;2-jpa의-장점&quot;&gt;2. JPA의 장점&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Hibernate가 JPA의 구현체&lt;/em&gt;&lt;/strong&gt;&lt;br /&gt;
1) 객체 지향적 DB 접근&lt;br /&gt;
2) 성능 최적화 기능&lt;br /&gt;
    - 조회 시 캐싱 지원 (같은 트랙잭션 안에서)&lt;br /&gt;
    - INSERT 버퍼링 기능 (같은 트랜잭션 안에서)&lt;br /&gt;
    - 지연로딩, 즉시로딩 옵션화&lt;/p&gt;
&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memberDAO&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memberId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Team&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;team&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getTeam&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;team&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//값이 필요한 시점에 한번만 SELECT 수행&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;3-jpa의-단점---mybatis와-비교&quot;&gt;3. JPA의 단점 - Mybatis와 비교&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;SQL에 대한 모든 컨트롤을 하고자 할때 적절하지 않음.&lt;/li&gt;
  &lt;li&gt;SQL을 최적화해야할 때 적절하지 않음.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;4-결론&quot;&gt;4. 결론&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;JPA는 Mybatis에 비해 어렵지만 객체 지향적인 DB 작업가능.&lt;/li&gt;
  &lt;li&gt;Hibernate 구현체가 아니더라도 Spring Data JPA 와 같은 인터페이스와 함께 별도 구현체를 더해서 사용도 가능.&lt;/li&gt;
  &lt;li&gt;대규모 시스템에서 데이터 엔지니어(또는 DA)와 협업이 필요할 경우 적합하지 않음&lt;br /&gt;
  ex) Native 쿼리를 자주 사용해야하는 경우&lt;br /&gt;
  ex) Hint index를 넣어야 하는 경우&lt;/li&gt;
  &lt;li&gt;SQL 의존도가 낮은 시스템에서 비교적 유용.&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;생각해볼-문제-study-item&quot;&gt;생각해볼 문제 (Study Item)&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;JPA를 사용할 경우 복잡한 쿼리는(outer, multiple join) 어떻게 해결할지?&lt;br /&gt;
  ☞ Join 할 Object를 지정해주는 방식. (N+1 문제 발생)
    &lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;nd&quot;&gt;@ManyToOne&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fetch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FetchType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;LAZY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@JoinColumn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;wedul_classes_id&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@JsonBackReference&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;WedulClasses&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wedulClasses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;☞ native left fetch join, EntityGraph 이용 (비효율…)&lt;br /&gt;
  &lt;strong&gt;☞ QueryDSL이 SQL과 같은 쿼리를 인터페이스를 통해 사용할 수 있게 해준다.&lt;/strong&gt;&lt;/p&gt;
    &lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;WedulClasses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;findAllWithStudent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nc&quot;&gt;QWedulClasses&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wedulClasses&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;QWedulClasses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;wedulClasses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;nc&quot;&gt;QWedulStudent&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wedulStudent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;QWedulStudent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;wedulStudent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wedulClasses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;leftJoin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wedulClasses&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;wedulStudentList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wedulStudent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;fetchJoin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;distinct&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;blockquote&gt;
      &lt;p&gt;&lt;em&gt;참고 블로그 : https://wedul.site/638&lt;/em&gt;&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;프로시저, Hint, Index 등을 쿼리에 강제로 넣어야하는 경우는 어떻게 해야하는가?&lt;br /&gt;
  ☞ Native SQL query 필요
    &lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;JPA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;createNativeQuery&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&quot;select * from transaction with (INDEX(_dta_index_k1_1)) ...&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;Transaction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getResultList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;JPA 라이브러리에서 Transaction 내부 실행 순서를 관리하는데, 의도하지 않은 문제나 성능 튜닝이 필요하지는 않을지?&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Spring Data JPA와 Hibernate 둘다 동일하게 where 조건을 함수명으로하여 자동으로 쿼리 생성하는지?&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;5-query-dsl--fetch-join&quot;&gt;5. Query DSL &amp;amp; Fetch Join&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;복잡한 쿼리(Multiple Join, 조건) 및 N+1 문제 등의 JPA의 한계를 극복하기 위한 라이브러리&lt;/li&gt;
  &lt;li&gt;가장 큰 장점으로 개발자는 비지니스 로직에만 집중할 수 있어 복잡한 Join 및 조건 처리도 Code로 빠르게 쿼리를 작성할 수 있다.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;생각해볼 내용 :
1) 복잡한 Query나 DBA와 작성한 Query의 경우 Query를 코드로 Migration이 필요하다. (쿼리와 불일치 가능성 존재)
2) DB Scheme 나 기존 쿼리가 변경될 경우 관련 Java 코드를 수정해야한다.
3) 컴파일 시점에 에러가 확인되므로 변경사항에 대한 코드 개발이 어렵다.
4) 쿼리 계획을 JPA가 하므로 DBMS 성능에 대한 이슈가 생길 수 있다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;※ Query DSL 예시 1&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;JPAQueryFactoryquery&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;JPAQueryFactory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;em&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;QMemberm&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;QMember&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;QTeamt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;QTeam&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;team&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;​&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;selectFrom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;team&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;eq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;teamA&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
         &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;※ Query DSL 예시 2&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;※ Fetch Join (N+1 문제 해결) 예시&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;SQL 에서 사용하는 개념이아닌 JPQL에서 사용한다. JPQL의 한계를 극복하기 위한 Join 기법이다.
    &lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;Select&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Member&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;join&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fetch&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;team&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p&gt;얼핏 보면 SQL과 유사해보이는데 차이점이 있다.
우선 첫 번째는, join 뒤에 fetch가 붙는다.
그리고 프로젝션에 m(Member)만 존재한다. (이 부분이 매우 중요)&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;위 JQPL은 아래의 SQL로 변역된다.&lt;/p&gt;
&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;no&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.*,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.*&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;MEMBER&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;M&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;INNER&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;JOIN&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;TEAMT&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ON&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;TEAM_ID&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ID&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;blockquote&gt;
  &lt;p&gt;즉, Fetch Join의 목적은 관계 있는 Entity를 한 방에 가져오는데 그 목적이 있다.
즉, Fetch Join은 지연로딩을 하지 않고 즉시 로딩(EAGER)로 가져오는 쿼리이다.
가령 N명의 멤버는 1개의 팀을 가질 수 있다는 다대일 관계를 생각해보자.
여기서 N명의 멤버를 가져오기위한 쿼리가 발생할 것이고,
이후 각 멤버는 팀을 프록시 객체로 받아온 뒤 프록시 객체의 값에 접근하려고 할 때 실제 쿼리를 날려서 팀의 정보를 가져오게 된다.
문제는 이 때, N명의 멤버가 모두 각기 다른 팀을 가진다고 가정하면 1명의 멤버마다 그 멤버가 소속된 팀의 쿼리가 나아갈 것이고 (1차캐시가 안될거니까) 이것이 우리가 흔히 말하는 N+1 문제가 발생하게 되는 원인이다.
사실 이러한 N+1 문제는 지연로딩이든 즉시로딩이든 발생하는 문제인데, 이를 해결하는 방법 중 하나가 바로 JPQL의 Fetch Join이다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;참조 : https://sloth.tistory.com/m/13&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;6-서비스-특성-별-쿼리-특징&quot;&gt;6. 서비스 특성 별 쿼리 특징&lt;/h1&gt;

&lt;p&gt;JPA, Query DSL이 안좋다고 생각하는 것은 아니다.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;반복적인 CRUD에서 자유로워 진다.&lt;/li&gt;
  &lt;li&gt;실시간 처리가 많거나 스키마가 비즈니스 로직과 연결되는 서비스에서는 코드 기반으로 빠른 개발이 가능하다.&lt;/li&gt;
  &lt;li&gt;객체 지향과 RDBMS를 연결할 때 서로의 패러다임의 차이를 줄이려는 시도.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;JPA, Query DSL은 분명 장점이 많고 효율적인 코드 작성이 가능한 훌륭한 도구이다. &lt;strong&gt;JPA가 유리한 서비스와 유리한 팀이 있다.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;그렇기 때문에 JPA, Query DSL에 대해서 잠깐 공부해보자.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Query DSL 공식 레퍼런스 : https://querydsl.com/static/querydsl/4.0.1/reference/ko-KR/html_single/#d0e1450&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;느낌은 너무 방대한 양이다. 패러다임 불일치를 극복하고 복잡한 쿼리까지 해결하려고 대단한 정성을 들여 만든 라이브러리 느낌이다. 이를 공부해야하는 개발자도 대단한 정성이 필요하다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;☞ 쿼리를 사용하지 않으려다가 더 많은 학습과 개발이 필요하고 필연적인 유지보수 여려움 및 DB 성능상의 문제가 생길 수 있음&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;☞ 서비스가 커지고 고도화 될 수록 JPA로 인한 코드양이 늘어나게 되고 의존성이 커지게 된다. Native Query를 사용해야하는 경우가 증가하고 결국 Native Query와 JPA를 함께 사용해야한다.&lt;/strong&gt;&lt;/p&gt;

&lt;h1 id=&quot;7-software-아키텍쳐-및-clean-code-관점&quot;&gt;7. Software 아키텍쳐 및 Clean Code 관점&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;코드가 Query DSL에 의존하게된다.&lt;/li&gt;
  &lt;li&gt;스키마나 쿼리 변경사항이 생기면 코드를 변경해야한다.&lt;/li&gt;
  &lt;li&gt;Query DSL 코드가 점점 복잡해지고 길어져서 수정하기 어렵다.&lt;/li&gt;
  &lt;li&gt;EntityManager와 Transaction등의 내부 동작이 있기 때문에 상세히 제어가 어렵다.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;☞ 코드와 쿼리의 분리 필요.&lt;/strong&gt;
&lt;strong&gt;☞ 더 나아가서는 복잡한 쿼리는 프로시저로 만들고 서로 영향성이 없도록 관리하며 사용하는 방법이 유리.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ORM은 꼭 필요한 도구이므로 Hibernate, Mybatis를 ORM 목적으로 사용하고, 서비스의 구조와 방향에 적합한 라이브러리를 검토하여 사용하는 것이 우선되어야 한다.&lt;/strong&gt; » 장기적으로 볼 때 ORM으로만 사용하는 것이 좋을 것 같다.&lt;/p&gt;</content><author><name>Hwanjong(Leader)</name></author><category term="backend" /><category term="spring" /><category term="java" /><category term="jpa" /><summary type="html">JPA (Java Persistence API) 1. JPA 란? JPA는 DB 작업을 객체 기반으로 다루는 인터페이스 표준 으로 관계형 데이터 베이스를 어떻게 사용해야하는지를 정의 - Hibernate : JPA를 준수하여 구현한 JPA 구현체 라이브러리 (by Hibernate 개발자)</summary></entry></feed>