๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
  • ์žฅ์›์ต ๊ธฐ์ˆ ๋ธ”๋กœ๊ทธ
๐Ÿ“š ์‹œ๋ฆฌ์ฆˆ/- ๋ฐฐ์›Œ๋ณด์ž Spring Data JPA

[๋ฐฐ์›Œ๋ณด์ž Spring Data JPA] Spring Data JPA ์˜ ๊ธฐ๋ณธ๊ณผ ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ

by Wonit 2021. 4. 7.

ํ•ด๋‹น ๊ธ€์€ ๋ฐฐ์›Œ๋ณด์ž Spring Data JPA ์‹œ๋ฆฌ์ฆˆ ์ž…๋‹ˆ๋‹ค.
ํ•ด๋‹น ์‹œ๋ฆฌ์ฆˆ์˜ ๋‚ด์šฉ์ด ์ด์–ด์ง€๋Š” ํ˜•ํƒœ์ด๋ฏ€๋กœ ๊ธ€์˜ ๋‚ด์šฉ ์ค‘์— ์ƒ๋žต๋˜๋Š” ๋ง๋“ค์ด ์žˆ์„ ์ˆ˜ ์žˆ์œผ๋‹ˆ, ์ž์„ธํ•œ ์‚ฌํ•ญ์€ ์•„๋ž˜ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”!


์˜ค๋Š˜์€ JPA ์— ๋Œ€ํ•œ ๊ธฐ๋ณธ๊ณผ Spring Data JPA ์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณผ ๊ฒƒ์ด๋‹ค.

 

์šฐ์„  Spring์„ ํ†ตํ•ด์„œ JPA๋ฅผ ์ ‘ํ•œ ์‚ฌ๋žŒ์—๊ฒŒ๋Š” ์ƒˆ๋กœ์šธ ์ˆ˜ ์žˆ๋Š”๋ฐ, Spring์—์„œ ์‚ฌ์šฉํ•˜๋Š” JPA์€ JPA๋ฅผ ์ด์šฉํ•˜์—ฌ Spring ์ด ๋งŒ๋“  ํ”„๋กœ์ ํŠธ์ด๋‹ค.

 

๋ฌด์Šจ ์ฐจ์ด์ผ๊นŒ?

 

์šฐ์„  JPA์— ๋Œ€ํ•ด์„œ ๋จผ์ € ์•Œ์•„๋ณด์ž.

JPA

JPA๋Š” ORM ํ‘œ์ค€์ธ๋ฐ, ORM์€ ๋ฌด์—‡์ผ๊นŒ?

๊ฐ์ฒด ๊ด€๊ณ„ ๋งคํ•‘์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด ๊ฐ„์˜ ํ˜ธํ™˜๋˜์ง€ ์•Š๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€ํ™˜ํ•˜๋Š” ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ธฐ๋ฒ•์ด๋‹ค.
๊ฐ์ฒด ์ง€ํ–ฅ ์–ธ์–ด์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” "๊ฐ€์ƒ" ๊ฐ์ฒด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

JPA์™€ ORM์„ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์šฐ์„  ๋ถˆํŽธํ•œ ๊ณผ๊ฑฐ๋ฅผ ๋ด์•ผ ํ•œ๋‹ค.

 

๊ณผ๊ฑฐ์—๋Š” SQL ์ค‘์‹ฌ์ ์ธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ํ•˜๋˜ ์‹œ๋Œ€์˜€๋‹ค.

 

๊ฑฐ๊ธฐ์—” ๋‘ ๊ฐ€์ง€ ๋ถˆํŽธํ•จ์ด ์กด์žฌํ–ˆ๋Š”๋ฐ,

  1. SQL์— ์˜์กด์ ์ธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ
  2. SQL๊ณผ ๊ฐ์ฒด ์‚ฌ์ด์˜ ์ž„ํ”ผ๋˜์Šค ๋ถˆ์ผ์น˜

๋ผ๋Š” ๋ฌธ์ œ๋“ค์ด ์žˆ์—ˆ๋‹ค.

 

SQL์— ์˜์กด์ ์ธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ

JDBC API๋ฅผ ์ด์šฉํ•˜์—ฌ db์— ์ €์žฅํ•˜๋Š” ์—ฌ๋Ÿฌ ์ฟผ๋ฆฌ๋“ค์€ ๋Œ€๋ถ€๋ถ„ SQL์— ์˜์กด์ ์ด๋‹ค๋ผ๊ณ  ํ‘œํ˜„ํ•œ๋‹ค.

 

์™œ ๊ทธ๋Ÿด๊นŒ?

 

๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ƒ์ƒ์„ ํ•ด๋ณด์ž.

 

์šฐ๋ฆฌ๊ฐ€ User ํ…Œ์ด๋ธ”์— ์–ด๋–ค ํ•„๋“œ๋ฅผ ๋งŒ๋“ค๊ณ  ์ด๋ฅผ JDBC API๋ฅผ ์ด์šฉํ•˜์—ฌ ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ฆฐ๋‹ค.

 

๊ทธ๋Ÿผ ํ•ด๋‹น ์ฟผ๋ฆฌ์— ๋งž๊ฒŒ ResultSet์„ ๊ฐ๊ฐ์˜ ๊ธฐ๋Šฅ๋งˆ๋‹ค ์„ธํŒ…ํ•ด์•ผํ•œ๋‹ค.

 

ํ•˜์ง€๋งŒ ์—ฌ๊ธฐ์„œ ์—”ํ‹ฐํ‹ฐ์— ์ƒˆ๋กœ์šด ํ•„๋“œ๊ฐ€ ๋“ค์–ด๊ฐ€๊ฒŒ ๋œ๋‹ค๋ฉด?

 

๊ทธ๋Ÿผ CRUD์™€ ๊ด€๋ จ๋œ ๋ชจ๋“  JDBC API์˜ ResultSet์„ ์ˆ˜์ •ํ•ด์„œ ๋งคํ•‘์„ ํ•ด์•ผํ•œ๋‹ค.

 

์ด๋ฅผ ๋‘๊ณ  SQL ์— ์˜์กด์ ์ด๋‹ค ๋ผ๊ณ  ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

 

SQL๊ณผ ๊ฐ์ฒด ์‚ฌ์ด์˜ ์ž„ํ”ผ๋˜์Šค ๋ถˆ์ผ์น˜

User table์ด ์กด์žฌํ•œ๋‹ค๊ณ  ํ•ด๋ณด์ž.

 

๊ทธ๋ฆฌ๊ณ  ํ•ด๋‹น User ํ…Œ์ด๋ธ”์—๋Š” Team ํ…Œ์ด๋ธ”๊ณผ ์™ธ๋ž˜ ํ‚ค๋กœ ๋งคํ•‘๋˜์–ด์žˆ๋‹ค๊ณ  ํ–ˆ์„๋•Œ, User A๊ฐ€ ์–ด๋–ค ํŒ€์— ์†ํ•ด์žˆ๋Š”์ง€ ์•Œ๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ž๋ฐ”์—์„œ ์–ด๋–ป๊ฒŒ ํ• ๊นŒ?

 

public static void main(String[] args) {
  DBConnection connection = new DBConnection();

  User user = connection.findUser("jang")
  Team team = user.getTeam();
  System.out.println(team.getName());
}

๊ทธ๋Ÿผ SQL, ์ฆ‰ RDB ์—์„œ๋Š” ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ?

 

SELECT T.name
FROM user U
    INNER JOIN team T
    ON T.id = T.id
WHERE U.name = "jang";

์ด๋Ÿฐ ์‹์œผ๋กœ ํ•˜๋ ค๋‚˜?

 

๊ฐ™์€ ๊ธฐ๋Šฅ (A๊ฐ€ ์–ด๋–ค ํŒ€์— ์†ํ•ด์žˆ๋Š”์ง€ ์•Œ๊ธฐ ์œ„ํ•ด์„œ๋Š”)์„ ํ•˜๋Š”๋ฐ, SQL๊ณผ Java ์‚ฌ์ด์—์„œ๋Š” ๋งŽ์€ ๋‹ค๋ฅธ ์ ๋“ค์ด ์žˆ๋‹ค.

 

์ด๋ฅผ ํŒจ๋Ÿฌ๋‹ค์ž„, ์ž„ํ”ผ๋˜์Šค ๋ถˆ์ผ์น˜๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

 

์ด๋Ÿฐ ์ด์œ ์— JPA๊ฐ€ ๋“ฑ์žฅํ–ˆ๊ณ  ์ด๋“ค์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ๋‹ค.

 

์ž์„ธํžˆ ์–ด๋–ค ๋ฌธ์ œ์—์„œ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ–ˆ๋Š”์ง€๋Š” ์ง€๊ธˆ ์ค‘์š”ํ•˜์ง€ ์•Š์œผ๋‹ˆ ๋„˜์–ด๊ฐ€๋„๋ก ํ•˜๊ฒ ๋‹ค.

 

Spring Data JPA๋ž€?

JPA๋Š” ORM Framework ์ด๋‹ค.

 

์ฆ‰, ๋…๋ฆฝ์ ์ธ ํ•˜๋‚˜์˜ ํ”„๋ ˆ์ž„์›Œํฌ์ธ ๊ฒƒ์ด๋‹ค.

 

ํ•˜์ง€๋งŒ ์•ž์„œ ๋ง ํ–ˆ๋“ฏ Spring์„ ํ†ตํ•ด JPA๋ฅผ ๋ฐฐ์šด ์‚ฌ๋žŒ๋“ค์—๊ฒŒ๋Š” JPA๋Š” Spring์ด ๋งŒ๋“  ๊ฒƒ ์ฏค์œผ๋กœ ์•Œ๊ณ  ์žˆ๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค.

 

Spring Data JPA๋Š” Spring์ด JPA๋ฅผ Spring์—์„œ ๋” ์‰ฝ๊ณ  ๊ฐ„ํŽธํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋งŒ๋“  Spring Data์˜ ํ”„๋กœ์ ํŠธ ์ค‘ ํ•˜๋‚˜ ์ด๋‹ค.

 

Spring ๊ณต์‹ ๋ฌธ์„œ์—์„œ Spring Data ํ”„๋กœ์ ํŠธ๋ฅผ ํ™•์ธํ•˜๋ฉด ๋งŽ์€ Data ํ”„๋กœ์ ํŠธ๋“ค์ด ์กด์žฌํ•œ๋‹ค.

 

Spring Data JPA ์‚ฌ์šฉํ•˜๊ธฐ

Spring Data JPA๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹น์—ฐํ•˜๊ฒŒ ๊ทธ์— ๋งž๋Š” ์˜์กด์„ฑ์„ ์„ค์น˜ํ•ด์•ผ ํ•œ๋‹ค.

 

Maven

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <version>2.4.4</version>
</dependency>

Gradle

implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: '2.4.4'

Spring Data JPA์˜ ์„ค์ •๊ณผ DB ์—ฐ๊ฒฐ

Springboot ํ”„๋กœ์ ํŠธ์—์„œ Data JPA๋ฅผ ์ด์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์„ธ ๊ฐ€์ง€๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

 

  1. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—”์ง„
  2. JPA ์„ค์ •
  3. Lombok ์„ค์ •

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—”์ง„

ํ•ด๋‹น ์‹œ๋ฆฌ์ฆˆ์—์„œ ์‚ฌ์šฉํ•  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—”์ง„์€ H2 Database์ด๋‹ค.

 

H2๋Š” ๋ธŒ๋ผ์šฐ์ € ๊ธฐ๋ฐ˜์˜ ์ฝ˜์†”๋ชจ๋“œ๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์žˆ๊ณ , ๋ณ„๋„์˜ ์„ค์น˜๊ณผ์ •์ด ์—†์ด ์šฉ๋Ÿ‰๋„ 2MB์ดํ•˜๋กœ ๋งค์šฐ ์ €์šฉ๋Ÿ‰์ด๋‹ค.

 

๊ฐ€๋ณ๊ธฐ ๋•Œ๋ฌธ์— ๋น ๋ฅด๋ฉฐ ํ…Œ์ŠคํŠธ ์šฉ๋„๋กœ ์ž์ฃผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ์ด๋ฒˆ ๊ธฐํšŒ์— ์•Œ์•„๋‘๋Š” ๊ฒƒ๋„ ์ข‹์€ ๋ฐฉ๋ฒ•์ด๋‹ค.

 

์ž์„ธํ•œ ์„ค์น˜๋Š” ์ƒ๋žตํ•˜๊ณ  Knowledge Repository ๋‹˜์˜ ๋ธ”๋กœ๊ทธ h2 ์„ค์น˜ ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

JPA ์„ค์ •

jpa ์„ค์ •์€ application.properties ์—์„œ ํ•œ๋‹ค.

 

์šฐ๋ฆฌ๋Š” yml์„ ์ด์šฉํ•ด์„œ ์„ค์ •์„ ํ•ด๋ณด์ž.

 

resources ์•„๋ž˜์— application.yml ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๊ณ  ์•„๋ž˜์™€ ๊ฐ™์ด ์ ์–ด๋ณด์ž.

 

spring:
  datasource:
    url: jdbc:h2:tcp://localhost/~/dbname # ๋ณธ์ธ์˜ db connection url
    username: name # ๋ณธ์ธ์˜ db username
    password: pw # ๋ณธ์ธ์˜ db password
    driver-class-name: org.h2.Driver

  jpa:
    hibernate:
      ddl-auto: create
    properties:
      show_sql: true
      format_sql: true

์œ„์˜ ๋ช…๋ น์–ด๋“ค์„ ์•Œ์•„๋ณด์ž.

  • datasource
    • datasource : ๋ฐ์ดํ„ฐ ์†Œ์Šค์— ๋Œ€ํ•œ ์ •๋ณด ๋ธ”๋ก์ด๋‹ค.
      • hibernate
      • jpa ์˜ ๊ตฌํ˜„์ฒด์ธ hibernate๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๋ฏ€๋กœ hibernate ์„ค์ •์„ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค.
        • ddl-auto
          • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ดˆ๊ธฐํ™” ์ „๋žต์ด๋‹ค. 5๊ฐ€์ง€ ์ „๋žต์ด ์กด์žฌํ•œ๋‹ค.
            1. none : ์•„๋ฌด๊ฒƒ๋„ ์‹คํ–‰ํ•˜์ง€ ์•Š์Œ
            2. create : SessionFactory๊ฐ€ ์‹œ์ž‘๋  ๋•Œ ๊ธฐ์กด์˜ ํ…Œ์ด๋ธ” ์‚ญ์ œ ํ›„ ์žฌ์ƒ์„ฑ
            3. create-drop : SessionFactory ๊ฐ€ ์ข…๋ฃŒ๋œ๋‹ค๋ฉด drop
            4. update : ๋ณ€๊ฒฝ๋œ ์Šคํ‚ค๋งˆ๋งŒ ์ ์šฉ
            5. validate : ์—”ํ‹ฐํ‹ฐ์™€ ํ…Œ์ด๋ธ”์ด ์ •์ƒ ๋งคํ•‘ ๋˜์—ˆ๋Š”์ง€๋งŒ ํ™•์ธ
    • jpa : jpa ์— ๋Œ€ํ•œ ์ •๋ณด ๋ธ”๋ก์ด๋‹ค.
      • properties
      • hibernate ๊ธฐ๋ณธ ์„ค์ •์ด๋‹ค.
        • show_sql
          • JPA๊ฐ€ ์ƒ์„ฑํ•˜๋Š” ์ฟผ๋ฆฌ๋ฅผ ์ฝ˜์†”๋กœ ์ถœ๋ ฅํ•œ๋‹ค.
        • format_sql
          • ์ฝ˜์†”๋กœ ์ฟผ๋ฆฌ๊ฐ€ ์ถœ๋ ฅ๋  ๋•Œ ์ด์˜๊ฒŒ ํฌ๋งคํŒ…๋œ๋‹ค.

์ž์„ธํ•œ ์‚ฌํ•ญ์€ hibernate ์ฐธ์กฐํ•˜๋ฉด ์•Œ ์ˆ˜ ์žˆ๋‹ค.

Lombok ์„ค์ •

๋กฌ๋ณต์€ Getter/Setter, Constructor, ToString, Builder ๋“ฑ ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์„ ์ปดํŒŒ์ผ ์‹œ์ ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์ธ๋ฐ, ์ž์„ธํ•œ ์‚ฌํ•ญ์€ ๊ฒ€์ƒ‰์„ ํ•ด๋ณด๊ธธ ๋ฐ”๋ž€๋‹ค.

 

์šฐ๋ฆฌ ์˜ˆ์ œ์—์„œ๋Š” Lombok ์„ ์ด์šฉํ•  ์˜ˆ์ •์ด๋‹ค.

JPA ์‚ฌ์šฉํ•ด๋ณด๊ธฐ

๋‹ค์Œ ์‹œ๊ฐ„์— ์ œ๋Œ€๋กœ ์‚ฌ์šฉํ•ด ๋ณผ ์˜ˆ์ •์ธ๋ฐ, ์šฐ์„  db ์„ค์ •์ด ์ž˜ ์ ์šฉ ๋˜์—ˆ๋Š”์ง€ ํ…Œ์ŠคํŠธ๋ฅผ ํ•ด๋ณด์ž.

๋‹ค์Œ 3๊ฐœ์˜ ํŒŒ์ผ์„ ๋งŒ๋“ค์ž.

  1. Member
  2. MemberRepository
  3. MemberRepositoryTest

Member ํด๋ž˜์Šค

@Entity
@Getter @Setter @Builder
public class Member {
    @Id @GeneratedValue
    private Long id;
    private String username;
    private int age;
}

MemberRepository ์ธํ„ฐํŽ˜์ด์Šค

public interface MemberRepository extends JpaRepository<Member, Long> {
}

MemberRepositoryTest ํด๋ž˜์Šค

@SpringBootTest
@Transactional
@Rollback(false)
public class MemberRepositoryTest {

    @Autowired
    MemberRepository memberRepository;

    @Test
    public void saveMemberTest() {
        // given
        long id = 2L;
        String username = "Member B";
        int age = 21;

        // when
        Member member = Member.builder()
                .username(username)
                .age(age)
                .build();
        Member saveMember = memberRepository.save(member);

        // then
        Assertions.assertEquals(saveMember.getAge(), age);
        Assertions.assertEquals(saveMember.getUsername(), username);
    }
}

๊ทธ๋Ÿผ ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

๋Œ“๊ธ€