๊ด€๋ฆฌ ๋ฉ”๋‰ด

์‚ถ์˜ ๊ณต์œ 

[Spring] Spring Data JPA — ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž‘์—…์„ ๊ฐ„ํŽธํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๊ธฐ์ˆ  ๋ณธ๋ฌธ

Web Dev/BackEnd

[Spring] Spring Data JPA — ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž‘์—…์„ ๊ฐ„ํŽธํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๊ธฐ์ˆ 

dkrehd 2025. 5. 9. 01:25
728x90
๋ฐ˜์‘ํ˜•

๐Ÿ“  Spring Data JPA — ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž‘์—…์„ ๊ฐ„ํŽธํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๊ธฐ์ˆ 

์•ˆ๋…•ํ•˜์„ธ์š”, ๊ฐœ๋ฐœ์ž ์—ฌ๋Ÿฌ๋ถ„! ์šฐ๋ฆฌ๊ฐ€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค ๋•Œ, ์‚ฌ์šฉ์ž์˜ ์ •๋ณด, ๊ฒŒ์‹œ๊ธ€, ์ƒํ’ˆ ๋ชฉ๋ก ๋“ฑ ์ˆ˜๋งŽ์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ๊ด€๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฐ์ดํ„ฐ๋Š” ๋ณดํ†ต ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ผ๋Š” ์ฒด๊ณ„์ ์ธ ์ €์žฅ์†Œ์— ๋ณด๊ด€๋˜์ฃ .

๊ทธ๋Ÿฐ๋ฐ ์ž๋ฐ”์™€ ๊ฐ™์€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๊ฐ€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ์ง์ ‘ '๋Œ€ํ™”'ํ•˜๋ ค๋ฉด SQL์ด๋ผ๋Š” ํŠน๋ณ„ํ•œ ์–ธ์–ด๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๊ณ , ๋•Œ๋กœ๋Š” ์ด ๊ณผ์ •์ด ๊ฝค ๋ณต์žกํ•˜๊ณ  ๋ฐ˜๋ณต์ ์ธ ์ž‘์—…์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งˆ์น˜ ์™ธ๊ตญ์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ •ํ•ด์ง„ ์–‘์‹์— ๋งž์ถฐ ์„œ๋ฅ˜๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•˜๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ์ฃ .

์ด๋Ÿฌํ•œ ๋ฒˆ๊ฑฐ๋กœ์›€์„ ์ค„์—ฌ์ฃผ๊ณ , ๊ฐœ๋ฐœ์ž๊ฐ€ ์ข€ ๋” ์ž๋ฐ” ์ฝ”๋“œ ์ž์ฒด์— ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ๋ฉ‹์ง„ ๋„๊ตฌ๊ฐ€ ๋ฐ”๋กœ Spring Data JPA์ž…๋‹ˆ๋‹ค. ์˜ค๋Š˜์€ ์ด Spring Data JPA๊ฐ€ ๋ฌด์—‡์ด๊ณ , ์–ด๋–ป๊ฒŒ ์šฐ๋ฆฌ์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž‘์—…์„ ํŽธ๋ฆฌํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์ฃผ๋Š”์ง€ ํ•ต์‹ฌ ์›๋ฆฌ๋ฅผ ์ค‘์‹ฌ์œผ๋กœ ์‰ฝ๊ฒŒ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


๐Ÿข 1. Spring Data JPA๋ž€?

๐Ÿ“Œ ๋จผ์ €, Spring Data๋ถ€ํ„ฐ!

  • Spring Data๋Š” ์—ฌ๋Ÿฌ ์ข…๋ฅ˜์˜ ๋ฐ์ดํ„ฐ ์ €์žฅ์†Œ(์˜ˆ: MySQL, MongoDB, Redis)๋ฅผ ์ผ๊ด€๋˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ๋„๊ตฌ์˜ˆ์š”.
  • ์ฆ‰, ์ €์žฅ์†Œ๊ฐ€ ๋‹ฌ๋ผ๋„ ์‚ฌ์šฉ๋ฒ•์€ ๊ฑฐ์˜ ๋˜‘๊ฐ™๊ฒŒ ๋งŒ๋“ค์–ด์ค˜์š”.

๐Ÿ“Œ ๊ทธ์ค‘์—์„œ๋„ ๊ฐ€์žฅ ๋งŽ์ด ์“ฐ๋Š” ๊ฑด?

๋ฐ”๋กœ Spring Data JPA์ž…๋‹ˆ๋‹ค!

  • ์ด๊ฑด JPA๋ผ๋Š” ๊ธฐ์ˆ ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋งŒ๋“ค์–ด์กŒ์–ด์š”.
  • JpaRepository ๊ฐ™์€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์†๋ฐ›๊ธฐ๋งŒ ํ•ด๋„, ์ €์žฅ, ์กฐํšŒ, ์ˆ˜์ •, ์‚ญ์ œ๊ฐ€ ๋‹ค ๋ผ์š”!

๐ŸŽฎ ์ฆ‰, ๋ณต์žกํ•œ SQL ์•ˆ ์“ฐ๊ณ ๋„ DB๋ž‘ ๋Œ€ํ™”ํ•  ์ˆ˜ ์žˆ๋Š” ๋งˆ๋ฒ• ๊ฐ™์€ ๋„๊ตฌ!


๐Ÿ“š 2. CRUDRepository: ๊ธฐ๋ณธ ๊ธฐ๋Šฅ์€ ์—ฌ๊ธฐ ๋‹ค ์žˆ์–ด์š”!

Spring Data JPA๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ€์žฅ ๋จผ์ € ๋งŒ๋‚˜๊ฒŒ ๋˜๋Š” ์นœ๊ตฌ ์ค‘ ํ•˜๋‚˜๊ฐ€ ๋ฐ”๋กœ CrudRepository ์ธํ„ฐํŽ˜์ด์Šค์ž…๋‹ˆ๋‹ค. ์ด๋ฆ„์—์„œ ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด, ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ์— ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ด๊ณ  ํ•„์ˆ˜์ ์ธ CRUD ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

  • Create (์ƒ์„ฑ - ๋ฐ์ดํ„ฐ ์ €์žฅ)
  • Read (์ฝ๊ธฐ - ๋ฐ์ดํ„ฐ ์กฐํšŒ)
  • Update (๊ฐฑ์‹  - ๋ฐ์ดํ„ฐ ์ˆ˜์ •)
  • Delete (์‚ญ์ œ - ๋ฐ์ดํ„ฐ ์‚ญ์ œ)

๋†€๋ผ์šด ์ ์€, ๊ฐœ๋ฐœ์ž๊ฐ€ ์ด CrudRepository ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์†๋ฐ›๋Š” ์ƒˆ๋กœ์šด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋งŒ๋“ค๊ธฐ๋งŒ ํ•˜๋ฉด, Spring Data JPA๊ฐ€ ์ž๋™์œผ๋กœ ๊ธฐ๋ณธ์ ์ธ CRUD ๋ฉ”์„œ๋“œ ๊ตฌํ˜„์ฒด๋ฅผ ๋งŒ๋“ค์–ด์ค€๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค! ๊ฐœ๋ฐœ์ž๋Š” ์ง์ ‘ SQL์„ ์ž‘์„ฑํ•˜๊ฑฐ๋‚˜ ๋ณต์žกํ•œ JPA ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•  ํ•„์š”๊ฐ€ ๊ฑฐ์˜ ์—†์Šต๋‹ˆ๋‹ค.

๋”ฑ ๋‘ ๊ฐ€์ง€๋งŒ ๋ช…์‹œํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค:

  1. ์–ด๋–ค ์—”ํ‹ฐํ‹ฐ(Entity, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”๊ณผ ๋งคํ•‘๋  ์ž๋ฐ” ๊ฐ์ฒด) ๋ฅผ ๋‹ค๋ฃฐ ๊ฒƒ์ธ์ง€ (์˜ˆ: Board ํด๋ž˜์Šค)
  2. ๊ทธ ์—”ํ‹ฐํ‹ฐ์˜ ID(์‹๋ณ„์ž) ํƒ€์ž…์ด ๋ฌด์—‡์ธ์ง€ (์˜ˆ: Long ํƒ€์ž…)

๐Ÿ›  CRUD๋ž€?

๊ธฐ๋Šฅ์„ค๋ช…๋ฉ”์„œ๋“œ ์˜ˆ์‹œ
์กฐํšŒ ๋ฐ์ดํ„ฐ ์ฝ๊ธฐ findById(), findAll()
์ €์žฅ/์ˆ˜์ • ๋ฐ์ดํ„ฐ ๋„ฃ๊ธฐ ๋˜๋Š” ๋ฐ”๊พธ๊ธฐ save()
์‚ญ์ œ ๋ฐ์ดํ„ฐ ์—†์• ๊ธฐ deleteById(), delete()
 

BoardRepository (๊ฒŒ์‹œํŒ ๋ฐ์ดํ„ฐ ์ ‘๊ทผ ์ธํ„ฐํŽ˜์ด์Šค) ์˜ˆ์‹œ:

import org.springframework.data.repository.CrudRepository;

// Board ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋‹ค๋ฃจ๊ณ , Board์˜ ID ํƒ€์ž…์€ Long์ด๋‹ค.
public interface BoardRepository extends CrudRepository<Board, Long> {
    // ๊ธฐ๋ณธ์ ์ธ CRUD ๋ฉ”์„œ๋“œ๋“ค์€ ์ด๋ฏธ ์—ฌ๊ธฐ์— ์ค€๋น„๋˜์–ด ์žˆ์–ด์š”!
    // ํŠน๋ณ„ํ•œ ์กฐํšŒ ์กฐ๊ฑด์ด ํ•„์š”ํ•˜๋ฉด ์—ฌ๊ธฐ์— ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
}

์ •๋ง ๊ฐ„๋‹จํ•˜์ฃ ? ์ด ์ธํ„ฐํŽ˜์ด์Šค๋งŒ ์ •์˜ํ•˜๋ฉด, Spring Data JPA๊ฐ€ ๋‚ด๋ถ€์ ์œผ๋กœ ์‹ค์ œ ์ž‘๋™ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•ด์ค๋‹ˆ๋‹ค.

CrudRepository์˜ ์ฃผ์š” ๊ธฐ๋ณธ ์ œ๊ณต ๋ฉ”์„œ๋“œ ๐Ÿ“œ

์ž‘์—… ๋ถ„๋ฅ˜๋ฉ”์„œ๋“œ (๊ธฐ๋Šฅ)์„ค๋ช… (์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ฒŒ ํ’€์–ด์„œ)
์ƒ์„ฑ/์ˆ˜์ • save(S entity) "์ด ์—”ํ‹ฐํ‹ฐ(๋ฐ์ดํ„ฐ)๋ฅผ ์ €์žฅํ•ด์ค˜!" (ID๊ฐ€ ์—†๊ฑฐ๋‚˜ DB์— ์—†์œผ๋ฉด ์ƒˆ๋กœ ์ €์žฅ, ID๊ฐ€ DB์— ์ด๋ฏธ ์กด์žฌํ•˜๋ฉด ํ•ด๋‹น ๋ฐ์ดํ„ฐ ์ˆ˜์ •)
์กฐํšŒ findById(ID id) "์ด ID๋ฅผ ๊ฐ€์ง„ ์—”ํ‹ฐํ‹ฐ ํ•˜๋‚˜๋งŒ ์ฐพ์•„์ค˜!" (๊ฒฐ๊ณผ๋Š” Optional<S> ํƒ€์ž…์œผ๋กœ ๋ฐ˜ํ™˜๋˜์–ด null ์ฒ˜๋ฆฌ๊ฐ€ ์šฉ์ด)
  findAll() "ํ•ด๋‹น ํƒ€์ž…์˜ ๋ชจ๋“  ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋‹ค ๋ณด์—ฌ์ค˜!"
  count() "์—”ํ‹ฐํ‹ฐ๊ฐ€ ์ด ๋ช‡ ๊ฐœ ์žˆ๋Š”์ง€ ์•Œ๋ ค์ค˜!"
  existsById(ID id) "์ด ID๋ฅผ ๊ฐ€์ง„ ์—”ํ‹ฐํ‹ฐ๊ฐ€ ์‹ค์ œ๋กœ ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธํ•ด์ค˜!" (์กด์žฌํ•˜๋ฉด true, ์—†์œผ๋ฉด false)
์‚ญ์ œ deleteById(ID id) "์ด ID๋ฅผ ๊ฐ€์ง„ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์‚ญ์ œํ•ด์ค˜!"
  delete(S entity) "์ด ์—”ํ‹ฐํ‹ฐ ๊ฐ์ฒด ์ž์ฒด๋ฅผ ์‚ญ์ œํ•ด์ค˜!"
  deleteAll() "ํ•ด๋‹น ํƒ€์ž…์˜ ๋ชจ๋“  ์—”ํ‹ฐํ‹ฐ๋ฅผ ์‚ญ์ œํ•ด์ค˜! (์ฃผ์˜ํ•ด์„œ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค!)"
  deleteAll(Iterable<? extends S> entities) "์ด ๋ชฉ๋ก์— ์žˆ๋Š” ์—”ํ‹ฐํ‹ฐ๋“ค๋งŒ ๊ณจ๋ผ์„œ ์‚ญ์ œํ•ด์ค˜!"
Sheets๋กœ ๋‚ด๋ณด๋‚ด๊ธฐ
  • S๋Š” ์—”ํ‹ฐํ‹ฐ ํƒ€์ž…์„, ID๋Š” ํ•ด๋‹น ์—”ํ‹ฐํ‹ฐ์˜ ID ํƒ€์ž…์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

ํ•œ ๋‹จ๊ณ„ ๋”: PagingAndSortingRepository ๐Ÿ“ˆ๐Ÿ“„

๋งŒ์•ฝ ๋‹ค๋ฃจ์–ด์•ผ ํ•  ๋ฐ์ดํ„ฐ๊ฐ€ ์ˆ˜์ฒœ, ์ˆ˜๋งŒ ๊ฑด์ด๋ผ๋ฉด ํ•œ ๋ฒˆ์— ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ ํ™”๋ฉด์— ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ์€ ๋น„ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค. ๋งˆ์น˜ ๋‘๊บผ์šด ๋ฐฑ๊ณผ์‚ฌ์ „์„ ํ•œ ํŽ˜์ด์ง€์”ฉ ๋„˜๊ฒจ๋ณด๊ฑฐ๋‚˜, ์›ํ•˜๋Š” ๋‚ด์šฉ์„ ์ฐพ๊ธฐ ์œ„ํ•ด ํŠน์ • ์ˆœ์„œ๋กœ ์ •๋ ฌํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•˜์ฃ .

PagingAndSortingRepository ๋Š” CrudRepository์˜ ๊ธฐ๋Šฅ์„ ๋ชจ๋‘ ๊ฐ€์ง€๋ฉด์„œ, ์ถ”๊ฐ€์ ์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์œ ์šฉํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค์ž…๋‹ˆ๋‹ค.

  • ํŽ˜์ด์ง• (Paging): ๋Œ€๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์—ฌ๋Ÿฌ ํŽ˜์ด์ง€๋กœ ๋‚˜๋ˆ„์–ด ์กฐํšŒํ•˜๋Š” ๊ธฐ๋Šฅ (์˜ˆ: 10๊ฐœ์”ฉ ๋Š์–ด์„œ 1ํŽ˜์ด์ง€, 2ํŽ˜์ด์ง€ ๋ณด๊ธฐ)
  • ์ •๋ ฌ (Sorting): ๋ฐ์ดํ„ฐ๋ฅผ ํŠน์ • ๊ธฐ์ค€(์˜ˆ: ์ž‘์„ฑ์ผ ์ˆœ, ์ด๋ฆ„ ์ˆœ)์œผ๋กœ ์ •๋ ฌํ•˜์—ฌ ์กฐํšŒํ•˜๋Š” ๊ธฐ๋Šฅ

PagingAndSortingRepository๋Š” CrudRepository๋ฅผ ์ƒ์†(ํ™•์žฅ) ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, CrudRepository์˜ ๋ชจ๋“  ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ํŽ˜์ด์ง•๊ณผ ์ •๋ ฌ ๊ด€๋ จ ๋ฉ”์„œ๋“œ๋„ ์ถ”๊ฐ€๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Java
 
import org.springframework.data.repository.PagingAndSortingRepository;

// Board ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋‹ค๋ฃจ๊ณ  ID๋Š” Long ํƒ€์ž…์ด๋ฉฐ, ํŽ˜์ด์ง•๊ณผ ์ •๋ ฌ ๊ธฐ๋Šฅ๋„ ์‚ฌ์šฉํ•œ๋‹ค.
public interface BoardPagingRepository extends PagingAndSortingRepository<Board, Long> {
    // CrudRepository์˜ ๋ฉ”์„œ๋“œ + ํŽ˜์ด์ง•/์ •๋ ฌ ๊ด€๋ จ ๋ฉ”์„œ๋“œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ!
}

โœ๏ธ 3. ๊ฒŒ์‹œํŒ ์˜ˆ์ œ - Board ํด๋ž˜์Šค

์ด์ œ Board ์—”ํ‹ฐํ‹ฐ์™€ BoardRepository๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‹ค์ œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž‘์—…์„ ์–ด๋–ป๊ฒŒ ํ•˜๋Š”์ง€ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ๋‹จ๊ณ„๋ณ„๋กœ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

1. Board.java (๊ฒŒ์‹œ๊ธ€ ์ •๋ณด๋ฅผ ๋‹ด๋Š” ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค)

๋จผ์ €, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”๊ณผ ๋งคํ•‘๋  Board ํด๋ž˜์Šค(์—”ํ‹ฐํ‹ฐ)๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

import jakarta.persistence.Entity; // ๋˜๋Š” javax.persistence.*;
import jakarta.persistence.Id;
import jakarta.persistence.Temporal;
import jakarta.persistence.TemporalType;
import java.util.Date;

@Entity // ์ด ํด๋ž˜์Šค๊ฐ€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”๊ณผ ์—ฐ๊ฒฐ๋  ์—”ํ‹ฐํ‹ฐ์ž„์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
public class Board {
    @Id // bno ํ•„๋“œ๊ฐ€ ์ด ์—”ํ‹ฐํ‹ฐ์˜ ๊ณ ์œ  ์‹๋ณ„์ž(PK)์ž„์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
//    @GeneratedValue // ID ์ž๋™ ์ƒ์„ฑ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์ฃผ์„์„ ํ•ด์ œํ•˜์„ธ์š”.
    private Long bno; // ๊ฒŒ์‹œ๋ฌผ ๋ฒˆํ˜ธ

    private String title;   // ์ œ๋ชฉ
    private String writer;  // ์ž‘์„ฑ์ž
    private String content; // ๋‚ด์šฉ
    private Long viewCnt;   // ์กฐํšŒ์ˆ˜

    @Temporal(value= TemporalType.DATE) // ๋‚ ์งœ ์ •๋ณด๋งŒ ์ €์žฅ (์‹œ๊ฐ„ ์ œ์™ธ)
    private Date inDate;    // ์ž‘์„ฑ์ผ
    @Temporal(value= TemporalType.DATE)
    private Date upDate;    // ์ˆ˜์ •์ผ

    // toString(), Getters, Setters ...
    // (์ œ๊ณตํ•ด์ฃผ์‹  ์ฝ”๋“œ์™€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค)
}
  • @Entity: ์ด Board ํด๋ž˜์Šค๊ฐ€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ํŠน์ • ํ…Œ์ด๋ธ”์— ๋Œ€์‘๋˜๋Š” '์‹ค์ฒด'์ž„์„ JPA์—๊ฒŒ ์•Œ๋ ค์ค๋‹ˆ๋‹ค.
  • @Id: bno ํ•„๋“œ๊ฐ€ ๊ฐ ๊ฒŒ์‹œ๊ธ€์„ ์œ ์ผํ•˜๊ฒŒ ๊ตฌ๋ถ„ํ•˜๋Š” ๊ธฐ๋ณธ ํ‚ค(Primary Key)์ž„์„ ๋ช…์‹œํ•ฉ๋‹ˆ๋‹ค.
  • @Temporal: Date ํƒ€์ž… ํ•„๋“œ๋ฅผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์–ด๋–ค ํ˜•์‹(๋‚ ์งœ, ์‹œ๊ฐ„, ๋‚ ์งœ+์‹œ๊ฐ„)์œผ๋กœ ์ €์žฅํ• ์ง€ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

 


๐Ÿ’พ 4. BoardRepository ์ธํ„ฐํŽ˜์ด์Šค

 

์•ž์„œ ๋ณธ ๊ฒƒ์ฒ˜๋Ÿผ ๋งค์šฐ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

import org.springframework.data.repository.CrudRepository;

public interface BoardRepository extends CrudRepository<Board, Long> {
    // ํ˜„์žฌ๋Š” ๊ธฐ๋ณธ CRUD ๊ธฐ๋Šฅ๋งŒ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ์ถ”๊ฐ€ ๋ฉ”์„œ๋“œ ์ •์˜๋Š” ์—†์Šต๋‹ˆ๋‹ค.
}

์ด๋ ‡๊ฒŒ ํ•œ ์ค„๋งŒ ์ž‘์„ฑํ•ด๋„,
save, findById, deleteById, findAll ๋“ฑ ๊ธฐ๋ณธ ๊ธฐ๋Šฅ์ด ์ž๋™์œผ๋กœ ์ƒ๊น๋‹ˆ๋‹ค!


โœ… 5. ๊ธฐ๋Šฅ๋ณ„ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ๋”ฐ๋ผํ•ด๋ณด๊ธฐ!

์ด์ œ BoardRepository๊ฐ€ ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜๋Š”์ง€ JUnit ํ…Œ์ŠคํŠธ๋ฅผ ํ†ตํ•ด ํ™•์ธํ•ด๋ด…๋‹ˆ๋‹ค.

import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Date;
import static org.junit.jupiter.api.Assertions.assertTrue; // ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ ํ™•์ธ์šฉ

@SpringBootTest // ์Šคํ”„๋ง ๋ถ€ํŠธ ํ™˜๊ฒฝ์—์„œ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
@TestMethodOrder(MethodOrderer.OrderAnnotation.class) // @Order ์–ด๋…ธํ…Œ์ด์…˜ ์ˆœ์„œ๋Œ€๋กœ ํ…Œ์ŠคํŠธ ์‹คํ–‰
class BoardRepositoryTest {

    @Autowired // ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๊ฐ€ BoardRepository ๊ตฌํ˜„์ฒด๋ฅผ ์ž๋™์œผ๋กœ ์ฃผ์ž…ํ•ด์ค๋‹ˆ๋‹ค.
    private BoardRepository boardRepository;

    @Test
    @Order(1) // ์ฒซ ๋ฒˆ์งธ๋กœ ์‹คํ–‰๋  ํ…Œ์ŠคํŠธ: ๋ฐ์ดํ„ฐ ์‚ฝ์ž…
    public void insertTest() {
        System.out.println("๋ฐ์ดํ„ฐ ์‚ฝ์ž… ํ…Œ์ŠคํŠธ ์‹œ์ž‘...");
        Board board = new Board();      // ์ƒˆ๋กœ์šด Board ๊ฐ์ฒด ์ƒ์„ฑ
        board.setBno(1L);               // ID๋ฅผ ์ง์ ‘ ์„ค์ • (์ž๋™ ์ƒ์„ฑ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ)
        board.setTitle("์ฒซ ๋ฒˆ์งธ ๊ฒŒ์‹œ๊ธ€");
        board.setContent("Spring Data JPA ํ…Œ์ŠคํŠธ ์ค‘์ž…๋‹ˆ๋‹ค.");
        board.setWriter("๊ฐœ๋ฐœ์žA");
        board.setViewCnt(0L);
        board.setInDate(new Date());
        board.setUpDate(new Date());

        boardRepository.save(board);    // CrudRepository์˜ save ๋ฉ”์„œ๋“œ๋กœ ๋ฐ์ดํ„ฐ ์ €์žฅ!
        System.out.println("ID 1๋ฒˆ ๊ฒŒ์‹œ๊ธ€ ์ €์žฅ ์™„๋ฃŒ.");
    }

    @Test
    @Order(2) // ๋‘ ๋ฒˆ์งธ๋กœ ์‹คํ–‰๋  ํ…Œ์ŠคํŠธ: ๋ฐ์ดํ„ฐ ์กฐํšŒ
    public void selectTest() {
        System.out.println("\n๋ฐ์ดํ„ฐ ์กฐํšŒ ํ…Œ์ŠคํŠธ ์‹œ์ž‘...");
        // ID๊ฐ€ 1์ธ Board๋ฅผ ์กฐํšŒ. orElse(null)์€ ํ•ด๋‹น ID์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์œผ๋ฉด null์„ ๋ฐ˜ํ™˜.
        Board board = boardRepository.findById(1L).orElse(null);
        System.out.println("์กฐํšŒ๋œ ๊ฒŒ์‹œ๊ธ€: " + board);
        assertTrue(board != null, "1๋ฒˆ ๊ฒŒ์‹œ๊ธ€์ด ์กฐํšŒ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค."); // board๊ฐ€ null์ด ์•„๋‹ˆ๋ฉด ํ…Œ์ŠคํŠธ ์„ฑ๊ณต
    }

    @Test
    @Order(3) // ์„ธ ๋ฒˆ์งธ๋กœ ์‹คํ–‰๋  ํ…Œ์ŠคํŠธ: ๋ฐ์ดํ„ฐ ์ˆ˜์ •
    public void updateTest() {
        System.out.println("\n๋ฐ์ดํ„ฐ ์ˆ˜์ • ํ…Œ์ŠคํŠธ ์‹œ์ž‘...");
        Board board = boardRepository.findById(1L).orElse(null);
        assertTrue(board != null, "์ˆ˜์ •ํ•  1๋ฒˆ ๊ฒŒ์‹œ๊ธ€์ด ์กด์žฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.");

        board.setTitle("์ œ๋ชฉ ์ˆ˜์ •๋จ - Spring Data JPA"); // ์ œ๋ชฉ ์ˆ˜์ •
        boardRepository.save(board); // ๋‹ค์‹œ save ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ. ID(bno)๊ฐ€ ์กด์žฌํ•˜๋ฏ€๋กœ ์ˆ˜์ •(UPDATE)๋จ.

        Board updatedBoard = boardRepository.findById(1L).orElse(null);
        System.out.println("์ˆ˜์ • ํ›„ ์กฐํšŒ๋œ ๊ฒŒ์‹œ๊ธ€: " + updatedBoard);
        assertTrue(updatedBoard != null && "์ œ๋ชฉ ์ˆ˜์ •๋จ - Spring Data JPA".equals(updatedBoard.getTitle()), "์ œ๋ชฉ์ด ์„ฑ๊ณต์ ์œผ๋กœ ์ˆ˜์ •๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.");
        System.out.println("๊ฒŒ์‹œ๊ธ€ ์ˆ˜์ • ์™„๋ฃŒ.");
    }

    @Test
    @Order(4) // ๋„ค ๋ฒˆ์งธ๋กœ ์‹คํ–‰๋  ํ…Œ์ŠคํŠธ: ๋ฐ์ดํ„ฐ ์‚ญ์ œ
    public void deleteTest() {
        System.out.println("\n๋ฐ์ดํ„ฐ ์‚ญ์ œ ํ…Œ์ŠคํŠธ ์‹œ์ž‘...");
        boardRepository.deleteById(1L); // ID๊ฐ€ 1์ธ Board ์‚ญ์ œ

        Board board = boardRepository.findById(1L).orElse(null); // ์‚ญ์ œ ํ›„ ๋‹ค์‹œ ์กฐํšŒ
        System.out.println("์‚ญ์ œ ํ›„ ์กฐํšŒ๋œ ๊ฒŒ์‹œ๊ธ€: " + board);
        assertTrue(board == null, "1๋ฒˆ ๊ฒŒ์‹œ๊ธ€์ด ์„ฑ๊ณต์ ์œผ๋กœ ์‚ญ์ œ๋˜์–ด null์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค."); // board๊ฐ€ null์ด๋ฉด ํ…Œ์ŠคํŠธ ์„ฑ๊ณต
        System.out.println("๊ฒŒ์‹œ๊ธ€ ์‚ญ์ œ ์™„๋ฃŒ.");
    }
}
  • @SpringBootTest: ํ…Œ์ŠคํŠธ ์‹œ ์‹ค์ œ ์Šคํ”„๋ง ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ปจํ…์ŠคํŠธ๋ฅผ ๋กœ๋“œํ•˜์—ฌ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • @Autowired: BoardRepository ํƒ€์ž…์˜ ๋นˆ(Spring Data JPA๊ฐ€ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•œ ๊ตฌํ˜„์ฒด)์„ ์Šคํ”„๋ง์ด ์ฐพ์•„์„œ ์ฃผ์ž…ํ•ด์ค๋‹ˆ๋‹ค.
  • @Order(์ˆซ์ž): ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ์˜ ์‹คํ–‰ ์ˆœ์„œ๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ์˜ ์ƒํƒœ์— ์˜์กด์ ์ธ CRUD ํ…Œ์ŠคํŠธ์—์„œ๋Š” ์ˆœ์„œ๊ฐ€ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.
  • save() ๋ฉ”์„œ๋“œ์˜ ์ง€๋Šฅ์ ์ธ ๋™์ž‘: insertTest์—์„œ๋Š” ID๊ฐ€ ์—†๋Š” ์ƒˆ๋กœ์šด Board ๊ฐ์ฒด๋ฅผ save() ํ–ˆ์œผ๋ฏ€๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ƒˆ๋กœ์šด ํ–‰์ด ์‚ฝ์ž…(INSERT)๋ฉ๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด, updateTest์—์„œ๋Š” findById()๋กœ ๊ธฐ์กด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ ์ˆ˜์ •ํ•œ ํ›„ save()๋ฅผ ํ˜ธ์ถœํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋•Œ Board ๊ฐ์ฒด๋Š” ์ด๋ฏธ ID(bno)๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๊ณ , ์ด ID๊ฐ€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์กด์žฌํ•˜๋ฏ€๋กœ Spring Data JPA๋Š” ์ด๋ฅผ ๊ฐ์ง€ํ•˜์—ฌ ์ƒˆ๋กœ์šด ํ–‰์„ ์‚ฝ์ž…ํ•˜๋Š” ๋Œ€์‹  ๊ธฐ์กด ํ–‰์˜ ๋‚ด์šฉ์„ ๊ฐฑ์‹ (UPDATE)ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“ ์š”์•ฝ ์ •๋ฆฌ

๊ฐœ๋…ํ•œ ์ค„ ์š”์•ฝ
Spring Data ์ €์žฅ์†Œ ์ข…๋ฅ˜์™€ ์ƒ๊ด€์—†์ด ๋˜‘๊ฐ™์ด ๋‹ค๋ฃจ๊ธฐ
Spring Data JPA JPA๋ฅผ ์‰ฝ๊ฒŒ ์“ฐ๊ฒŒ ํ•ด์ฃผ๋Š” ๋„๊ตฌ
CrudRepository ๊ธฐ๋ณธ ์ €์žฅ/์กฐํšŒ/์ˆ˜์ •/์‚ญ์ œ ๊ธฐ๋Šฅ ์ œ๊ณต
PagingAndSortingRepository ํŽ˜์ด์ง•๊ณผ ์ •๋ ฌ ๊ธฐ๋Šฅ๊นŒ์ง€ ์ง€์›
save() ์ €์žฅ๋„ ๋˜๊ณ  ์ˆ˜์ •๋„ ๋จ
findById() ID๋กœ ํ•˜๋‚˜ ์กฐํšŒ
deleteById() ID๋กœ ํ•˜๋‚˜ ์‚ญ์ œ
findAll() ์ „์ฒด ์กฐํšŒ
 

๐ŸŽฏ ๋งˆ๋ฌด๋ฆฌ

์˜ค๋Š˜์€ Spring Data JPA๊ฐ€ ๋ฌด์—‡์ธ์ง€, ๊ทธ๋ฆฌ๊ณ  CrudRepository์™€ ๊ฐ™์€ ํŽธ๋ฆฌํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ์–ผ๋งˆ๋‚˜ ์‰ฝ๊ฒŒ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์‚ดํŽด๋ณด์•˜์Šต๋‹ˆ๋‹ค. ๋ณต์žกํ•œ SQL ๋ฌธ์žฅ์ด๋‚˜ JPA์˜ ๋‚ด๋ถ€ ๋™์ž‘์„ ๊นŠ์ด ์•Œ์ง€ ๋ชปํ•ด๋„, Spring Data JPA๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์ž˜ ์ •์˜๋œ ๋ฉ”์„œ๋“œ๋“ค์„ ํ™œ์šฉํ•˜๋ฉด ๊ธฐ๋ณธ์ ์ธ ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ๋Š” ์ •๋ง ๊ฐ„ํŽธํ•ด์ง‘๋‹ˆ๋‹ค.

๋ฐ˜์‘ํ˜•