STUDY๐Ÿ„

[Spring ๊ธฐ๋ณธ] 2. ์Šคํ”„๋ง ํ•ต์‹ฌ ์›๋ฆฌ ์ดํ•ด1 - ์˜ˆ์ œ ๋งŒ๋“ค๊ธฐ

์ด๋ฆฌ์ญ 2025. 3. 21. 17:05

์•ˆ๋…•ํ•˜์„ธ์š”!

์ด๋ฒˆ ์„น์…˜๋ถ€ํ„ฐ ๋ณธ๊ฒฉ์ ์œผ๋กœ ์ฝ”๋“œ ์œ„์ฃผ๋กœ ์ž‘์„ฑํ•ด๋ณผ๊ฑฐ ๊ฐ™์•„์š”!

๊ทธ๋Ÿผ ๊ณ ๊ณ !!


1. ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ

์šฐ์„  ๋ณธ๊ฒฉ์ ์œผ๋กœ ์Šคํ”„๋ง์„ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— ์ˆœ์ˆ˜ํ•˜๊ฒŒ ์ž๋ฐ”๋กœ๋งŒ ๊ตฌํ˜„์„ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ฝ”๋“œ๊ฐ€ ๋ณ€๊ฒฝ์ด ๋˜๋„ ์œ ์—ฐํ•˜๊ฒŒ ๋Œ€์ฒ˜๊ฐ€ ๊ฐ€๋Šฅํ• ๊นŒ์š”?

์ฐจ๊ทผ์ฐจ๊ทผ ์ง„ํ–‰ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

๋จผ์ € ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ์„ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Java17๊ณผ IDE: IntelliJ๋ฅผ ์„ค์น˜ํ•˜๊ณ , ์Šคํ”„๋ง ๋ถ€ํŠธ ์Šคํƒ€ํ„ฐ ์‚ฌ์ดํŠธ๋กœ ์ด๋™ํ•ด์„œ ์Šคํ”„๋ง ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

https://start.spring.io

์œ„์˜ ๋งํฌ๊ฐ€ ์Šคํ”„๋ง ๋ถ€ํŠธ ์Šคํƒ€ํ„ฐ ์‚ฌ์ดํŠธ ์ž…๋‹ˆ๋‹ค.

 

๋“ค์–ด๊ฐ€๋ณด๋ฉด..

์ด๋Ÿฐ์‹์œผ๋กœ ๋‚˜์˜ต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์—์„œ Project๋Š” Gradle - Groovy, Language๋Š” Java, Spring Boot๋Š” 3.4.4๋กœ ํ•ด๋ณผ๊ฒŒ์š”.

SNAPSHOT๊ณผ M2๋Š” ์•„์ง ๋ถˆ์•ˆ์ •ํ•˜๋‹ค๊ณ  ํ•ด์•ผํ•˜๋‚˜? ๊ทธ๋ž˜์„œ ์•ˆ์ •๋œ ๋ฒ„์ „ ์ค‘ ์ตœ์‹  ๋ฒ„์ „์ธ 3.4.4๋กœ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋ฐ‘์— ๋ณด๋ฉด Project Metadata๋ผ๊ณ  ์žˆ์„ ๊ฒ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ Group์€ hello, Artifact๋Š” core๋กœ ์ ์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. (Group๊ณผ Artifact ์•„๋ฌด๊ฑฐ๋‚˜ ์ ์–ด๋„ ๋ฉ๋‹ˆ๋‹ค.)

Artifact๋ฅผ core๋กœ ์ ์œผ๋ฉด Name๊ณผ Package name์ด ์ž๋™์œผ๋กœ core ๊ด€๋ จ๋˜๊ฒŒ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

Packaging์€ Jar๋กœ ํ•˜๋ฉด ๋˜๊ณ , Java๋Š” 17๋ฒ„์ „์œผ๋กœ ํ•ด๋ณผ๊ฒŒ์š”. ๋” ์ตœ์‹  ๋ฒ„์ „์œผ๋กœ ํ•ด๋ด๋„ ๋ฉ๋‹ˆ๋‹ค.

 

์˜†์— ์žˆ๋Š” Dependencies๋Š” ์•„๋ฌด ๊ฒƒ๋„ ์ถ”๊ฐ€(์„ ํƒ) ์•ˆ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์•„๋ฌด ๊ฒƒ๋„ ์„ ํƒ ์•ˆ ํ•˜๋ฉด ์Šคํ”„๋ง ๋ถ€ํŠธ๊ฐ€ ์Šคํ”„๋ง core์ชฝ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋งŒ ๊ฐ€์ง€๊ณ  ๋ช‡ ๊ฐœ ๊ฐ„๋‹จํžˆ ๊ตฌ์„ฑํ•ด์ค๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๋ณ„๋„์˜ ์˜์กด ๊ด€๊ณ„๋Š” ์„ค์ •ํ•˜์ง€ ์•Š๊ณ  ๋ฐ‘์— GENERATE ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด core.zip์œผ๋กœ ๋‹ค์šด๋กœ๋“œ ๋  ํ…๋ฐ ๊ทธ๊ฑฐ ์••์ถ• ํ’€๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์••์ถ• ํ‘ผ ๊ฒƒ์„ ๊ณต๋ถ€ํ•˜๊ธฐ ์ข‹์€? ํด๋”๋กœ ์˜ฎ๊ฒจ๋†“์œผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

ํ”„๋กœ์ ํŠธ๋ฅผ ์—ด์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

ํ”„๋กœ์ ํŠธ ์—ด๊ธฐ ๋ˆ„๋ฅด๊ณ  ์•„๊นŒ core ํด๋” ์˜ฎ๊ฒจ ๋†“์€ ๊ฒฝ๋กœ๋กœ ๋“ค์–ด๊ฐ€์„œ 

core์—์„œ build.gradle์„ ๋ˆ„๋ฅด๊ณ  ํ”„๋กœ์ ํŠธ๋ฅผ ์—ด์–ด๋ณผ๊ฒŒ์š”.

 

๊ทธ๋Ÿฌ๊ณ  ์Šคํ”„๋ง์ด ์ž˜ ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์™ผ์ชฝ core ํด๋”์—์„œ src ํด๋”์—์„œ main์—์„œ java์—์„œ hello์—์„œ core๋กœ ๋“ค์–ด๊ฐ€๋ฉด coreApplication์ด ๋‚˜์˜ต๋‹ˆ๋‹ค.

coreApplication์— ๋“ค์–ด๊ฐ€์„œ ์œ„์— ์ดˆ๋ก์ƒ‰ ์‚ผ๊ฐํ˜•์„ ๋ˆ„๋ฅด๋ฉด ์‹คํ–‰์ด ๋ฉ๋‹ˆ๋‹ค.

์„ฑ๊ณต์ ์œผ๋กœ ์‹คํ–‰์ด ๋˜๋ฉด ์œ„์˜ ์‚ฌ์ง„์ฒ˜๋Ÿผ ๋‚˜์˜ฌ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿผ ๋ณธ๊ฒฉ์ ์œผ๋กœ ์‹œ์ž‘ํ•ด๋ณผ๊ฒŒ์š”!


2. ๋น„์ฆˆ๋‹ˆ์Šค ์š”๊ตฌ์‚ฌํ•ญ๊ณผ ์„ค๊ณ„

๊ฐœ๋ฐœ์„ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— ์š”๊ตฌ์‚ฌํ•ญ๊ณผ ์„ค๊ณ„ ๋‹จ๊ณ„๋Š” ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.

ํ•œ ๋ฒˆ ์š”๊ตฌ์‚ฌํ•ญ ์ •๋ฆฌ์™€ ์„ค๊ณ„๋ฅผ ํ•ด๋ณผ๊นŒ์š”?

  • ํšŒ์›
    • ํšŒ์›์„ ๊ฐ€์ž…ํ•˜๊ณ  ์กฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ํšŒ์›์€ ์ผ๋ฐ˜๊ณผ VIP ๋‘ ๊ฐ€์ง€ ๋“ฑ๊ธ‰์ด ์žˆ์Šต๋‹ˆ๋‹ค.
    • ํšŒ์› ๋ฐ์ดํ„ฐ๋Š” ์ž์ฒด DB๋ฅผ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๊ณ , ์™ธ๋ถ€ ์‹œ์Šคํ…œ๊ณผ ์—ฐ๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (๋ฏธํ™•์ •)
  • ์ฃผ๋ฌธ๊ณผ ํ• ์ธ ์ •์ฑ…
    • ํšŒ์›์€ ์ƒํ’ˆ์„ ์ฃผ๋ฌธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ํšŒ์› ๋“ฑ๊ธ‰์— ๋”ฐ๋ผ ํ• ์ธ ์ •์ฑ…์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ํ• ์ธ ์ •์ฑ…์€ ๋ชจ๋“  VIP๋Š” 1,000์›์„ ํ• ์ธํ•ด์ฃผ๋Š” ๊ณ ์ • ๊ธˆ์•ก ํ• ์ธ์„ ์ ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. (๋‚˜์ค‘์— ๋ณ€๊ฒฝ๋  ์ˆ˜๋„..?)
    • ํ• ์ธ ์ •์ฑ…์€ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Šต๋‹ˆ๋‹ค. ํšŒ์‚ฌ์˜ ๊ธฐ๋ณธ ํ• ์ธ ์ •์ฑ…์„ ์•„์ง ์ •ํ•˜์ง€ ๋ชปํ•˜์˜€๊ณ , ์˜คํ”ˆ ์ง์ „๊นŒ์ง€ ๊ณ ๋ฏผ์„ ๋ฏธ๋ฃจ๊ณ  ์‹ถ๋‹ค. ์ตœ์•…์˜ ๊ฒฝ์šฐ ํ• ์ธ์„ ์ ์šฉํ•˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. (๋ฏธํ™•์ •)

์š”๊ตฌ์‚ฌํ•ญ์„ ๋ณด๋ฉด ํšŒ์› ๋ฐ์ดํ„ฐ, ํ• ์ธ ์ •์ฑ… ๊ฐ™์€ ๋ถ€๋ถ„์€ ์ง€๊ธˆ ๊ฒฐ์ •ํ•˜๊ธฐ ์–ด๋ ค์šด ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๊ณ  ์ด๋Ÿฐ ์ •์ฑ…์ด ๊ฒฐ์ •๋  ๋•Œ๊นŒ์ง€ ๊ฐœ๋ฐœ์„ ๋ฌด๊ธฐํ•œ ๊ธฐ๋‹ค๋ฆด ์ˆ˜๋„ ์—†์Šต๋‹ˆ๋‹ค.

๊ทธ๋ ‡์ง€๋งŒ ์•ž์—์„œ ๊ฐ์ฒด ์ง€ํ–ฅ ์„ค๊ณ„ ๋ฐฉ๋ฒ•์„ ๋ฐฐ์› ์œผ๋ฏ€๋กœ, ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋งŒ๋“ค๊ณ  ๊ตฌํ˜„์ฒด๋ฅผ ์–ธ์ œ๋“ ์ง€ ๊ฐˆ์•„๋ผ์šธ ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค!

 

์ฃผ์˜! ํ”„๋กœ์ ํŠธ ํ™˜๊ฒฝ์„ค์ •์„ ํŽธ๋ฆฌํ•˜๊ฒŒ ํ•˜๋ ค๊ณ  ์Šคํ”„๋ง ๋ถ€ํŠธ๋ฅผ ์‚ฌ์šฉํ•œ ๊ฒƒ์ด๊ณ , ์ง€๊ธˆ์€ ์Šคํ”„๋ง ์—†๋Š” ์ˆœ์ˆ˜ํ•œ ์ž๋ฐ”๋กœ๋งŒ ๊ฐœ๋ฐœ์„ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์Šคํ”„๋ง ๊ด€๋ จ์€ ๋‚˜์ค‘์— ๋‚˜์˜ฌ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.


3. ํšŒ์› ๋„๋ฉ”์ธ

3-1. ํšŒ์› ๋„๋ฉ”์ธ ์„ค๊ณ„

  • ํšŒ์›
    • ํšŒ์›์„ ๊ฐ€์ž…ํ•˜๊ณ  ์กฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ํšŒ์›์€ ์ผ๋ฐ˜๊ณผ VIP ๋‘ ๊ฐ€์ง€ ๋“ฑ๊ธ‰์ด ์žˆ์Šต๋‹ˆ๋‹ค.
    • ํšŒ์› ๋ฐ์ดํ„ฐ๋Š” ์ž์ฒด DB๋ฅผ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๊ณ , ์™ธ๋ถ€ ์‹œ์Šคํ…œ๊ณผ ์—ฐ๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (๋ฏธํ™•์ •)
  • ํšŒ์› ๋„๋ฉ”์ธ ํ˜‘๋ ฅ ๊ด€๊ณ„

ํ˜‘๋ ฅ ๊ด€๊ณ„๋Š” ๊ธฐํš์ž๋„ ๋ณผ ์ˆ˜ ์žˆ๋Š” ๊ทธ๋ฆผ์ž…๋‹ˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํšŒ์› ์„œ๋น„์Šค๋ฅผ ํ˜ธ์ถœํ•˜๊ณ , ํšŒ์› ์„œ๋น„์Šค๋Š” ํšŒ์› ๊ฐ€์ž…๊ณผ ํšŒ์› ์กฐํšŒ๋ผ๋Š” 2๊ฐ€์ง€ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ, ํšŒ์› ์„œ๋น„์Šค, ํšŒ์› ์ €์žฅ์†Œ=์—ญํ•  / ๋ฉ”๋ชจ๋ฆฌ ํšŒ์› ์ €์žฅ์†Œ, DB ํšŒ์› ์ €์žฅ์†Œ, ์™ธ๋ถ€ ์‹œ์Šคํ…œ ์—ฐ๋™ ํšŒ์› ์ €์žฅ์†Œ=๊ตฌํ˜„

 

  • ํšŒ์› ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ

ํšŒ์› ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ์€ ํšŒ์› ๋„๋ฉ”์ธ ํ˜‘๋ ฅ ๊ด€๊ณ„๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๊ฐœ๋ฐœ์ž๋“ค์ด ๊ตฌ์ฒดํ™”ํ•ด์„œ ๋งŒ๋“ค์–ด๋ƒ…๋‹ˆ๋‹ค.

ํšŒ์› ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•˜๋Š” ๊ณ„์ธต์„ ๋”ฐ๋กœ ํšŒ์› ์ €์žฅ์†Œ(MemberRepository)๋ผ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

์šฐ์„ , ๋ฉ”๋ชจ๋ฆฌ ํšŒ์› ์ €์žฅ์†Œ๋ถ€ํ„ฐ ๊ตฌํ˜„ํ•ด์„œ ํšŒ์› ์„œ๋น„์Šค(MemberService)๋ฅผ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋งŒ๋“ค๊ณ  ๊ทธ๊ฒƒ์— ๋Œ€ํ•œ ๊ตฌํ˜„์ฒด๋กœ MemberServiceImpl์„ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

 

๊ตฌํ˜„ํ•ด์•ผ ํ•  ๊ฒƒ์€ ํšŒ์› ๊ฐ€์ž…๊ณผ ํšŒ์› ์กฐํšŒ 2๊ฐ€์ง€ ์ธ๋ฐ ์™œ MemberServiceImpl ํ•˜๋‚˜๋งŒ ๊ตฌํ˜„์ฒด์ผ๊นŒ์š”?

์™œ๋ƒํ•˜๋ฉด, ํšŒ์›๊ณผ ๊ด€๋ จ๋œ ๋ชจ๋“  ๊ธฐ๋Šฅ๋“ค์€ ํšŒ์› ์„œ๋น„์Šค ํด๋ž˜์Šค ์•ˆ์— ๊ตฌํ˜„๋˜์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ , ํšŒ์› ์ €์žฅ์†Œ์ธ MemberRepository๋ฅผ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋งŒ๋“ค์–ด์„œ MemberRepository์— ๋Œ€ํ•œ ๊ตฌํ˜„์ฒด๋กœ MemoryMemberRepository์™€ DbMemberRepository๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

 

  • ํšŒ์› ๊ฐ์ฒด ๋‹ค์ด์–ด๊ทธ๋žจ

ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ๊ณผ ๊ฐ์ฒด ๋‹ค์ด์–ด๊ทธ๋žจ์˜ ์ฐจ์ด์ 

- ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ-
์‹œ์Šคํ…œ์˜ ์ •์ ์ธ ๊ตฌ์กฐ๋ฅผ ์„ค๊ณ„ํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
์–ด๋–ค ํด๋ž˜์Šค๊ฐ€ ์žˆ๊ณ , ํด๋ž˜์Šค ๊ฐ„์˜ ๊ด€๊ณ„(์ƒ์†, ์—ฐ๊ด€, ์˜์กด, ์ง‘ํ•ฉ ๋“ฑ)์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋‹ค์ด์–ด๊ทธ๋žจ์ž…๋‹ˆ๋‹ค.
์‹ค์ œ ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•˜์ง€ ์•Š๊ณ  ํด๋ž˜์Šค๋งŒ ๋ถ„์„ํ•ด์„œ ๋ณผ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

-๊ฐ์ฒด ๋‹ค์ด์–ด๊ทธ๋žจ-
์‹ค์ œ ์‹คํ–‰์ค‘์ธ ๊ฐ์ฒด๋“ค์˜ ์ƒํƒœ๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ๋‹ค์ด์–ด๊ทธ๋žจ์ž…๋‹ˆ๋‹ค.
ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํŠน์ • ์‹œ์ ์—์„œ ์ƒ์„ฑ๋œ ๊ฐ์ฒด๋“ค์˜ ๊ด€๊ณ„๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

 

 

3-2. ํšŒ์› ๋„๋ฉ”์ธ ๊ฐœ๋ฐœ

๋ณธ๊ฒฉ์ ์œผ๋กœ ๊ฐœ๋ฐœ์„ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์šฐ์„  member๋ผ๋Š” ํŒจํ‚ค์ง€๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿฌ๊ณ  member ํŒจํ‚ค์ง€ ์•ˆ์— ๋“ฑ๊ธ‰์„ ๋‚˜ํƒ€๋‚ด๋Š” Grade ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

์ฃผ์˜ํ•  ์ ์€ Grade ํด๋ž˜์Šค๋Š” ๋ฐ‘์— ์‚ฌ์ง„์ฒ˜๋Ÿผ ์—ด๊ฑฐํ˜• ์ฆ‰, enum์œผ๋กœ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

 

Grade ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ณ  ๋‚˜๋ฉด,

package hello.core.member;

public enum Grade {
}

์ด๋Ÿฐ ์‹์œผ๋กœ Grade๋ผ๋Š” enum ํด๋ž˜์Šค๊ฐ€ ๋งŒ๋“ค์–ด ์ง‘๋‹ˆ๋‹ค.

package hello.core.member;

public enum Grade {
    BASIC,
    VIP
}

์ด ํด๋ž˜์Šค ์•ˆ์— ์ €ํฌ๊ฐ€ ์š”๊ตฌ์‚ฌํ•ญ์— ์ ์—ˆ๋˜ ๋“ฑ๊ธ‰ ์ข…๋ฅ˜์ธ BASIC๊ณผ VIP๋ฅผ ์ ์—ˆ์Šต๋‹ˆ๋‹ค.

 

package hello.core.member;

public class Member {
}

๊ทธ๋ฆฌ๊ณ , Member ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Member ์—”ํ‹ฐํ‹ฐ๋Š” java ํด๋ž˜์Šค๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

package hello.core.member;

public class Member {
    private Long id;
    private String name;
    private Grade grade;
}

ํšŒ์› ์—”ํ‹ฐํ‹ฐ๋Š” ์†์„ฑ์ด id, ์ด๋ฆ„, ๋“ฑ๊ธ‰ ์ด 3๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿฌ๊ณ  ์ƒ์„ฑ์ž๋ฅผ ๋งŒ๋“ค์–ด๋ณผ๊ฑด๋ฐ, Mac์€ command + n์„ ๋™์‹œ์— ๋ˆ„๋ฅด๋ฉด ๋˜๊ณ , Window๋Š” Alt + Insert๋ฅผ ๋™์‹œ์— ๋ˆ„๋ฅด๋ฉด ๋ฉ๋‹ˆ๋‹ค.

public class Member {
    private Long id;
    private String name;
    private Grade grade;

    public Member(Long id, String name, Grade grade) {
        this.id = id;
        this.name = name;
        this.grade = grade;
    }
}

์•„๊นŒ์™€ ๊ฐ™์€ ๋‹จ์ถ•ํ‚ค๋ฅผ ๋ˆŒ๋Ÿฌ์„œ ์ด๋ฒˆ์—” Getter์™€ Setter๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

public class Member {
   ...
    public Member(Long id, String name, Grade grade) {
        ...
    }
	//Getter
    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public Grade getGrade() {
        return grade;
    }
	//Setter
    public void setId(Long id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setGrade(Grade grade) {
        this.grade = grade;
    }
}

Getter์™€ Setter๋ฅผ ๋งŒ๋“ค ๋•Œ ํ•ญ๋ชฉ ๋‹ค ์„ ํƒํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์•„๊นŒ ์žˆ๋˜ member ํŒจํ‚ค์ง€์—์„œ ์šฐํด๋ฆญํ•˜์—ฌ Javaclass์—์„œ ์ด๋ฆ„์€ MemberRepository๋กœ ํ•˜์—ฌ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋งŒ๋“ค์–ด๋ณผ๊ฑฐ์—์š”.

๋งŒ๋“ค์–ด๋ณด๋ฉด

package hello.core.member;

public interface MemberRepository {
}

์ด๋Ÿฐ ์‹์œผ๋กœ ๋‚˜์˜ฌ๊ฑฐ์—์š”.

public interface MemberRepository {
    void save(Member member);
    Member findById(Long memberId);
}

์ธํ„ฐํŽ˜์ด์Šค๋Š” ํ•จ์ˆ˜์˜ ํ˜•ํƒœ๋งŒ ์ •์˜ํ•˜๋Š” ๊ฒƒ์ด์–ด์„œ ์ค‘๊ด„ํ˜ธ ์•ˆ์˜ ๋กœ์ง ์ฝ”๋“œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

 

์ธํ„ฐํŽ˜์ด์Šค์ธ MemberRepository๋ฅผ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค์ธ MemoryMemberRepository๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์•„๊นŒ์™€ ๊ฐ™์€ ํŒจํ‚ค์ง€์— Javaclass ํ˜•ํƒœ๋กœ ๋งŒ๋“ค๊ณ , ๋ฐ‘์—์™€ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.

package hello.core.member;

public class MemoryMemberRepository implements MemberRepository{
}

์™œ implements๋ฅผ ์‚ฌ์šฉํ–ˆ๋ƒ๋ฉด MemberRepository๋ผ๋Š” ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ๋งŒ๋“ค๊ธฐ๋กœ ์ •ํ•ด๋†“์€ ํ•จ์ˆ˜๋“ค์„ ๊ตฌํ˜„ํ•  ํด๋ž˜์Šค๋ผ๋Š” ๊ฒƒ์„ ๋ช…์‹œํ•˜๊ธฐ ์œ„ํ•ด์„œ ์ž…๋‹ˆ๋‹ค.

๊ทผ๋ฐ ์ด๋ ‡๊ฒŒ ๋˜์–ด์žˆ์œผ๋ฉด ๋นจ๊ฐ„์ค„์ด ๋œฐ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

public class MemoryMemberRepository implements MemberRepository{
    @Override
    public void save(Member member) {
        
    }

    @Override
    public Member findById(Long memberId) {
        return null;
    }
}

window ๊ธฐ์ค€ Alt + Enter๋ฅผ ๋ˆ„๋ฅด๊ณ  ๋ฉ”์„œ๋“œ ๊ตฌํ˜„์„ ๋ˆ„๋ฅด๋ฉด ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ์ •์˜ํ•œ ํ•จ์ˆ˜๋“ค์„ ์˜ค๋ฒ„๋ผ์ด๋“œ ํ•˜๋Š” ๊ธฐ๋Šฅ์ด ๋‚˜์˜ต๋‹ˆ๋‹ค.

import java.util.HashMap;
import java.util.Map;

public class MemoryMemberRepository implements MemberRepository{
    private static Map<Long, Member> store = new HashMap<>();
    @Override
    public void save(Member member) {
        store.put(member.getId(), member);
    }

    @Override
    public Member findById(Long memberId) {
        return store.get(memberId);
    }
}
  • private static Map<Long, Member> store = new HashMap<>();

Map์€ 2๊ฐœ์˜ ํƒ€์ž…์„ ๊ฐ–๊ณ  ์žˆ๋Š” ๋ฐฐ์—ด์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์ฒซ ๋ฒˆ์งธ ํƒ€์ž…์€ ํ•ด๋‹น ๊ฐ’์˜ ๊ณ ์œ  ํ‚ค์ด๊ณ , ๋‘ ๋ฒˆ์งธ ํƒ€์ž…์€ ํ•ด๋‹น ๊ฐ’์˜ value ์ž…๋‹ˆ๋‹ค.

ํ˜•ํƒœ๊ฐ€ [ {1,์‹œ์›”}, {2,์ญ}, {3,์ฝ”๋”ฉ}] ์ด๋Ÿฐ ๋Š๋‚Œ์ž…๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์—์„œ Map<Long, Member>๋Š” ๊ณ ์œ ํ‚ค๋Š” Long ํƒ€์ž…, value๋Š” ์ด์ „์— ์ •ํ•œ Member ํด๋ž˜์Šค ํƒ€์ž…์ž…๋‹ˆ๋‹ค.

Member ํด๋ž˜์Šค๋Š” id์™€ name๊ณผ grade๋ฅผ ๊ฐ–๊ณ  ์žˆ๋Š” ์ง‘ํ•ฉ์ž…๋‹ˆ๋‹ค. (1, ์‹œ์›”, VIP) ์š”๋Ÿฐ ๋Š๋‚Œ?

store๋Š” ๋ณ€์ˆ˜ ์ด๋ฆ„์œผ๋กœ ์•„๋ฌด๊ฑฐ๋‚˜ ์ง€์ •ํ•ด๋„ ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ , Map์€ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์ข…๋ฅ˜๊ฐ€ ์žˆ๋Š”๋ฐ HashMap์€ ํ•ด์‹œ ํ…Œ์ด๋ธ”์„ ์‚ฌ์šฉํ•ด์„œ ๋น ๋ฅธ ๊ฒ€์ƒ‰ ์†๋„๋ฅผ ์ œ๊ณตํ•˜๋Š” Map ์ž…๋‹ˆ๋‹ค.

 

HashMap์—๋Š” put() ๊ธฐ๋Šฅ๊ณผ get() ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

put()์€ ๊ฐ’์„ ๋„ฃ๋Š” ๊ธฐ๋Šฅ์ด๊ณ , ์ธ์ž๊ฐ’์œผ๋กœ ๊ณ ์œ ํ‚ค๊ณผ value 2๊ฐœ๋ฅผ ๋„ฃ์–ด์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.

get()์€ ๊ฐ’์„ ์ฐพ๋Š” ๊ธฐ๋Šฅ์ด๊ณ , ๊ณ ์œ ํ‚ค๋งŒ ์ธ์ž๊ฐ’์œผ๋กœ ๋„ฃ์–ด์ฃผ๋ฉด value๋ฅผ ์ฐพ์•„์ค๋‹ˆ๋‹ค.

 

์—ฌ๊ธฐ์—์„œ๋Š” ๊ณ ์œ ํ‚ค๊ฐ€ member.getId์˜ ๊ฐ’์ž…๋‹ˆ๋‹ค. value๋Š” member ์ž์ฒด์ž…๋‹ˆ๋‹ค.

 

๊ทธ ๋‹ค์Œ์œผ๋กœ MemberService ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

package hello.core.member;

public interface MemberService {
    void join(Member member); //ํšŒ์› ๊ฐ€์ž…

    Member findMember(Long memberId); //ํšŒ์› ์กฐํšŒ
}

ํšŒ์› ๊ฐ€์ž…๊ณผ ํšŒ์› ์กฐํšŒ ๊ธฐ๋Šฅ์„ ๋„ฃ๊ณ , ๊ตฌํ˜„์ฒด์ธ MemberServiceImpl์„ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

package hello.core.member;

public class MemberServiceImpl implements MemberService{

    private final MemberRepository memberRepository = new MemoryMemberRepository();
    @Override
    public void join(Member member) {
        memberRepository.save(member);
    }

    @Override
    public Member findMember(Long memberId) {
        return memberRepository.findById(memberId);
    }
}

MemberService์˜ ๊ตฌํ˜„์ฒด์—ฌ์„œ implements๋ฅผ ์‚ฌ์šฉํ–ˆ๊ณ , ์•„๊นŒ์ฒ˜๋Ÿผ Alt + Enter ํ‚ค๋ฅผ ๋ˆŒ๋Ÿฌ ๋ฉ”์„œ๋“œ ๊ตฌํ˜„์„ ํ•ฉ๋‹ˆ๋‹ค.

 

  •  private final MemberRepository memberRepository = new MemoryMemberRepository();

์—ฌ๊ธฐ์„œ final์€ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋Š” ๋ณ€์ˆ˜๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

MemberRepository๋Š” ์ด๋ฏธ ๊ตฌ์„ฑ์ด ์™„๋ฃŒ๋˜์–ด์žˆ๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— MemberService์—์„œ MemberRepository๊ฐ€ ๋ณ€๊ฒฝ์ด ๋˜๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค. ๋•Œ๋ฌธ์— final์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ , MemberRepository์˜ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š”๋ฐ memberRepository๋ผ๋Š” ๋ณ€์ˆ˜๋ช…์„ ์‚ฌ์šฉํ•˜์—ฌ MemoryMemberRepository์—์„œ ๊ตฌํ˜„ํ•œ ๊ธฐ๋Šฅ๋“ค์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. (MemoryMemberRepository๋Š” MemberRepository์˜ ๊ตฌํ˜„์ฒด์ด๊ธฐ ๋•Œ๋ฌธ์—)

 

 

3-3. ํšŒ์› ๋„๋ฉ”์ธ ์‹คํ–‰๊ณผ ํ…Œ์ŠคํŠธ

์œ„์—์„œ ํšŒ์› ๋„๋ฉ”์ธ ๊ฐœ๋ฐœํ•œ ๊ฒƒ์„ ์‹คํ–‰๊ณผ ํ…Œ์ŠคํŠธ๋ฅผ ํ•ด๋ณผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋จผ์ €, core ํด๋” ์•ˆ์— MemberApp์ด๋ผ๊ณ  ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด์ค๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๊ณ  ๋ฉ”์ธ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค๊ณ , Member๋ฅผ ํšŒ์›๊ฐ€์ž…ํ•˜๊ณ  ์กฐํšŒ๋ฅผ ํ•ด๋ณผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

package hello.core;

import hello.core.member.Grade;
import hello.core.member.Member;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;

public class MemberApp {
    public static void main(String[] args) {
        MemberService memberService = new MemberServiceImpl();
        Member member = new Member(1L, "์‹œ์›”", Grade.VIP);
        memberService.join(member);

        Member findMember = memberService.findMember(1L);
        System.out.println("new member = " + member.getName());
        System.out.println("findMember = " + findMember.getName());
    }
}

new MemberServiceImpl()์„ ํ†ตํ•ด MemberServiceImpl์—์„œ ๊ตฌํ˜„ํ–ˆ๋˜ join๊ณผ findMember๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•ด๋ณผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์šฐ์„ , ๊ฐ€์ž…์‹œํ‚ฌ ํšŒ์› ์ •๋ณด๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

new Member(1L, "์‹œ์›”", Grade.VIP);๋ฅผ ํ†ตํ•ด id๋Š” 1๋ฒˆ์ด๊ณ , ์ด๋ฆ„์€ ์‹œ์›”์ด๊ณ , ๋“ฑ๊ธ‰์€ VIP์ธ Member๋ฅผ ํ•˜๋‚˜ ์ƒ์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.

ํ•ด๋‹น ๋ฉค๋ฒ„๋ฅผ ํšŒ์›๊ฐ€์ž… ์‹œํ‚ค๊ธฐ ์œ„ํ•ด MemberService.join()์„ ํ˜ธ์ถœํ•˜์—ฌ MemoryMemberRepository์˜ store์— ์ €์žฅ๋˜๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

๋ฐฉ๊ธˆ ์ €์žฅํ•œ ํšŒ์›์„ id๋ฅผ ํ†ตํ•ด ์กฐํšŒํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

MemberService.findMember()๋ฅผ ํ†ตํ•ด ๋ฐฉ๊ธˆ ์ €์žฅํ•œ "์‹œ์›”"์„ ์กฐํšŒํ• ๊ฑด๋ฐ, "์‹œ์›”"์˜ id ๊ฐ’์€ 1์ด๊ธฐ ๋•Œ๋ฌธ์— ์ธ์ž๊ฐ’์œผ๋กœ 1์„ ๋„ฃ์–ด์ค๋‹ˆ๋‹ค. (Long ํƒ€์ž…์ด์–ด์„œ 1L)

ํ˜ธ์ถœํ•˜๋ฉด ๋ฆฌํ„ด๊ฐ’์œผ๋กœ member๊ฐ€ ๋‚˜์˜ค๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ๊ธฐ์„œ ์ด์ „์— ๋งŒ๋“ค์—ˆ๋˜ getter๋“ค์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฆ„์ด๋‚˜ ๋“ฑ๊ธ‰ ๋“ฑ์„ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (findMember.getName())

 

์ด๋ฆ„์„ ํ˜ธ์ถœํ–ˆ์œผ๋ฏ€๋กœ ๊ฒฐ๊ณผ๋Š” ์ด๋ ‡๊ฒŒ ๋‚˜์˜ต๋‹ˆ๋‹ค.

 

์—ฌ๊ธฐ๋Š” ๋ณด๋ฉด ์•„์‹œ๋‹ค์‹œํ”ผ ์ˆœ์ˆ˜ํ•˜๊ฒŒ ์ž๋ฐ”๋งŒ ์‚ฌ์šฉํ•œ ๊ฒƒ์ด๊ณ , ์Šคํ”„๋ง ๊ด€๋ จ ์ฝ”๋“œ๊ฐ€ 1๋„ ์—†์Šต๋‹ˆ๋‹ค.

๊ทผ๋ฐ, ์ด๋ ‡๊ฒŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ์ง์œผ๋กœ ํ…Œ์ŠคํŠธ ํ•˜๋Š” ๊ฒƒ์€ ์ข‹์€ ๋ฐฉ๋ฒ•์ด ์•„๋‹™๋‹ˆ๋‹ค.

JUnit ํ…Œ์ŠคํŠธ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

์ด๋ฒˆ์—๋Š” main ํŒจํ‚ค์ง€๊ฐ€ ์•„๋‹Œ test ํŒจํ‚ค์ง€ ์•ˆ์— ๋งŒ๋“ค ๊ฒƒ์ž…๋‹ˆ๋‹ค.

test ํŒจํ‚ค์ง€ ์•ˆ์˜ java ์•ˆ์˜ hello ์•ˆ์˜ core ์•ˆ์—์„œ member ํŒจํ‚ค์ง€๋ฅผ ๋งŒ๋“ค์–ด์„œ ๊ฑฐ๊ธฐ์— MemberServiceTest๋ผ๋Š” ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

package hello.core.member;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;

public class MemberServiceTest {
    MemberService memberService = new MemberServiceImpl();
    @Test
    void join() {
        //given //์ด๋Ÿฐ ํ™˜๊ฒฝ์ด ์ฃผ์–ด์กŒ์„ ๋•Œ
        Member member = new Member(1L, "์‹œ์›”", Grade.VIP);

        //when //์ด๋ ‡๊ฒŒ ํ–ˆ์„ ๋•Œ
        memberService.join(member);
        Member findMember = memberService.findMember(1L);

        //then //์ด๋ ‡๊ฒŒ ๋œ๋‹ค
        Assertions.assertThat(member).isEqualTo(findMember);

    }
}

MemberService์˜ ๊ธฐ๋Šฅ์„ ํ…Œ์ŠคํŠธํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฉ”์„œ๋“œ๋“ค์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•˜์—ฌ new MemberServiceImpl()์„ ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

@Test๊ฐ€ ๋ถ™์€ ๋ฉ”์„œ๋“œ๋Š” ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ ๋ฉ”์„œ๋“œ๋ผ๊ณ  ์„ ์–ธํ•˜๋Š” annotation์ž…๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ๋Š” ํฌ๊ฒŒ given, when, then 3๋‹จ๊ณ„๋กœ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

given์€ ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์„ ๊ฐ–์ถ”๋Š” ๋‹จ๊ณ„์ด๊ณ , when์€ ํ…Œ์ŠคํŠธ ํ•  ์ƒํ™ฉ์„ ์ง„ํ–‰ํ•˜๋Š” ๋‹จ๊ณ„์ด๊ณ , then์€ ์˜ˆ์ƒํ•œ๋Œ€๋กœ ์ž˜ ์ž‘๋™ํ–ˆ๋Š”์ง€ ํ…Œ์ŠคํŠธํ•˜๋Š” ๋‹จ๊ณ„์ž…๋‹ˆ๋‹ค.

 

  • Member member = new Member(1L, "์‹œ์›”", Grade.VIP);
    • ํ…Œ์ŠคํŠธ ์ „ "์‹œ์›”"์ด๋ผ๋Š” ๋ฉค๋ฒ„ํ˜• ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
    • ํšŒ์›๊ฐ€์ž… ์ „์— ํšŒ์›๊ฐ€์ž… ์ฐฝ์— ํšŒ์›์˜ ์ •๋ณด๋“ค์„ ์ ์–ด๋†“๊ธฐ๋งŒ ํ•œ ์ƒํƒœ์™€ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค.
  • memberService.join(member);
    • ํ…Œ์ŠคํŠธ ํ•  ์ƒํ™ฉ์ธ "์‹œ์›”"์ด๋ผ๋Š” ๋ฉค๋ฒ„๋ฅผ ํšŒ์›๊ฐ€์ž…์‹œํ‚ค๋Š” ๋‹จ๊ณ„์ž…๋‹ˆ๋‹ค.
    • ์—ฌ๊ธฐ์„œ findMember๋Š” ํšŒ์›๊ฐ€์ž…ํ•œ ์‚ฌ์šฉ์ž๋ฅผ ์กฐํšŒํ•˜๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.
  • Assertions.assertThat(member).isEqualTo(findMember);
    • Assertions๋Š” JUnit์—์„œ ์ œ๊ณตํ•˜๋Š” ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ๋“ค์˜ ์ง‘ํ•ฉ ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค.
      ๊ทธ ์ค‘ ์ €ํฌ๋Š” assertThat()์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
    • assertThat()์€ ๋น„๊ต ๋Œ€์ƒ์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
      ์ €ํฌ๋Š” ๋งจ ์ฒ˜์Œ ์ƒ์„ฑํ•œ ๋ฉค๋ฒ„ํ˜• ๋ณ€์ˆ˜๋ฅผ ๋น„๊ต ๋Œ€์ƒ์— ์ง€์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.
    • ํ•ด๋‹น ๋ณ€์ˆ˜๊ฐ€ MemberService.findMember()๋ฅผ ํ†ตํ•ด ์กฐํšŒํ•ด์„œ ๊ฐ€์ ธ์˜จ ๋ฉค๋ฒ„์™€ ๊ฐ™์•„์•ผ ํ…Œ์ŠคํŠธ๊ฐ€ ์„ฑ๊ณตํ•ฉ๋‹ˆ๋‹ค.

 

ํ…Œ์ŠคํŠธ ์‹คํ–‰์„ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ํ•  ๋•Œ๋Š” ์ถœ๋ ฅ์„ ํ•˜์—ฌ ๋ˆˆ์œผ๋กœ ๊ฒ€์ •์„ ํ•˜๋Š”๋ฐ JUnit์„ ์‚ฌ์šฉํ•˜๋ฉด ํ…Œ์ŠคํŠธ ์„ฑ๊ณตํ•˜๋ฉด ๋ฐ‘์— ์‚ฌ์ง„์ฒ˜๋Ÿผ ๋‚˜์˜ต๋‹ˆ๋‹ค.

์‹คํŒจํ•˜๋ฉด ๋นจ๊ฐ„์ƒ‰์œผ๋กœ ๋œจ๋ฉด์„œ X๋‚˜์˜ค๊ณ  ๋ญ ์˜ค๋ฅ˜ ๋œน๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ๋ฅผ ๋ฉ”์ธ ํ•จ์ˆ˜์— ํ•˜์ง€ ์•Š๋Š” ์ด์œ 

๋ฉ”์ธ ํ•จ์ˆ˜์—์„œ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด ๊ฐ’ ํ™•์ธ์„ ์œ„ํ•ด System.out.println()๊ณผ ๊ฐ™์€ ์ถœ๋ ฅ ํ•จ์ˆ˜๋ฅผ ์จ์„œ ์ถœ๋ ฅ ๋กœ๊ทธ๋ฅผ ๋ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
์ด ๊ณผ์ •์€ ๋งค์šฐ ๋ฒˆ๊ฑฐ๋กญ๊ณ  ์‹ค์ˆ˜๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์–ด์„œ ํ™•์‹คํ•˜๊ฒŒ โœ”๏ธ ํ˜น์€ โŒ๊ฐ€ ๋‚˜์˜ค๋Š” JUnit ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿฐ๋ฐ ์ด ํšŒ์› ๋„๋ฉ”์ธ ์„ค๊ณ„์—๋Š” ๋ฌธ์ œ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ์ฝ”๋“œ๋ฅผ ์งœ๋ฉด ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ถ”์ƒํ™”์—๋„ ๊ตฌ์ฒดํ™”์—๋„ ์˜์กดํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

(ex. MemberService๊ฐ€ MemberRepository์—๋„ ์˜์กดํ•˜๊ณ , MemoryMemberRepository์—๋„ ์˜์กดํ•ฉ๋‹ˆ๋‹ค.)

DIP๋ฅผ ์œ„๋ฐ˜ํ•˜๋Š” ๊ฒƒ์ด์ฃ .


4. ์ฃผ๋ฌธ๊ณผ ํ• ์ธ ๋„๋ฉ”์ธ

4-1. ์ฃผ๋ฌธ๊ณผ ํ• ์ธ ๋„๋ฉ”์ธ ์„ค๊ณ„

  • ์ฃผ๋ฌธ๊ณผ ํ• ์ธ ์ •์ฑ…
    • ํšŒ์›์€ ์ƒํ’ˆ์„ ์ฃผ๋ฌธํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ํšŒ์› ๋“ฑ๊ธ‰์— ๋”ฐ๋ผ ํ• ์ธ ์ •์ฑ…์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ํ• ์ธ ์ •์ฑ…์€ "๋ชจ๋“  VIP๋Š” 1,000์›์„ ํ• ์ธํ•ด์ฃผ๋Š” ๊ณ ์ • ๊ธˆ์•ก ํ• ์ธ์„ ์ ์šฉํ•ด๋‹ฌ๋ผ."์ž…๋‹ˆ๋‹ค. (๋‚˜์ค‘์— ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ๋‹ค)
    • ํ• ์ธ ์ •์ฑ…์€ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’๋‹ค. ํšŒ์‚ฌ์˜ ๊ธฐ๋ณธ ํ• ์ธ ์ •์ฑ…์„ ์•„์ง ์ •ํ•˜์ง€ ๋ชปํ–ˆ๊ณ , ์˜คํ”ˆ ์ง์ „๊นŒ์ง€ ๊ณ ๋ฏผ์„ ๋ฏธ๋ฃจ๊ณ  ์‹ถ๋‹ค. ์ตœ์•…์˜ ๊ฒฝ์šฐ ํ• ์ธ์„ ์ ์šฉํ•˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ๋‹ค. (๋ฏธํ™•์ •)
  • ์ฃผ๋ฌธ ๋„๋ฉ”์ธ ํ˜‘๋ ฅ, ์—ญํ• , ์ฑ…์ž„

1. ์ฃผ๋ฌธ ์ƒ์„ฑ: ํด๋ผ์ด์–ธํŠธ๋Š” ์ฃผ๋ฌธ ์„œ๋น„์Šค์— ์ฃผ๋ฌธ ์ƒ์„ฑ์„ ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค.

2. ํšŒ์› ์กฐํšŒ: ํ• ์ธ์„ ์œ„ํ•ด์„œ๋Š” ํšŒ์› ๋“ฑ๊ธ‰์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ฃผ๋ฌธ ์„œ๋น„์Šค๋Š” ํšŒ์› ์ €์žฅ์†Œ์—์„œ ํšŒ์›์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

3. ํ• ์ธ ์ ์šฉ: ์ฃผ๋ฌธ ์„œ๋น„์Šค๋Š” ํšŒ์› ๋“ฑ๊ธ‰์— ๋”ฐ๋ฅธ ํ• ์ธ ์—ฌ๋ถ€๋ฅผ ํ• ์ธ ์ •์ฑ…์— ์œ„์ž„ํ•ฉ๋‹ˆ๋‹ค.

4. ์ฃผ๋ฌธ ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜: ์ฃผ๋ฌธ ์„œ๋น„์Šค๋Š” ํ• ์ธ ๊ฒฐ๊ณผ๋ฅผ ํฌํ•จํ•œ ์ฃผ๋ฌธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์ฐธ๊ณ : ์‹ค์ œ๋กœ๋Š” ์ฃผ๋ฌธ ๋ฐ์ดํ„ฐ๋ฅผ DB์— ์ €์žฅํ•˜๊ฒ ์ง€๋งŒ, ์˜ˆ์ œ๊ฐ€ ๋„ˆ๋ฌด ๋ณต์žกํ•ด์งˆ ์ˆ˜ ์žˆ์–ด์„œ ์ƒ๋žตํ•˜๊ณ , ๋‹จ์ˆœํžˆ ์ฃผ๋ฌธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

 

  • ์ฃผ๋ฌธ ๋„๋ฉ”์ธ ์ „์ฒด

ํ• ์ธ ์ •์ฑ… ์—ญํ•  ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ ํ• ์ธ์„ ํ•  ๊ฑด์ง€์— ๋”ฐ๋ผ ๊ตฌํ˜„์ฒด๋ฅผ ๋‚˜๋ˆด์Šต๋‹ˆ๋‹ค.

๊ณ ์ • ๊ธˆ์•ก์„ ํ• ์ธํ•˜๋Š” ์ •์•ก ํ• ์ธ ์ •์ฑ…๊ณผ % ํ• ์ธํ•˜๋Š” ์ •๋ฅ  ํ• ์ธ ์ •์ฑ…์„ ํ• ์ธ ์ •์ฑ… ์—ญํ• ์˜ ๊ตฌํ˜„์ฒด๋กœ ๋‚˜ํƒ€๋ƒˆ์Šต๋‹ˆ๋‹ค.

 

ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ฃผ๋ฌธ ์ƒ์„ฑ์„ ์š”์ฒญํ•  ์ฃผ๋ฌธ ์„œ๋น„์Šค ์—ญํ•  ์ธํ„ฐํŽ˜์ด์Šค๋Š” ํšŒ์›์˜ ๋“ฑ๊ธ‰์„ ํ™•์ธํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํšŒ์› ์ €์žฅ์†Œ ์—ญํ• ์ด ํ•„์š”ํ•˜๊ณ , ๋“ฑ๊ธ‰์— ๋”ฐ๋ผ ๊ฐ€๊ฒฉ์„ ํ• ์ธํ•ด์ค˜์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ• ์ธ ์ •์ฑ… ์—ญํ• ๋„ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

 

์—ญํ• ๊ณผ ๊ตฌํ˜„์„ ๋ถ„๋ฆฌํ•ด์„œ ์ž์œ ๋กญ๊ฒŒ ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ์กฐ๋ฆฝํ•  ์ˆ˜ ์žˆ๊ฒŒ ์„ค๊ณ„ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋•๋ถ„์— ํšŒ์› ์ €์žฅ์†Œ๋Š” ๋ชฐ๋ก ์ด๊ณ , ํ• ์ธ ์ •์ฑ…๋„ ์œ ์—ฐํ•˜๊ฒŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

  • ์ฃผ๋ฌธ ๋„๋ฉ”์ธ ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ

- ์ธํ„ฐํŽ˜์ด์Šค OrderService = ์ฃผ๋ฌธ ์„œ๋น„์Šค ์—ญํ• 

- OrderServiceImpl = ์ฃผ๋ฌธ ์„œ๋น„์Šค ๊ตฌํ˜„์ฒด

- ์ธํ„ฐํŽ˜์ด์Šค DiscountPolicy = ํ• ์ธ ์ •์ฑ… ์—ญํ• 

- FixDiscountPolicy = ์ •์•ก ํ• ์ธ ์ •์ฑ…

- RateDiscountPolicy = ์ •๋ฅ  ํ• ์ธ ์ •์ฑ…

 

  • ์ฃผ๋ฌธ ๋„๋ฉ”์ธ ๊ฐ์ฒด ๋‹ค์ด์–ด๊ทธ๋žจ1

ํšŒ์›์„ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์กฐํšŒํ•˜๊ณ , ์ •์•ก ํ• ์ธ ์ •์ฑ…(๊ณ ์ • ๊ธˆ์•ก)์„ ์ง€์›ํ•ด๋„ ์ฃผ๋ฌธ ์„œ๋น„์Šค๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค.

์—ญํ• ๋“ค์˜ ํ˜‘๋ ฅ ๊ด€๊ณ„๋ฅผ ๊ทธ๋Œ€๋กœ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

  • ์ฃผ๋ฌธ ๋„๋ฉ”์ธ ๊ฐ์ฒด ๋‹ค์ด์–ด๊ทธ๋žจ2

ํšŒ์›์„ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์•„๋‹Œ ์‹ค์ œ DB์—์„œ ์กฐํšŒํ•˜๊ณ , ์ •๋ฅ  ํ• ์ธ ์ •์ฑ…(์ฃผ๋ฌธ ๊ธˆ์•ก์— ๋”ฐ๋ผ % ํ• ์ธ)์„ ์ง€์›ํ•ด๋„ ์ฃผ๋ฌธ ์„œ๋น„์Šค๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค.

ํ˜‘๋ ฅ ๊ด€๊ณ„๋ฅผ ๊ทธ๋Œ€๋กœ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

4-2. ์ฃผ๋ฌธ๊ณผ ํ• ์ธ ๋„๋ฉ”์ธ ๊ฐœ๋ฐœ - ์ •์•ก ํ• ์ธ ์ •์ฑ…(FixDiscountPolicy)

์œ„์˜ ์„ค๊ณ„๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๊ฐœ๋ฐœ์„ ํ•œ ๋ฒˆ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋จผ์ €, hello ํด๋” ์•ˆ์˜ core ํŒจํ‚ค์ง€ ์•ˆ์— discount๋ผ๋Š” ํŒจํ‚ค์ง€๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๊ณ  ์ด ํŒจํ‚ค์ง€ ์•ˆ์— DiscountPolicy ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

package hello.core.discount;

import hello.core.member.Member;

public interface DiscountPolicy {

    //@return ํ• ์ธ ๋Œ€์ƒ ๊ธˆ์•ก
    int discount(Member member, int price);
}

DiscountPolicy์˜ ๊ตฌํ˜„์ฒด๊ฐ€ ๊ตฌํ˜„ํ•ด์•ผ ํ•  ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

์™œ ์ธ์ž๊ฐ’์ด 2๊ฐœ์ผ๊นŒ์š”?

ํ• ์ธ์„ ํ•˜๋ ค๋ฉด ์ด ์‚ฌ๋žŒ์˜ Grade์™€ ๋ฌผ๊ฑด์˜ ๊ฐ€๊ฒฉ์„ ์•Œ์•„์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

Grade๊ฐ€ VIP์ด๋ฉด ๊ตฌํ˜„์ฒด์˜ ํ• ์ธ ์ •์ฑ…์— ๋”ฐ๋ผ ์› ๊ฐ€๊ฒฉ์—์„œ ํ• ์ธ๋œ ๊ฐ€๊ฒฉ์œผ๋กœ return์„ ํ•ด์ค๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿฌ๊ณ  DiscountPolicy์˜ ๊ตฌํ˜„์ฒด ์ค‘์— ์ •์•ก ํ• ์ธ ์ •์ฑ… ๊ตฌํ˜„์ฒด๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์•„๊นŒ์ฒ˜๋Ÿผ discount ํŒจํ‚ค์ง€ ์•ˆ์— FixDiscountPolicy ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด์ค๋‹ˆ๋‹ค.

๋งŒ๋“ค์–ด๋ณด๋ฉด

package hello.core.discount;

import hello.core.member.Member;

public class FixDiscountPolicy implements DiscountPolicy {
    @Override
    public int discount(Member member, int price) {
        return 0;
    }
}

์ด๋ ‡๊ฒŒ ๋‚˜์˜ค๋Š”๋ฐ ์ด๊ฒƒ์€ ์œ„์—์„œ MemoryMemberRepository๋•Œ ํ–ˆ๋˜ ๊ฒƒ์ฒ˜๋Ÿผ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•  ํด๋ž˜์Šค๋ผ๊ณ  ๋ช…์‹œํ•˜๊ธฐ ์œ„ํ•ด์„œ implements๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๋นจ๊ฐ„ ์ค„์ด ๋œจ๋Š”๋ฐ ์ด ์—ญ์‹œ Alt + Enter ํ‚ค๋ฅผ ๋ˆŒ๋Ÿฌ์„œ ๋ฉ”์„œ๋“œ ๊ตฌํ˜„์„ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

๋ฉ”์„œ๋“œ ๊ตฌํ˜„ ํ•˜๋ฉด ์˜ค๋ฒ„๋ผ์ด๋“œ๋ฅผ ํ•˜๊ฒŒ ๋˜๋Š”๋ฐ ์•„๊นŒ ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ์ •์˜ํ–ˆ๋˜ discount ๋ฉ”์„œ๋“œ๋ฅผ ์žฌ์ •์˜ํ–ˆ์Šต๋‹ˆ๋‹ค.

public class FixDiscountPolicy implements DiscountPolicy {
    private int discountFixAmount = 1000; //1000์› ํ• ์ธ

    @Override
    public int discount(Member member, int price) {
        if(member.getGrade() == Grade.VIP) {
            return discountFixAmount;  //1,000์›์„ ํ• ์ธํ•˜๋ ค๊ณ 
        }
        else {
            return 0; //ํ• ์ธํ•  ๊ธˆ์•ก์ด ์—†๋‹ค๋Š” ๋œป
        }
    }
}

๋งˆ์ € ๋” ๊ตฌํ˜„ํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

ํ• ์ธํ•  ๊ธˆ์•ก์„ 1,000์›์œผ๋กœ ์ •์˜ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— private int discountFixAmout = 1000;๋กœ ๋ณ€์ˆ˜๋ฅผ ์ง€์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ํ• ์ธ์€ VIP๋งŒ ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ‘์— ํ•จ์ˆ˜์— if๋ฌธ์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

๋งŒ์•ฝ์— VIP ๋“ฑ๊ธ‰์ด๋ฉด discountFixAmount ๋ณ€์ˆ˜๋ฅผ ๋ฆฌํ„ดํ•˜๊ฒŒ๋” ํ–ˆ๊ณ , ์•„๋‹ ๊ฒฝ์šฐ 0์œผ๋กœ ๋ฆฌํ„ด๋˜๊ฒŒ ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

 

๊ทธ ๋‹ค์Œ ์ฃผ๋ฌธ ์„œ๋น„์Šค ์ธํ„ฐํŽ˜์ด์Šค์™€ ๊ตฌํ˜„์ฒด๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด core ํŒจํ‚ค์ง€ ์•ˆ์— order๋ผ๋Š” ํŒจํ‚ค์ง€๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๊ณ  order ํŒจํ‚ค์ง€ ์•ˆ์— order ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

package hello.core.order;

public class Order {
    private Long memberId; //ํšŒ์› id
    private String itemName; //๋ฌผ๊ฑด ์ด๋ฆ„
    private int itemPrice; //๋ฌผ๊ฑด ๊ธˆ์•ก
    private int discountPrice; //ํ• ์ธ ๊ธˆ์•ก

    public Order(Long memberId, String itemName, int itemPrice, int discountPrice) {
        this.memberId = memberId;
        this.itemName = itemName;
        this.itemPrice = itemPrice;
        this.discountPrice = discountPrice;
    }

    //๋น„์ฆˆ๋‹ˆ์Šค ๊ณ„์‚ฐ ๋กœ์ง
    public int calculatePrice() {
        return itemPrice - discountPrice;
    }

    public Long getMemberId() {
        return memberId;
    }

    public String getItemName() {
        return itemName;
    }

    public int getItemPrice() {
        return itemPrice;
    }

    public int getDiscountPrice() {
        return discountPrice;
    }

    public void setMemberId(Long memberId) {
        this.memberId = memberId;
    }

    public void setItemName(String itemName) {
        this.itemName = itemName;
    }

    public void setItemPrice(int itemPrice) {
        this.itemPrice = itemPrice;
    }

    public void setDiscountPrice(int discountPrice) {
        this.discountPrice = discountPrice;
    }

    //๋ฌธ์ž์—ด ์ถœ๋ ฅ์„ ํ•  ๋•Œ ๋ณด๊ธฐ ์‰ฝ๊ฒŒ ํ•˜๋ ค๊ณ 
    @Override
    public String toString() {
        return "Order{" +
                "memberId=" + memberId +
                ", itemName='" + itemName + '\'' +
                ", itemPrice=" + itemPrice +
                ", discountPrice=" + discountPrice +
                '}';
    }
}

๋จผ์ €, ์ฃผ๋ฌธ ๋ฐ์ดํ„ฐ๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„œ ์ฃผ๋ฌธํ•œ ์‚ฌ์šฉ์ž์˜ id๊ฐ€ ํ•„์š”ํ•˜๊ณ  ์ฃผ๋ฌธํ•œ ๋ฌผํ’ˆ์˜ ์ด๋ฆ„, ๊ฐ€๊ฒฉ๊ณผ ํ• ์ธํ•  ๊ฐ€๊ฒฉ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ์ € 4๊ฐœ์˜ ํ•„๋“œ(์—”ํ‹ฐํ‹ฐ ๋‚ด์˜ ๋ณ€์ˆ˜๋“ค)๋ฅผ ๊ฐ๊ฐ ๋งŒ๋“ค์–ด์„œ Alt + Insert ํ‚ค๋ฅผ ๋ˆŒ๋Ÿฌ ์ƒ์„ฑ์ž์™€ Getter, Setter๋ฅผ ์ƒ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ ๊ตฌ๋งคํ•  ์ตœ์ข… ๋ฌผ๊ฑด ๊ฐ€๊ฒฉ์„ ๊ณ„์‚ฐํ•˜๊ธฐ ์œ„ํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๊ณ„์‚ฐ ๋กœ์ง์œผ๋กœ calculatePrice๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ ์ฃผ๋ฌธ ์ •๋ณด๋ฅผ ๋ฌธ์ž์—ด๋กœ ํŽธํ•˜๊ฒŒ ์ถœ๋ ฅํ•˜๊ธฐ ์œ„ํ•ด์„œ Alt + Insert ํ‚ค๋ฅผ ๋ˆŒ๋Ÿฌ์„œ toString()์„ ์ƒ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

 

๋งˆ์ง€๋ง‰์œผ๋กœ ์ฃผ๋ฌธ ์„œ๋น„์Šค ์ธํ„ฐํŽ˜์ด์Šค์™€ ์ฃผ๋ฌธ ์„œ๋น„์Šค ๊ตฌํ˜„์ฒด๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์šฐ์„  ์ฃผ๋ฌธ ์„œ๋น„์Šค ์ธํ„ฐํŽ˜์ด์Šค๋ถ€ํ„ฐ ๋งŒ๋“ค๊ฑด๋ฐ์š”.

order ํŒจํ‚ค์ง€ ์•ˆ์— OrderService๋ผ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

package hello.core.order;

public interface OrderService {
    Order createOrder(Long memberId, String itemName, int itemPrice);
}

createOrder๋Š” Order๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฉ”์„œ๋“œ ์ž…๋‹ˆ๋‹ค.

Order๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ํšŒ์› id, ๋ฌผ๊ฑด ์ด๋ฆ„, ๋ฌผ๊ฑด ๊ฐ€๊ฒฉ์„ ์ธ์ž๊ฐ’์œผ๋กœ ๊ฐ–๊ณ  Order๋ฅผ ์ƒ์„ฑํ•ด์„œ ๋ฆฌํ„ดํ•˜๋Š” ๊ธฐ๋Šฅ์„ ํ•ฉ๋‹ˆ๋‹ค.

 

 

์ฃผ๋ฌธ ์„œ๋น„์Šค ๊ตฌํ˜„์ฒด๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์•„๊นŒ์™€ ๊ฐ™์€ order ํŒจํ‚ค์ง€ ์•ˆ์— OrderServiceImpl์ด๋ผ๋Š” ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด์ค๋‹ˆ๋‹ค.

package hello.core.order;

import hello.core.discount.DiscountPolicy;
import hello.core.discount.FixDiscountPolicy;
import hello.core.member.Member;
import hello.core.member.MemberRepository;
import hello.core.member.MemoryMemberRepository;

public class OrderServiceImpl implements OrderService{

    private final MemberRepository memberRepository = new MemoryMemberRepository();
    private final DiscountPolicy discountPolicy = new FixDiscountPolicy();

    //์ง€๊ธˆ OrderService ์ž…์žฅ์—์„œ๋Š” "ํ• ์ธ์— ๊ด€ํ•œ ๊ฒƒ์€ discountPolicy ์•Œ์•„์„œ ํ•˜๊ณ , ๊ฒฐ๊ณผ๋งŒ ๋˜์ ธ์ค˜."
    //๊ทธ๋ž˜์„œ ๋‹จ์ผ์ฑ…์ž„์›์น™์„ ์ž˜ ์ง€ํ‚จ ์‚ฌ๋ก€
    //๋งŒ์•ฝ์— ํ• ์ธ์— ๋Œ€ํ•œ ๋ณ€๊ฒฝ์ด ํ•„์š”ํ•˜๋ฉด ํ• ์ธ ์ชฝ๋งŒ ์ˆ˜์ •ํ•˜๋ฉด ๋จ (์ฃผ๋ฌธ์ชฝ๊นŒ์ง€ ์ˆ˜์ •ํ•  ํ•„์š” ์—†์Œ)
    @Override
    public Order createOrder(Long memberId, String itemName, int itemPrice) {
        Member member = memberRepository.findById(memberId);
        int discountPrice = discountPolicy.discount(member, itemPrice);

        return new Order(memberId, itemName, itemPrice, discountPrice);
    }
}

findById()๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ ํ•ด๋‹น ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ–ˆ๋˜ MemoryMemberRepository๋ฅผ ํ• ๋‹น๋ฐ›์•˜์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ, discountPrice๋ฅผ ๊ณ„์‚ฐํ•˜๊ธฐ ์œ„ํ•ด์„œ discount()๋ฅผ ๊ตฌํ˜„ํ–ˆ๋˜ FixDiscountPolicy๋ฅผ ํ• ๋‹น๋ฐ›์•˜์Šต๋‹ˆ๋‹ค.

 

createOrder๋Š” Order๋ฅผ ์ƒ์„ฑํ•ด์„œ ๋ฆฌํ„ดํ•˜๋Š” ๋ฉ”์„œ๋“œ ์ž…๋‹ˆ๋‹ค.

ํ˜„์žฌ Order๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” memberId์™€ itemName, itemPrice๋ฅผ ์ธ์ž๊ฐ’์œผ๋กœ ๋ฐ›์•„์™”์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ, discountPrice๋Š” Order ์•ˆ์—๋Š” ์žˆ์ง€๋งŒ, ์‚ฌ์šฉ์ž๊ฐ€ ์ฃผ๋ฌธ์„ ์š”์ฒญํ•  ๋•Œ ์ „๋‹ฌํ•˜๋Š” ๊ฐ’์€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— OrderServiceImpl์˜ createOrder ํ•จ์ˆ˜ ์•ˆ์—์„œ ๊ณ„์‚ฐ์ด ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

(int discountPrice = discountPolicy.discount(member, itemPrice);)

 

 

4-3. ์ฃผ๋ฌธ๊ณผ ํ• ์ธ ๋„๋ฉ”์ธ ์‹คํ–‰๊ณผ ํ…Œ์ŠคํŠธ - ์ •์•ก ํ• ์ธ ์ •์ฑ…(FixDiscountPolicy)

ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๊ธฐ ์œ„ํ•ด์„œ ์šฐ์„  core๋ผ๋Š” ํŒจํ‚ค์ง€ ์•ˆ์— OrderApp์ด๋ผ๋Š” ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

package hello.core;

import hello.core.member.Grade;
import hello.core.member.Member;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
import hello.core.order.Order;
import hello.core.order.OrderService;
import hello.core.order.OrderServiceImpl;

public class OrderApp {
    public static void main(String[] args) {
        MemberService memberService = new MemberServiceImpl();
        OrderService orderService = new OrderServiceImpl();

        Long memberId = 1L;
        Member member = new Member(memberId, "์‹œ์›”", Grade.VIP);
        memberService.join(member);

        Order order = orderService.createOrder(memberId, "์ดˆ์ฝœ๋ฆฟ", 10000);

        System.out.println("order = " + order);

ํšŒ์› id์™€ ์ด๋ฆ„๊ณผ ๋“ฑ๊ธ‰์ด ์žˆ๋Š” Member๋ฅผ ์ƒ์„ฑํ•˜์—ฌ MemberServiceImpl์—์„œ ์ œ๊ณตํ•˜๋Š” ํšŒ์›๊ฐ€์ž…(join)๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ , ์ฃผ๋ฌธ์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด OrderServiceImpl์—์„œ ์ œ๊ณตํ•˜๋Š” createOrder๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ, ์ธ์ž๊ฐ’์œผ๋กœ ๋ฐฉ๊ธˆ ํšŒ์›๊ฐ€์ž…ํ•œ ํšŒ์›์˜ id์™€ ๋ฌผ๊ฑด ์ด๋ฆ„, ๋ฌผ๊ฑด ๊ฐ€๊ฒฉ์„ ๋„ฃ์–ด์คฌ์Šต๋‹ˆ๋‹ค.

 

"์‹œ์›”"์ด์˜ ๋“ฑ๊ธ‰์€ VIP์ด๊ธฐ ๋•Œ๋ฌธ์— Order๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ ํ• ์ธ๋  ๊ฐ€๊ฒฉ(discountPrice)์€ 1,000์›์ด ๋˜์–ด์•ผํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ฒฐ๊ณผ์—์„œ ๋ณด๋ฉด ์•„์‹œ๋‹ค์‹œํ”ผ discountPrice๊ฐ€ 1,000์›์œผ๋กœ ์ž˜ ์„ค์ •๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

 

๊ทผ๋ฐ ์ด ๊ฒ€์‚ฌ ๋ฐฉ๋ฒ•์€ ์œ„์—์„œ๋„ ์–˜๊ธฐํ–ˆ๋‹ค์‹œํ”ผ ์ข‹์ง€ ์•Š์€ ๋ฐฉ๋ฒ•์ด๊ธฐ ๋•Œ๋ฌธ์— JUnit์„ ์‚ฌ์šฉํ•ด์„œ ํ…Œ์ŠคํŠธ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋ฐ‘์— Test๋ผ๋Š” ํด๋” ์•ˆ์˜ hello ํด๋” ์•ˆ์˜ core ํŒจํ‚ค์ง€ ์•ˆ์—์„œ order๋ผ๋Š” ํŒจํ‚ค์ง€๋ฅผ ๋งŒ๋“ค์–ด ๊ฑฐ๊ธฐ์— OrderServiceTest๋ผ๋Š” ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

package hello.core.order;

import hello.core.member.Grade;
import hello.core.member.Member;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;

public class OrderServiceTest {

    MemberService memberService = new MemberServiceImpl();
    OrderService orderService = new OrderServiceImpl();

    @Test
    void createOrder() {
        Long memberId = 1L;
        Member member = new Member(memberId, "์‹œ์›”", Grade.VIP);
        memberService.join(member);

        Order order = orderService.createOrder(memberId, "์ดˆ์ฝœ๋ฆฟ", 10000);
        Assertions.assertThat(order.getDiscountPrice()).isEqualTo(1000);
    }
}

 

์œ„์—์„œ์ฒ˜๋Ÿผ Assertions ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

VIP ๋“ฑ๊ธ‰์ธ "์‹œ์›”"์ด๊ฐ€ 10,000์› ์งœ๋ฆฌ์ธ ์ดˆ์ฝœ๋ฆฟ์„ ์ฃผ๋ฌธํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•ด๋‹น ์ฃผ๋ฌธ์˜ discountPrice๋Š” 1,000์›์ด ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๋Š” ์ž˜ ๋‚˜์™”์„๊นŒ์š”?

์ž˜ ๋‚˜์™”์Šต๋‹ˆ๋‹ค.

๋๋‚ฌ์Šต๋‹ˆ๋‹ค.


์—ฌ๊ธฐ๊นŒ์ง€ ๋„์•~

์ฒ˜์Œ ์ œ๋Œ€๋กœ ์Šคํ”„๋ง ๋ฐฐ์›Œ๋ณด๋Š”๊ฑฐ๋ผ ์ซŒ ์–ด๋ ต๋„ค์š”..ใ…Ž

๋‹ค์Œ์— ๋˜ ์˜ค๊ฒ ์Šด๋‹ค

์•ˆ๋‡ฝ!