JPA

Java Persistence API์˜ ์•ฝ์ž๋กœ, ์ž๋ฐ” ์ง„์˜์˜ ORM ๊ธฐ์ˆ  ํ‘œ์ค€์ด๋‹ค.

  • ORM ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ํ‘œ์ค€ ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ชจ์Œ

  • ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ๊ตฌํ˜„์ฒด๋Š” Hibernate, EclipseLink, DataNucleus ๋“ฑ ์กด์žฌ(๋ณดํ†ต Hibernate ์‚ฌ์šฉ)

JPA ์‚ฌ์šฉ์˜ ์ด์ 

๊ฐ์ฒด ์ค‘์‹ฌ ๊ฐœ๋ฐœ

SQL ์ค‘์‹ฌ์˜ ๋ฐ์ดํ„ฐ ์ ‘๊ทผ์—์„œ ๋ฒ—์–ด๋‚˜ ๊ฐ์ฒด ์ค‘์‹ฌ์˜ ๊ฐœ๋ฐœ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.


@Entity
public class Member {

    @Id
    @GeneratedValue
    private Long id;
    private String name;

    // ์—ฐ๊ด€๊ด€๊ณ„ ๋งคํ•‘
    @OneToMany(mappedBy = "member")
    private List<Order> orders = new ArrayList<>();
}

SQL ์ฟผ๋ฆฌ์— ์˜์กดํ•˜๋Š” ๋Œ€์‹  ๊ฐ์ฒด์ง€ํ–ฅ์ ์ธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

์ƒ์‚ฐ์„ฑ ๋ฐ ์œ ์ง€๋ณด์ˆ˜์„ฑ

  • ์ƒ์‚ฐ์„ฑ: save(), findById() ๋“ฑ ๊ธฐ๋ณธ์ ์ธ CRUD ๋ฉ”์„œ๋“œ๊ฐ€ ๊ธฐ๋ณธ์œผ๋กœ ์ œ๊ณต

  • ์œ ์ง€๋ณด์ˆ˜์„ฑ: ํ…Œ์ด๋ธ”์— ์ปฌ๋Ÿผ์ด ์ถ”๊ฐ€๋˜๊ฑฐ๋‚˜ ๋ณ€๊ฒฝ๋  ๋•Œ, ๋งคํ•‘๋œ ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค ์ค‘์‹ฌ์˜ ์ˆ˜์ • ์ž‘์—…

ํŒจ๋Ÿฌ๋‹ค์ž„ ๋ถˆ์ผ์น˜ ํ•ด๊ฒฐ

๊ฐ์ฒด์ง€ํ–ฅ ์–ธ์–ด์™€ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์‚ฌ์ด์—๋Š” ๊ทผ๋ณธ์ ์ธ ํŒจ๋Ÿฌ๋‹ค์ž„์˜ ๋ถˆ์ผ์น˜๋ฅผ JPA๊ฐ€ ํ•ด๊ฒฐํ•ด์ค€๋‹ค.

  • ์—ฐ๊ด€๊ด€๊ณ„: ์™ธ๋ž˜ ํ‚ค(Foreign Key) ๋Œ€์‹  ๊ฐ์ฒด์˜ ์ฐธ์กฐ(Reference)๋ฅผ ์‚ฌ์šฉํ•œ ์—ฐ๊ด€๊ด€๊ณ„ ๋งคํ•‘

  • ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„ ํƒ์ƒ‰: ์—ฐ๊ด€๋œ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ, JOIN ์ฟผ๋ฆฌ ์—†์ด ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„๋ฅผ ์ž์œ ๋กญ๊ฒŒ ํƒ์ƒ‰ ๊ฐ€๋Šฅ

  • ๋™์ผ์„ฑ ๋น„๊ต: JPA๋Š” ๊ฐ™์€ ํŠธ๋žœ์žญ์…˜ ๋‚ด์—์„œ ์กฐํšŒํ•œ ๋™์ผํ•œ ๋กœ์šฐ์— ๋Œ€ํ•ด ํ•ญ์ƒ ๋™์ผํ•œ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ๋ณด์žฅ ๋ฐ ๊ฐ์ฒด์˜ ๋™๋“ฑ์„ฑ ๋น„๊ต ๊ฐ€๋Šฅ

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋…๋ฆฝ์„ฑ

JPA๋Š” ํ‘œ์ค€ ์ธํ„ฐํŽ˜์ด์Šค์ด๋ฏ€๋กœ, ์„ค์ • ํŒŒ์ผ์—์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฐฉ์–ธ(Dialect)๋งŒ ๊ต์ฒดํ•˜๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ์˜ ์ˆ˜์ • ์—†์ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ข…๋ฅ˜๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.

์„ฑ๋Šฅ ์ตœ์ ํ™”

JPA๋Š” ๋‹จ์ˆœํžˆ SQL์„ ๋Œ€์‹  ์ƒ์„ฑํ•ด์ฃผ๋Š” ๊ฒƒ์—์„œ ๊ทธ์น˜์ง€ ์•Š๊ณ , ๋‹ค์–‘ํ•œ ์„ฑ๋Šฅ ์ตœ์ ํ™” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.

  • 1์ฐจ ์บ์‹œ

    • ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ ๋‚ด๋ถ€์— ์กด์žฌํ•˜๋Š” ์—”ํ‹ฐํ‹ฐ ์ €์žฅ์†Œ๋กœ, ํŠธ๋žœ์žญ์…˜ ๋ฒ”์œ„ ์•ˆ์—์„œ ๋™์ž‘

    • em.find() ๋“ฑ์„ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ฒ˜์Œ ์กฐํšŒํ•˜๋ฉด, ํ•ด๋‹น ์—”ํ‹ฐํ‹ฐ์˜ ์ธ์Šคํ„ด์Šค๋ฅผ 1์ฐจ ์บ์‹œ์— ์ €์žฅํ•˜๊ณ  ๊ทธ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜

    • ์ดํ›„ ๊ฐ™์€ ํŠธ๋žœ์žญ์…˜ ๋‚ด์—์„œ ๋™์ผํ•œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋‹ค์‹œ ์กฐํšŒํ•  ๊ฒฝ์šฐ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ ‘๊ทผํ•˜์ง€ ์•Š๊ณ  1์ฐจ ์บ์‹œ์— ์žˆ๋Š” ์—”ํ‹ฐํ‹ฐ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜

    • ๊ฐ™์€ ํŠธ๋žœ์žญ์…˜ ๋‚ด์—์„œ ์กฐํšŒํ•œ ์—”ํ‹ฐํ‹ฐ์˜ ๋ฐ˜๋ณต ๊ฐ€๋Šฅํ•œ ์ฝ๊ธฐ(Repeatable Read)์™€ ๊ฐ์ฒด ๋™์ผ์„ฑ ๋ณด์žฅ

  • ์“ฐ๊ธฐ ์ง€์—ฐ (Transactional Write-Behind)

    • em.persist()์™€ ๊ฐ™์€ ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด, JPA๋Š” ํ•ด๋‹น SQL ์ฟผ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ ๋‚ด๋ถ€์˜ ์“ฐ๊ธฐ ์ง€์—ฐ SQL ์ €์žฅ์†Œ์— ์ฟผ๋ฆฌ๋ฅผ ์ €์žฅ

    • ์ด๋ ‡๊ฒŒ ๋ชจ์•„๋‘” ์ฟผ๋ฆฌ๋“ค์€ ํŠธ๋žœ์žญ์…˜์ด ์ปค๋ฐ‹๋˜๋Š” ์‹œ์ ์— flush()๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด์„œ ํ•œ๊บผ๋ฒˆ์— ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋กœ ์ „์†ก

  • ์ง€์—ฐ ๋กœ๋”ฉ (Lazy Loading)

    • ์—ฐ๊ด€๊ด€๊ณ„๊ฐ€ ์„ค์ •๋œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์กฐํšŒํ•  ๋•Œ, ์‹ค์ œ๋กœ ํ•ด๋‹น ์—”ํ‹ฐํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์‹œ์ ๊นŒ์ง€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์กฐํšŒ๋ฅผ ๋ฏธ๋ฃจ๋Š” ๊ธฐ์ˆ 

    • ๋ฐ์ดํ„ฐ ์กฐํšŒ ์‹œ ์—ฐ๊ด€๋œ ์—”ํ‹ฐํ‹ฐ ์ปฌ๋ ‰์…˜(@OneToMany(fetch = FetchType.LAZY))์€ ์‹ค์ œ ๋ฐ์ดํ„ฐ๊ฐ€ ์•„๋‹Œ ํ”„๋ก์‹œ(Proxy) ๊ฐ์ฒด๋กœ ์ดˆ๊ธฐ

      • ***ToOne -> ๊ธฐ๋ณธ๊ฐ’ ์ฆ‰์‹œ ๋กœ๋”ฉ / ***ToMany -> ๊ธฐ๋ณธ๊ฐ’ ์ง€์—ฐ ๋กœ๋”ฉ

    • ์ดํ›„ ์ฝ”๋“œ์—์„œ ์‹ค์ œ ์ปฌ๋ ‰์…˜์— ์ ‘๊ทผํ•˜๋Š” ์‹œ์ ์—, JPA๊ฐ€ ์กฐํšŒ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์‹ค์ œ ๋ฐ์ดํ„ฐ๋กœ ์ดˆ๊ธฐํ™”

JPA์˜ ๋™์ž‘ ๊ณผ์ •

JPA๋Š” EntityManagerFactory์™€ EntityManager๋ฅผ ์ค‘์‹ฌ์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค.

  • EntityManagerFactory

    • EntityManager๋ฅผ ์ƒ์„ฑํ•˜๋Š” ํŒฉํ† ๋ฆฌ

    • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ปค๋„ฅ์…˜ ํ’€๊ณผ ๊ฐ™์€ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ด€๋ฆฌ(์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „์ฒด์—์„œ ๋‹จ ํ•˜๋‚˜๋งŒ ์ƒ์„ฑ๋˜์–ด ๊ณต์œ )

    • ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ์ ‘๊ทผํ•ด๋„ ์•ˆ์ „ํ•˜๊ฒŒ ๊ณต์œ  ๊ฐ€๋Šฅ

  • EntityManager

    • ์‹ค์งˆ์ ์ธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž‘์—…(์ €์žฅ, ์ˆ˜์ •, ์‚ญ์ œ, ์กฐํšŒ ๋“ฑ)์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฐ์ฒด

    • ๋‚ด๋ถ€์— ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ปค๋„ฅ์…˜์„ ์œ ์ง€ํ•˜๋ฉด์„œ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋ฅผ ํ†ตํ•ด ์—”ํ‹ฐํ‹ฐ๋ฅผ ๊ด€๋ฆฌ

์Šคํ”„๋ง ๋ถ€ํŠธ์—์„œ์˜ JPA ์„ค์ •

๊ณผ๊ฑฐ์—๋Š” DataSource, EntityManagerFactory, PlatformTransactionManager ๋“ฑ JPA๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•ด์•ผ ํ–ˆ๋‹ค.

  • DataSource: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ปค๋„ฅ์…˜ ์ •๋ณด๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” ๊ฐ์ฒด

  • JpaVendorAdapter: ์‚ฌ์šฉํ•  JPA ๊ตฌํ˜„์ฒด(์˜ˆ: Hibernate)์— ๋Œ€ํ•œ ์„ธ๋ถ€ ์„ค์ •์„ ๋‹ด๋Š” ๊ฐ์ฒด

  • LocalContainerEntityManagerFactoryBean: DataSource์™€ JpaVendorAdapter ์ •๋ณด๋ฅผ ์กฐํ•ฉํ•˜์—ฌ EntityManagerFactory๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฐ์ฒด

  • JpaTransactionManager: JPA์˜ ํŠธ๋žœ์žญ์…˜์„ ์Šคํ”„๋ง์˜ ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ ์ฒด๊ณ„(@Transactional)์™€ ์—ฐ๋™์‹œ์ผœ์ฃผ๋Š” ๊ฐ์ฒด

์Šคํ”„๋ง ๋ถ€ํŠธ์˜ JPA ์ž๋™ ์„ค์ •

ํ•˜์ง€๋งŒ ์˜ค๋Š˜๋‚  ์Šคํ”„๋ง ๋ถ€ํŠธ ํ™˜๊ฒฝ์—์„œ๋Š” ๋‘ ๊ฐ€์ง€ ์„ค์ •๋งŒ์œผ๋กœ JPA๋ฅผ ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

  • spring-boot-starter-data-jpa ์˜์กด์„ฑ ์ถ”๊ฐ€

  • application.properties (๋˜๋Š” .yml) ํŒŒ์ผ์— ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ ‘์† ์ •๋ณด์™€ ๊ธฐ๋ณธ์ ์ธ JPA ์˜ต์…˜ ๋ช…์‹œ

์ฐธ๊ณ ์ž๋ฃŒ

Last updated

Was this helpful?