๐ŸŽฏ F-lab Java 7์ฃผ์ฐจ ํ•™์Šต ์ปค๋ฆฌํ˜๋Ÿผ

7์ฃผ์ฐจ ์ž๋ฃŒ์˜ ๋ชจ๋“  ํ† ํ”ฝ์„ ๋‘ ๊ฐœ์˜ ํฐ ํ๋ฆ„์œผ๋กœ ์ •๋ฆฌํ•œ ํ•™์Šต ๊ฒฝ๋กœ.
1) ๋ฐ์ดํ„ฐ ๋ชจ๋ธ๋ง๊ณผ ORM โ€” SQL JOIN โ†’ ORM ํŒจ๋Ÿฌ๋‹ค์ž„ โ†’ JPA ์ž…๋ฌธ โ†’ ์—”ํ‹ฐํ‹ฐ ๋งคํ•‘
2) ํŠธ๋žœ์žญ์…˜ ์ถ”์ƒํ™”์˜ ์ง„ํ™” โ€” ์ˆ˜๋™ ๊ด€๋ฆฌ โ†’ PlatformTransactionManager โ†’ @Transactional

6์ฃผ์ฐจ์—์„œ JDBC์™€ JdbcTemplate์œผ๋กœ DB ์ ‘๊ทผ์„ ์ตํ˜”๋‹ค๋ฉด, 7์ฃผ์ฐจ๋Š” ํ•œ ๋‹จ๊ณ„ ๋” ๋†’์€ ์ถ”์ƒํ™”๋กœ ์˜ฌ๋ผ๊ฐ„๋‹ค.

์‚ฌ์ „ ๋ฉ”๋ชจ: ์ž๋ฃŒ ์ฒซ ๋ถ€๋ถ„์˜ "์Šคํ”„๋ง ๋นˆ์ด๋ž€?"์€ 5์ฃผ์ฐจ Phase 8(ApplicationContext + DI)์˜ ๋ณต์Šต ํฌ์ธํŠธ์ด๋ฏ€๋กœ ๋ณธ ์ปค๋ฆฌํ˜๋Ÿผ์—์„œ๋Š” Phase๋กœ ๋ถ„๋ฆฌํ•˜์ง€ ์•Š๊ณ  ํ•™์Šต ์šด์˜ ํŒ์—์„œ ์งง๊ฒŒ ๋‹ค๋ฃฌ๋‹ค.


๐Ÿ“Š ํ•™์Šต ๊ฒฝ๋กœ ํ•œ๋ˆˆ์— ๋ณด๊ธฐ

[Part A โ€” ๋ฐ์ดํ„ฐ ๋ชจ๋ธ๋ง๊ณผ ORM]
  [Phase 1] SQL JOIN โ€” ๊ด€๊ณ„ํ˜• DB์˜ ๋ณธ์งˆ
     โ†“
  [Phase 2] ORM ํŒจ๋Ÿฌ๋‹ค์ž„ โ€” ๊ฐ์ฒด์™€ ๊ด€๊ณ„์˜ ๋งŒ๋‚จ
     โ†“
  [Phase 3] JPA ์ž…๋ฌธ
     โ†“
  [Phase 4] JPA ์—”ํ‹ฐํ‹ฐ ๋งคํ•‘

[Part B โ€” ํŠธ๋žœ์žญ์…˜ ์ถ”์ƒํ™”์˜ ์ง„ํ™”]
  [Phase 5] ์ˆ˜๋™ ํŠธ๋žœ์žญ์…˜์˜ ํ•œ๊ณ„
     โ†“
  [Phase 6] PlatformTransactionManager (์ธํ„ฐํŽ˜์ด์Šค ์ถ”์ƒํ™”)
     โ†“
  [Phase 7] @Transactional (์„ ์–ธ์  ํŠธ๋žœ์žญ์…˜)

์ด 7 Phase ร— 24 Unit

๐Ÿ”— 1~7์ฃผ์ฐจ ํ๋ฆ„ ์ •๋ฆฌ

์ฃผ์ฐจ์ฃผ์ œํ•ต์‹ฌ ๋ณ€ํ™”
1์ฃผ์ฐจOOPยทJVMยทGCยท์ปฌ๋ ‰์…˜ยทI/O ๊ฐœ๋ก ์ž๋ฐ” ํฐ ๊ทธ๋ฆผ
2์ฃผ์ฐจJVM ๋‚ด๋ถ€ยท๋ฐ”์ดํŠธ์ฝ”๋“œยทG1 GC"์–ด๋–ป๊ฒŒ ๋Œ์•„๊ฐ€๋‚˜"
3์ฃผ์ฐจ์ปฌ๋ ‰์…˜ยท์ œ๋„ค๋ฆญยทํ•จ์ˆ˜ํ˜•์ž๋ฐ” ํ‘œํ˜„๋ ฅ
4์ฃผ์ฐจ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉยท๋™์‹œ์„ฑยทExecutor๋™์‹œ์„ฑ ์ •๋ณต
5์ฃผ์ฐจAtomic + Spring IoC/DI ์ž…๋ฌธ์ž๋ฐ” โ†’ Spring ๋‹ค๋ฆฌ
6์ฃผ์ฐจํ…Œ์ŠคํŠธ + ์›น ์ธํ”„๋ผ + DB ์ ‘๊ทผ ์ง„ํ™”Spring ์‹ค์ „ ํ™˜๊ฒฝ
7์ฃผ์ฐจ (์ง€๊ธˆ)ORM/JPA + ํŠธ๋žœ์žญ์…˜ ์ถ”์ƒํ™”DB ์ถ”์ƒํ™”์˜ ์ •์ 

๐Ÿ—“๏ธ ๊ถŒ์žฅ ํ•™์Šต ์ผ์ • (์••์ถ• 6์ผ)

DayPhaseํ•™์Šต ๋ชฉํ‘œ
1์ผ์ฐจPhase 1SQL JOIN 4์ข… ๋งˆ์Šคํ„ฐ
2์ผ์ฐจPhase 2 + 3ORM ํŒจ๋Ÿฌ๋‹ค์ž„ + JPA ์ž…๋ฌธ
3์ผ์ฐจPhase 4JPA ์—”ํ‹ฐํ‹ฐ ๋งคํ•‘ ์–ด๋…ธํ…Œ์ด์…˜
4์ผ์ฐจPhase 5 + 6์ˆ˜๋™ ํŠธ๋žœ์žญ์…˜ โ†’ PlatformTransactionManager
5์ผ์ฐจPhase 7@Transactional ๋™์ž‘ ์›๋ฆฌ
6์ผ์ฐจ์ข…ํ•ฉ ์ž๊ธฐ ์ ๊ฒ€ + ์‹ค์Šต์ „์ฒด ์ •๋ฆฌ

์ž๋ฃŒ ๋ถ„๋Ÿ‰์ด 5ยท6์ฃผ์ฐจ๋ณด๋‹ค ๊ฐ€๋ฒผ์›€. 6์ผ ์ผ์ •์œผ๋กœ ์ถฉ๋ถ„ํ•˜๋‚˜, JPA ์‹ค์Šต์„ ๋” ํ•˜๋ ค๋ฉด +3์ผ.


๐Ÿ—‚๏ธ Part A โ€” ๋ฐ์ดํ„ฐ ๋ชจ๋ธ๋ง๊ณผ ORM

๐Ÿ“š Phase 1 โ€” SQL JOIN: ๊ด€๊ณ„ํ˜• DB์˜ ๋ณธ์งˆ

๋ชฉํ‘œ: 4๊ฐ€์ง€ JOIN์˜ ๊ฒฐ๊ณผ๋ฅผ ๋จธ๋ฆฟ์†์—์„œ ๊ทธ๋ฆด ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค. JPA๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•œ ํ•„์ˆ˜ ๊ธฐ์ดˆ.

Unit 1.1 โ€” JOIN์ด ํ•„์š”ํ•œ ์ด์œ  (์ •๊ทœํ™”์˜ ๊ฒฐ๊ณผ)

์„ ์ˆ˜ ์ง€์‹: 6์ฃผ์ฐจ Phase 4 (DB ์„ธ์…˜)

ํ•ต์‹ฌ ๊ฐœ๋…

์™œ JOIN์ด ํ•„์š”ํ•œ๊ฐ€:

  • ๊ด€๊ณ„ํ˜• DB๋Š” ์ •๊ทœํ™” ๋ฅผ ํ†ตํ•ด ์ค‘๋ณต์„ ์ œ๊ฑฐ
  • ํ•˜๋‚˜์˜ ์ •๋ณด๊ฐ€ ์—ฌ๋Ÿฌ ํ…Œ์ด๋ธ”์— ๋ถ„์‚ฐ๋จ
  • ์˜ˆ: ์ง์›๊ณผ ๋ถ€์„œ๊ฐ€ ๋ณ„๋„ ํ…Œ์ด๋ธ”์— ์ €์žฅ
employees (์ง์›)              departments (๋ถ€์„œ)
โ”Œโ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”Œโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚idโ”‚ name  โ”‚dept_id    โ”‚   โ”‚ id โ”‚ dept_name    โ”‚
โ”œโ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค   โ”œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ 1โ”‚Alice  โ”‚       101 โ”‚   โ”‚101 โ”‚ HR           โ”‚
โ”‚ 2โ”‚Bob    โ”‚       102 โ”‚   โ”‚102 โ”‚ Engineering  โ”‚
โ”‚ 3โ”‚Charlieโ”‚      NULL โ”‚   โ”‚103 โ”‚ Sales        โ”‚
โ””โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ””โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

โ†’ "Alice๊ฐ€ ์–ด๋А ๋ถ€์„œ?" ๋‹ตํ•˜๋ ค๋ฉด ๋‘ ํ…Œ์ด๋ธ”์„ ํ•ฉ์ณ์•ผ ํ•จ โ†’ JOIN

์ž๊ธฐ ์ ๊ฒ€

  • ์ •๊ทœํ™”์˜ ์žฅ๋‹จ์ ์€? (ํžŒํŠธ: ์ค‘๋ณต โ†“, JOIN ๋น„์šฉ โ†‘)
  • "๋น„์ •๊ทœํ™”(์—ญ์ •๊ทœํ™”)"๋ฅผ ์“ฐ๋Š” ์‹œ๋‚˜๋ฆฌ์˜ค๋Š”? (ํžŒํŠธ: ๋ถ„์„์šฉ DB)

Unit 1.2 โ€” INNER JOIN (๊ต์ง‘ํ•ฉ)

์„ ์ˆ˜ ์ง€์‹: Unit 1.1

ํ•ต์‹ฌ ๊ฐœ๋…

"๋‘ ํ…Œ์ด๋ธ”์—์„œ ๊ณตํ†ต๋œ ๊ฐ’ ์ด ์žˆ๋Š” ํ–‰๋งŒ ๋ฐ˜ํ™˜"

SELECT e.id, e.name, d.department_name
FROM employees e
INNER JOIN departments d ON e.department_id = d.id;

๊ฒฐ๊ณผ:

id โ”‚ name  โ”‚ department_name
โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
 1 โ”‚ Alice โ”‚ HR
 2 โ”‚ Bob   โ”‚ Engineering

Charlie(๋ถ€์„œ NULL) ์™€ Sales(์ง์› ์—†์Œ) ๋Š” ์ œ์™ธ๋จ.

์ž๊ธฐ ์ ๊ฒ€

  • INNER JOIN๊ณผ ๋‹จ์ˆœ SELECT FROM A, B WHERE A.x = B.y ์˜ ์ฐจ์ด๋Š”?
  • ON ์กฐ๊ฑด๊ณผ WHERE ์กฐ๊ฑด์˜ ์ฐจ์ด๋Š”? (ํžŒํŠธ: OUTER JOIN์—์„œ ๋‹ค๋ฆ„)

Unit 1.3 โ€” LEFT JOIN๊ณผ RIGHT JOIN

์„ ์ˆ˜ ์ง€์‹: Unit 1.2

ํ•ต์‹ฌ ๊ฐœ๋…

LEFT JOIN: ์™ผ์ชฝ ํ…Œ์ด๋ธ”์˜ ๋ชจ๋“  ํ–‰ ๋ฐ˜ํ™˜, ์˜ค๋ฅธ์ชฝ ๋งค์นญ ์—†์œผ๋ฉด NULL

SELECT e.id, e.name, d.department_name
FROM employees e
LEFT JOIN departments d ON e.department_id = d.id;
id โ”‚ name    โ”‚ department_name
โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
 1 โ”‚ Alice   โ”‚ HR
 2 โ”‚ Bob     โ”‚ Engineering
 3 โ”‚ Charlie โ”‚ NULL          โ† ๋ถ€์„œ ์—†๋Š” ์ง์›๋„ ํฌํ•จ

RIGHT JOIN: ์™ผ์ชฝ/์˜ค๋ฅธ์ชฝ์ด ๋ฐ˜๋Œ€

SELECT e.id, e.name, d.department_name
FROM employees e
RIGHT JOIN departments d ON e.department_id = d.id;
id   โ”‚ name  โ”‚ department_name
โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
   1 โ”‚ Alice โ”‚ HR
   2 โ”‚ Bob   โ”‚ Engineering
NULL โ”‚ NULL  โ”‚ Sales         โ† ์ง์› ์—†๋Š” ๋ถ€์„œ๋„ ํฌํ•จ

์ž๊ธฐ ์ ๊ฒ€

  • LEFT JOIN๊ณผ RIGHT JOIN ์ค‘ ์–ด๋А ์ชฝ์ด ์‹ค๋ฌด์—์„œ ๋” ์ž์ฃผ ์“ฐ์ด๋Š”๊ฐ€?
  • A LEFT JOIN B ์™€ B RIGHT JOIN A ๋Š” ๊ฐ™์€๊ฐ€?

Unit 1.4 โ€” FULL OUTER JOIN (ํ•ฉ์ง‘ํ•ฉ)

์„ ์ˆ˜ ์ง€์‹: Unit 1.3

ํ•ต์‹ฌ ๊ฐœ๋…

"์–‘์ชฝ ํ…Œ์ด๋ธ”์˜ ๋ชจ๋“  ํ–‰ ๋ฐ˜ํ™˜, ๋งค์นญ ์—†์œผ๋ฉด NULL"

SELECT e.id, e.name, d.department_name
FROM employees e
FULL OUTER JOIN departments d ON e.department_id = d.id;
id   โ”‚ name    โ”‚ department_name
โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
   1 โ”‚ Alice   โ”‚ HR
   2 โ”‚ Bob     โ”‚ Engineering
   3 โ”‚ Charlie โ”‚ NULL          โ† ๋ถ€์„œ ์—†๋Š” ์ง์›
NULL โ”‚ NULL    โ”‚ Sales         โ† ์ง์› ์—†๋Š” ๋ถ€์„œ

MySQL์€ FULL OUTER JOIN์„ ์ง€์›ํ•˜์ง€ ์•Š์Œ โ†’ LEFT JOIN UNION RIGHT JOIN ์œผ๋กœ ์šฐํšŒ.

์ž๊ธฐ ์ ๊ฒ€

  • FULL OUTER JOIN์˜ ๊ฒฐ๊ณผ ํ–‰ ์ˆ˜๋Š” INNER JOIN๊ณผ ์–ด๋–ป๊ฒŒ ๋‹ค๋ฅธ๊ฐ€?
  • 4๊ฐ€์ง€ JOIN ๊ฒฐ๊ณผ์˜ ํฌํ•จ๊ด€๊ณ„๋ฅผ ๋ฒค๋‹ค์ด์–ด๊ทธ๋žจ์œผ๋กœ?

Unit 1.5 โ€” JOIN ์„ ํƒ ๊ฐ€์ด๋“œ

์„ ์ˆ˜ ์ง€์‹: Unit 1.4

์„ ํƒ ๋งคํŠธ๋ฆญ์Šค:

์‹œ๋‚˜๋ฆฌ์˜คJOIN ์ข…๋ฅ˜
์–‘์ชฝ์— ๋ชจ๋‘ ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋งŒ ํ•„์š”INNER JOIN
์™ผ์ชฝ ํ…Œ์ด๋ธ”์˜ ๋ชจ๋“  ๋ฐ์ดํ„ฐ + ๋งค์นญ๋˜๋Š” ์˜ค๋ฅธ์ชฝLEFT JOIN
๋‘ ํ…Œ์ด๋ธ” ๋ชจ๋‘์˜ ๋ชจ๋“  ๋ฐ์ดํ„ฐFULL OUTER JOIN
"๋ถ€์„œ ์—†๋Š” ์ง์›๋งŒ" ๊ฐ™์€ ์ฐจ์ง‘ํ•ฉLEFT JOIN + WHERE NULL

์‹ค๋ฌด ํŒ:

  • LEFT JOIN์ด ๊ฐ€์žฅ ๋นˆ๋ฒˆ (๋ˆ„๋ฝ ์—†์ด ๋‹ค ๋ณด๊ณ  ์‹ถ์Œ)
  • INNER JOIN์€ ์นด์šดํŠธยท์ง‘๊ณ„์— ์œ ์šฉ
  • RIGHT JOIN์€ ๊ฑฐ์˜ ์•ˆ ์”€ (๊ฐ€๋…์„ฑ โ†“ โ†’ LEFT JOIN์œผ๋กœ ํ‘œํ˜„)

์ž๊ธฐ ์ ๊ฒ€

  • "๋ถ€์„œ ์—†๋Š” ์ง์› ์ฐพ๊ธฐ" ์ฟผ๋ฆฌ๋Š”?
  • "์ง์› ์—†๋Š” ๋ถ€์„œ ์ฐพ๊ธฐ" ์ฟผ๋ฆฌ๋Š”?

๐Ÿ“š Phase 2 โ€” ORM ํŒจ๋Ÿฌ๋‹ค์ž„

๋ชฉํ‘œ: ORM์ด ์™œ ํ•„์š”ํ•œ์ง€๋ฅผ, ๊ฐ์ฒด์™€ ๊ด€๊ณ„ ๋ชจ๋ธ์˜ ๋ณธ์งˆ์  ๋ฏธ์Šค๋งค์น˜๋กœ ์ดํ•ดํ•œ๋‹ค.

Unit 2.1 โ€” ๊ฐ์ฒด-๊ด€๊ณ„ ๋ฏธ์Šค๋งค์น˜

์„ ์ˆ˜ ์ง€์‹: 1์ฃผ์ฐจ Phase 1 (OOP), Phase 1 (JOIN)

ํ•ต์‹ฌ ๊ฐœ๋…

๊ฐ์ฒด์™€ ๊ด€๊ณ„ํ˜• DB๋Š” ๋‹ค๋ฅธ ํŒจ๋Ÿฌ๋‹ค์ž„:

์ธก๋ฉด๊ฐ์ฒด (OOP)๊ด€๊ณ„ํ˜• DB
๋ชจ๋ธ๋ง์ƒํƒœ + ํ–‰๋™ํ–‰๊ณผ ์—ด
์ƒ์†์žˆ์Œ์—†์Œ
์—ฐ๊ด€ ๊ด€๊ณ„์ฐธ์กฐ (order.member)์™ธ๋ž˜ ํ‚ค (FK)
์‹๋ณ„๊ฐ์ฒด ์‹๋ณ„์ž (==)PK
๋ฐ์ดํ„ฐ ํƒ€์ž…ํ’๋ถ€ (List, Map, ...)์ œํ•œ์ 

โ†’ ์ด ์ฐจ์ด๋ฅผ ๋ฉ”์šฐ๋Š” ์ฝ”๋“œ๋ฅผ ๋งค๋ฒˆ ์†์œผ๋กœ ์“ฐ๋Š” ๊ฒŒ ORM ๋“ฑ์žฅ ์ „์˜ ๊ณ ํ†ต

์ž๊ธฐ ์ ๊ฒ€

  • Order ๊ฐ์ฒด๊ฐ€ List<OrderItem> ์„ ๊ฐ–๋Š” ๊ตฌ์กฐ๋ฅผ RDB๋กœ ์–ด๋–ป๊ฒŒ ํ‘œํ˜„ํ•˜๋Š”๊ฐ€?
  • ๊ฐ์ฒด์˜ ์ƒ์†์„ RDB๋กœ ํ‘œํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ• 3๊ฐ€์ง€๋Š”? (ํžŒํŠธ: SINGLE_TABLE, JOINED, TABLE_PER_CLASS)

Unit 2.2 โ€” ORM์˜ ์ •์˜์™€ ํšจ๊ณผ

์„ ์ˆ˜ ์ง€์‹: Unit 2.1

ํ•ต์‹ฌ ๊ฐœ๋…

ORM (Object-Relational Mapping):

  • ๊ฐ์ฒด๋Š” ๊ฐ์ฒด๋Œ€๋กœ ์„ค๊ณ„
  • ๊ด€๊ณ„ํ˜• DB๋Š” DB๋Œ€๋กœ ์„ค๊ณ„
  • ORM ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์ค‘๊ฐ„์—์„œ ๋งคํ•‘

ํšจ๊ณผ:

  • ๋งคํ•‘ ์ฝ”๋“œ๋ฅผ ์ž๋™ ์ƒ์„ฑ โ†’ ๊ฐœ๋ฐœ ์†๋„ โ†‘
  • DB ๋ณ€๊ฒฝ ์‹œ ์ฝ”๋“œ ๋ณ€๊ฒฝ โ†“
  • ๊ฐ์ฒด์ง€ํ–ฅ์  ์ฝ”๋“œ ์œ ์ง€

๋Œ€์ค‘์  ORM:

  • Java: Hibernate, EclipseLink
  • Python: SQLAlchemy, Django ORM
  • Ruby: ActiveRecord
  • C#: Entity Framework

์ž๊ธฐ ์ ๊ฒ€

  • ORM์ด SQL์„ ์™„์ „ํžˆ ๋Œ€์ฒดํ•˜๋Š”๊ฐ€? (ํžŒํŠธ: NO, ๋ณต์žก ์ฟผ๋ฆฌ๋Š” ์—ฌ์ „ํžˆ SQL)
  • ORM์˜ ๋‹จ์  3๊ฐ€์ง€๋Š”? (ํžŒํŠธ: ํ•™์Šต๊ณก์„ , N+1, ์„ฑ๋Šฅ ํŠœ๋‹ ์–ด๋ ค์›€)

๐Ÿ“š Phase 3 โ€” JPA ์ž…๋ฌธ

๋ชฉํ‘œ: JPA๊ฐ€ ์ž๋ฐ” ์ง„์˜์˜ ORM ํ‘œ์ค€์ž„์„ ์ดํ•ดํ•˜๊ณ , JdbcTemplate/MyBatis์™€์˜ ๊ฒฐ์ •์  ์ฐจ์ด๋ฅผ ์žก๋Š”๋‹ค.

Unit 3.1 โ€” SQL Mapper์˜ ํ•œ๊ณ„

์„ ์ˆ˜ ์ง€์‹: 6์ฃผ์ฐจ Phase 7 (JdbcTemplate)

ํ•ต์‹ฌ ํ•œ๊ณ„

JdbcTemplate, MyBatis ๊ฐ™์€ SQL Mapper ๋Š”:

  • โœ… ์ž์› ๊ด€๋ฆฌ ์ž๋™ํ™”
  • โœ… ๊ฒฐ๊ณผ ๋งคํ•‘ ์ž๋™ํ™”
  • โŒ SQL์€ ์—ฌ์ „ํžˆ ์ง์ ‘ ์ž‘์„ฑ
  • โŒ ๊ฐ์ฒด-๊ด€๊ณ„ ๋งคํ•‘์€ ์—ฌ์ „ํžˆ ์ˆ˜๋™

์˜ˆ์‹œ (JdbcTemplate):

String sql = "SELECT * FROM item WHERE id = ?";
Item item = jdbcTemplate.queryForObject(sql, itemRowMapper, id);
// โ†‘ SQL๊ณผ RowMapper๋ฅผ ์ง์ ‘ ์ž‘์„ฑ

โ†’ "SQL ์ž์ฒด๋ฅผ ์•ˆ ์“ฐ๋Š” ๋ฐฉ๋ฒ•์€ ์—†์„๊นŒ?"

์ž๊ธฐ ์ ๊ฒ€

  • JdbcTemplate์ด ํ•ด๊ฒฐํ•˜์ง€ ๋ชปํ•˜๋Š” ๋งคํ•‘ ์ž‘์—…์€?
  • ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„(์˜ˆ: Order โ†’ List) ๋ฅผ SQL Mapper๋กœ ์ฒ˜๋ฆฌํ•˜๋ฉด?

Unit 3.2 โ€” JPA์˜ ๋“ฑ์žฅ

์„ ์ˆ˜ ์ง€์‹: Unit 3.1

ํ•ต์‹ฌ ๊ฐœ๋…

JPA (Java Persistence API):

  • ์ž๋ฐ” ์ง„์˜์˜ ORM ํ‘œ์ค€ ์ธํ„ฐํŽ˜์ด์Šค
  • ๊ตฌํ˜„์ฒด: Hibernate(๊ฐ€์žฅ ๋Œ€์ค‘์ ), EclipseLink
  • ์–ด๋…ธํ…Œ์ด์…˜ ๊ธฐ๋ฐ˜ ๋งคํ•‘
  • SQL์„ JPA๊ฐ€ ๋Œ€์‹  ์ž‘์„ฑ

SQL Mapper vs JPA:

SQL Mapper (JdbcTemplate, MyBatis)JPA
SQL ์ž‘์„ฑ๊ฐœ๋ฐœ์žJPA๊ฐ€ ์ž๋™ ์ƒ์„ฑ
๋งคํ•‘RowMapper๋กœ ์ˆ˜๋™์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ ์„ ์–ธ
๊ฐ์ฒด ๊ทธ๋ž˜ํ”„์ˆ˜๋™ ์ฒ˜๋ฆฌ์ž๋™ (Lazy Loading)
ํ•™์Šต ๊ณก์„ ๋‚ฎ์Œ๋†’์Œ
๋ณต์žก ์ฟผ๋ฆฌ์ž์œ ์–ด๋ ค์›€ (๋„ค์ดํ‹ฐ๋ธŒ ์ฟผ๋ฆฌ ํ•„์š”)

์ž๊ธฐ ์ ๊ฒ€

  • JPA๋ฅผ ์“ฐ๋ฉด SQL์„ ์ „ํ˜€ ์•ˆ ์จ๋„ ๋˜๋Š”๊ฐ€? (ํžŒํŠธ: NO, ๋ณต์žก ํ†ต๊ณ„ ๋“ฑ)
  • JPA๊ฐ€ ๋งŒ๋“  SQL์„ ์–ด๋–ป๊ฒŒ ํ™•์ธํ• ๊นŒ? (ํžŒํŠธ: show-sql, format-sql)

Unit 3.3 โ€” JPA์˜ ๋™์ž‘ ์œ„์น˜

์„ ์ˆ˜ ์ง€์‹: Unit 3.2

ํ•ต์‹ฌ ๊ทธ๋ฆผ

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚      Application Code           โ”‚
โ”‚  (Item, Member, Order ๊ฐ์ฒด...)   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
             โ”‚ JPA API
             โ†“
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚           JPA                   โ”‚  โ† ๊ฐ์ฒด โ†” SQL ๋ณ€ํ™˜
โ”‚     (Hibernate ๊ตฌํ˜„์ฒด)           โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
             โ”‚ JDBC API
             โ†“
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚            JDBC                 โ”‚  โ† Connection, PreparedStatement
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
             โ”‚ DB Driver
             โ†“
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚            DB                   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

ํ•ต์‹ฌ ์œ„์น˜:

  • JPA = ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ JDBC ์‚ฌ์ด์˜ ์ค‘๊ฐ„ ๊ณ„์ธต
  • ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” ์—ฌ์ „ํžˆ JDBC๋ฅผ ์‚ฌ์šฉ
  • 6์ฃผ์ฐจ์—์„œ ๋ณธ DataSource, ConnectionPool์€ ๊ทธ๋Œ€๋กœ ํ™œ์šฉ

์ž๊ธฐ ์ ๊ฒ€

  • JPA๋ฅผ ์“ฐ๋ฉด JDBC๋ฅผ ์•ˆ ์“ฐ๋Š”๊ฐ€? (ํžŒํŠธ: ๋‚ด๋ถ€์ ์œผ๋กœ ์‚ฌ์šฉ)
  • HikariCP๋Š” JPA์—์„œ๋„ ํ™œ์šฉ๋˜๋Š”๊ฐ€? (ํžŒํŠธ: YES)

Unit 3.4 โ€” JPA ์ƒํƒœ๊ณ„ (์Šคํ”„๋ง ๋ฐ์ดํ„ฐ JPA, Querydsl)

์„ ์ˆ˜ ์ง€์‹: Unit 3.3

ํ•ต์‹ฌ ๊ฐœ๋…

JPA๋ฅผ ๋” ํŽธ๋ฆฌํ•˜๊ฒŒ ์“ฐ๊ธฐ ์œ„ํ•œ ๋„๊ตฌ๋“ค:

Spring Data JPA:

  • JPA๋ฅผ ๋” ์ถ”์ƒํ™”
  • Repository ์ธํ„ฐํŽ˜์ด์Šค๋งŒ ๋งŒ๋“ค๋ฉด ์ž๋™ ๊ตฌํ˜„
  • findByName(name) ๊ฐ™์€ ๋ฉ”์„œ๋“œ ์ด๋ฆ„์œผ๋กœ ์ฟผ๋ฆฌ ์ž๋™ ์ƒ์„ฑ
public interface ItemRepository extends JpaRepository<Item, Long> {
    List<Item> findByItemNameContaining(String keyword);
    // โ†‘ ๊ตฌํ˜„์ฒด๋Š” Spring์ด ์ž๋™ ์ƒ์„ฑ
}

Querydsl:

  • ํƒ€์ž… ์•ˆ์ „ํ•œ ๋™์  ์ฟผ๋ฆฌ
  • ์ปดํŒŒ์ผ ์‹œ์ ์— ์˜ค๋ฅ˜ ๊ฒ€์ถœ
  • ๋ณต์žกํ•œ ์ฟผ๋ฆฌ์—์„œ ๊ฐ•๋ ฅ
queryFactory
    .selectFrom(item)
    .where(item.price.gt(1000)
           .and(item.itemName.contains(keyword)))
    .fetch();

์‹ค๋ฌด ์กฐํ•ฉ: Spring Data JPA + Querydsl (๊ฐ€์žฅ ์ผ๋ฐ˜์ )

์ž๊ธฐ ์ ๊ฒ€

  • "Spring Data JPA" ์™€ "JPA"๋Š” ๊ฐ™์€ ๊ฒƒ์ธ๊ฐ€? (ํžŒํŠธ: ๋‹ค๋ฆ„)
  • ๋‹จ์ˆœ CRUD๋Š” Spring Data JPA, ๋ณต์žก ์ฟผ๋ฆฌ๋Š”?

๐Ÿ“š Phase 4 โ€” JPA ์—”ํ‹ฐํ‹ฐ ๋งคํ•‘

๋ชฉํ‘œ: ์ž๋ฐ” ๊ฐ์ฒด๋ฅผ DB ํ…Œ์ด๋ธ”๊ณผ ๋งคํ•‘ํ•˜๋Š” ์–ด๋…ธํ…Œ์ด์…˜ 4์ข…์„ ์†์— ์ตํžŒ๋‹ค.

Unit 4.1 โ€” @Entity์™€ ์—”ํ‹ฐํ‹ฐ ๊ฐœ๋…

์„ ์ˆ˜ ์ง€์‹: Phase 3

ํ•ต์‹ฌ ๊ฐœ๋…

@Entity
public class Item {
    // ...
}
  • @Entity: ์ด ํด๋ž˜์Šค๊ฐ€ JPA๊ฐ€ ๊ด€๋ฆฌํ•˜๋Š” ๊ฐ์ฒด์ž„์„ ํ‘œ์‹œ
  • ์ด ์–ด๋…ธํ…Œ์ด์…˜์ด ์žˆ์–ด์•ผ JPA๊ฐ€ ์ธ์‹
  • @Entity ๊ฐ€ ๋ถ™์€ ๊ฐ์ฒด = ์—”ํ‹ฐํ‹ฐ(Entity)

์—”ํ‹ฐํ‹ฐ์˜ ์กฐ๊ฑด:

  • @Entity ์–ด๋…ธํ…Œ์ด์…˜
  • ๊ธฐ๋ณธ ์ƒ์„ฑ์ž ํ•„์ˆ˜ (JPA๊ฐ€ ๋ฆฌํ”Œ๋ ‰์…˜์œผ๋กœ ๊ฐ์ฒด ์ƒ์„ฑ)
  • final ํด๋ž˜์Šค โŒ (JPA๊ฐ€ ํ”„๋ก์‹œ ๋งŒ๋“ค์–ด์•ผ ํ•จ)

์ž๊ธฐ ์ ๊ฒ€

  • DTO์™€ Entity์˜ ์ฐจ์ด๋Š”?
  • ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค๋ฅผ final๋กœ ๋งŒ๋“ค๋ฉด ์–ด๋–ค ๋ฌธ์ œ๊ฐ€? (ํžŒํŠธ: ํ”„๋ก์‹œ)

Unit 4.2 โ€” @Id์™€ PK ๋งคํ•‘

์„ ์ˆ˜ ์ง€์‹: Unit 4.1

ํ•ต์‹ฌ ๊ฐœ๋…

@Entity
public class Item {
    @Id
    private Long id;
    // ...
}
  • @Id: ํ…Œ์ด๋ธ”์˜ PK ์ปฌ๋Ÿผ๊ณผ ๋งคํ•‘
  • ๋ชจ๋“  ์—”ํ‹ฐํ‹ฐ๋Š” @Id ๊ฐ€ ๋ฐ˜๋“œ์‹œ 1๊ฐœ (ํ˜น์€ ๋ณตํ•ฉ ํ‚ค)

์ž๊ธฐ ์ ๊ฒ€

  • @Id ์—†์ด ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋งŒ๋“ค๋ฉด?
  • ๋ณตํ•ฉ ํ‚ค๋Š” ์–ด๋–ป๊ฒŒ ํ‘œํ˜„ํ•˜๋Š”๊ฐ€? (ํžŒํŠธ: @IdClass, @EmbeddedId)

Unit 4.3 โ€” @GeneratedValue ์ „๋žต

์„ ์ˆ˜ ์ง€์‹: Unit 4.2

ํ•ต์‹ฌ ๊ฐœ๋…

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

4๊ฐ€์ง€ ์ƒ์„ฑ ์ „๋žต:

์ „๋žต๋™์ž‘์ ํ•ฉ DB
IDENTITYDB์˜ auto_increment ์‚ฌ์šฉMySQL, PostgreSQL
SEQUENCEDB ์‹œํ€€์Šค ๊ฐ์ฒด ์‚ฌ์šฉOracle, PostgreSQL
TABLEํ‚ค ์ƒ์„ฑ์šฉ ํ…Œ์ด๋ธ” ์‚ฌ์šฉ๋ชจ๋“  DB (์„ฑ๋Šฅ โ†“)
AUTODB์— ๋”ฐ๋ผ ์ž๋™ ์„ ํƒ(๊ธฐ๋ณธ๊ฐ’)

MySQL์—์„œ IDENTITY ์˜๋ฏธ:

  • DB๊ฐ€ PK ๊ฐ’์„ ๊ฒฐ์ • (auto_increment)
  • INSERT ํ›„์—์•ผ ID ๊ฐ’์„ ์•Œ ์ˆ˜ ์žˆ์Œ

์ž๊ธฐ ์ ๊ฒ€

  • IDENTITY ์ „๋žต์˜ ๋‹จ์ ์€? (ํžŒํŠธ: ๋ฐฐ์น˜ INSERT ๋ถˆ๊ฐ€)
  • SEQUENCE๊ฐ€ IDENTITY๋ณด๋‹ค ๋น ๋ฅธ ์ด์œ ๋Š”? (ํžŒํŠธ: ๋ฏธ๋ฆฌ ๋ฐ›์•„๋‘ )

Unit 4.4 โ€” @Column๊ณผ ์ปฌ๋Ÿผ ๋งคํ•‘

์„ ์ˆ˜ ์ง€์‹: Unit 4.3

ํ•ต์‹ฌ ๊ฐœ๋…

@Column(name = "item_name", length = 10)
private String itemName;

์ฃผ์š” ์˜ต์…˜:

  • name: DB ์ปฌ๋Ÿผ๋ช… (์ง€์ • ์•ˆ ํ•˜๋ฉด ํ•„๋“œ๋ช… ๊ทธ๋Œ€๋กœ)
  • length: ๋ฌธ์ž์—ด ์ตœ๋Œ€ ๊ธธ์ด (DDL ์ƒ์„ฑ ์‹œ ํ™œ์šฉ)
  • nullable: NULL ํ—ˆ์šฉ ์—ฌ๋ถ€
  • unique: UNIQUE ์ œ์•ฝ
  • columnDefinition: ์ปฌ๋Ÿผ DDL ์ง์ ‘ ์ž‘์„ฑ

์˜ˆ์‹œ:

@Column(name = "user_email", length = 100, nullable = false, unique = true)
private String email;

์ž๊ธฐ ์ ๊ฒ€

  • @Column ์˜ต์…˜์ด DB ์Šคํ‚ค๋งˆ์— ์–ด๋–ป๊ฒŒ ๋ฐ˜์˜๋˜๋Š”๊ฐ€? (ํžŒํŠธ: ddl-auto ์„ค์ •)
  • length๋งŒ ์ง€์ •ํ•˜๋ฉด ๋‹ค๋ฅธ ์˜ต์…˜์€ ์–ด๋–ป๊ฒŒ ๋˜๋Š”๊ฐ€? (ํžŒํŠธ: ๊ธฐ๋ณธ๊ฐ’)

Unit 4.5 โ€” ์ž๋™ ๋งคํ•‘ ๊ทœ์น™ (camelCase โ†” snake_case)

์„ ์ˆ˜ ์ง€์‹: Unit 4.4

ํ•ต์‹ฌ ๊ฐœ๋…

Spring Boot์˜ JPA ํ†ตํ•ฉ:

  • ์ž๋ฐ” ํ•„๋“œ: itemName (camelCase)
  • DB ์ปฌ๋Ÿผ: item_name (snake_case)
  • โ†’ ์ž๋™ ๋ณ€ํ™˜

์ฆ‰:

@Column(name = "item_name")  // ๋ช…์‹œ์ 
private String itemName;

// ๋˜๋Š”

private String itemName;  // ์ž๋™์œผ๋กœ item_name์œผ๋กœ ๋งคํ•‘

โ†’ Spring Boot ํ™˜๊ฒฝ์—์„œ @Column(name = "item_name") ์€ ์ƒ๋žต ๊ฐ€๋Šฅ.

์ž๊ธฐ ์ ๊ฒ€

  • ์ด ์ž๋™ ๋ณ€ํ™˜์„ ๋„๋ ค๋ฉด? (ํžŒํŠธ: NamingStrategy ์„ค์ •)
  • ์นด๋ฉœโ†’์Šค๋„ค์ดํฌ ์ž๋™ ๋ณ€ํ™˜์˜ ์ด๋ฆ„์€? (ํžŒํŠธ: SpringPhysicalNamingStrategy)

๐Ÿ”„ Part B โ€” ํŠธ๋žœ์žญ์…˜ ์ถ”์ƒํ™”์˜ ์ง„ํ™”

๐Ÿ“š Phase 5 โ€” ์ˆ˜๋™ ํŠธ๋žœ์žญ์…˜์˜ ํ•œ๊ณ„

๋ชฉํ‘œ: "์™œ @Transactional ์ด ํ•„์š”ํ•œ๊ฐ€" ๋ผ๋Š” ์งˆ๋ฌธ์— ์ง์ ‘ ์ฝ”๋“œ๋กœ ๋‹ตํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

Unit 5.1 โ€” ํŠธ๋žœ์žญ์…˜์ด ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๊ณผ ๊ฒฐํ•ฉ๋˜๋Š” ๋ฌธ์ œ

์„ ์ˆ˜ ์ง€์‹: 6์ฃผ์ฐจ Phase 6 (ํŠธ๋žœ์žญ์…˜ ACID)

ํ•ต์‹ฌ ์‹œ๋‚˜๋ฆฌ์˜ค

๊ณ„์ขŒ ์ด์ฒด:

  • A๊ณ„์ขŒ 10,000์›, B๊ณ„์ขŒ 10,000์›
  • A โ†’ B๋กœ 2,000์› ์ด์ฒด
  • ์ตœ์ข…: A๋Š” 8,000์›, B๋Š” 12,000์›

์›์ž์„ฑ ๋ณด์žฅ ์กฐ๊ฑด:

  • ์ถœ๊ธˆ๊ณผ ์ž…๊ธˆ์ด ํ•˜๋‚˜์˜ ํŠธ๋žœ์žญ์…˜ ์•ˆ์—์„œ ์‹คํ–‰
  • โ†’ ๊ฐ™์€ Connection ์‚ฌ์šฉ ํ•„์š”
  • โ†’ Connection์„ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์— ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌ
public void transfer(Connection conn, ...) {  // โ† Connection์ด ๋งค๊ฐœ๋ณ€์ˆ˜
    accountDao.withdraw(conn, fromId, amount);
    accountDao.deposit(conn, toId, amount);
}

โ†’ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด Connection์„ ์‹ ๊ฒฝ ์จ์•ผ ํ•จ = ์ถ”์ƒํ™” ๊นจ์ง

์ž๊ธฐ ์ ๊ฒ€

  • Connection์„ ์ „๋‹ฌํ•˜์ง€ ์•Š๊ณ  ํŠธ๋žœ์žญ์…˜์„ ๋ฌถ์„ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์€?
  • ์ด ๋ฌธ์ œ์™€ 5์ฃผ์ฐจ์˜ "๊ด€์‹ฌ์‚ฌ ๋ถ„๋ฆฌ" ๋Š” ์–ด๋–ป๊ฒŒ ์—ฐ๊ฒฐ๋˜๋Š”๊ฐ€?

Unit 5.2 โ€” ์ˆ˜๋™ ํŠธ๋žœ์žญ์…˜์˜ 3๊ฐ€์ง€ ํ•จ์ •

์„ ์ˆ˜ ์ง€์‹: Unit 5.1

ํ•ต์‹ฌ ์ฝ”๋“œ

public void performTransaction() throws SQLException {
    Connection conn = null;
    try {
        conn = dataSource.getConnection();
        conn.setAutoCommit(false);  // ํŠธ๋žœ์žญ์…˜ ์‹œ์ž‘

        // ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง 1
        PreparedStatement ps1 = conn.prepareStatement("INSERT ...");
        ps1.executeUpdate();

        // ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง 2
        PreparedStatement ps2 = conn.prepareStatement("UPDATE ...");
        ps2.executeUpdate();

        conn.commit();  // ๋ชจ๋‘ ์„ฑ๊ณตํ•˜๋ฉด ์ปค๋ฐ‹
    } catch (Exception e) {
        if (conn != null) conn.rollback();  // ์‹คํŒจ ์‹œ ๋กค๋ฐฑ
        throw e;
    } finally {
        if (conn != null) conn.close();  // ์ž์› ํ•ด์ œ
    }
}

3๊ฐ€์ง€ ํ•จ์ •:
1. ํŠธ๋žœ์žญ์…˜ ๋ˆ„์ˆ˜: setAutoCommit, commit, rollback ์ฝ”๋“œ ๋งค๋ฒˆ ๋ฐ˜๋ณต
2. ์˜ˆ์™ธ ๋ˆ„์ˆ˜: SQLException์ด ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๊นŒ์ง€ ์ „ํŒŒ
3. JDBC ๋ฐ˜๋ณต: Connection ์ƒ์„ฑยทclose ์ฝ”๋“œ ๋ฐ˜๋ณต

โ†’ 6์ฃผ์ฐจ์˜ JdbcTemplate์€ ๋ถ€๋ถ„์  ํ•ด๊ฒฐ, ํŠธ๋žœ์žญ์…˜์€ ๊ทธ๋Œ€๋กœ ๋‚จ์Œ

์ž๊ธฐ ์ ๊ฒ€

  • ์œ„ ์ฝ”๋“œ์—์„œ ๋ณ€ํ•˜์ง€ ์•Š๋Š” ๋ถ€๋ถ„๊ณผ ๋ณ€ํ•˜๋Š” ๋ถ€๋ถ„์€?
  • 5์ฃผ์ฐจ์˜ ์–ด๋–ค ๋””์ž์ธ ํŒจํ„ด์œผ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์„๊นŒ? (ํžŒํŠธ: ํ…œํ”Œ๋ฆฟ ๋ฉ”์†Œ๋“œ)

๐Ÿ“š Phase 6 โ€” PlatformTransactionManager (ํŠธ๋žœ์žญ์…˜์˜ ์ถ”์ƒํ™”)

๋ชฉํ‘œ: Spring์ด ํŠธ๋žœ์žญ์…˜์„ ์–ด๋–ป๊ฒŒ ์ถ”์ƒํ™”ํ–ˆ๋Š”์ง€๋ฅผ ๋ณธ๋‹ค. 5์ฃผ์ฐจ์˜ DataSource์™€ ๊ฐ™์€ ์‚ฌ์ƒ.

Unit 6.1 โ€” PlatformTransactionManager ์ธํ„ฐํŽ˜์ด์Šค

์„ ์ˆ˜ ์ง€์‹: Phase 5

ํ•ต์‹ฌ ๊ฐœ๋…

"์Šคํ”„๋ง ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ์˜ ์ค‘์‹ฌ ์ธํ„ฐํŽ˜์ด์Šค"

ํ•ต์‹ฌ ๋ฉ”์„œ๋“œ:

public interface PlatformTransactionManager {
    TransactionStatus getTransaction(TransactionDefinition def);
    void commit(TransactionStatus status);
    void rollback(TransactionStatus status);
}

์—ญํ• :

  • ํŠธ๋žœ์žญ์…˜ ์‹œ์ž‘/์ปค๋ฐ‹/๋กค๋ฐฑ์„ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ์ถ”์ƒํ™”
  • ์‹ค์ œ ๋™์ž‘์€ ๊ตฌํ˜„์ฒด์— ์œ„์ž„
  • ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์€ ์ธํ„ฐํŽ˜์ด์Šค์—๋งŒ ์˜์กด

์ž๊ธฐ ์ ๊ฒ€

  • ์ด ํŒจํ„ด์€ 6์ฃผ์ฐจ์˜ ์–ด๋–ค ์ถ”์ƒํ™”์™€ ๋‹ฎ์•˜๋Š”๊ฐ€? (ํžŒํŠธ: DataSource)
  • "Platform"์ด ์ด๋ฆ„์— ๋“ค์–ด๊ฐ„ ์ด์œ ๋Š”?

Unit 6.2 โ€” 3๊ฐ€์ง€ ์ฃผ์š” ๊ตฌํ˜„์ฒด

์„ ์ˆ˜ ์ง€์‹: Unit 6.1

ํ•ต์‹ฌ ๊ตฌํ˜„์ฒด

๊ตฌํ˜„์ฒด์‚ฌ์šฉ์ฒ˜
DataSourceTransactionManagerJDBC, JdbcTemplate, MyBatis
HibernateTransactionManagerHibernate (์ง์ ‘ ์‚ฌ์šฉ)
JpaTransactionManagerJPA

์ƒํ™ฉ๋ณ„ ์„ ํƒ:

  • JdbcTemplate ์“ฐ๋ฉด โ†’ DataSourceTransactionManager
  • JPA ์“ฐ๋ฉด โ†’ JpaTransactionManager
  • ๋‘˜ ๋‹ค ์“ฐ๋ฉด โ†’ JpaTransactionManager (JPA ๊ฑฐ ์“ฐ๋ฉด JDBC๋„ ๊ฐ™์ด ๋จ)

Spring Boot์˜ ์ž๋™ ๊ตฌ์„ฑ:

  • ์˜์กด์„ฑ์— ๋”ฐ๋ผ ์ž๋™ ์„ ํƒ
  • spring-boot-starter-data-jpa โ†’ JpaTransactionManager ์ž๋™ ์„ค์ •

์ž๊ธฐ ์ ๊ฒ€

  • ๊ฐ™์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋‘ TransactionManager๋ฅผ ์“ธ ์ˆ˜ ์žˆ๋Š”๊ฐ€?
  • ํŠธ๋žœ์žญ์…˜ ๋งค๋‹ˆ์ €๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ๋ฉด ์–ด๋–ป๊ฒŒ ๊ตฌ๋ถ„ํ•˜๋Š”๊ฐ€? (ํžŒํŠธ: @Transactional("name"))

Unit 6.3 โ€” ์‚ฌ์šฉ ์ „ํ›„ ๋น„๊ต

์„ ์ˆ˜ ์ง€์‹: Unit 6.2

Before (์ˆ˜๋™ ๊ด€๋ฆฌ):

Connection conn = dataSource.getConnection();
conn.setAutoCommit(false);
try {
    userDao.insertUser(conn, "John");
    accountDao.updateBalance(conn, 1, -100);
    conn.commit();
} catch (Exception e) {
    conn.rollback();
    throw e;
} finally {
    conn.close();
}

After (PlatformTransactionManager):

TransactionStatus status = transactionManager.getTransaction(
    new DefaultTransactionDefinition()
);
try {
    userDao.insertUser("John");           // Connection ์•ˆ ๋ณด์ž„
    accountDao.updateBalance(1, -100);    // Connection ์•ˆ ๋ณด์ž„
    transactionManager.commit(status);
} catch (Exception e) {
    transactionManager.rollback(status);
    throw e;
}

์–ป์€ ๊ฒƒ:

  • Connection ๋งค๊ฐœ๋ณ€์ˆ˜ ์‚ฌ๋ผ์ง
  • DB ์ข…๋ฅ˜ ๋ฌด๊ด€ (์ธํ„ฐํŽ˜์ด์Šค ์˜์กด)
  • ์ฝ”๋“œ ์ค„์–ด๋“ฆ

์•„์ง ๋‚จ์€ ๊ฒƒ:

  • try/catch/commit/rollback ๋ณด์ผ๋Ÿฌํ”Œ๋ ˆ์ดํŠธ
  • โ†’ ๋‹ค์Œ ๋‹จ๊ณ„: @Transactional

์ž๊ธฐ ์ ๊ฒ€

  • ์ด ๋‹จ๊ณ„์—์„œ๋„ ์—ฌ์ „ํžˆ ๋ฐ˜๋ณต๋˜๋Š” ์ฝ”๋“œ๋Š”?
  • 5์ฃผ์ฐจ์˜ "ํ…œํ”Œ๋ฆฟ ๋ฉ”์†Œ๋“œ ํŒจํ„ด" ์œผ๋กœ ์ด ๋ฐ˜๋ณต์„ ์ค„์ผ ์ˆ˜ ์žˆ์„๊นŒ?

๐Ÿ“š Phase 7 โ€” @Transactional (์„ ์–ธ์  ํŠธ๋žœ์žญ์…˜)

๋ชฉํ‘œ: ํŠธ๋žœ์žญ์…˜ ์ฝ”๋“œ์˜ ๋ณด์ผ๋Ÿฌํ”Œ๋ ˆ์ดํŠธ๋ฅผ ์–ด๋…ธํ…Œ์ด์…˜ ํ•œ ์ค„๋กœ ์ค„์ด๋Š” ๋งˆ์ง€๋ง‰ ๋‹จ๊ณ„. AOP์˜ ์ฒซ ๋งŒ๋‚จ.

Unit 7.1 โ€” ํ”„๋ก์‹œ ํŒจํ„ด ๋ง›๋ณด๊ธฐ (AOP์˜ ์ถœ๋ฐœ์ )

์„ ์ˆ˜ ์ง€์‹: Phase 6, 5์ฃผ์ฐจ ๋””์ž์ธ ํŒจํ„ด

ํ•ต์‹ฌ ๊ฐœ๋…

ํ”„๋ก์‹œ ํŒจํ„ด:

"์›๋ณธ ๊ฐ์ฒด์˜ ๋Œ€๋ฆฌ์ž(Proxy)๋ฅผ ๋งŒ๋“ค์–ด์„œ, ์›๋ณธ ํ˜ธ์ถœ ์ „ํ›„์— ์ถ”๊ฐ€ ์ž‘์—…์„ ๋ผ์›Œ ๋„ฃ๋Š” ํŒจํ„ด"

[ํด๋ผ์ด์–ธํŠธ] โ”€โ”€> [Proxy] โ”€โ”€โ”
                          โ”‚ ํŠธ๋žœ์žญ์…˜ ์‹œ์ž‘
                          โ†“
                       [์›๋ณธ ๊ฐ์ฒด.๋ฉ”์„œ๋“œ()]
                          โ”‚
                          โ”‚ ์ปค๋ฐ‹/๋กค๋ฐฑ
                          โ†“
              โ”˜

Spring์˜ ํ™œ์šฉ:

  • @Transactional ์ด ๋ถ™์€ ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ๋Š” ๋นˆ์€
  • ์‹ค์ œ๋กœ๋Š” ํ”„๋ก์‹œ ๊ฐ์ฒด๊ฐ€ ๋“ฑ๋ก๋จ
  • ํ”„๋ก์‹œ๊ฐ€ ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ๋ฅผ ์ž๋™์œผ๋กœ ๋ผ์›Œ ๋„ฃ์Œ

์ž๊ธฐ ์ ๊ฒ€

  • ํ”„๋ก์‹œ ํŒจํ„ด๊ณผ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ํŒจํ„ด์˜ ์ฐจ์ด๋Š”?
  • 6์ฃผ์ฐจ์˜ JdbcTemplate๊ณผ ํ”„๋ก์‹œ๋Š” ์–ด๋–ป๊ฒŒ ๋‹ค๋ฅธ๊ฐ€? (ํžŒํŠธ: ํ˜ธ์ถœ vs ๊ฐ€๋กœ์ฑ„๊ธฐ)

Unit 7.2 โ€” @Transactional์˜ ๋™์ž‘ ์›๋ฆฌ

์„ ์ˆ˜ ์ง€์‹: Unit 7.1

ํ•ต์‹ฌ ๊ฐœ๋…

์„ ์–ธ์  ํŠธ๋žœ์žญ์…˜:

@Service
public class TransferService {

    @Transactional
    public void transfer(Long fromId, Long toId, int amount) {
        accountDao.withdraw(fromId, amount);
        accountDao.deposit(toId, amount);
    }
}

ํ•œ ์ค„ ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ ๋‹ค์Œ์ด ์ž๋™:

  • ํŠธ๋žœ์žญ์…˜ ์‹œ์ž‘
  • ์ •์ƒ ์ข…๋ฃŒ ์‹œ ์ปค๋ฐ‹
  • ์˜ˆ์™ธ ๋ฐœ์ƒ ์‹œ ๋กค๋ฐฑ
  • Connection ๊ด€๋ฆฌ

ํ”„๋ก์‹œ๊ฐ€ ํ•˜๋Š” ์ผ (์˜์‚ฌ์ฝ”๋“œ):

public void transfer(Long fromId, Long toId, int amount) {
    TransactionStatus status = txManager.getTransaction(...);
    try {
        targetService.transfer(fromId, toId, amount);  // ์‹ค์ œ ๋ฉ”์„œ๋“œ
        txManager.commit(status);
    } catch (Exception e) {
        txManager.rollback(status);
        throw e;
    }
}

ํ•ต์‹ฌ ํ†ต์ฐฐ:

  • 5์ฃผ์ฐจ์˜ OOP ์›์น™๋“ค(ํ…œํ”Œ๋ฆฟ ๋ฉ”์†Œ๋“œ, ์ „๋žต ํŒจํ„ด, OCP, DI) +
  • 6์ฃผ์ฐจ์˜ PlatformTransactionManager ์ถ”์ƒํ™” +
  • ํ”„๋ก์‹œ ํŒจํ„ด (AOP)
  • โ†’ ํ•˜๋‚˜์˜ ์–ด๋…ธํ…Œ์ด์…˜ ์œผ๋กœ ๋ฌถ์ž„

์ž๊ธฐ ์ ๊ฒ€

  • @Transactional์ด ๋ถ™์€ ๋นˆ์„ ์ง์ ‘ ์ธ์Šคํ„ด์Šคํ™”ํ•˜๋ฉด ํŠธ๋žœ์žญ์…˜์ด ๋™์ž‘ํ•˜๋Š”๊ฐ€? (ํžŒํŠธ: NO, ํ”„๋ก์‹œ ํ•„์š”)
  • private ๋ฉ”์„œ๋“œ์— @Transactional์„ ๋ถ™์ด๋ฉด? (ํžŒํŠธ: ๋™์ž‘ ์•ˆ ํ•จ)

Unit 7.3 โ€” @Transactional ์‚ฌ์šฉ ์‹œ ์ฃผ์˜์‚ฌํ•ญ

์„ ์ˆ˜ ์ง€์‹: Unit 7.2

ํ•ต์‹ฌ ํ•จ์ • 5๊ฐ€์ง€:

โ‘  private ๋ฉ”์„œ๋“œ์—๋Š” ๋™์ž‘ ์•ˆ ํ•จ

@Service
public class MyService {
    @Transactional
    private void internal() { }  // โŒ ํ”„๋ก์‹œ๊ฐ€ ๋ชป ๊ฐ€๋กœ์ฑ”
}

โ‘ก Self-invocation (์ž๊ธฐ ํ˜ธ์ถœ) ๋ฌธ์ œ

@Service
public class MyService {
    public void outer() {
        this.inner();  // โŒ ํ”„๋ก์‹œ ๊ฑฐ์น˜์ง€ ์•Š์Œ โ†’ ํŠธ๋žœ์žญ์…˜ ์•ˆ ๊ฑธ๋ฆผ
    }

    @Transactional
    public void inner() { ... }
}

โ‘ข ๊ธฐ๋ณธ ๋กค๋ฐฑ์€ RuntimeException๋งŒ

@Transactional
public void method() throws Exception {  // ์ฒดํฌ ์˜ˆ์™ธ
    throw new IOException();  // โŒ ๋กค๋ฐฑ ์•ˆ ๋จ!
}

// ํ•ด๊ฒฐ
@Transactional(rollbackFor = Exception.class)

โ‘ฃ ํŠธ๋žœ์žญ์…˜ ์ „ํŒŒ ์˜ต์…˜ ์ดํ•ด

  • REQUIRED (๊ธฐ๋ณธ): ๊ธฐ์กด ํŠธ๋žœ์žญ์…˜ ์žˆ์œผ๋ฉด ์ฐธ์—ฌ, ์—†์œผ๋ฉด ์ƒˆ๋กœ ์‹œ์ž‘
  • REQUIRES_NEW: ํ•ญ์ƒ ์ƒˆ ํŠธ๋žœ์žญ์…˜
  • NESTED: ์ค‘์ฒฉ ํŠธ๋žœ์žญ์…˜ (Savepoint)

โ‘ค readOnly ํ™œ์šฉ

@Transactional(readOnly = true)
public List<Item> findAll() { ... }
  • ์ฝ๊ธฐ ์ „์šฉ โ†’ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ ์ตœ์ ํ™” โ†’ ์„ฑ๋Šฅ โ†‘

์ž๊ธฐ ์ ๊ฒ€

  • self-invocation ๋ฌธ์ œ๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•˜๋Š”๊ฐ€? (ํžŒํŠธ: ๋ณ„๋„ ๋นˆ ๋ถ„๋ฆฌ, AspectJ)
  • ์ฒดํฌ ์˜ˆ์™ธ์—์„œ ๋กค๋ฐฑ์ด ๊ธฐ๋ณธ์ด ์•„๋‹Œ ์ด์œ ๋Š”? (ํžŒํŠธ: ๋น„์ฆˆ๋‹ˆ์Šค ์˜ˆ์™ธ์™€ ์‹œ์Šคํ…œ ์˜ˆ์™ธ ๊ตฌ๋ถ„)

๐ŸŽ“ ์ข…ํ•ฉ ์ž๊ธฐ ์ ๊ฒ€ (7์ฃผ์ฐจ ์กธ์—… ์‹œํ—˜)

SQL JOIN

  1. INNER JOIN, LEFT JOIN, RIGHT JOIN, FULL OUTER JOIN์˜ ์ฐจ์ด๋ฅผ ๊ฒฐ๊ณผ ํ–‰ ๊ด€์ ์—์„œ?
  2. "๋ถ€์„œ ์—†๋Š” ์ง์›" ๋งŒ ์ฐพ๋Š” ์ฟผ๋ฆฌ๋Š”?
  3. MySQL์—์„œ FULL OUTER JOIN์„ ์–ด๋–ป๊ฒŒ ์šฐํšŒํ•˜๋Š”๊ฐ€?

ORM๊ณผ JPA

  1. ๊ฐ์ฒด-๊ด€๊ณ„ ๋ฏธ์Šค๋งค์น˜์˜ 5๊ฐ€์ง€ ์ธก๋ฉด์€?
  2. ORM์˜ ์ •์˜์™€ ORM์ด SQL์„ ์™„์ „ํžˆ ๋Œ€์ฒดํ•˜์ง€ ๋ชปํ•˜๋Š” ์ด์œ ๋Š”?
  3. JPA์™€ Hibernate์˜ ๊ด€๊ณ„๋Š”?
  4. JPA๊ฐ€ JDBC๋ฅผ ๋Œ€์ฒดํ•˜๋Š”๊ฐ€? (ํžŒํŠธ: NO, ์œ„์— ์–นํž˜)
  5. Spring Data JPA์™€ JPA์˜ ์ฐจ์ด๋Š”?
  6. Querydsl์ด ํ•„์š”ํ•œ ์‹œ๋‚˜๋ฆฌ์˜ค๋Š”?

JPA ๋งคํ•‘

  1. @Entity์˜ ์กฐ๊ฑด 3๊ฐ€์ง€๋Š”?
  2. @GeneratedValue์˜ 4๊ฐ€์ง€ ์ „๋žต๊ณผ ๊ฐ๊ฐ ์ ํ•ฉํ•œ DB๋Š”?
  3. IDENTITY ์ „๋žต์˜ ๋‹จ์ ์€?
  4. @Column์ด ์ƒ๋žต ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ์™€ ๊ทธ ์ด์œ ๋Š”?

์ˆ˜๋™ ํŠธ๋žœ์žญ์…˜์˜ ํ•œ๊ณ„

  1. ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์— Connection์„ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌํ•˜๋Š” ๊ฒŒ ์™œ ๋‚˜์œ ์„ค๊ณ„์ธ๊ฐ€?
  2. ์ˆ˜๋™ ํŠธ๋žœ์žญ์…˜์˜ 3๊ฐ€์ง€ ํ•จ์ •์€?

PlatformTransactionManager

  1. PlatformTransactionManager์˜ ํ•ต์‹ฌ ๋ฉ”์„œ๋“œ 3๊ฐœ๋Š”?
  2. 3๊ฐ€์ง€ ์ฃผ์š” ๊ตฌํ˜„์ฒด์™€ ๊ฐ๊ฐ์˜ ์‚ฌ์šฉ์ฒ˜๋Š”?
  3. JpaTransactionManager ํ•˜๋‚˜๋กœ JDBC ํŠธ๋žœ์žญ์…˜๋„ ์ฒ˜๋ฆฌ๋˜๋Š” ์ด์œ ๋Š”?

@Transactional

  1. @Transactional์ด ๋™์ž‘ํ•˜๊ธฐ ์œ„ํ•œ ์กฐ๊ฑด์€? (ํžŒํŠธ: ํ”„๋ก์‹œ)
  2. self-invocation ๋ฌธ์ œ๋ž€?
  3. private ๋ฉ”์„œ๋“œ์— @Transactional์ด ๋™์ž‘ํ•˜์ง€ ์•Š๋Š” ์ด์œ ๋Š”?
  4. ๊ธฐ๋ณธ ๋กค๋ฐฑ ๋Œ€์ƒ์ด RuntimeException ๋ฟ์ธ ์ด์œ ๋Š”?
  5. @Transactional(readOnly = true) ์˜ ํšจ๊ณผ๋Š”?
  6. ํŠธ๋žœ์žญ์…˜ ์ „ํŒŒ ์†์„ฑ REQUIRED์™€ REQUIRES_NEW์˜ ์ฐจ์ด๋Š”?

๐Ÿ“Œ ํ•™์Šต ์šด์˜ ํŒ

5์ฃผ์ฐจ ๋ณต์Šต โ€” ์Šคํ”„๋ง ๋นˆ ๋‹ค์‹œ ๋ณด๊ธฐ

์ด๋ฒˆ ์ž๋ฃŒ ๋„์ž…๋ถ€์˜ "์Šคํ”„๋ง ๋นˆ์ด๋ž€?"์€ 5์ฃผ์ฐจ Phase 8(ApplicationContext + DI)์˜ ๋ณต์Šต ํฌ์ธํŠธ์ž…๋‹ˆ๋‹ค. ๋‹ค์Œ 3๊ฐ€์ง€๋ฅผ ๋‹ค์‹œ ์งš๊ณ  ๊ฐ€์‹œ๋ฉด ์ถฉ๋ถ„ํ•ด์š”:

  1. ๋นˆ์€ ApplicationContext๊ฐ€ ๊ด€๋ฆฌํ•˜๋Š” ๊ฐ์ฒด
  2. ๊ธฐ๋ณธ์€ ์‹ฑ๊ธ€ํ†ค โ€” 4์ฃผ์ฐจ ๋™์‹œ์„ฑ๊ณผ ์—ฐ๊ฒฐ๋จ
  3. DI๋Š” ๋นˆ๋ผ๋ฆฌ์˜ ๊ด€๊ณ„ ์„ค์ •

9-์„น์…˜ ๋งˆ์Šคํ„ฐ ํ”„๋กฌํ”„ํŠธ๋กœ ๊นŠ์ด ํŒŒ์•ผ ํ•  Unit

๋ฐ˜๋“œ์‹œ ๊นŠ์ด ํŒŒ๊ธฐ:

  • Unit 1.5 โ€” JOIN ์„ ํƒ ๊ฐ€์ด๋“œ (์‹ค๋ฌด ๋งค์ผ ์‚ฌ์šฉ)
  • Unit 3.2 โ€” JPA์˜ ๋“ฑ์žฅ (SQL Mapper์™€์˜ ๋ณธ์งˆ์  ์ฐจ์ด)
  • Unit 3.4 โ€” Spring Data JPA + Querydsl (์‹ค๋ฌด ํ‘œ์ค€)
  • Unit 4.3 โ€” @GeneratedValue ์ „๋žต (DB๋ณ„ ์ฐจ์ด)
  • Unit 7.1 โ€” ํ”„๋ก์‹œ ํŒจํ„ด (AOP์˜ ์ถœ๋ฐœ์ , ๋ฉด์ ‘ ๋‹จ๊ณจ)
  • Unit 7.2 โ€” @Transactional ๋™์ž‘ ์›๋ฆฌ (โ˜…โ˜…โ˜… ๋ฉด์ ‘ ๋‹จ๊ณจ)
  • Unit 7.3 โ€” @Transactional 5๊ฐ€์ง€ ํ•จ์ • (์‹ค๋ฌด ์ง๊ฒฐ)

Phase๋ณ„ ์ง„๋„ ์ฒดํฌ๋ฆฌ์ŠคํŠธ

[ ] Phase 1 โ€” SQL JOIN (Unit 1.1~1.5)
[ ] Phase 2 โ€” ORM ํŒจ๋Ÿฌ๋‹ค์ž„ (Unit 2.1~2.2)
[ ] Phase 3 โ€” JPA ์ž…๋ฌธ (Unit 3.1~3.4)
[ ] Phase 4 โ€” JPA ์—”ํ‹ฐํ‹ฐ ๋งคํ•‘ (Unit 4.1~4.5)
[ ] Phase 5 โ€” ์ˆ˜๋™ ํŠธ๋žœ์žญ์…˜์˜ ํ•œ๊ณ„ (Unit 5.1~5.2)
[ ] Phase 6 โ€” PlatformTransactionManager (Unit 6.1~6.3)
[ ] Phase 7 โ€” @Transactional (Unit 7.1~7.3)
[ ] ์ข…ํ•ฉ ์ž๊ธฐ ์ ๊ฒ€ 24๋ฌธํ•ญ ํ†ต๊ณผ

6์ฃผ์ฐจ โ†’ 7์ฃผ์ฐจ ์—ฐ๊ฒฐ ํฌ์ธํŠธ

6์ฃผ์ฐจ์—์„œ ๋ณธ ์ถ”์ƒํ™”์˜ ์‚ฌ์ƒ์ด ์ด๋ฒˆ ์ฃผ์— ๋‘ ๋ฒˆ ๋” ๋ฐ˜๋ณต๋ฉ๋‹ˆ๋‹ค:

6์ฃผ์ฐจ7์ฃผ์ฐจ
DataSource (์ปค๋„ฅ์…˜ ์ถ”์ƒํ™”)PlatformTransactionManager (ํŠธ๋žœ์žญ์…˜ ์ถ”์ƒํ™”)
JdbcTemplate (๋ฐ˜๋ณต ์ œ๊ฑฐ)@Transactional (๋ณด์ผ๋Ÿฌํ”Œ๋ ˆ์ดํŠธ ์ œ๊ฑฐ)
SQL ๋งคํ•‘ RowMapperJPA ์–ด๋…ธํ…Œ์ด์…˜ ๋งคํ•‘

โ†’ "Spring์€ ๋Š์ž„์—†์ด ์ถ”์ƒํ™”ํ•œ๋‹ค" โ€” 6, 7์ฃผ์ฐจ์˜ ์ผ๊ด€๋œ ๋ฉ”์‹œ์ง€.


1~7์ฃผ์ฐจ ํ†ตํ•ฉ ํ๋ฆ„

  • 1~3์ฃผ์ฐจ: ์ž๋ฐ” ์–ธ์–ด ์ž์ฒด (OOPยทJVMยท์ปฌ๋ ‰์…˜ยทํ•จ์ˆ˜ํ˜•)
  • 4์ฃผ์ฐจ: ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ์™€ ๋™์‹œ์„ฑ
  • 5์ฃผ์ฐจ: Spring IoC/DI ์ž…๋ฌธ
  • 6์ฃผ์ฐจ: ํ…Œ์ŠคํŠธ + ์›น ์ธํ”„๋ผ + DB ์ ‘๊ทผ์˜ ์ง„ํ™”
  • 7์ฃผ์ฐจ (์ง€๊ธˆ): JPA(ORM) + ํŠธ๋žœ์žญ์…˜ ์ถ”์ƒํ™”
profile
Software Developer

0๊ฐœ์˜ ๋Œ“๊ธ€