<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>charmdong.log</title>
        <link>https://velog.io/</link>
        <description>자유롭고 싶은 개발자</description>
        <lastBuildDate>Fri, 07 Jan 2022 02:05:11 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>charmdong.log</title>
            <url>https://images.velog.io/images/dev_donggun/profile/7fc90bd4-4d0e-4983-a1bf-c366516b2a3a/프사2.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. charmdong.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/dev_donggun" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Persistence Context]]></title>
            <link>https://velog.io/@dev_donggun/persistence-context</link>
            <guid>https://velog.io/@dev_donggun/persistence-context</guid>
            <pubDate>Fri, 07 Jan 2022 02:05:11 GMT</pubDate>
            <description><![CDATA[<h2 id="1-영속성-컨텍스트의-특징"><strong>1. 영속성 컨텍스트의 특징</strong></h2>
<p>1. 식별자 값</p>
<blockquote>
<p>영속성 컨텍스트는 엔티티를 <strong>식별자 값(@Id로 테이블의 기본 키와 매핑한 값)으로 구분</strong>한다. 그러므로 영속 상태에 있는 엔티티는 반드시 식별자 값을 가져야 한다.</p>
</blockquote>
<p>2. 데이터베이스 저장</p>
<blockquote>
<p>JPA는 보통 Transaction을 <strong>commit</strong>하는 순간 <strong>영속성 컨텍스트에 새로 저장된 엔티티를 데이터베이스에 반영</strong>하며, 이를 <strong>Flush</strong>라고 한다.</p>
</blockquote>
<p>3. 장점</p>
<ul>
<li>1차 캐시</li>
<li>동일성 보장</li>
<li>Transaction을 지원하는 쓰기 지연</li>
<li>변경 감지</li>
<li>지연 로딩</li>
</ul>
<h2 id="2-entity-조회"><strong>2. Entity 조회</strong></h2>
<p>영속성 컨텍스트(PC, Persistence Context)는 내부에 <strong>1차 캐시</strong>를 가지고 있어 <strong>영속 상태의 엔티티가 모두 이곳에 저장</strong>된다. PC안에 [Key: @Id로 매핑된 식별자, Value: 엔티티 인스턴스] 구조로 된 Map이 존재한다.</p>
<pre><code>// 엔티티 생성 - 비영속
Member member = new Member();
member.setId(&quot;member1&quot;);
member.setName(&quot;donggun&quot;);

// 엔티티 영속 상태
em.persist(member);</code></pre><p>위 코드를 실행하게 되면 1차 캐시에 member 엔티티를 저장하게 된다. 이 엔티티는 아직 데이터베이스에 저장되지는 않는다.</p>
<p>1차 캐시의 Key는 식별자 값이다. 이 <strong>식별자 값은 데이터베이스 기본 키와 매핑</strong>된다. 따라서 PC에 데이터를 저장하고 조회하는 모든 기준은 DB의 기본 키 값이다.</p>
<pre><code>Member member = em.find(Member.class, &quot;member1&quot;);</code></pre><p>find() 메소드의 첫 번째 전달인자는 엔티티 클래스의 타입이고,  두 번째 전달인자는 조회하고자 하는 엔티티의 식별자 값이다. </p>
<p><strong>find() 호출 시 동작 과정</strong></p>
<blockquote>
<p>1. 1차 캐시에서 식별자 값을 기반으로 엔티티를 탐색한다.<br>2. 1차 캐시에 찾는 엔티티가 존재하지 않는다면 데이터베이스에서 조회한다.  </p>
<p><strong>데이터베이스에서의 조회</strong><br>1. 찾고자 하는 엔티티가 1차 캐시에 존재하지 않으면 엔티티 매니저는 DB를 조회해 엔티티를 생성한다. <br>2. 이렇게 생성된 엔티티를 1차 캐시에 저장하고, 영속 상태의 엔티티를 반환한다.</p>
</blockquote>
<p><strong>영속 엔티티의 동일성 보장</strong></p>
<pre><code>Member memberA = em.find(Member.class, &quot;member1&quot;);
Member memberB = em.find(Member.class, &quot;member1&quot;);

// 동일성 비교
System.out.println(memberA == memberB);</code></pre><p>위 코드를 실행해보면 True가 출력될 것이다. 그 이유는 find() 메소드를 반복해서 호출하더라도 PC는 <strong>1차 캐시에 있는 동일한 인스턴스를 반환</strong>하기 때문이다. 따라서 PC는 성능상의 이점과 엔티티의 동일성을 보장하게 된다.</p>
<h2 id="3-entity-등록"><strong>3. Entity 등록</strong></h2>
<pre><code>EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();

// 데이터 변경 시에는 엔티티 매니저가 트랜잭션을 시작한다.
tx.begin();

em.persist(memberA);
em.persist(memberB);
// 여기까지 INSERT SQL를 DB에 보내지 않는다.

// 커밋을 하는 순간 INSERT SQL을 전송한다.
tx.commit();</code></pre><p>엔티티 매니저는 트랜잭션을 커밋하기 직전까지 DB에 엔티티를 저장하지 않고 내부 쿼리 저장소에 INSERT SQL을 모아둔다. 이후 트랜잭션 커밋을 할 때 모아두었던 쿼리를 DB에 보낸다. 이를 Transactional write-behind, 트랜잭션을 지원하는 <strong>쓰기 지연</strong>이라고 한다.</p>
<p><strong>쓰기 지연 과정</strong></p>
<blockquote>
<p>1. memberA를 영속화 한다. (em.persist)<br>2. PC는 1차 캐시에 엔티티를 저장하면서 동시에 엔티티 정보로 INSERT SQL을 생성한다.<br>3. 생성된 INSERT SQL을 PC 내부의 쓰기 지연 SQL 저장소에 보관한다.<br>4. 트랜잭션을 커밋하면 엔티티 매니저가 PC를 Flush한다. (Flush는 PC의 변경 내용(등록, 수정, 삭제)을 DB에 동기화하는 작업을 말한다.) 간단하게 말해서, PC 내부의 쓰기 지연 SQL 저장소에 모아둔 쿼리를 DB로 전송한다.<br>5. PC의 변경 내용을 DB에 동기화한 후, 실제 DB Transaction을 커밋한다.  </p>
<p>이렇게 쓰기 지연이 가능한 이유는, 등록 쿼리가 생성될 때마다 전송하더라도 DB 트랜잭션이 일어나지 않으면 소용이 없기 때문이다.</p>
</blockquote>
<h4 id="예외">예외</h4>
<blockquote>
<p><mark style="background-color:lightblue;"><strong>IDENTITY 전략</strong></mark>을 사용해 기본 키를 할당하는 경우에는 <mark style="background-color:lightblue;">쓰기 지연이 동작하지 않는다.</mark></p>
<ul>
<li>엔티티가 영속 상태가 되려면 식별자가 반드시 필요하다. IDENTITY 식별자 생성 전략은 엔티티를 데이터베이스에 저장해야 식별자를 구할 수 있으므로 <mark style="color:;">*<em>em.persist()를 호출하는 즉시 INSERT SQL이 데이터베이스에 전달된다. *</em></mark></li>
</ul>
</blockquote>
<h2 id="4-entity-수정"><strong>4. Entity 수정</strong></h2>
<p><strong>변경 감지</strong></p>
<pre><code>EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();

// 트랜잭션 시작
tx.begin();

// 영속 상태 엔티티 조회
Member memberA = em.find(Member.class, &quot;memberA&quot;);

// 엔티티 데이터 수정
memberA.setName(&quot;hello&quot;);
memberA.setAge(25);

// 트랜잭션 커밋
tx.commit();</code></pre><p>JPA로 엔티티의 데이터를 수정할 때는 단순하게 엔티티를 <strong>조회</strong>한 뒤 원하는 데이터를 수정하기만 하면 된다. 왜냐? 엔티티의 변경사항을 DB에서 자동으로 반영하는 <strong>변경 감지</strong>라는 기능 덕분에 가능하다.</p>
<p>JPA는 PC에 엔티티를 보관할 때, 최초의 상태를 복사해 저장하는데, 이를 <strong>스냅샷</strong>이라고 한다. 엔티티의 수정 과정은 다음과 같다.</p>
<blockquote>
<p>1. 트랜잭션을 커밋하면 엔티티 매니저 내부에서 먼저 flush()가 호출된다.<br>2. 엔티티와 스냅샷을 비교하여 변경된 엔티티를 탐색한다.<br>3. 변경된 엔티티가 존재하면 UPDATE 쿼리를 생성해서 쓰기 지연 SQL 저장소에 전송한다.<br>4. 쓰기 지연 SQL 저장소의 SQL을 DB에 전송한다.<br>5. DB 트랜잭션을 커밋한다.</p>
</blockquote>
<p>위 과정에서 보듯이, 스냅샷과 현재 엔티티를 비교하기 때문에 <strong>변경 감지는 PC가 관리하는 영속 상태의 엔티티에만 적용</strong>된다. </p>
<p>JPA는 기본적으로 변경 사항이 존재한다면 엔티티의 모든 필드를 업데이트 하는데, 이는 데이터 전송량이 증가하는 단점이 존재하지만 여러 장점이 존재해 모든 필드를 업데이트 한다.</p>
<blockquote>
<p>1. 모든 필드를 사용하면 수정 쿼리가 항상 동일하다. 이로 인해 애플리케이션 로딩 시점에 수정 쿼리를 미리 생성해두고 재사용할 수 있다.<br>2. DB에 동일한 쿼리를 전송하면 DB는 이전에 파싱된 쿼리를 재사용할 수 있다.</p>
</blockquote>
<p>하지만 필드가 너무 많거나 저장되는 내용의 크기가 크다면 수정된 데이터만 업데이트 하도록 동적으로 UPDATE SQL을 생성해서 사용할 수도 있다. 이때는 엔티티 클래스에 <strong>@org.hibernate.annotations.DynamicUpdate</strong> 어노테이션을 추가해주면 수정된 데이터만 동적으로 UPDATE 쿼리를 생성한다.</p>
<h2 id="5-entity-삭제"><strong>5. Entity 삭제</strong></h2>
<p>엔티티를 삭제하기 위해서는 Entity 수정때와 같이 <strong>먼저 조회를 해야한다</strong>. </p>
<pre><code>// 1. 엔티티 조회
Member memberA = em.find(Member.class, &quot;memberA&quot;);

// 2. 엔티티 제거
em.remove(memberA);</code></pre><p>em.remove()를 호출한다고 해서 바로 엔티티가 삭제되는 것은 아니다. 엔티티 등록과 비슷하게 DELETE SQL을 쓰기 지연 저장소에 등록한 뒤 트랜잭션 커밋을 통해 Flush가 호출되면 DB에 SQL이 전송된다. 단, remove()를 호출하는 순간에 삭제하고자 하는 엔티티는 PC로부터 제거된다. 즉, PC에서는 즉각 사라지지만 DB에서는 그렇지 않다는 것이다.</p>
<ul>
<li>참고 문헌: 자바 ORM 표준 JPA 프로그래밍 (김영한 지음)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Persistence Context와 Entity 생명주기]]></title>
            <link>https://velog.io/@dev_donggun/persistence-context-entity-lifecycle</link>
            <guid>https://velog.io/@dev_donggun/persistence-context-entity-lifecycle</guid>
            <pubDate>Fri, 07 Jan 2022 01:25:22 GMT</pubDate>
            <description><![CDATA[<h2 id="1-영속성-컨텍스트-persistence-context"><strong>1. 영속성 컨텍스트 (Persistence Context)</strong></h2>
<p><strong>Entity를 영구적으로 저장하는 공간 및 환경</strong>이라고 생각하면 된다. EM(Entity Manager)는 Entity를 저장하거나 조회하면 EM은 PC(Persistence Context)에 Entity를 보관하고 관리한다. PC는 EM을 생성할 때 하나 만들어진다. <strong>PC에 접근하고 관리하기 위해서는 EM을 통해야 한다.</strong></p>
<hr>
<h2 id="2-entity의-생명주기"><strong>2. Entity의 생명주기</strong></h2>
<h4 id="1-비영속"><strong>1. 비영속</strong></h4>
<blockquote>
<p>Entity 객체를 생성한 후 아직 저장하지 않은 상태이다. 따라서, PC와 DB와는 전혀 관련이 없다.</p>
</blockquote>
<pre><code>Member member = new Member();
member.setId(&quot;sample1&quot;);
member.setUserName(&quot;test1&quot;);</code></pre><h4 id="2-영속"><strong>2. 영속</strong></h4>
<blockquote>
<p>EM을 통해서 Entity가 PC에 저장되어 관리되는 상태이다. 즉, 영속 상태는 PC에 의해 관리된다는 것을 의미한다.</p>
</blockquote>
<pre><code>Member member = new Member();
member.setId(&quot;sample1&quot;);
member.setUserName(&quot;test1&quot;);

// Entity 객체를 저장해 영속 상태로 만듦
em.persist(member);</code></pre><h4 id="3-준영속"><strong>3. 준영속</strong></h4>
<blockquote>
<p>PC가 관리하던 영속 상태의 Entity를 PC가 관리하지 않게 되는 상태이다. <br>em.detach()를 호출하면 준영속 상태가 된다. em.close(), em.clear()를 호출해 PC를 초기화해도 PC가 관리하던 영속 상태의 Entity는 준영속 상태가 된다.</p>
</blockquote>
<pre><code>Member member = new Member();
member.setId(&quot;sample1&quot;);
member.setUserName(&quot;test1&quot;);

// Entity 객체를 저장해 영속 상태로 만듦
em.persist(member);

// 영속 상태의 Entity를 준영속 상태로 만든다.
em.detach(member);</code></pre><h4 id="4-삭제"><strong>4. 삭제</strong></h4>
<blockquote>
<p>Entity를 PC와 DB에서 삭제한다.</p>
</blockquote>
<pre><code>Member member = new Member();
member.setId(&quot;sample1&quot;);
member.setUserName(&quot;test1&quot;);

// Entity 객체를 저장해 영속 상태로 만듦
em.persist(member);

// 영속 상태의 Entity를 준영속 상태로 만든다.
em.detach(member);

// Entity 객체를 삭제한다.
em.remove(member);</code></pre><p>오늘은 영속성 컨텍스트가 무엇인지와 영속성 컨텍스트에 저장되고 관리되는 Entity의 생명주기에 대해 간단하게 알아보았다. 다음에는 영속성 컨텍스트의 특징과 Entity 조회, 등록, 수정, 삭제에 대해 자세히 알아보도록 하겠다.</p>
<ul>
<li>참고 문헌: 자바 ORM 표준 JPA 프로그래밍 (김영한 지음)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[JPA 설정 및 어플리케이션 개발]]></title>
            <link>https://velog.io/@dev_donggun/JPA-config</link>
            <guid>https://velog.io/@dev_donggun/JPA-config</guid>
            <pubDate>Fri, 07 Jan 2022 01:23:29 GMT</pubDate>
            <description><![CDATA[<h2 id="1-persistencexml-설정"><strong>1. persistence.xml 설정</strong></h2>
<p>JPA는 persistence.xml 파일을 통해 필요한 설정 정보를 관리한다. META-INF/persistence.xml 클래스 패스 경로에 있다면 별도의 설정 없이 JPA가 인식할 수 있다.</p>
<p><img src="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcmN91z%2Fbtq5FWFzTO4%2FeXX0a9CzxVuWTPXZkVkYE0%2Fimg.png" alt=""></p>
<blockquote>
<pre><code>&lt;persistence xmln=&quot;https://xmlns.jcp.org/xml/ns/persistence&quot; version=&quot;2.1&quot;&gt;</code></pre></blockquote>
<pre><code>
설정 파일은 위와 같이 persistence로 시작한다. 여기서 xml 네임스페이스(xmlns)와 버전을 지정한다. 

&gt; ```
&lt;persistence-unit name=&quot;jpabook&quot;&gt;</code></pre><p>영속성 유닛 (persistence unit)은 일반적으로 연결할 데이터베이스당 하나의 영속성 유닛을 등록한다. </p>
<blockquote>
<pre><code>&lt;property name=&quot;javax.persistence.jdbc.driver&quot; value=&quot;org.h2.Driver&quot;/&gt;  
&lt;property name=&quot;javax.persistence.jdbc.user&quot; value=&quot;sa&quot;/&gt;
&lt;property name=&quot;javax.persistence.jdbc.password&quot; value=&quot;&quot;/&gt;
&lt;property name=&quot;javax.persistence.jdbc.url&quot; value=&quot;jdbc:h2:tcp://localhost/~/test&quot;/&gt;</code></pre></blockquote>
<pre><code>
위의 4가지 속성은 JPA 표준 속성으로 JDBC 드라이버, DB 접속 아이디, DB 접속 패스워드, DB 접속 URL로 구성된다.

&gt; ```
&lt;property name=&quot;hibernate.dialect&quot; value=&quot;org.hibernate.dialect.H2Dialect&quot; /&gt;</code></pre><p>하이버네이트 속성으로, 데이터베이스 방언(SQL 표준을 지키기 않거나 특정 데이터베이스만의 고유한 기능)을 설정한다. </p>
<p>[옵션]으로 설정된 부분들은 하이버네이트 전용 속성으로 실행한 SQL를 출력하고 보기 쉽게 정렬, 주석도 함께 출력, 키 생성 전략을 설정해 준 것이다.</p>
<h2 id="2-어플리케이션-개발"><strong>2. 어플리케이션 개발</strong></h2>
<h3 id="21-entity-manager-설정">2.1. Entity Manager 설정</h3>
<blockquote>
<p>Entity Manager 생성 과정  </p>
<p>1. Persistence가 persistence.xml을 통해 설정 정보를 조회한다.<br>2. Persistence가 EntityManagerFactory를 생성한다.<br>3. EntityManagerFactory가 EntityManager를 생성한다.</p>
</blockquote>
<ul>
<li><strong>EntityManagerFactory 생성</strong></li>
</ul>
<p>JPA를 시작하기 위해서는 persistence.xml의 설정 정보를 통해 EntityManagerFactory를 생성해야 한다. 이를 위해 Persistence 클래스를 사용한다.</p>
<pre><code>EntityManagerFactory emf = Persistence.createEntityManagerFactory(&quot;jpabook&quot;);</code></pre><p>앞서 말했듯이, META-INF/persistence.xml에서 이름이 jpabook인 영속성 유닛을 찾아 EntityManagerFactory를 생성하게 된다. 이 때, JPA를 동작시키키 위한 기반 객체를 생성하고, 상황에 따라서는 데이터베이스 커넥션 풀도 생성해야 하므로 <strong>EntityManagerFactory를 생성하는 비용은 매우 크다</strong>. 따라서 <strong>EntityManagerFactory는 어플리케이션 전체에서 딱 한 번만 생성하고 공유해 사용하도록 해야한다.</strong></p>
<ul>
<li><strong>EntityManager 생성</strong></li>
</ul>
<pre><code>EntityManager em = emf.createEntityManager();</code></pre><p>EntityManagerFactory를 이용해 EntityManager를 생성한다. JPA의 대부분의 기능은 EntityManager가 제공한다. <strong>EntityManager는 DB 커넥션과 밀접한 관계가 있기 때문에 스레드 간에 공유 및 재사용을 해서는 안된다.</strong></p>
<ul>
<li><strong>close</strong></li>
</ul>
<pre><code>// EntityManager 종료
em.close();

// EntityManagerFactory 종료
emf.close();</code></pre><p>사용이 끝난 EntityManager는 <strong>반드시 종료</strong>해야 하고, 어플리케이션을 종료할 때도 EntityManagerFactory를 종료해야 한다.</p>
<h3 id="22-transaction">2.2. Transaction</h3>
<p>JPA를 사용할 때는 반드시 Transaction 안에서 데이터를 변경해야 한다. </p>
<pre><code>EntityTransaction tx = em.getTransaction(); //트랜잭션 기능 획득

    try {
        tx.begin(); //트랜잭션 시작
        logic(em);  //비즈니스 로직
        tx.commit();//트랜잭션 커밋
    } 

    catch (Exception e) {
        e.printStackTrace();
        tx.rollback(); //트랜잭션 롤백
    } 

    finally {
        em.close(); //엔티티 매니저 종료
    }

emf.close(); //엔티티 매니저 팩토리 종료</code></pre><p>Transaction을 시작하려면 EntityManager로부터 getTransaction()을 통해 트랜잭션 API를 받아와야 한다.  </p>
<h3 id="23-crud--jpql">2.3. CRUD / JPQL</h3>
<pre><code>EntityManagerFactory emf = Persistence.createEntityManagerFactory(&quot;jpabook&quot;);
EntityManager em = emf.createEntityManager();

// 1. 등록
String name = &quot;Hello&quot;;
Member member = new Member();
member.setName(name);

em.persist(member);

// 2. 수정
member.setAge(29);

// 3. 삭제
em.remove(member);

// 4. 단 건 조회
Member searchMember = em.find(Member.class, name);</code></pre><p>어플리케이션이 필요한 데이터만 불러오기 위해서는 검색 조건이 포함된 SQL을 사용하는 수밖에 없다. 따라서 JPA는 JPQL(Java Persistence Query Language)라는 쿼리 언어로 이러한 문제를 해결한다. 이는 추후에 더 자세하게 알아보도록 하겠다.</p>
<ul>
<li>참고 문헌: 자바 ORM 표쥰 JPA 프로그래밍 (저자: 김영한)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[JPA란?]]></title>
            <link>https://velog.io/@dev_donggun/JPA</link>
            <guid>https://velog.io/@dev_donggun/JPA</guid>
            <pubDate>Fri, 07 Jan 2022 01:17:43 GMT</pubDate>
            <description><![CDATA[<h2 id="jpa란"><strong>JPA란?</strong></h2>
<p>Java Persistence API로, 자바 진영의 ORM 기술 표준을 말한다. JPA는 애플리케이션과 JDBC 사이에서 동작한다. </p>
<blockquote>
<p><strong>ORM이란?</strong>  </p>
<p>1. <strong>Object-Relation Mapping</strong> 이름 그대로 객체와 관계형 데이터베이스를 매핑함을 의미한다.<br>2. ORM 프레임워크는 객체와 테이블을 매핑해서 패러다임의 불일치 문제를 개발자를 대신해 해결해준다.<br>3. 개발자는 객체 측면에서는 정교한 객체 모델링을 할 수 있게 되고, 관계형 데이터베이스는 데이터베이스에 맞도록 모델링을 할 수 있다. 그리고 이 둘을 매핑하는 방법만 ORM 프레임워크에게 알려주면 된다.<br>-&gt; 개발자는 데이터 중심의 관계형 데이터베이스를 사용해도 <strong>객체지향 애플리케이션 개발에 집중</strong>할 수 있게 된다.</p>
</blockquote>
<p>JPA는 자바 ORM 기술에 대한 API 표준 명세이며, 쉽게 말해 인터페이스의 집합이라고 볼 수 있다. 이러한 표준 덕분에 특정 구현 기술에 대한 의존도를 줄일 수 있고 다른 구현 기술로 쉽게 이동할 수 있다는 장점을 제공한다. </p>
<h2 id="jpa를-왜-사용해야-하는가"><strong>JPA를 왜 사용해야 하는가?</strong></h2>
<p>1. 생산성</p>
<blockquote>
<p>간단한 CRUD SQL처럼 JDBC API를 사용하는 지루하고 반복적인 일을 JPA가 대신 처리해준다.<br>JPA에는 &#39;CREATE TABLE&#39; 같은 DDL문을 자동으로 생성해주는 기능도 존재한다. 이런 기능들을 사용하면 데이터베이스 설계 중심의 패러다임을 <strong>객체 설계 중심</strong>으로 역전시킬 수 있다.</p>
</blockquote>
<p>2. 유지보수</p>
<blockquote>
<p>SQL을 직접 다루면 Entity에 필드 하나를 추가해도 관련된 CRD SQL과 결과를 매핑하기 위한 JDBC API를 모두 변경해야 한다. 하지만 JPA를 사용하게 되면 필드를 추가하거나 삭제해도 수정해야할 코드가 줄어든다. 따라서 <strong>객체지향 언어가 가진 장점들을 활용해서 유연하고 유지보수하기 좋은 도메인 모델을 편리하게 설계</strong>할 수 있다.</p>
</blockquote>
<p>3. 패러다임의 불일치 해결</p>
<blockquote>
<p>JPA는 상속, 연관관계, 객체 그래프 탐색, 비교하기와 같은 패러다임의 불일치 문제를 해결해준다.</p>
</blockquote>
<p>4. 성능</p>
<blockquote>
<p>JPA는 애플리케이션과 데이터베이스 사이에서 동작하며 다양한 성능 최적화 기회를 제공한다.   </p>
<p>String memberId = &quot;hello&quot;;<br>Member member1 = jpa.find(memberId);<br>Member member2 = jpa.find(memberId);  </p>
<p>위의 경우 JPA를 사용하게 되면 회원을 조회하는 SELECT SQL을 한 번만 데이터베이스에 전달하고 두 번째는 앞서 조회한 회원 객체를 사용하게 된다. </p>
</blockquote>
<p>5. 데이터 접근 추상화와 벤더 독립성</p>
<blockquote>
<p>관계형 데이터베이스는 같은 기능도 벤더마다 사용법이 다른 경우가 많다. JPA는 애플리케이션과 데이터베이스 사이에 추상화된 데이터 접근 계층을 제공함으로써 애플리케이션이 특정 데이터베이스 기술에 종속되지 않도록 해준다. 데이터베이스를 변경하더라도 JPA에게 어떤 데이터베이스를 사용하는지 알려주기만 하면 된다.</p>
</blockquote>
<ul>
<li>참고 문헌: 자바 ORM 표준 JPA 프로그래밍 (김영한 지음)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[HTTP Status - 상태코드]]></title>
            <link>https://velog.io/@dev_donggun/http-status</link>
            <guid>https://velog.io/@dev_donggun/http-status</guid>
            <pubDate>Wed, 29 Sep 2021 14:44:24 GMT</pubDate>
            <description><![CDATA[<h2 id="2xx---요청-정상-처리"><strong>2XX - 요청 정상 처리</strong></h2>
<blockquote>
<p><strong>• 201 Created</strong><br>- 요청이 성공적으로 처리되어 새로운 리소스가 생성되었음을 의미한다.<br>- 생성된 리소스는 응답의 Location 헤더 필드로 식별할 수 있다.<br>- POST 요청으로 신규 리소스를 생성했을 때 응답이다.  </p>
<p><strong>• 204 No Content</strong><br>- 요청을 성공적으로 처리했으나, 응답 Payload에 보낼 데이터가 없음을 의미한다.<br>- 웹 문서 편집기에서 [저장]을 요청할 경우가 대표적인 예시이다.<br>- [저장]의 결과로 어떤 내용도 없어도 괜찮다.<br>- [저장]을 하더라도 같은 화면을 유지해야 한다.</p>
</blockquote>
<hr>
<h2 id="3xx-redirection---요청을-완료하기-위해서-추가-행동이-필요"><strong>3XX (Redirection) - 요청을 완료하기 위해서 추가 행동이 필요</strong></h2>
<blockquote>
<p>• 웹 브라우저는 3XX 응답에 Location 헤더가 존재하면, Location 위치로 이동한다.  </p>
<p><strong>◆ 영구 Redirection</strong><br>- 특정 리소스의 URI가 영구적으로 이동함<br>- 기존 URL은 더 이상 사용하지 않는다. <br>- 실무에서 사용할 일 드물다.  </p>
<p><strong>• 301 Moved Permanently</strong><br>- 리다이렉트 시, 요청 메서드가 <strong>GET으로 변경되고, 본문이 제거될 수도 있다</strong>. (반드시 변경되는 것은 아님)<br>(ex.처음 요청 시 POST로 요청했더라도 리다이렉트시에는 GET으로 요청 메서드가 변경되고, 이에 따라 본문이 제거될 수 있음)  </p>
<p><strong>• 308 Permanent Redirect</strong><br>- 301과 동일한 기능<br>- 리다이렉트 시, <strong>요청 메서드와 본문을 유지한다.</strong>  </p>
<hr>
<p><strong>◆ 일시 Redirection</strong><br>- 일시적인 URI 변경 (주문 완료 후 주문 내역 화면으로 이동 - PRG(POST-REDIRECT-GET)패턴)  </p>
<p><strong>• 302 Found</strong><br>- 리다이렉트 시 요청 메서드가 <strong>GET으로 변하고, 본문이 제거될 수도 있다</strong>. (가능성이 있음)  </p>
<p><strong>• 307 Temporary Redirect</strong><br>- 리다이렉트 시 <strong>요청 메서드와 본문을 유지</strong>한다. (요청 메서드를 변경하면 안됨)  </p>
<p><strong>• 303 See Other</strong><br>- 리다이렉트 시 <strong>요청 메서드가 GET으로 변경</strong>된다.  </p>
<p><strong>✓ PRG 패턴</strong><br>- POST / REDIRECT / GET<br>- POST로 요청을 보낸 후 웹 브라우저를 새로고침하게 되면 중복으로 요청을 발생할 수 있다.<br>- POST로 요청을 보낸 후 결과 화면을 GET메서드로 리다이렉트하면, 새로고침을 하더라도 결과 화면에 대해 GET요청을 보내게 되어 POST에 대한 중복 요청이 발생하지 않는다.<br>- 리다이렉트 된 이후에는 새로고침을 하더라도 GET으로 결과 화면만 조회한다.  </p>
<hr>
<p><strong>◆ 특수 Redirection</strong><br>- 캐시 사용  </p>
<p><strong>• 304 Not Modified</strong><br>- 캐시를 사용하기 위한 목적으로 사용한다.<br>- 클라이언트가 요청한 리소스가 수정되지 않았음을 알려주는 역할을 한다.<br>- 클라이언트가 로컬 PC에 저장된 캐시를 재사용한다. (<strong>캐시로 리다이렉트</strong>)  
- 조건부 GET, HEAD 요청시에 사용할 수 있다.</p>
</blockquote>
<hr>
<h2 id="4xx---클라이언트-에러"><strong>4XX - 클라이언트 에러</strong></h2>
<blockquote>
<p>- 클라이언트의 요청에 잘못된 문법과 같은 문제로 서버가 요청을 수행할 수 없음을 의미한다.<br>- 클라이언트가 잘못된 요청을 보낸 것이기 때문에 똑같은 요청을 하더라도 에러가 발생한다.  </p>
<p><strong>• 401 Unauthorized</strong><br>- 클라이언트가 해당 리소스에 접근하기 위해서는 인증이 필요함을 의미한다.<br>- 응답에 <strong>WWW-Authenticate</strong> 헤더와 함께 인증 방법을 알려준다.<br>- 비하인드 : 인증에 대한 에러 메시지인데 에러명은 [인가]이다. 처음에 잘못 설정해서 그냥 쓴다고 한다.  </p>
<p><strong>• 403 Forbidden</strong><br>- 요청을 이해는 했지만 승인을 거부함을 의미한다.<br>- 인증은 됐으나, 접근 권한이 불충분한 경우에 사용된다.  </p>
<p><strong>• 404 Not Found</strong><br>- 요청 리소스를 찾을 수 없음을 의미한다.<br>- 클라이언트가 리소스에 대한 권한이 부족한 경우, 해당 리소스를 노출하지 않고 싶을 때 사용한다.</p>
</blockquote>
<hr>
<h2 id="5xx---서버-에러"><strong>5XX - 서버 에러</strong></h2>
<blockquote>
<p>- 서버 문제로 인해 발생하는 에러이다.<br>- 서버 문제가 해결되면 요청이 성공할 수 있다.<br>- 일반적으로 대부분의 서버 에러는 <strong>500</strong> 에러를 사용한다.  </p>
<p><strong>• 503 Service Unavailable</strong><br>- 서비스 이용 불가를 의미한다.<br>- 서버의 일시적 과부하 또는 예정된 작업으로 인해 일시적으로 요청을 처리할 수 없는 경우 사용한다.</p>
</blockquote>
]]></description>
        </item>
    </channel>
</rss>