10. ๐Ÿ›ก๏ธ ๊ฒฌ๊ณ ํ•œ ์ฝ”๋“œ๋ฅผ ์œ„ํ•œ ํ…Œ์ŠคํŠธ ์ „๋žต๊ณผ ์ž๋™ํ™”

2026๋…„ 3์›” 5์ผ ์ˆ˜์ •๋จ

๐Ÿ“‹ ๊ฐœ์š”

๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ถ€ํ„ฐ E2E ํ…Œ์ŠคํŠธ๊นŒ์ง€, ๊ฒฌ๊ณ ํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ํ…Œ์ŠคํŠธ ์ „๋žต๊ณผ ์ž๋™ํ™” ํ™˜๊ฒฝ์„ ๋งˆ์Šคํ„ฐํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“Œ ์ด ๋ฉด์ ‘ ํ•ญ๋ชฉ์˜ ๋ชฉํ‘œ

โฑ๏ธ ์˜ˆ์ƒ ์ฝ๊ธฐ ์‹œ๊ฐ„: 22๋ถ„ (ํ•ต์‹ฌ ์š”์•ฝ: 11๋ถ„)

๐Ÿ—บ๏ธ ์ด ์ฑ•ํ„ฐ์˜ ํ๋ฆ„
[๊ฐœ๋… ์‚ฌ์ „] โ†’ [์งˆ๋ฌธ 1: ํ…Œ์ŠคํŠธ ํ”ผ๋ผ๋ฏธ๋“œ & ์ „๋žต] โ†’ [์งˆ๋ฌธ 2: ์ปดํฌ๋„ŒํŠธ ํ…Œ์ŠคํŠธ (RTL)] โ†’ [์‹ค์ „ ๋ณ€ํ˜• ์งˆ๋ฌธ]

๐ŸŽฏ ์ด ์ฑ•ํ„ฐ๋ฅผ ๋‹ค ์ฝ์œผ๋ฉด ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ

  • ๋‹จ์œ„ ํ…Œ์ŠคํŠธ์™€ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ์˜ ์ฐจ์ด์™€ ๊ฐ๊ฐ์˜ ์ ์ ˆํ•œ ๋น„์œจ์„ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.
  • '์‚ฌ์šฉ์ž ์ค‘์‹ฌ'์˜ ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•ด React Testing Library๋ฅผ ํ™œ์šฉํ•˜๋Š” ๋ฒ•์„ ์ตํž™๋‹ˆ๋‹ค.
  • ํšŒ๊ท€ ํ…Œ์ŠคํŠธ(Regression Test)๊ฐ€ ์œ ์ง€๋ณด์ˆ˜ ๋น„์šฉ์„ ์–ด๋–ป๊ฒŒ ์ค„์—ฌ์ฃผ๋Š”์ง€ ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“š ํ•ต์‹ฌ ๊ฐœ๋… ์‚ฌ์ „ (Concept Glossary)

1. ํ…Œ์ŠคํŠธ ํ”ผ๋ผ๋ฏธ๋“œ (Testing Pyramid)

ํ•˜๋‹จ(Unit)์€ ๋งŽ๊ณ  ์ƒ๋‹จ(E2E)์€ ์ ์€ ๊ตฌ์กฐ์˜ ํ…Œ์ŠคํŠธ ์ „๋žต์ž…๋‹ˆ๋‹ค. ๋น„์šฉ์ด ์‹ธ๊ณ  ๋น ๋ฅธ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๊ณ , ๋ณต์žกํ•˜๊ณ  ๋А๋ฆฐ ํ†ตํ•ฉ/E2E ํ…Œ์ŠคํŠธ๋Š” ํ•ต์‹ฌ ํ๋ฆ„์—๋งŒ ์ง‘์ค‘ํ•ฉ๋‹ˆ๋‹ค.

2. RTL (React Testing Library)

์ปดํฌ๋„ŒํŠธ์˜ ๋‚ด๋ถ€ ๊ตฌํ˜„(state, props)์ด ์•„๋‹ˆ๋ผ, ์‚ฌ์šฉ์ž๊ฐ€ ํ™”๋ฉด์—์„œ ๋ณด๋Š” ๊ฒฐ๊ณผ๋ฌผ(text, role ๋“ฑ)์„ ์ค‘์‹ฌ์œผ๋กœ ํ…Œ์ŠคํŠธํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. ์ฝ”๋“œ ๋ฆฌํŒฉํ† ๋ง ์‹œ ํ…Œ์ŠคํŠธ๊ฐ€ ๊นจ์ง€์ง€ ์•Š๋Š” ์•ˆ์ „ํ•จ์„ ์ค๋‹ˆ๋‹ค.

3. ๋ชจํ‚น (Mocking)

์‹ค์ œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋‚˜ ์™ธ๋ถ€ API ๋Œ€์‹  ๊ฐ€์งœ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์„ ๊ฒฉ๋ฆฌํ•˜๋Š” ๊ธฐ์ˆ ์ž…๋‹ˆ๋‹ค. ์™ธ๋ถ€ ํ™˜๊ฒฝ์— ์˜์กดํ•˜์ง€ ์•Š๊ณ  ํ•ญ์ƒ ์ผ๊ด€๋œ ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๋ฅผ ์–ป๊ธฐ ์œ„ํ•ด ํ•„์ˆ˜์ ์ž…๋‹ˆ๋‹ค.


๐Ÿ—บ๏ธ ์ด ๋ฌธ์„œ์˜ ๋ฐฐ๊ฒฝ ์„ธ๊ณ„๊ด€: '์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ'

  • ๐Ÿฃ ์˜์ฒ  ( ์‹ ์ž… ): "์˜ํ˜ธ ๋‹˜! '์˜์ˆ˜๋„ค ๋Œ“๊ธ€' ๊ธฐ๋Šฅ์„ ํ•˜๋‚˜ ๊ณ ์ณค๋Š”๋ฐ ๋ฉ€์ฉกํ•˜๋˜ '๊ฒŒ์‹œ๊ธ€ ์ˆ˜์ •'์ด ํ„ฐ์กŒ์–ด์š”! ๐Ÿ˜ฑ ์‚ฌ๋žŒ์ด ์ผ์ผ์ด ๋‹ค ๋ˆŒ๋Ÿฌ๋ณผ ์ˆ˜๋„ ์—†๊ณ ... ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์งœ๋ฉด ์ง„์งœ ์ด๋Ÿฐ ๊ฑฐ ๋‹ค ์žก์•„์ฃผ๋‚˜์š”?"
  • ๐Ÿฆ ์˜ํ˜ธ ( ๋ฆฌ๋“œ ): "์˜์ฒ  ๋‹˜, ํ…Œ์ŠคํŠธ๋Š” '๋‚˜์ค‘์— ๊ท€์ฐฎ์ง€ ์•Š์œผ๋ ค๊ณ  ์ง€๊ธˆ ๊ท€์ฐฎ์Œ์„ ๊ฐ์ˆ˜ํ•˜๋Š” ์ผ'์ž…๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๊ฐ€ ์žˆ๋‹ค๋ฉด ์šฐ๋ฆฌ๋Š” ์–ด์ œ์˜ ๋‚ด๊ฐ€ ์ง  ์ฝ”๋“œ๋ฅผ ๋ฏฟ๊ณ  ์˜ค๋Š˜ ๋งˆ์Œ๊ป ๋ฆฌํŒฉํ† ๋งํ•  ์ˆ˜ ์žˆ์ฃ . ์ž, ์–ด๋–ค ๊ฑธ ๋จผ์ € ํ…Œ์ŠคํŠธํ• ์ง€ ํ”ผ๋ผ๋ฏธ๋“œ๋ถ€ํ„ฐ ์„ธ์›Œ๋ด…์‹œ๋‹ค."

Q1. ๋‹จ์œ„ ํ…Œ์ŠคํŠธ(Unit Test)์™€ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ(Integration Test)์˜ ์ฐจ์ด์ ์€ ๋ฌด์—‡์ด๋ฉฐ, ์‹ค๋ฌด์—์„œ ์–ด๋–ค ๋น„์ค‘์œผ๋กœ ์ž‘์„ฑํ•˜์‹œ๋‚˜์š”?

๐ŸŽฏ ์ถœ์ œ ์˜๋„

ํ…Œ์ŠคํŠธ์˜ ๋น„์šฉ๊ณผ ๊ฐ€์น˜๋ฅผ ์ดํ•ดํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ์ฝ”๋“œ์— ํ…Œ์ŠคํŠธ๋ฅผ ์งœ๋Š” ๊ฒƒ์€ ๋ถˆ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ, ํšจ์œจ์ ์ธ ํ…Œ์ŠคํŠธ ์ „๋žต์„ ์„ธ์šธ ์ˆ˜ ์žˆ๋Š” ํŒ๋‹จ๋ ฅ์„ ํ‰๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿฃ ์˜์ฒ ์ด์˜ Naive ๊ตฌํ˜„ (Bad Case)

์˜์ฒ ์ด๋Š” ๋ชจ๋“  ์ž‘์€ ํ•จ์ˆ˜ ํ•˜๋‚˜ํ•˜๋‚˜์— ํ…Œ์ŠคํŠธ๋ฅผ ์งœ๋А๋ผ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ๊ฐœ๋ฐœ ์†๋„๊ฐ€ ๋„ˆ๋ฌด ๋А๋ ค์กŒ์Šต๋‹ˆ๋‹ค.

// ๐Ÿฃ ์˜์ฒ : "1 + 1 ํ•จ์ˆ˜๋„ ํ…Œ์ŠคํŠธ๋ฅผ ์งœ์•ผ ์•ˆ์‹ฌ์ด ๋ผ์š”!"
test('add function', () => {
    expect(add(1, 1)).toBe(2); // โš ๏ธ ๋„ˆ๋ฌด ์‚ฌ์†Œํ•œ ํ…Œ์ŠคํŠธ์— ์—๋„ˆ์ง€๋ฅผ ๋‚ญ๋น„ ์ค‘
});
// โš ๏ธ ๋ฌธ์ œ: ์‹ค์ œ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์„œ๋ฒ„์™€ ์–ด๋–ป๊ฒŒ ํ†ต์‹ ํ•˜๋Š”์ง€ ๋“ฑ ์ •์ž‘ ์ค‘์š”ํ•œ 'ํ๋ฆ„'์€ ํ…Œ์ŠคํŠธ ์•ˆ ํ•จ

๐Ÿฆ ์˜ํ˜ธ์˜ ํŒฉํญ ์กฐ์–ธ
"์˜์ฒ  ๋‹˜, ํ•จ์ˆ˜๊ฐ€ ์ž˜ ๋„๋Š” ๊ฒƒ๋„ ์ค‘์š”ํ•˜์ง€๋งŒ ๋” ์ค‘์š”ํ•œ ๊ฑด ์‚ฌ์šฉ์ž๊ฐ€ ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ค๋А๋ƒ์ž…๋‹ˆ๋‹ค. ์‚ฌ์†Œํ•œ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜ 100๊ฐœ๋ณด๋‹ค, '๋กœ๊ทธ์ธ ํ›„ ๊ฒŒ์‹œ๊ธ€ ์“ฐ๊ธฐ'๋ผ๋Š” ํ•˜๋‚˜์˜ ํ๋ฆ„์„ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ฒŒ ํ›จ์”ฌ ๊ฐ€์น˜ ์žˆ์–ด์š”."

๐Ÿฆ ์˜ํ˜ธ์˜ ์•„ํ‚คํ…์ฒ˜ ๊ฐ€์ด๋“œ (Good Case)

์˜ํ˜ธ ๋ฆฌ๋“œ๊ฐ€ ์ œ์•ˆํ•˜๋Š” ๊ท ํ˜• ์žกํžŒ ํ…Œ์ŠคํŠธ ๋น„์ค‘์ž…๋‹ˆ๋‹ค.

// ๐Ÿฆ ์˜ํ˜ธ: "๋น„์ฆˆ๋‹ˆ์Šค ํ•ต์‹ฌ ๋กœ์ง์€ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋กœ, ์ปดํฌ๋„ŒํŠธ ๊ฐ„ ํ˜‘์—…์€ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๋กœ ์žก์œผ์„ธ์š”."
 
// 1. ๋‹จ์œ„ ํ…Œ์ŠคํŠธ (Unit): 
// - ๋ณต์žกํ•œ ๊ณ„์‚ฐ์‹, ์ˆœ์ˆ˜ ํ•จ์ˆ˜, ๋น„์ฆˆ๋‹ˆ์Šค ๊ทœ์น™ (์˜ˆ: ํฌ์ธํŠธ ์ ๋ฆฝ ๊ณ„์‚ฐ ๋กœ์ง)
// - ๋น„์ค‘: 60% (๋น ๋ฅด๊ณ  ์ •ํ™•ํ•จ)
 
// 2. ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ (Integration):
// - ํ›…๊ณผ ์ปดํฌ๋„ŒํŠธ์˜ ์ƒํ˜ธ์ž‘์šฉ, API ๋ชจํ‚น ๋ฐ์ดํ„ฐ์™€ UI์˜ ์—ฐ๋™
// - ๋น„์ค‘: 30% (์‹ค์ œ ์‚ฌ์šฉ์ž์™€ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๊ฐ€์น˜ ์ œ๊ณต)
 
// 3. E2E ํ…Œ์ŠคํŠธ (Playwright/Cypress):
// - ๊ฒฐ์ œ ์„ฑ๊ณต, ํšŒ์›๊ฐ€์ž… ๋“ฑ ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ํฌ๋ฆฌํ‹ฐ์ปฌ ํŒจ์Šค
// - ๋น„์ค‘: 10% (๋А๋ฆฌ์ง€๋งŒ ํ™•์‹คํ•œ ๋ณด์ฆ)

๐Ÿ“Š ๋ ˆ๋ฒจ๋ณ„ ๋‹ต๋ณ€ ๊ฐ€์ด๋“œ (Self-Check)

  • Level 1 (Junior): "๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋Š” ์ž‘์€ ํ•จ์ˆ˜๋ฅผ, ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๋Š” ์—ฌ๋Ÿฌ ๊ฐœ๊ฐ€ ํ•ฉ์ณ์ง„ ๊ฒƒ์„ ํ…Œ์ŠคํŠธํ•ฉ๋‹ˆ๋‹ค. ๋‘˜ ๋‹ค ๋งŽ์ด ์งœ๋ฉด ์ข‹์Šต๋‹ˆ๋‹ค."
  • Level 2 (Senior): "๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋Š” ๊ฒฉ๋ฆฌ๋œ ํ™˜๊ฒฝ์—์„œ ์„ธ๋ถ€ ๋กœ์ง์„ ๊ฒ€์ฆํ•˜๊ณ , ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๋Š” ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ๊ฐ€ ์‹ค์ œ ๋น„์ฆˆ๋‹ˆ์Šค ์š”๊ตฌ์‚ฌํ•ญ๋Œ€๋กœ ๋ Œ๋”๋ง๋˜๋Š”์ง€ ํ™•์ธํ•จ์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ROI(ํˆฌ์ž ๋Œ€๋น„ ํšจ๊ณผ) ๊ด€์ ์—์„œ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ์˜ ๋น„์ค‘์„ ๋†’์—ฌ '๋ฆฌํŒฉํ† ๋ง ๋‚ด์„ฑ'์„ ํ™•๋ณดํ•˜๋Š” ์ „๋žต์„ ์ œ์‹œํ•ฉ๋‹ˆ๋‹ค."
  • Level 3 (Specialist): "TDD(Test Driven Development)๋ฅผ ํ†ตํ•œ ์„ค๊ณ„ ๊ฐœ์„  ์‚ฌ๋ก€๋ฅผ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ MSW(Mock Service Worker)๋ฅผ ํ™œ์šฉํ•ด ๋„คํŠธ์›Œํฌ ๊ณ„์ธต๊นŒ์ง€ ๋ชจํ‚นํ•˜์—ฌ ํ”„๋ก ํŠธ์—”๋“œ ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์„ ์‹ค์ œ์™€ ๊ฐ€๊น๊ฒŒ ๊ตฌ์ถ•ํ•œ ๊ฒฝํ—˜์„ ๋ถ„์„ํ•ฉ๋‹ˆ๋‹ค. 'ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•ด ํ…Œ์ŠคํŠธ๋ฅผ ์งœ๋Š” ๊ฒƒ'์ด ์•„๋‹Œ, ์ฝ”๋“œ์˜ ์„ค๊ณ„ ์ˆ˜์ค€์„ ๋†’์ด๋Š” ๋„๊ตฌ๋กœ์„œ์˜ ํ…Œ์ŠคํŠธ๋ฅผ ๊ฐ•์กฐํ•ฉ๋‹ˆ๋‹ค."

Q2. React Testing Library(RTL)์—์„œ '๊ตฌํ˜„ ์„ธ๋ถ€ ์ •๋ณด'๊ฐ€ ์•„๋‹Œ '์‚ฌ์šฉ์ž ๊ด€์ '์œผ๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•˜๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”?

๐ŸŽฏ ์ถœ์ œ ์˜๋„

์ฝ”๋“œ๋ฅผ ๊ณ ์ณค์„ ๋•Œ ํ…Œ์ŠคํŠธ๊ฐ€ ๊นจ์ง€๋Š” '์ทจ์•ฝํ•œ ํ…Œ์ŠคํŠธ'์˜ ๋ฌธ์ œ๋ฅผ ์ธ์ง€ํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ๋ณ€ํ™”์— ์œ ์—ฐํ•œ ๊ฒฌ๊ณ ํ•œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์งค ์ˆ˜ ์žˆ๋Š”์ง€ ํ‰๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿฃ ์˜์ฒ ์ด์˜ Naive ๊ตฌํ˜„ (Bad Case)

์˜์ฒ ์ด๋Š” ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์˜ state ๊ฐ’์ด๋‚˜ ํ•จ์ˆ˜ ์ด๋ฆ„์ด ์ •ํ™•ํ•œ์ง€ ํ…Œ์ŠคํŠธํ•˜๋ ค ํ•ฉ๋‹ˆ๋‹ค.

// ๐Ÿฃ ์˜์ฒ : "๋‚ด๋ถ€์˜ isOpen ์ƒํƒœ๊ฐ€ true์ธ์ง€ ํ™•์ธํ•˜๋ฉด ๋˜๊ฒ ์ฃ ?"
const wrapper = shallow(<Modal />);
expect(wrapper.state('isOpen')).toBe(true); 
// โš ๏ธ ๋ฌธ์ œ: state ์ด๋ฆ„์„ 'isVisible'๋กœ ๋ฐ”๊พธ๋Š” ์ˆœ๊ฐ„, ๊ธฐ๋Šฅ์€ ๋ฉ€์ฉกํ•ด๋„ ํ…Œ์ŠคํŠธ๋Š” ๊นจ์ง (๋ฆฌํŒฉํ† ๋ง ๋ฐฉํ•ด)

๐Ÿฆ ์˜ํ˜ธ์˜ ํŒฉํญ ์กฐ์–ธ
"์˜์ฒ  ๋‹˜, ์‚ฌ์šฉ์ž๋Š” ์ปดํฌ๋„ŒํŠธ ์ด๋ฆ„์ด ๋ญ”์ง€, ์ƒํƒœ ๋ณ€์ˆ˜๋ช…์ด ๋ญ”์ง€ ๊ด€์‹ฌ ์—†์–ด์š”. ์˜ค์ง 'ํ™”๋ฉด์— ๋ชจ๋‹ฌ์ด ๋–ด๋Š”๊ฐ€'๋งŒ ๊ด€์‹ฌ ์žˆ์ฃ . ์‚ฌ์šฉ์ž์˜ ๋ˆˆ์œผ๋กœ ์ฝ”๋“œ๋ฅผ ๋ณด์„ธ์š”."

๐Ÿฆ ์˜ํ˜ธ์˜ ์•„ํ‚คํ…์ฒ˜ ๊ฐ€์ด๋“œ (Good Case)

์˜ํ˜ธ ๋ฆฌ๋“œ๊ฐ€ RTL์˜ ์ฒ ํ•™์„ ๋‹ด์€ ํ…Œ์ŠคํŠธ๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

// ๐Ÿฆ ์˜ํ˜ธ: "์‚ฌ์šฉ์ž๊ฐ€ ๋ณด๋Š” ํ…์ŠคํŠธ, ๋ฒ„ํŠผ ์†์„ฑ์œผ๋กœ ์ ‘๊ทผํ•˜์„ธ์š”."
 
import { render, screen, fireEvent } from '@testing-library/react';
 
test('๋ชจ๋‹ฌ ์—ด๊ธฐ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ํ™˜์˜ ๋ฉ”์‹œ์ง€๊ฐ€ ๋‚˜ํƒ€๋‚œ๋‹ค', () => {
    render(<WelcomeModal />);
    
    // 1. "๋ชจ๋‹ฌ ์—ด๊ธฐ"๋ผ๊ณ  ์จ์ง„ ๋ฒ„ํŠผ์„ ์ฐพ์•„์„œ ํด๋ฆญ (์‚ฌ์šฉ์ž ํ–‰์œ„)
    const openBtn = screen.getByRole('button', { name: /๋ชจ๋‹ฌ ์—ด๊ธฐ/i });
    fireEvent.click(openBtn);
    
    // 2. ํ™”๋ฉด์— "ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค"๋ผ๋Š” ๊ธ€์ž๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธ (์‚ฌ์šฉ์ž ๊ฒฝํ—˜)
    expect(screen.getByText(/ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค/i)).toBeInTheDocument();
    
    // โœ… ์ด์ œ ๋‚ด๋ถ€ ๋ณ€์ˆ˜๋ช…์„ ์•„๋ฌด๋ฆฌ ๋ฐ”๊ฟ”๋„ ๊ธฐ๋Šฅ๋งŒ ๊ฐ™์œผ๋ฉด ์ด ํ…Œ์ŠคํŠธ๋Š” ํ†ต๊ณผํ•ฉ๋‹ˆ๋‹ค!
});

๐Ÿ“Š ๋ ˆ๋ฒจ๋ณ„ ๋‹ต๋ณ€ ๊ฐ€์ด๋“œ (Self-Check)

  • Level 1 (Junior): "RTL์€ ์‚ฌ์šฉ์ž๊ฐ€ ๋ณด๋Š” ๊ฒƒ์„ ํ…Œ์ŠคํŠธํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์•ผ ๊ธฐ๋Šฅ์ด ๋ฐ”๋€Œ์–ด๋„ ํ…Œ์ŠคํŠธ๊ฐ€ ์ž˜ ๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค."
  • Level 2 (Senior): "๋ธŒ๋ผ์šฐ์ € ์ ‘๊ทผ์„ฑ(Accessibility)์„ ๊ณ ๋ คํ•œ getByRole, getByLabelText ๋“ฑ์˜ ์ฟผ๋ฆฌ๋ฅผ ์šฐ์„  ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋ฅผ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ํ…Œ์ŠคํŠธ์˜ ๊ฒฌ๊ณ ํ•จ์„ ๋†’์ผ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์›น ์ ‘๊ทผ์„ฑ์„ ๊ฐ•์ œํ•˜๋Š” ๋ถ€์ˆ˜ ํšจ๊ณผ๊ฐ€ ์žˆ์Œ์„ ์–ธ๊ธ‰ํ•ฉ๋‹ˆ๋‹ค."
  • Level 3 (Specialist): "'ํ™”์ดํŠธ๋ฐ•์Šค ํ…Œ์ŠคํŠธ'์™€ '๋ธ”๋ž™๋ฐ•์Šค ํ…Œ์ŠคํŠธ'์˜ ๊ฐœ๋…์„ ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค. ๋‚ด๋ถ€ ๊ตฌํ˜„์„ ๋ชจ๋ฅด๋Š” ์ƒํƒœ์—์„œ ์ž…์ถœ๋ ฅ(UI ์ƒํ˜ธ์ž‘์šฉ๊ณผ ๊ฒฐ๊ณผ)๋งŒ ๊ฒ€์ฆํ•˜๋Š” ๋ธ”๋ž™๋ฐ•์Šค ํ…Œ์ŠคํŠธ๊ฐ€ ๋ฆฌํŒฉํ† ๋ง ํšจ์œจ์„ ์–ผ๋งˆ๋‚˜ ๊ทน๋Œ€ํ™”ํ•˜๋Š”์ง€ ์‚ฌ๋ก€๋ฅผ ์ œ์‹œํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ๋น„๋™๊ธฐ ํ…Œ์ŠคํŠธ ์‹œ findBy ์ฟผ๋ฆฌ์™€ waitFor๋ฅผ ์ •ํ™•ํžˆ ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ๋ถ„์„ํ•ฉ๋‹ˆ๋‹ค."

Q175. TDD(ํ…Œ์ŠคํŠธ ์ฃผ๋„ ๊ฐœ๋ฐœ)์˜ ์‚ฌ์ดํด๊ณผ ์‹ค๋ฌด์—์„œ์˜ ํ˜„์‹ค์ ์ธ ์ ์šฉ ๋ฐฉ์•ˆ์€?

  • ๐ŸŽฏ ์ถœ์ œ ์˜๋„: ์ด๋ก ์ ์ธ TDD ์ง€์‹์„ ๋„˜์–ด, ์‹ค์ œ ์—…๋ฌด ์†๋„์™€ ํ’ˆ์งˆ ์‚ฌ์ด์˜ ๊ท ํ˜•์„ ๋งž์ถœ ์ค„ ์•„๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
  • ๐Ÿ’ก ํ•ต์‹ฌ ์›๋ฆฌ & ๋‹ต๋ณ€: TDD๋Š” Red(์‹คํŒจํ•˜๋Š” ํ…Œ์ŠคํŠธ) โ†’ Green(๊ตฌํ˜„) โ†’ Refactor(๊ฐœ์„ ) ์ˆœ์„œ๋กœ ์ง„ํ–‰๋ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ชจ๋“  ๊ธฐ๋Šฅ์— ์ ์šฉํ•˜๊ธด ํž˜๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‹ค๋ฌด์—์„œ๋Š” ๋ณต์žกํ•œ ์—ฃ์ง€ ์ผ€์ด์Šค๊ฐ€ ๋งŽ์€ ๊ณตํ†ต ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜๋‚˜, ์„œ๋ฒ„ ์‘๋‹ต์— ๋”ฐ๋ผ UI๊ฐ€ ๋ฏผ๊ฐํ•˜๊ฒŒ ๋ณ€ํ•˜๋Š” ๋ณต์žกํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ํผ ๋กœ์ง ๋“ฑ์— ์„ ํƒ์ ์œผ๋กœ ์ ์šฉํ•˜์—ฌ ์„ค๊ณ„์˜ ์™„์„ฑ๋„๋ฅผ ๋†’์ด๋Š” ๊ฒƒ์ด ํ˜„์‹ค์ ์ž…๋‹ˆ๋‹ค.

Q180. ์Šค๋ƒ…์ƒท ํ…Œ์ŠคํŠธ(Snapshot Testing)์˜ ์žฅ๋‹จ์ ๊ณผ ์–ธ์ œ ์‚ฌ์šฉํ•˜๋ฉด ์œ ํšจํ•œ๊ฐ€์š”?

  • ๐ŸŽฏ ์ถœ์ œ ์˜๋„: ํ…Œ์ŠคํŠธ์˜ ํŽธ๋ฆฌํ•จ ๋’ค์— ์ˆจ์€ ์œ„ํ—˜์„ฑ(๋ฌด์˜๋ฏธํ•œ ์—…๋ฐ์ดํŠธ)์„ ์ธ์ง€ํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
  • ๐Ÿ’ก ํ•ต์‹ฌ ์›๋ฆฌ & ๋‹ต๋ณ€: ์Šค๋ƒ…์ƒท ํ…Œ์ŠคํŠธ๋Š” ์ด์ „ UI ๊ฒฐ๊ณผ๋ฌผ๊ณผ ํ˜„์žฌ๋ฅผ ๋น„๊ตํ•˜์—ฌ ์˜๋„์น˜ ์•Š์€ ๋ณ€ํ™”๋ฅผ ๊ฐ์ง€ํ•˜๋Š” ๋ฐ ๋งค์šฐ ๋น ๋ฅด๊ณ  ํŽธ๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์กฐ๊ธˆ๋งŒ ์Šคํƒ€์ผ์„ ๊ณ ์ณ๋„ ํ…Œ์ŠคํŠธ๊ฐ€ ๊นจ์ ธ ์ˆ˜๋™์œผ๋กœ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•˜๋Š” ๋ฒˆ๊ฑฐ๋กœ์›€์ด ์ปค์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋กœ์ง์ด ์ž์ฃผ ๋ฐ”๋€Œ๋Š” ์ปดํฌ๋„ŒํŠธ๋ณด๋‹ค๋Š”, ๋””์ž์ธ ์‹œ์Šคํ…œ์˜ ๊ณตํ†ต UI ์ปดํฌ๋„ŒํŠธ๋‚˜ ์ ˆ๋Œ€ ๋ฐ”๋€Œ๋ฉด ์•ˆ ๋˜๋Š” ์„ค์น˜ํ˜• ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋“ฑ์˜ ํšŒ๊ท€ ๋ฐฉ์ง€ ๋ชฉ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ข‹์Šต๋‹ˆ๋‹ค.

Q195. ์ข‹์€ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์˜ 5๋Œ€ ์›์น™(FIRST)์ด๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”?

  • ๐ŸŽฏ ์ถœ์ œ ์˜๋„: ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž์ฒด๊ฐ€ ์œ ์ง€๋ณด์ˆ˜ํ•˜๊ธฐ ์ข‹์€ 'ํ’ˆ์งˆ'์„ ๊ฐ–์ถ”๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
  • ๐Ÿ’ก ํ•ต์‹ฌ ์›๋ฆฌ & ๋‹ต๋ณ€: FIRST ์›์น™์€ Fast(๋น ๋ฅด๊ฒŒ ์‹คํ–‰), Independent(๋…๋ฆฝ์  ์‹คํ–‰), Repeatable(์–ด๋””์„œ๋“  ๊ฐ™์€ ๊ฒฐ๊ณผ), Self-Validating(์„ฑ๊ณต/์‹คํŒจ ์—ฌ๋ถ€ ์ž๋™ ํŒ๋ณ„), Timely(์ฝ”๋“œ ๊ตฌํ˜„ ์ „ํ›„ ์ ์‹œ์— ์ž‘์„ฑ)๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ํŠนํžˆ ๋…๋ฆฝ์„ฑ๊ณผ ๋ฐ˜๋ณต ๊ฐ€๋Šฅ์„ฑ์ด ์ค‘์š”ํ•œ๋ฐ, ์ด์ „ ํ…Œ์ŠคํŠธ์˜ ์ƒํƒœ๊ฐ€ ๋‹ค์Œ ํ…Œ์ŠคํŠธ์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๋„๋ก ๋งค๋ฒˆ ํ™˜๊ฒฝ์„ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์€ ํ…Œ์ŠคํŠธ์˜ ๊ธฐ์ดˆ์ž…๋‹ˆ๋‹ค.

๐Ÿฃ ์˜์ฒ ์ด์˜ ๋ณต๊ธฐ ์ผ๊ธฐ

์˜ค๋Š˜ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์งœ๋ณด๋ฉด์„œ ๋А๊ผˆ๋‹ค. ๊ทธ๋™์•ˆ ๋‚˜๋Š” "์ œ๋ฐœ ๋ฒ„๊ทธ ์•ˆ ๋‚˜๊ฒŒ ํ•ด์ฃผ์„ธ์š”"๋ผ๊ณ  ๊ธฐ๋„ํ•˜๋ฉฐ ์ฝ”๋”ฉํ–ˆ๋Š”๋ฐ, ์ด์ œ๋Š” "์ด ํ…Œ์ŠคํŠธ๊ฐ€ ๋‚ด ์ฝ”๋“œ๋ฅผ ์ง€์ผœ์ฃผ๊ณ  ์žˆ๋‹ค"๋Š” ๋“ ๋“ ํ•œ ๋ฐฉํŒจ๋ฅผ ์–ป์—ˆ๋‹ค. ํŠนํžˆ '์‚ฌ์šฉ์ž ๊ด€์ '์—์„œ ํ…Œ์ŠคํŠธ๋ฅผ ์งœ๋Š” ๋ฒ•์„ ๋ฐฐ์šฐ๋‹ˆ, ๋‚ด๊ฐ€ ๋งŒ๋“œ๋Š” ๊ธฐ๋Šฅ์ด ์ง„์งœ ์‚ฌ์šฉ์ž์—๊ฒŒ ์–ด๋–ค ๊ฐ€์น˜๋ฅผ ์ฃผ๋Š”์ง€ ๋‹ค์‹œ ํ•œ๋ฒˆ ์ƒ๊ฐํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

๐Ÿ’ก "ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋Š” ๋ฏธ๋ž˜์˜ ๋‚ด๊ฐ€ ๊ณผ๊ฑฐ์˜ ๋‚˜์—๊ฒŒ ๊ฐ์‚ฌ๋ฅผ ํ‘œํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ์ตœ๊ณ ์˜ ์„ ๋ฌผ์ด๋‹ค."

๋‚ด์ผ์€ ์›น์„ ์œ„ํ˜‘ํ•˜๋Š” ์–ด๋‘ ์˜ ๊ทธ๋ฆผ์ž(?)๋ฅผ ๋ง‰๋Š” ๋ฒ•, '๋ณด์•ˆ & ์„ฑ๋Šฅ ์—”์ง€๋‹ˆ์–ด๋ง 2ํƒ„'์„ ๋ฐฐ์šด๋‹ค. ๋ณด์•ˆ์€ ๋šซ๋ ค์•ผ ์•„๋Š” ๋ฒ•์ด๋ผ๋Š”๋ฐ ๋ฏธ๋ฆฌ๋ฏธ๋ฆฌ ์ž˜ ๋ง‰์•„์•ผ์ง€! ๐Ÿ”โš”๏ธ