Published on

🀿 숨 κΎΉ μ°Έκ³  λ”₯λ‹€μ΄λΈŒ 3 : 숨 κΎΉμ°Έκ³  λ”₯λ‹€μ΄λΈŒ - JPA μ—­μ‚¬νŽΈ

Authors
  • avatar
    Name
    Woojin Son
    Twitter

숨 κΎΉμ°Έκ³  λ”₯λ‹€μ΄λΈŒ - JPA μ—­μ‚¬νŽΈ

Intro

🫧 β€œORM이 μ΄λ ‡κ²ŒκΉŒμ§€ μ˜€κΈ°κΉŒμ§€, μ–Όλ§ˆλ‚˜ μˆ¨μ„ μ°Έμ•„μ•Ό ν–ˆμ„κΉŒμš”?"

λ‹€μ‹œ λŒμ•„μ™”μŠ΅λ‹ˆλ‹€. ν•œλ™μ•ˆ νœ΄μ‹κΈ°λ₯Ό μ’€ κ°€μ‘ŒμŠ΅λ‹ˆλ‹€. 개인적으둜 λ‹€μ‚¬λ‹€λ‚œ ν•œ 8월을 λ³΄λƒˆμ—ˆμ–΄μš”.
경쑰사도 μžˆμ—ˆκ³ , 정신을 μ°¨λ €λ³΄λ‹ˆ 이미 8월이 사라 μ Έ μžˆμ—ˆμ—ˆμ£ .

JPA 에 λŒ€ν•œ 글을 ν•œλ²ˆ μ°ν•˜κ²Œ 써본 적이 μ—†λŠ” 것 κ°™μ•„ 글을 써볼까 ν•©λ‹ˆλ‹€. JPA λ§Žμ΄λ“€ μ“°μ‹œμ£ .

처음 JPA λ₯Ό 썼던 μ‹œκΈ°κ°€ λ– μ˜€λ¦…λ‹ˆλ‹€. 잘 적응이 λ˜μ§€ μ•Šμ•˜λ˜ 기얡이 많이 λ‚¨μ•„μš”. JDBC 둜 DB 컀λ„₯μ…˜μ„ λ§Œλ“€κ³  String Query λ₯Ό λ‚ λ¦¬λ˜ 게 ν•™λΆ€ μ‹œμ ˆμ˜ κΈ°μ–΅μ΄μ—ˆλŠ”λ°...막상 κ·Έλ ‡κ²Œ μ‹€λ¬΄μ—μ„œ 업무λ₯Ό ν•  일은 μ—†μ—ˆμŠ΅λ‹ˆλ‹€.

μ‹€λ¬΄μ—μ„œ 3λ…„μ°¨λ₯Ό μ§„ν–‰ν•˜κ³ μžˆλŠ” 이 μˆœκ°„, JPA λ₯Ό μ–Όλ§ˆλ‚˜ 잘 μ•Œκ³  μ“°κ³  μžˆλŠ” μ§€ 문득 κΆκΈˆν•΄μ‘ŒμŠ΅λ‹ˆλ‹€. 이번 ν¬μŠ€νŒ…λ„ κ°€λŠ₯ν•˜λ©΄ λκΉŒμ§€ λ”₯λ‹€μ΄λΈŒ ν•΄ λ³΄κ² μŠ΅λ‹ˆλ‹€.

β˜• 컀피 ν•œμž” ν•˜λ©΄μ„œ μ½μ–΄μ£Όμ„Έμš”. μ΄λ²ˆμ—λ„ λ”₯λ‹€μ΄λΈŒ~! λ‹¬λ €λ³΄κ² μŠ΅λ‹ˆλ‹€.

JPA μ†Œκ°œ

Java Persistance Api λŠ” μžλ°”μ§„μ˜μ„ λŒ€ν‘œν•˜λŠ” Object Relational Mapping (ORM) μž…λ‹ˆλ‹€. Java μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ 데이터와 직접 λ§žλ‹Ώμ•„μžˆλŠ” 뢀뢄을 λ‹΄λ‹Ήν•˜μ£ .

ORM μ΄λΌλŠ” 단어λ₯Ό ν•œλ²ˆ λ©΄λ°€νžˆ λ³΄κ² μŠ΅λ‹ˆλ‹€. 객체와 κ΄€κ³„μžˆλŠ” 데이터λ₯Ό λ§€ν•‘ μ‹œμΌœμ£ΌλŠ” 역할을 ν•˜λŠ” 게 ORM 이죠. λ°μ΄ν„°λ² μ΄μŠ€ λ‚΄ ν…Œμ΄λΈ”μ˜ 데이터λ₯Ό 읽어왔닀면, μ‹€μ œλ‘œ μ‚¬μš©ν•  수 μžˆλŠ” 객체둜 λ§€ν•‘ν•΄μ£ΌλŠ” μž‘μ—…μ΄ ν•„μš”ν•©λ‹ˆλ‹€. ORM 덕뢄에 μš°λ¦¬λŠ” 이런 μž‘μ—…λ“€μ„ μˆ˜λ™μœΌλ‘œ ν•˜μ§€ μ•Šμ•„λ„ λ©λ‹ˆλ‹€.

ORM 의 μ„ νƒμ§€λŠ” μ—¬λŸ¬κ°€μ§€κ°€ 있고 JPA λŠ” κ·Έ 쀑 ν•˜λ‚˜μž…λ‹ˆλ‹€. MyBatis λ₯Ό μ“Έ μˆ˜λ„ 있고 Kotlin 베이슀의 개발자라면 Exposed λ₯Ό μ‚¬μš©ν•  μˆ˜λ„ 있죠. JPA λŠ” 였랜 μ‹œκ°„ μ‚¬μš©λ˜μ–΄μ„œ λ ˆνΌλŸ°μŠ€κ°€ λ§Žμ€ ORM μž…λ‹ˆλ‹€. μ–΄μ§€κ°„ν•΄μ„œλŠ” Spring μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ κ°œλ°œν•  λ•Œ μ‹€νŒ¨ν•˜μ§€ μ•Šμ£ . λ‹€λ§Œ, JPA κ·Έ μžμ²΄κ°€ κ°€μ§€λŠ” 단점도 μžˆλ‹€λ³΄λ‹ˆ 상황에 λ”°λΌμ„œ νŒλ‹¨ν•΄μ„œ μ‚¬μš©ν•˜μ…”μ•Ό ν•©λ‹ˆλ‹€.

이번 ν¬μŠ€νŒ…μ—μ„œλŠ” 이런 기술적인 μ΄μ•ΌκΈ°λ³΄λ‹€λŠ” 역사에 λŒ€ν•œ 이야기λ₯Ό ν• κΉŒ ν•©λ‹ˆλ‹€. 아무리 이번 μ‹œλ¦¬μ¦ˆμ˜ λͺ©μ μ΄ λ”₯λ‹€μ΄λΈŒλΌκ³  해도 λ„ˆλ¬΄ κΈ€ ν•˜λ‚˜μ—μ„œ λ‚΄μš©μ„ λ°©λŒ€ν•˜κ²Œ, 깊게 닀루면 ν”Όλ‘œλ„κ°€ λ†’μ•„μ§€λ”λΌκ΅¬μš”.

JPA 역사 이야기

1. JDBC 의 μ‹œλŒ€

학뢀생 λ•Œ μ›Ή μ• ν”Œλ¦¬μΌ€μ΄μ…˜ κ°œλ°œμ„ Java λ₯Ό 톡해 λ°°μ›Œ λ³Έ μ‚¬λžŒμ΄λΌλ©΄ μ•„λ§ˆ μ•„λž˜μ˜ ν”Œλ‘œμš°λ‘œ 데이터 접근을 μ²˜λ¦¬ν–ˆμ„ κ²ƒμž…λ‹ˆλ‹€.

Connection -> Statement -> ResultSet -> while(rs.next()) {...}

Connection conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement("SELECT * FROM MEMBER");
ResultSet rs = ps.executeQuery();

while (rs.next()) {
    Member m = new Member();
    m.setId(rs.getLong("id"));
    m.setName(rs.getString("name"));
}

사싀 이 ν”„λ‘œμ„ΈμŠ€λŠ” 2000λ…„λŒ€ 초반의 μžλ°” μ§„μ˜μ˜ 데이터 μ ‘κ·Ό 방식을 μš”μ•½ν•œ κ²ƒμž…λ‹ˆλ‹€.

JSP 와 Servlet, 그리고 HTML, CSS, JS 둜 μ›Ή μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μˆ˜μ—…μ„ λ“€μ—ˆλ˜ 적이 μžˆμŠ΅λ‹ˆλ‹€. λ‹Ήμ‹œμ˜ μˆ˜μ—…μ΄ 이둠에 λͺ©μ μ΄ μžˆμ—ˆλ‹€λŠ” 것을 κ°μ•ˆν•˜λ©΄, ꡳ이 λ³΅μž‘ν•œ Spring 을 μ‚¬μš©ν•˜μ§€ μ•Šμ•˜λ˜ 이유λ₯Ό 이해할 수 μžˆμ—ˆμ£ . (학뢀생 기쀀에선 μΆ©λΆ„νžˆ λ³΅μž‘ν•  수 μžˆλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€. 사싀 μ§€κΈˆλ„ λ³΅μž‘ν•΄μš”...)

컀λ„₯μ…˜μ„ μ—΄κ³  λ‹«λŠ” 것, νŠΈλžœμž­μ…˜μ„ μ²˜λ¦¬ν•˜λŠ” 것, SQL 을 μž‘μ„±ν•˜λŠ” 것, 그리고 데이터λ₯Ό λ§€ν•‘ν•˜λŠ” 것 λͺ¨λ“  것듀이 μ²˜μŒμ—λŠ” μˆ˜λ™μœΌλ‘œ μ½”λ“œλ₯Ό μž‘μ„±ν•˜λŠ” κ²ƒμ—μ„œ μ‹œμž‘ν–ˆμŠ΅λ‹ˆλ‹€.

이 μ ‘κ·Ό λ°©μ‹μ˜ λ¬Έμ œκ°€ μžˆλ‹€λ©΄ 크게 μ•„λž˜μ™€ κ°™μŠ΅λ‹ˆλ‹€.

λ¨Όμ € SQL 을 직접 관리해야 ν•©λ‹ˆλ‹€. λ‹Ήμ‹œμ— QueryDSL 같은 게 μžˆμ„ 리가 μ—†μ£ . 였직 String 으둜 관리해야 ν•©λ‹ˆλ‹€. κ·Έ λ§ˆμ €λ„ JDK 17 의 멀티라인 String 을 μ“Έ 수 μžˆμ—ˆλ˜ 것도 μ•„λ‹κ²λ‹ˆλ‹€. λ¬Όλ‘  μ§€κΈˆλ„ μ΄λ ‡κ²Œ κ°œλ°œν•˜μ‹œλŠ” 뢄도 κ³„μ‹œκ² μ§€λ§Œ, 2000λ…„λŒ€ μ΄ˆλ°˜μ΄λΌλŠ” 것을 κΈ°μ–΅ν•˜μ…”μ•Ό ν•©λ‹ˆλ‹€. μš°λ¦¬κ°€ 정말 많이 μ“°κ³  μžˆλŠ” LTS 인 JDK 8 이 2014년에 μΆœμ‹œ 된 λ²„μ „μ΄λΌλŠ” 것을 μžŠμ–΄μ„œλŠ” μ•ˆλ©λ‹ˆλ‹€...

λ‹€μŒμœΌλ‘œ 객체와 λ°μ΄ν„°λ² μ΄μŠ€κ°„μ— λΆˆμΌμΉ˜κ°€ 생길 수 μžˆμŠ΅λ‹ˆλ‹€. λ¬Όλ‘  이건 μ§€κΈˆλ„ λΉ„μŠ·ν•œκ²Œ μ•„λ‹Œκ°€ 라고 생각할 수 μžˆμ§€λ§Œ, 개발 κ³Όμ •μ—μ„œ ν…Œμ΄λΈ” λͺ…μ„Έκ°€ λ³€κ²½λ˜λŠ” 경우 μƒλ‹Ήνžˆ λ§Žμ€ μ½”λ“œλ₯Ό μˆ˜μ •ν•΄μ•Ό ν•©λ‹ˆλ‹€. μ΅œμ†Œν•œ ORM 을 μ“°κ²Œ λœλ‹€λ©΄, ORM μ„ μ—μ„œ μ—λŸ¬μ²˜λ¦¬λ₯Ό ν•˜κ±°λ‚˜ 컬럼 ν•˜λ‚˜λ₯Ό λ¬΄μ‹œν•˜κ±°λ‚˜ λ“± λŒ€μ²˜λ₯Ό ν•  수 μžˆμ§€λ§Œ ν˜„μž¬μ˜ κ΅¬μ‘°μ—μ„œλŠ” 쉽지 μ•Šμ£ .

μ’…ν•©μ μœΌλ‘œ λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§λ³΄λ‹€ SQL κ·Έ μžμ²΄μ— 관리 ν¬μΈνŠΈκ°€ λŠ˜μ–΄λ‚˜λŠ” λ¬Έμ œκ°€ μƒκΉλ‹ˆλ‹€. SQL 을 μž‘μ„±ν•˜λŠ” 것 μžμ²΄κ°€ λ¬Έμ œλŠ” μ•„λ‹ˆκ² μ§€λ§Œ, μ •μž‘ μ½”λ“œλ₯Ό μž‘μ„±ν•΄μ•Ό ν•  μ‹œκ°„μ— SQL 을 μˆ˜μ •ν•˜λŠ” 것은 개발 곡수λ₯Ό μž‘μ•„λ¨ΉλŠ” μΌμž…λ‹ˆλ‹€.

λ¬Όλ‘  λ•Œλ‘œλŠ” SQL 둜 λ•Œμš°λŠ”κ²Œ λ‚˜μ€ 상황도 생기긴 ν•©λ‹ˆλ‹€. 톡계 처리λ₯Ό ν•  λ•ŒλŠ” RDB 에 따라 μ‚¬μš©ν•  수 μžˆλŠ” κΈ°λŠ₯듀을 μ¨λ¨ΉλŠ” 게 λ‚˜μ„ μˆ˜λ„ 있죠.

μ§€κΈˆ μ΄μ•ΌκΈ°ν•˜λŠ” λ‚΄μš©μ€ μ’€ 결이 λ‹€λ₯Έ λ‚΄μš©μ΄κΈ΄ ν•©λ‹ˆλ‹€. SQL κ·Έ μžμ²΄κ°€ 객체둜 μž‘μ„±λœ 게 μ•„λ‹Œμ΄μƒ 데이터 νƒ€μž…λ§Œ λ΄μ„œλŠ” String κ·Έ 이상 κ·Έ μ΄ν•˜λ„ μ•„λ‹Œ 게 ν˜„μž¬ μ‹œμ μ—μ„œμ˜ λ¬Έμ œμž…λ‹ˆλ‹€.

μˆ˜μ •μ‚¬ν•­μ΄ 생기든, λ³΅μž‘ν•˜μ§€λ§Œ ν•œλ°©μœΌλ‘œ 문제λ₯Ό ν•΄κ²°ν•  수 μžˆλŠ” 쿼리λ₯Ό μ“°λ“  μš°λ¦¬κ°€ μˆ˜μ •ν•˜κ³  κ΄€λ¦¬ν•˜λŠ” SQL 이 String λ³€μˆ˜ ν•˜λ‚˜μ— μ „λΆ€ μ§±λ°•ν˜€μžˆλ‹€κ³  생각해보면 이해가 μ’€ 더 μ‰¬μšΈ 것 κ°™μŠ΅λ‹ˆλ‹€. 쑰건에 따라 WHERE 문을 λ„£μ—ˆλ‹€ λΉΌκ³  싢은데 이 상황에선 μ–΄λ–»κ²Œ ν•˜λ©΄ μ’‹μ„κΉŒμš”...?

이쯀 되면 λˆ„κ΅°κ°€λŠ” 이런 생각을 ν•  μˆ˜λ„ μžˆμ„ 것 κ°™μŠ΅λ‹ˆλ‹€.

μ•„λ‹ˆ 걍 이거 λΉŒλ”κ°™μ€κ±Έλ‘œ ν•΄κ²° λͺ»ν•˜λ‚˜?

SQL 관리에 객체λ₯Ό ν™œμš©ν•΄λ³΄μž! λΌλŠ” 생각을 λˆ„κ΅°κ°€ ν•˜κΈ° μ‹œμž‘ν–ˆκ³ , 2001λ…„ κ²½ κ·Έ 아이디어λ₯Ό μ‹€ν˜„ ν•œ ν”„λ‘œμ νŠΈκ°€ λ“±μž₯ν–ˆμŠ΅λ‹ˆλ‹€.

2. Hibernate 의 λ“±μž₯ (2001 ~)

Hibernate λŠ” μš°λ¦¬κ°€ 이미 잘 μ•Œκ³  μžˆλŠ” ORM μž…λ‹ˆλ‹€. κ·Έ 전에도 μ‹œλ„κ°€ μ—†μ—ˆλ˜ 것은 μ•„λ‹Œλ°, λ°”λ‘œ EJB 의 Entity Bean μž…λ‹ˆλ‹€. ν•˜μ§€λ§Œ EJB 의 Entity Bean 은 λ³΅μž‘ν•œ XML μ„€μ •κ³Ό Vendor 쒅속성이 μžˆμ—ˆμŠ΅λ‹ˆλ‹€. (EJB κ·Έ 자체의 문제일 것 κ°™μŠ΅λ‹ˆλ‹€.)

Hibernate λŠ” μ΅œλŒ€ν•œ λ‹¨μˆœν•˜κ²Œ Annotation 베이슀둜 μ˜΅μ…˜μ„ μ§€μ •ν•  수 있고, μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ˜μ—­μ—μ„œ νŠΈλžœμž­μ…˜μ„ 컨트둀 ν•  수 μžˆλ‹€λŠ” 차별점을 κ°€μ‘ŒμŠ΅λ‹ˆλ‹€. λ˜ν•œ 1μ°¨, 2μ°¨ μΊμ‹œ κΈ°λŠ₯κ³Ό 같은 심화 κΈ°λŠ₯을 μ œκ³΅ν•˜μ£ .

κ°€μž₯ κ²°μ •μ μœΌλ‘œ DB 쀑심이 μ•„λ‹Œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ 객체 μ€‘μ‹¬μ˜ 섀계 철학을 κ°€μ‘ŒμŠ΅λ‹ˆλ‹€. μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ˜μ—­μ—μ„œκΉŒμ§€ DB의 μ˜μ‘΄μ„±μ„ κ°€μ Έκ°€μ§€ μ•ŠμœΌλ €κ³  λ…Έλ ₯ν–ˆλ‹€λŠ” 의미죠.

μ΄μ „μ—λŠ” DB μŠ€ν‚€λ§ˆ κ·Έ μžμ²΄κ°€ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ 섀계λ₯Ό μ§€λ°°ν•˜λŠ” 것이 일반적인 μƒν™©μ΄μ—ˆμŠ΅λ‹ˆλ‹€. Hibernate λŠ” ν…Œμ΄λΈ”μ΄ μ•„λ‹Œ 객체 λͺ¨λΈ (entity) λ₯Ό μš°μ„ ν–ˆμ£ . κ°μ²΄κ°„μ˜ 연관관계가 κ³§ λ°μ΄ν„°μ˜ 관계가 될 수 μžˆλ„λ‘ μ„€κ³„λ˜μ—ˆμŠ΅λ‹ˆλ‹€. Member.team, Order.items 와 같은 연관관계등이 κ·Έ μ˜ˆμ‹œμž…λ‹ˆλ‹€.

λ˜ν•œ JDBC 만 μ“Έ λ•Œμ™€λŠ” λ‹€λ₯΄κ²Œ, 객체의 μƒνƒœ λ³€ν™” κ·Έ 자체λ₯Ό μΆ”μ ν•˜λŠ” κΈ°λŠ₯이 μ‘΄μž¬ν–ˆμŠ΅λ‹ˆλ‹€. JDBC λŠ” 직접 UPDATE Query λ₯Ό λ‚ λ €μ€˜μ•Ό ν•˜μ£ . Hibernate μ—μ„œλŠ” 그럴 ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€.

member.setName("DevCow");
tx.commit(); // UPDATE μžλ™ μ‹€ν–‰ (Dirty Checking)

κ°œλ°œμžλŠ” 덕뢄에 데이터 μ‘°μž‘μ΄ μ•„λ‹ˆλΌ 객체의 μƒνƒœ 전이 (state transition) 을 λ‹€λ£¨κ²Œ λ˜μ—ˆμ£ .

λ˜ν•œ κ°μ²΄κ°„μ˜ 연관관계 κ·Έ μžμ²΄κ°€ λ°μ΄ν„°μ˜ κ΄€κ³„λ‘œ 인해 데이터 ν–‰ (Row) λ‹¨μœ„κ°€ μ•„λ‹Œ 객체 κ·Έ 자체λ₯Ό μ€‘μ‹¬μœΌλ‘œ μ½”λ“œλ₯Ό μž‘μ„±ν•  수 있게 λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

member.getTeam().getName(); // Lazy Loading으둜 μžλ™ 쑰회

JDBC μ˜€μœΌλ©΄ Join Query λ₯Ό μž‘μ„±ν•΄μ„œ λ‚ λ €μ•Ό ν•©λ‹ˆλ‹€. κ·Έλ ‡κ²Œ 쑰회 된 Row 듀을 또 λ‹€μ‹œ 가곡해야 ν•˜μ£ . 이런 κΈ°λŠ₯ 덕뢄에 DB ν…Œμ΄λΈ”μ΄ μ•„λ‹Œ κ°μ²΄κ°„μ˜ λ„€νŠΈμ›Œν¬κ°€ μ‚¬κ³ μ˜ λ‹¨μœ„κ°€ 될 수 μžˆμŠ΅λ‹ˆλ‹€.

Hibernate λŠ” 크게 λ„€ κ°€μ§€ 핡심 κΈ°λŠ₯을 κ°€μ§€κ³  μžˆμŠ΅λ‹ˆλ‹€.

  • Lazy Loading : ν•„μš”ν•œ μ‹œμ μ—λ§Œ λ‘œλ”©
  • Dirty Checking : λ³€κ²½ μžλ™ 감지
  • Session Cache : 동일 νŠΈλžœμž­μ…˜ λ‚΄ 동일 객체 보μž₯
  • HQL : SQL을 μΆ”μƒν™”ν•œ 객체지ν–₯ 쿼리

3. JPA 의 탄생 (2006)

Hibernate의 성곡을 λˆˆμ—¬κ²¨λ³Έ **Java Community Process (JCP)**λŠ” 각 λ²€λ”μ˜ ORM κΈ°μˆ μ„ 톡합해 ν‘œμ€€μ„ λ§Œλ“€κΈ°λ‘œ κ²°μ •ν•©λ‹ˆλ‹€.

λ‹Ήμ‹œμ— Hibernate 외에도 λ‹€λ₯Έ ORM 듀이 많이 μ‹œλ„λ˜λ˜ μ‹œκΈ°μ—ˆμŠ΅λ‹ˆλ‹€.

2006λ…„, EJB 3.0κ³Ό ν•¨κ»˜ **JPA 1.0 (Java Persistence API)**이 λ°œν‘œλ©λ‹ˆλ‹€. Hibernate 와 Toplink, Kodo 의 ν˜‘μ˜μ²΄μ—μ„œ λ°œν‘œλ˜μ—ˆμ£ .

@Entity
class Member {
    @Id @GeneratedValue
    Long id;
    String name;
}

이 μ½”λ“œ λͺ‡μ€„λ‘œ 객체가 μ˜μ†μ„± (persistence) λ₯Ό κ°€μ§€κ²Œ λ˜μ—ˆμ£ . κ·Έλ™μ•ˆμ˜ μˆ˜λ™ 맀핑이 μ΄λ ‡κ²Œ μ‹¬ν”Œν•΄μ‘ŒμŠ΅λ‹ˆλ‹€.

4. JPA 2.x - ORM의 μ •μ œκΈ°

κ·Έ μ΄ν›„λ‘œ JPA λŠ” κ³„μ†ν•΄μ„œ 버전을 올리며 ν‘œμ€€μ„ μž‘μ•„ κ°”μŠ΅λ‹ˆλ‹€. κ°„λž΅ν•œ νŒ¨μΉ˜λ…ΈνŠΈλŠ” μ•„λž˜μ™€ κ°™μŠ΅λ‹ˆλ‹€.

  • Jpa 2.0 (2009)

    • Criteria API둜 νƒ€μž…μ„Έμ΄ν”„ν•œ 쿼리 제곡
    • ElementCollection, MapKey λ“± μ»¬λ ‰μ…˜ λ§€ν•‘ κ°•ν™”
    • 1μ°¨ μΊμ‹œ, Flush λͺ¨λ“œ ν‘œμ€€ν™”
  • JPA 2.1 (2013)

    • EntityGraph: Fetch μ „λž΅ 동적 μ œμ–΄
    • AttributeConverter: VO ↔ 컬럼 λ³€ν™˜
    • Stored Procedure 호좜 지원

이 μ‹œκΈ° λΆ€ν„°λŠ” Spring Data JPA κ°€ λ“±μž₯ν•˜κΈ° μ‹œμž‘ν–ˆμŠ΅λ‹ˆλ‹€. μš°λ¦¬κ°€ μ΅μˆ™ ν•œ Repository μΈν„°νŽ˜μ΄μŠ€, CRUD μžλ™μ™„μ„±μ˜ μ‹œλŒ€κ°€ μ—΄λ¦°κ±°μ£ .

Hibernate λŠ” μ—¬μ „νžˆ JPA 의 κ΅¬ν˜„μ²΄λ‘œ μ§„ν™”ν–ˆμŠ΅λ‹ˆλ‹€. μ²˜μŒλΆ€ν„° JPA 의 κ΅¬ν˜„μ²΄λŠ” μ•„λ‹ˆμ—ˆκ² μ§€λ§Œ, ν‘œμ€€μ„ μž‘μ•„κ°€λ©° 사싀상 JPAλΌλŠ” ν‘œμ€€μ˜ κ΅¬ν˜„μ²΄κ°€ Hibernate κ°€ λ˜λŠ” ꡬ쑰가 κ΅³μ–΄μ§€κ²Œ 되죠.

5. Jakarta Persistence - ν‘œμ€€μ˜ κ³„μŠΉ (2019 ~ )

2019년에 ν•œ 사건이 ν„°μ§‘λ‹ˆλ‹€. Oracle 이 Java EE λ₯Ό Eclipse μž¬λ‹¨μ— μ΄κ΄€ν•˜κ²Œ λ˜μ—ˆμ£ . κ·Έ κ²°κ³Ό λͺ¨λ“  νŒ¨ν‚€μ§€λ“€μ΄ javax μ—μ„œ jakarta 둜 λ³€κ²½λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 더이상 Java EE κ°€ μ•„λ‹ˆλΌ Jakarta EE λ₯Ό λ”°λ₯΄κ²Œ λ˜μ—ˆκ΅ JPA 3.0 의 μ‹œλŒ€κ°€ 였게 λ˜μ—ˆμ£ .

JPA μ™Έμ˜ ORM?

JPA κ°€ 세상에 λ‚˜μ˜¨ μ§€ μ‹œκ°„μ΄ κ½€ 였래 지났죠. ν˜„μž¬λŠ” 정말 λ‹€μ–‘ν•œ 선택지듀이 μ‘΄μž¬ν•©λ‹ˆλ‹€. Spring Data JPA 와 QueryDSL 의 쑰합은 κ΅­λ£° μ‘°ν•©μœΌλ‘œ 유λͺ…ν•˜μ£ . ν•˜μ§€λ§Œ κ·Έ 외에도 jOOQ, Exposed (Kotlin) κ³Ό 같은 선택지도 μ‘΄μž¬ν•©λ‹ˆλ‹€. λ…ΌλΈ”λ‘œν‚Ή DB 접근이 ν•„μš”ν•œ κ²½μš°μ—” R2DBC κ°€ μš”κ΅¬λ˜κΈ°λ„ ν•˜μ£ .

κ°œμΈμ μœΌλ‘œλŠ” JPA + QueryDSL 의 쑰합을 κ°€μž₯ 였래 μ‚¬μš©ν–ˆμ§€λ§Œ, μ΅œκ·Όμ—λŠ” Exposed λ₯Ό μ‚¬μš©ν•΄λ³΄λ €κ³  λ…Έλ ₯μ€‘μž…λ‹ˆλ‹€. Java κ·Έ 자체의 단점을 Kotlin 이 많이 λ³΄μ™„ν•΄μ£ΌλŠ” 만큼 Java 에 맞게 μ΅œμ ν™” 된 Spring Data JPA μ—μ„œ λ²—μ–΄λ‚˜λ³΄λ €κ³  μ‘°κΈˆμ”© λ…Έλ ₯ ν•΄ 보고 μžˆμŠ΅λ‹ˆλ‹€.

Outro

JPA 의 μ—­μ‚¬λŠ” ORM μ΄λΌλŠ” 기술이 λ°œμ „ ν•΄ λ‚˜κ°€κ³  ν‘œμ€€ν™”κ°€ μ΄λ€„μ§€λŠ” κ³Όμ • κ·Έ μžμ²΄λΌκ³ λ„ λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€. λ§Žμ€ κ°œλ°œμžλ“€μ—κ²Œ 객체지ν–₯ κ·Έ 자체의 μ€‘μš”μ„±μ„ 집쀑할 수 μžˆλ„λ‘ 정립 ν•΄ κ°€λŠ” 과정을 μ­‰ λŒμ•„λ³΄λ©΄μ„œ, μ‹€μ œλ‘œ κ°œλ°œμžλ“€μ˜ μ½”λ“œ μž‘μ„± νŒ¨λŸ¬λ‹€μž„μ„ μƒλ‹Ήνžˆ 많이 λ°”κΏ¨λ‹€λŠ” 것을 μ²΄κ°ν–ˆμŠ΅λ‹ˆλ‹€.

λ‹€μŒ νŽΈμ—μ„œλŠ” JPA 의 λ‚΄λΆ€λ‘œ 깊게 νŒŒκ³ λ“€μ–΄κ°€λŠ” μž‘λ™μ›λ¦¬ νŽΈμž…λ‹ˆλ‹€. κΈ°λŒ€ν•΄μ£Όμ„Έμš”~πŸ™‹β€β™‚οΈ