๐Ÿ”น TDD์— ๋Œ€ํ•˜์—ฌ

TDD๊ฐ€ ํ•„์š”ํ•œ ์ด์œ 

  1. ์ฝ”๋“œ ํ’ˆ์งˆ ํ–ฅ์ƒ

    • TDD๋Š” ๋จผ์ € ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•œ ํ›„ ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๋ฏ€๋กœ, ์š”๊ตฌ์‚ฌํ•ญ์ด ์ฝ”๋“œ๋กœ ๋ช…ํ™•ํžˆ ๋ฐ˜์˜๋ฉ๋‹ˆ๋‹ค.
    • ์ฝ”๋“œ์˜ ๊ฒฐํ•จ์ด ์ดˆ๊ธฐ์— ๋ฐœ๊ฒฌ๋˜์–ด ์ˆ˜์ • ๋น„์šฉ์ด ๊ฐ์†Œํ•ฉ๋‹ˆ๋‹ค.
  2. ์œ ์ง€๋ณด์ˆ˜์„ฑ ๊ฐ•ํ™”

    • ์ž˜ ์ž‘์„ฑ๋œ ํ…Œ์ŠคํŠธ๋Š” ์ฝ”๋“œ๊ฐ€ ๋ฆฌํŒฉํ† ๋ง๋  ๋•Œ ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค.
    • ์‹ ๊ทœ ๊ธฐ๋Šฅ ์ถ”๊ฐ€ ์‹œ, ๊ธฐ์กด ์ฝ”๋“œ์™€์˜ ์ถฉ๋Œ์„ ๋น ๋ฅด๊ฒŒ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  3. ๋ช…ํ™•ํ•œ ์„ค๊ณ„ ์œ ๋„

    • TDD๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘๊ณ  ๋…๋ฆฝ์ ์ธ ๋‹จ์œ„๋กœ ๋‚˜๋ˆ„์–ด ์„ค๊ณ„ํ•˜๋„๋ก ์žฅ๋ คํ•ฉ๋‹ˆ๋‹ค.
    • ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ SRP(Single Responsibility Principle) ๋“ฑ ๊ฐ์ฒด์ง€ํ–ฅ ์›์น™์„ ๋”ฐ๋ฅด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
  4. ๊ฐœ๋ฐœ์ž ๊ฐ„ ํ˜‘์—… ๊ฐ•ํ™”

    • ํ…Œ์ŠคํŠธ๋Š” ๊ฐœ๋ฐœ์ž๋“ค ๊ฐ„์˜ ๋ช…์„ธ์„œ ์—ญํ• ์„ ํ•˜๋ฉฐ, ์ฝ”๋“œ์˜ ๋™์ž‘์„ ๋ช…ํ™•ํžˆ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.
    • ์ฝ”๋“œ๋ฆฌ๋ทฐ ์‹œ ํ…Œ์ŠคํŠธ๋ฅผ ํ†ตํ•ด ์˜๋„ํ•œ ๋™์ž‘์„ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

TDD ์ ์šฉ ๋ฒ”์œ„?

  1. ์ ์šฉ์ด ์ ํ•ฉํ•œ ์ƒํ™ฉ

    • ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง: ์ œํ’ˆ์˜ ์ฃผ์š” ๊ธฐ๋Šฅ์ด๋‚˜ ์„œ๋น„์Šค ๋กœ์ง์€ ํ…Œ์ŠคํŠธ๊ฐ€ ํ•„์ˆ˜์ ์ž…๋‹ˆ๋‹ค.
    • ๋ณต์žกํ•œ ๊ณ„์‚ฐ์ด๋‚˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜: ์˜ค์ž‘๋™์ด ์น˜๋ช…์ ์ธ ๋กœ์ง์—๋Š” TDD๊ฐ€ ํšจ๊ณผ์ ์ž…๋‹ˆ๋‹ค.
    • API ๊ฐœ๋ฐœ: REST API๋‚˜ GraphQL๊ณผ ๊ฐ™์€ ์ธํ„ฐํŽ˜์ด์Šค๋Š” TDD๋กœ ์‚ฌ์ „ ์ •์˜ํ•˜์—ฌ ์ผ๊ด€์„ฑ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.
    • CI/CD ํŒŒ์ดํ”„๋ผ์ธ: ์ž๋™ํ™”๋œ ํ…Œ์ŠคํŠธ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋ฐฐํฌ ์ „์— ์ฝ”๋“œ๋ฅผ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.
  2. ์ ์šฉ์ด ์–ด๋ ค์šด ์ƒํ™ฉ

    • UI/UX: ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋ณ€๋™์ด ์žฆ์•„ TDD๋ฅผ ์ ์šฉํ•˜๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ๋Œ€์‹  e2e ํ…Œ์ŠคํŠธ๋ฅผ ๊ณ ๋ คํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์ดˆ๊ธฐ ํ”„๋กœํ† ํƒ€์ž… ๊ฐœ๋ฐœ: ์ดˆ๊ธฐ์—๋Š” ๋น ๋ฅธ ๊ตฌํ˜„์ด ์šฐ์„ ์ด๋ฏ€๋กœ TDD๋ฅผ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์‹œ๊ฐ„/๋ฆฌ์†Œ์Šค ๋ถ€์กฑ: ๋ชจ๋“  ์ฝ”๋“œ๋ฅผ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์–ด๋ ค์šด ๊ฒฝ์šฐ, ํ•ต์‹ฌ ์˜์—ญ์— ์šฐ์„ ์ˆœ์œ„๋ฅผ ๋‘์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  3. ํ…Œ์ŠคํŠธ์˜ ๋ฒ”์œ„ ์กฐ์ •

    • ์œ ๋‹› ํ…Œ์ŠคํŠธ: ๊ฐ€์žฅ ์ž‘์€ ๋‹จ์œ„์˜ ์ฝ”๋“œ ๋™์ž‘์„ ํ…Œ์ŠคํŠธํ•ฉ๋‹ˆ๋‹ค.
    • ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ: ์—ฌ๋Ÿฌ ๋ชจ๋“ˆ์ด ํ•จ๊ป˜ ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
    • ์—”๋“œํˆฌ์—”๋“œ ํ…Œ์ŠคํŠธ(e2e): ์‚ฌ์šฉ์ž๊ฐ€ ์‹œ์Šคํ…œ ์ „์ฒด๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ์˜ ํ๋ฆ„์„ ํ…Œ์ŠคํŠธํ•ฉ๋‹ˆ๋‹ค.

์‹ค๋ฌด ํŒ: TDD๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ์ ์šฉํ•˜๋ ค๋ฉด?

  1. ์šฐ์„ ์ˆœ์œ„๋ฅผ ์ •ํ•˜๋ผ

    • ๋ชจ๋“  ์ฝ”๋“œ๋ฅผ ํ…Œ์ŠคํŠธํ•˜๊ธฐ๋ณด๋‹ค๋Š” ํ•ต์‹ฌ์ ์ธ ๊ธฐ๋Šฅ์— ์ง‘์ค‘ํ•ฉ๋‹ˆ๋‹ค.
    • ๋‚ฎ์€ ๋ฆฌ์Šคํฌ ์˜์—ญ์€ ์ดํ›„์— ์ปค๋ฒ„๋ฆฌ์ง€๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ์ž๋™ํ™”์™€ ๋ณ‘ํ–‰ํ•˜๋ผ

    • CI/CD ํ™˜๊ฒฝ์—์„œ ํ…Œ์ŠคํŠธ๊ฐ€ ์ž๋™์œผ๋กœ ์‹คํ–‰๋˜๋„๋ก ์„ค์ •ํ•˜์—ฌ, ์ฝ”๋“œ ํ’ˆ์งˆ์„ ์ง€์†์ ์œผ๋กœ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.
  3. ํ…Œ์ŠคํŠธ๋ฅผ ๋ฌธ์„œ๋กœ ํ™œ์šฉํ•˜๋ผ

    • ํ…Œ์ŠคํŠธ๋Š” ๋‹จ์ˆœํžˆ ๊ฒ€์ฆ ๋„๊ตฌ๊ฐ€ ์•„๋‹ˆ๋ผ, ์ฝ”๋“œ์˜ ์˜๋„๋ฅผ ์„ค๋ช…ํ•˜๋Š” ๋ฌธ์„œ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

ํ•„์š”ํ•˜๋‹ค๋ฉด ์‹ค๋ฌด์—์„œ์˜ ๋ฒ”์œ„๋Š” ์–ด๋””๊นŒ์ง€์ผ๊นŒ?

1. ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง

  • ์‚ฌ๋ก€: ๊ธˆ์œต ๊ณ„์‚ฐ, ๊ฒฐ์ œ ์‹œ์Šคํ…œ, ์ธ์ฆ ์‹œ์Šคํ…œ.
  • ์ด์œ : ๋กœ์ง ์˜ค๋ฅ˜๊ฐ€ ์‚ฌ์šฉ์ž ์‹ ๋ขฐ์— ํฐ ์˜ํ–ฅ์„ ๋ฏธ์น  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ˆ˜์ • ๋น„์šฉ์ด ํฌ๊ธฐ ๋•Œ๋ฌธ.
  • ์žฅ์ :
    • ์š”๊ตฌ์‚ฌํ•ญ ๋ณ€๊ฒฝ ์‹œ ๋น ๋ฅด๊ฒŒ ๋Œ€์‘ ๊ฐ€๋Šฅ.
    • ๊ฒฐํ•จ ๋ฐœ์ƒ ํ™•๋ฅ  ๊ฐ์†Œ.
  • TDD ๋„์ž… ํŒ๋‹จ ๊ธฐ์ค€:
    • ๋กœ์ง ๋ณต์žก๋„: ๋ณต์žกํ• ์ˆ˜๋ก ๋„์ž… ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’์Œ.
    • ์žฅ์•  ๋น„์šฉ: ์žฅ์•  ๋ฐœ์ƒ ์‹œ ์†์‹ค์ด ํฌ๋ฉด ๋ฐ˜๋“œ์‹œ ๋„์ž….

2. ๋Œ€๊ทœ๋ชจ ํ˜‘์—… ํ”„๋กœ์ ํŠธ

  • ์‚ฌ๋ก€: ์—ฌ๋Ÿฌ ํŒ€์ด API๋ฅผ ๊ฐœ๋ฐœํ•˜๊ณ  ์‚ฌ์šฉํ•˜๋Š” ์ƒํ™ฉ.
  • ์ด์œ : ์ธํ„ฐํŽ˜์ด์Šค ์‚ฌ์–‘์ด ๋ณ€๊ฒฝ๋˜๋ฉด ๋‹ค๋ฅธ ํŒ€์— ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ์Œ.
  • ์žฅ์ :
    • ๋ช…ํ™•ํ•œ ๋ช…์„ธ์„œ ์ œ๊ณต์œผ๋กœ ์˜์‚ฌ์†Œํ†ต ์˜ค๋ฅ˜ ๊ฐ์†Œ.
    • ์ฝ”๋“œ ๋ณ€๊ฒฝ ์‹œ, ๊ด€๋ จ ๊ธฐ๋Šฅ์ด ๊นจ์ง€์ง€ ์•Š๋„๋ก ๋ณดํ˜ธ.
  • TDD ๋„์ž… ํŒ๋‹จ ๊ธฐ์ค€:
    • ํŒ€ ๊ฐ„ ์˜์กด๋„๊ฐ€ ๋†’์„์ˆ˜๋ก ๋„์ž… ๊ฐ€์น˜ ์ฆ๊ฐ€.
    • ๊ณ„์•ฝ ๊ธฐ๋ฐ˜ API ์„ค๊ณ„(contract-first approach)์— ์ ํ•ฉ.

3. ๋ณต์žกํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜

  • ์‚ฌ๋ก€: ์ถ”์ฒœ ์‹œ์Šคํ…œ, ๋จธ์‹ ๋Ÿฌ๋‹ ๋ชจ๋ธ ์ „์ฒ˜๋ฆฌ ๋กœ์ง.
  • ์ด์œ : ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์ •ํ™•๋„๊ฐ€ ๋น„์ฆˆ๋‹ˆ์Šค ์„ฑ๊ณผ์™€ ์ง๊ฒฐ.
  • ์žฅ์ :
    • ๋‹ค์–‘ํ•œ ์ž…๋ ฅ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ ๊ฒ€์ฆ ๊ฐ€๋Šฅ.
    • ๊ฒฐ๊ณผ์˜ ์ผ๊ด€์„ฑ ์œ ์ง€.
  • TDD ๋„์ž… ํŒ๋‹จ ๊ธฐ์ค€:
    • ์ž…๋ ฅ/์ถœ๋ ฅ ๋ฐ์ดํ„ฐ์˜ ์กฐํ•ฉ์ด ๋ณต์žกํ• ์ˆ˜๋ก ํ•„์š”์„ฑ ์ฆ๊ฐ€.
    • ์ •ํ˜•ํ™”๋œ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค ์ž‘์„ฑ์ด ์šฉ์ดํ•œ ๊ฒฝ์šฐ ์ ํ•ฉ.

4. ํ”„๋กœํ† ํƒ€์ž… ๊ฐœ๋ฐœ

  • ์‚ฌ๋ก€: ์Šคํƒ€ํŠธ์—… ์ดˆ๊ธฐ ์ œํ’ˆ.
  • ์ด์œ : ๋น ๋ฅธ ํ”ผ๋“œ๋ฐฑ๊ณผ ์‹œ์žฅ ๊ฒ€์ฆ์ด ์šฐ์„ .
  • ๋‹จ์ :
    • ์ดˆ๊ธฐ์—๋Š” ๊ฐœ๋ฐœ ์†๋„๊ฐ€ ์ €ํ•˜๋  ์ˆ˜ ์žˆ์Œ.
    • ๋ถˆํ•„์š”ํ•œ ํ…Œ์ŠคํŠธ ์ž‘์„ฑ ๊ฐ€๋Šฅ์„ฑ.
  • TDD ๋„์ž… ํŒ๋‹จ ๊ธฐ์ค€:
    • ์ œํ’ˆ ์„ฑ๊ณต ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์€ ํ•ต์‹ฌ ๊ธฐ๋Šฅ์—๋งŒ ์ œํ•œ์ ์œผ๋กœ ์ ์šฉ.
    • ํ…Œ์ŠคํŠธ๋Š” ๋ฆฌํŒฉํ† ๋ง ์ดํ›„ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ์‹์„ ๋ณ‘ํ–‰.

5. ๊ธด ์ˆ˜๋ช… ์ฃผ๊ธฐ๋ฅผ ๊ฐ€์ง„ ํ”„๋กœ์ ํŠธ

  • ์‚ฌ๋ก€: ์žฅ๊ธฐ ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ํ•„์š”ํ•œ ๋ ˆ๊ฑฐ์‹œ ์‹œ์Šคํ…œ.
  • ์ด์œ : ์‹œ๊ฐ„์ด ์ง€๋‚˜๋„ ์ฝ”๋“œ ํ’ˆ์งˆ์„ ์œ ์ง€ํ•ด์•ผ ํ•จ.
  • ์žฅ์ :
    • ๊ธฐ์กด ์ฝ”๋“œ๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ๋ฆฌํŒฉํ† ๋ง ๊ฐ€๋Šฅ.
    • ์‹ ๊ทœ ๊ฐœ๋ฐœ์ž ์˜จ๋ณด๋”ฉ ์‹œ ์œ ์šฉํ•œ ํ•™์Šต ์ž๋ฃŒ ์ œ๊ณต.
  • TDD ๋„์ž… ํŒ๋‹จ ๊ธฐ์ค€:
    • ์œ ์ง€๋ณด์ˆ˜ ๋น„์šฉ์ด ํฌ๊ฑฐ๋‚˜, ์ƒˆ๋กœ์šด ์š”๊ตฌ์‚ฌํ•ญ์ด ์ž์ฃผ ์ถ”๊ฐ€๋˜๋Š” ํ”„๋กœ์ ํŠธ.

ํ…Œ์ŠคํŠธ ํˆด

1. JUnit 5 (Jupiter)

JUnit 5๋Š” ๋‹จ์œ„ ํ…Œ์ŠคํŠธ(Unit Test)๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์œ„ํ•œ ํ•ต์‹ฌ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. Spring Boot๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ JUnit 5๋ฅผ ์ง€์›ํ•˜๋ฉฐ, ๋‹ค์–‘ํ•œ ์• ๋„ˆํ…Œ์ด์…˜๊ณผ Assertions API๋ฅผ ํ†ตํ•ด ํ…Œ์ŠคํŠธ๋ฅผ ์‰ฝ๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฃผ์š” ์• ๋„ˆํ…Œ์ด์…˜

  1. @Test
    • ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜.
  2. @BeforeEach / @AfterEach
    • ๊ฐ๊ฐ ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ „ํ›„์— ์‹คํ–‰๋  ๋กœ์ง ์ •์˜.
  3. @BeforeAll / @AfterAll
    • ๊ฐ๊ฐ ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค ์‹คํ–‰ ์ „ํ›„์— ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰.
  4. @Disabled
    • ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ๋‚˜ ํด๋ž˜์Šค๋ฅผ ๋น„ํ™œ์„ฑํ™”.
  5. @Tag
    • ํ…Œ์ŠคํŠธ ๊ทธ๋ฃนํ™”(tagging) ๊ธฐ๋Šฅ ์ œ๊ณต.

Assertions API

  • assertEquals(expected, actual): ๋‘ ๊ฐ’์ด ๋™์ผํ•œ์ง€ ๋น„๊ต.
  • assertTrue(condition): ์กฐ๊ฑด์ด ์ฐธ์ธ์ง€ ํ™•์ธ.
  • assertThrows(exception, executable): ํŠน์ • ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š”์ง€ ํ™•์ธ.

์˜ˆ์ œ: ๊ฐ„๋‹จํ•œ JUnit ํ…Œ์ŠคํŠธ

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

class CalculatorTest {

    @Test
    void additionShouldBeCorrect() {
        Calculator calculator = new Calculator();
        int result = calculator.add(2, 3);
        assertEquals(5, result, "2 + 3์€ 5์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.");
    }

    @Test
    void divisionShouldThrowExceptionForZero() {
        Calculator calculator = new Calculator();
        assertThrows(ArithmeticException.class, () -> calculator.divide(5, 0));
    }
}

์žฅ์ 

  • ๋น ๋ฅธ ์‹คํ–‰: ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋Š” ๋‹ค๋ฅธ ๊ณ„์ธต๊ณผ ๋…๋ฆฝ์ ์ด๋ฏ€๋กœ ๋น ๋ฅด๊ฒŒ ์‹คํ–‰ ๊ฐ€๋Šฅ.
  • ๊ฐ„๋‹จํ•œ ์„ค์ •: ๋ณ„๋„์˜ ์ปจํ…์ŠคํŠธ ๋กœ๋”ฉ ์—†์ด ๋ฉ”์„œ๋“œ ๋‹จ์œ„๋กœ ๊ฒ€์ฆ ๊ฐ€๋Šฅ.

2. Spring Test Framework

Spring Test Framework๋Š” Spring Boot ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์Šคํ”„๋ง ์ปจํ…์ŠคํŠธ๋ฅผ ๋กœ๋“œํ•˜์—ฌ Spring Bean, ์˜์กด์„ฑ ์ฃผ์ž…, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๋™ ๋“ฑ์„ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฃผ์š” ์• ๋„ˆํ…Œ์ด์…˜

  1. @SpringBootTest

    • ์ „์ฒด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ปจํ…์ŠคํŠธ๋ฅผ ๋กœ๋“œ.
    • ๋‹จ์œ„ ํ…Œ์ŠคํŠธ์™€ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๋ฅผ ๋ชจ๋‘ ์ง€์›.
@SpringBootTest
class MyAppTests {
    @Test
    void contextLoads() {
    }
}
  1. @WebMvcTest
  • ์ปจํŠธ๋กค๋Ÿฌ ํ…Œ์ŠคํŠธ ์ „์šฉ์œผ๋กœ ์‚ฌ์šฉ.
  • MVC ๊ด€๋ จ ๋นˆ๋งŒ ๋กœ๋“œํ•˜์—ฌ REST API ํ…Œ์ŠคํŠธ์— ์ตœ์ ํ™”.
@WebMvcTest(controllers = MyController.class)
class MyControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @Test
    void shouldReturnDefaultMessage() throws Exception {
        mockMvc.perform(get("/api/hello"))
               .andExpect(status().isOk())
               .andExpect(content().string("Hello, World!"));
    }
}

  1. @DataJpaTest
  • JPA์™€ ๊ด€๋ จ๋œ ๋นˆ๋งŒ ๋กœ๋“œํ•˜์—ฌ ํ…Œ์ŠคํŠธ ์†๋„๋ฅผ ์ตœ์ ํ™”.
  • H2 Database์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ ๊ณ„์ธต ํ…Œ์ŠคํŠธ.
@DataJpaTest
class UserRepositoryTest {
    @Autowired
    private UserRepository userRepository;

    @Test
    void shouldSaveAndFindUser() {
        User user = new User("John Doe", "john@example.com");
        userRepository.save(user);

        Optional<User> result = userRepository.findByEmail("john@example.com");
        assertTrue(result.isPresent());
        assertEquals("John Doe", result.get().getName());
    }
}

4.@MockBean

  • ํŠน์ • ๋นˆ์„ ๋ชจํ‚นํ•˜์—ฌ ํ…Œ์ŠคํŠธ ์‹œ ์‹ค์ œ ๊ตฌํ˜„์ฒด ๋Œ€์‹  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ.
@SpringBootTest
class MyServiceTest {
    @MockBean
    private MyRepository myRepository;

    @Autowired
    private MyService myService;

    @Test
    void shouldUseMockedRepository() {
        when(myRepository.findSomething()).thenReturn("Mocked Result");

        String result = myService.getSomething();
        assertEquals("Mocked Result", result);
    }
}


์ตœ๊ทผ ์ž์ฒด ๋””๋„์Šค(๋‚ด๋ถ€ ๋กœ์ง ๋ถ€ํ•˜)์— ๋Œ€ํ•œ ๋Œ€์ฑ…

1. JMeter๋กœ JPA ์ฟผ๋ฆฌ ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ ์ค€๋น„

ํ•„์ˆ˜ ์š”๊ตฌ์‚ฌํ•ญ

  1. JDBC ๋“œ๋ผ์ด๋ฒ„ ์ค€๋น„

    • ํ…Œ์ŠคํŠธํ•  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ JDBC ๋“œ๋ผ์ด๋ฒ„๋ฅผ ๋‹ค์šด๋กœ๋“œํ•˜์—ฌ JMeter์˜ lib ๋””๋ ‰ํ† ๋ฆฌ์— ๋ณต์‚ฌ.
      • ์˜ˆ: MySQL์€ mysql-connector-java, PostgreSQL์€ postgresql.jar.
  2. ํ…Œ์ŠคํŠธ ๋Œ€์ƒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ค€๋น„

    • JPA๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์ง์ ‘ ํ…Œ์ŠคํŠธํ•˜๋ ค๋ฉด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ ‘์† ์ •๋ณด๊ฐ€ ํ•„์š”.
    • Spring Boot ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ํ†ตํ•ด ๋™์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰.

2. JMeter์—์„œ JDBC Request ์„ค์ •

1๋‹จ๊ณ„: JDBC Connection Configuration ์ถ”๊ฐ€

  1. JMeter์˜ Thread Group์— JDBC Connection Configuration์„ ์ถ”๊ฐ€.
  2. ์„ค์ •:
    • Variable Name: ์ปค๋„ฅ์…˜์„ ์ฐธ์กฐํ•  ์ด๋ฆ„ (์˜ˆ: DBConnection).
    • Database URL: JDBC URL (์˜ˆ: jdbc:mysql://localhost:3306/testdb).
    • JDBC Driver class: ๋“œ๋ผ์ด๋ฒ„ ํด๋ž˜์Šค ์ด๋ฆ„ (์˜ˆ: com.mysql.cj.jdbc.Driver).
    • Username/Password: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ ‘์† ์ •๋ณด.

2๋‹จ๊ณ„: JDBC Request ์ถ”๊ฐ€

  1. Thread Group์— JDBC Request๋ฅผ ์ถ”๊ฐ€.

  2. ์„ค์ •:

    • Variable Name: ์ด์ „ ๋‹จ๊ณ„์—์„œ ์„ค์ •ํ•œ Variable Name ์ž…๋ ฅ (DBConnection).
    • Query Type:
      • Select Statement: ๋ฐ์ดํ„ฐ ์กฐํšŒ ์ฟผ๋ฆฌ.
      • Update Statement: ๋ฐ์ดํ„ฐ ์ˆ˜์ • ์ฟผ๋ฆฌ.
    • Query: ์‹คํ–‰ํ•  SQL ์ฟผ๋ฆฌ.
      • ์˜ˆ: SELECT * FROM users WHERE status = 'ACTIVE';
  3. ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋™์ ์œผ๋กœ ์„ค์ •ํ•˜๋ ค๋ฉด Prepared Statement๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ:

    • SQL: SELECT * FROM users WHERE age > ?;
    • Parameters: 30 (๋™์ ์œผ๋กœ ์ „๋‹ฌํ•  ๊ฐ’).

3๋‹จ๊ณ„: ๋™์  ๋ถ€ํ•˜ ์ƒ์„ฑ

  1. Thread Group ์„ค์ •:

    • Number of Threads (Users): ๋™์‹œ ์‹คํ–‰ ์‚ฌ์šฉ์ž ์ˆ˜.
    • Ramp-Up Period: ์‚ฌ์šฉ์ž๊ฐ€ ๋ช‡ ์ดˆ์— ๊ฑธ์ณ ์ฆ๊ฐ€ํ• ์ง€ ์„ค์ •.
    • Loop Count: ๊ฐ ์‚ฌ์šฉ์ž๊ฐ€ ์‹คํ–‰ํ•  ์š”์ฒญ ๋ฐ˜๋ณต ํšŸ์ˆ˜.
  2. ๋ถ€ํ•˜๋ฅผ ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝ:

    • ์Šค๋ ˆ๋“œ ๊ทธ๋ฃน์—์„œ Scheduler๋ฅผ ํ™œ์„ฑํ™”ํ•˜์—ฌ ํŠน์ • ์‹œ๊ฐ„ ๊ฐ„๊ฒฉ์œผ๋กœ ๋ถ€ํ•˜๋ฅผ ์ฆ๊ฐ ๊ฐ€๋Šฅ.

3. JMeter์™€ JPA ์—ฐ๋™ ์ „๋žต

JPA ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ง์ ‘ ํ…Œ์ŠคํŠธ

  1. HTTP ์š”์ฒญ์„ ํ†ตํ•ด JPA ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ

    • REST API ์—”๋“œํฌ์ธํŠธ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ JPA ์ฟผ๋ฆฌ ์‹คํ–‰.
    • JMeter์˜ HTTP Sampler๋กœ ํ…Œ์ŠคํŠธ:
      • URL: http://localhost:8080/api/users?status=ACTIVE
      • Method: GET/POST.
  2. JPA ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜ ๋™์  ์„ค์ •

    • REST API์— ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜ ์ „๋‹ฌ.
    • JMeter์˜ CSV Data Set Config๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค์–‘ํ•œ ์ž…๋ ฅ๊ฐ’ ์‹œ๋ฎฌ๋ ˆ์ด์…˜:
      • CSV ํŒŒ์ผ: age,status 25,ACTIVE 30,INACTIVE 35,ACTIVE
      • ํ…Œ์ŠคํŠธ ์„ค์ •:
        • Parameter: ${age}์™€ ${status}๋กœ ๋Œ€์ฒด.

4. ๊ฒฐ๊ณผ ๋ถ„์„

JPA ์ฟผ๋ฆฌ ์„ฑ๋Šฅ ํ™•์ธ

  1. JMeter View Results Tree

    • ์ฟผ๋ฆฌ ์‹คํ–‰ ๊ฒฐ๊ณผ ๋ฐ ์‘๋‹ต ์‹œ๊ฐ„ ํ™•์ธ.
  2. Database Monitoring Tools

    • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์‹คํ–‰ ๊ณ„ํš(EXPLAIN) ํ™•์ธ.
    • DB์—์„œ ์ฟผ๋ฆฌ ์‹คํ–‰ ์‹œ๊ฐ„, CPU ์‚ฌ์šฉ๋Ÿ‰, I/O ๋ณ‘๋ชฉ ํŒŒ์•….
  3. Spring Actuator Metrics

    • @Timed ์• ๋„ˆํ…Œ์ด์…˜ ๋˜๋Š” Actuator ๋ฉ”ํŠธ๋ฆญ์„ ํ†ตํ•ด JPA ๋ฉ”์„œ๋“œ์˜ ์‹คํ–‰ ์‹œ๊ฐ„ ์ธก์ •.

5. ๋ถ€ํ•˜ ํ…Œ์ŠคํŠธ ์‹œ ์ฃผ์˜์‚ฌํ•ญ

  1. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ƒํƒœ ์ดˆ๊ธฐํ™”

    • ํ…Œ์ŠคํŠธ ์ „์— ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ƒํƒœ๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜์—ฌ ๊ฒฐ๊ณผ์˜ ์ผ๊ด€์„ฑ ์œ ์ง€.
  2. ์‹ค์ œ ํ™˜๊ฒฝ๊ณผ ๋™์ผํ•œ ์„ค์ •

    • ์‹ค์ œ ์šด์˜ ํ™˜๊ฒฝ์˜ DB ํฌ๊ธฐ, ์ปค๋„ฅ์…˜ ํ’€ ํฌ๊ธฐ, ๋„คํŠธ์›Œํฌ ์กฐ๊ฑด์„ ๋ฐ˜์˜.
  3. ์ ์ • ๋ถ€ํ•˜ ์„ค์ •

    • TPS(Transactions Per Second)๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋™์‹œ ์š”์ฒญ ์ˆ˜ ๊ฒฐ์ •