Skip to content

[3ํŒ€ ์—ฌ์ง„์„] Chapter ๐Ÿฆ 3-1. ํ”„๋ก ํŠธ์—”๋“œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ๐Ÿฆ#3

Open
realstone2 wants to merge 21 commits intohanghae-plus:hardfrom
realstone2:hard
Open

[3ํŒ€ ์—ฌ์ง„์„] Chapter ๐Ÿฆ 3-1. ํ”„๋ก ํŠธ์—”๋“œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ๐Ÿฆ#3
realstone2 wants to merge 21 commits intohanghae-plus:hardfrom
realstone2:hard

Conversation

@realstone2
Copy link

@realstone2 realstone2 commented Aug 16, 2025

๋‚œ์ด๋„์— ๋งž๋Š” ํ…œํ”Œ๋ฆฟ์„ ์„ ํƒํ•ด์„œ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”!


7์ฃผ์ฐจ ๊ณผ์ œ ์ฒดํฌํฌ์ธํŠธ

๊ธฐ๋ณธ

HARD

7์ฃผ์ฐจ ๊ณผ์ œ ์ฒดํฌํฌ์ธํŠธ

๊ธฐ๋ณธ๊ณผ์ œ

  • ์ด 11๊ฐœ์˜ ํŒŒ์ผ, 115๊ฐœ์˜ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ๋ฌด์‚ฌํžˆ ์ž‘์„ฑํ•˜๊ณ  ํ†ต๊ณผ์‹œํ‚จ๋‹ค.

์งˆ๋ฌธ

Q. handlersUtils์— ๋‚จ๊ธด ์งˆ๋ฌธ์— ๋‹ต๋ณ€ํ•ด์ฃผ์„ธ์š”.

์ผ๋‹จ ๋ฌธ์ œ๋Š” handler์—์„œ json์„ ์ˆ˜์ •ํ•˜๋Š” handler๊ฐ€ ์ „์—ญ์œผ๋กœ ์„ค์ • ๋˜์–ด์žˆ๋‹ค๋Š” ์ ์ด๋‹ค.
๋ณ‘๋ ฌ์ ์œผ๋กœ ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํ–‰๋ ๊ฒฝ์šฐ ๋ชจ๋‘๊ฐ€ ๊ฐ™์€ json์„ ์ˆ˜์ •ํ•˜๊ฒŒ๋˜๋Š” ๊ฒƒ์ด ๋ฌธ์ œ๋‹ค.

์–ด๋–ป๊ฒŒํ•˜๋ฉด ๋ณ‘๋ ฌ์ ์œผ๋กœ ํ…Œ์ŠคํŠธํ•  ๋•Œ ๋…๋ฆฝ์ ์œผ๋กœ ์‹คํ–‰์‹œํ‚ฌ๊นŒ?

  1. test๋งˆ๋‹ค ๋…๋ฆฝ์ ์œผ๋กœ events๋ฅผ ์…‹ํŒ…ํ•ด์•ผํ•œ๋‹ค.
  2. test๋งˆ๋‹ค server handler๊ฐ€ ๋…๋ฆฝ์ ์œผ๋กœ ๋™์ž‘ํ•ด์•ผํ•œ๋‹ค.

์งฑ๋Œ์„ ๊ณ„์† ๊ตด๋ ค๋ด๋„ API์ž์ฒด์—์„œ ์ˆ˜์ •ํ•˜๋Š” ๋‚ด์šฉ์ด๋‹ค๋ณด๋‹ˆ events๋ฅผ ๋…๋ฆฝ์ ์œผ๋กœ ์…‹ํŒ…ํ•˜๋ ค๋ฉด ๊ฒฐ๊ตญ ํ…Œ์ŠคํŠธ๋งˆ๋‹ค ์ƒˆ๋กœ handler๋ฅผ ์ƒ์„ฑํ•ด์•ผ๋˜๋Š”๊ฒŒ ์•„๋‹Œ๊ฐ€? ๋ผ๋Š” ๊ฒฐ๋ก ์„ ์ง€์—ˆ๋‹ค.

์–ด๋–ป๊ฒŒ ํ…Œ์ŠคํŠธ๋งˆ๋‹ค ์ƒˆ๋กœ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์…‹ํŒ…ํ•  ์ˆ˜ ์žˆ์„๊นŒ?

1. ํ…Œ์ŠคํŠธ๋งˆ๋‹ค setupServer ์„ค์ •ํ•˜๊ธฐ

https://mswjs.io/docs/api/setup-server

While we commend setting up request interception globally, as a part of your testing setup, you may also use setupServer in individual tests, if you want to. Just make sure to choose one pattern and follow it throughout your testsโ€”multiple setupServer calls is not a good idea!

๊ณต์‹๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•ด๋ดค์„ ๋•Œ setupServer๋Š” ๊ธ€๋กœ๋ฒŒ๋กœ ํ•œ๋ฒˆ ์„ ์–ธํ•˜๊ฑฐ๋‚˜, ํ…Œ์ŠคํŠธ๋ณ„๋กœ ์„ค์ •ํ•ด์•ผํ•œ๋‹ค๊ณ  ์ ํ˜€์žˆ๋‹ค.

์ค‘๋ณต์œผ๋กœ ์„ ์–ธํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค.

์ง€๊ธˆ ๊ตฌ์กฐ์—์„œ setupServer๋ฅผ ํ…Œ์ŠคํŠธ๋งˆ๋‹ค ๋™์ž‘์‹œํ‚ค๋ ค๋ฉด, global๋กœ mockingํ•˜๊ณ  ์žˆ๋Š” ๋กœ์ง์„ ์ œ๊ฑฐํ•ด์•ผํ•œ๋‹ค.

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

๋” ์ข‹์€ ๋ฐฉ๋ฒ•์ด ์—†์„๊นŒ?

2. handler override ํ•˜๊ธฐ

https://mswjs.io/docs/best-practices/network-behavior-overrides/#resetting-request-handlers

override๋ฅผ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์—†์„๊นŒ ์ฐพ์•„๋ณด๋˜์ค‘ ๋ฌธ์„œ ์ œ๋ชฉ์ด override์ธ ๋‚ด์šฉ์„ ์ฐพ์•˜๋‹ค.

server.use()์™€ resetHandlers()๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‚ด๊ฐ€ ํ•ด๊ฒฐํ•˜๊ณ ์ž ํ–ˆ๋˜ ๋‚ด์šฉ์„ ํ’€์–ด๋‚ผ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

  1. ์ „์—ญ์ ์œผ๋กœ setup server handler๋“ค์ด ์กด์žฌ
  2. ํ…Œ์ŠคํŠธ ๋‚ด๋ถ€์—์„œ ๊ฐ๊ฐ handler๋ฅผ use()ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด override๋ฅผ ํ•ด์ค˜์„œ ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘์‹œํ‚จ๋‹ค.
  3. overrideํ•œ ํ…Œ์ŠคํŠธ์—์„œ๋Š” ํ…Œ์ŠคํŠธ๊ฐ€ ๋๋‚  ๋•Œ resetHandlers()๋ฅผ ์‹คํ–‰์‹œ์ผœ ์›์ƒ๋ณต๊ตฌ

๊ทธ๋ฆผ์œผ๋กœ ๊ทธ๋ ค๋ณด๋ฉด ์ด๋Ÿฐ ๋ชจ์Šต์ด์ง€ ์•Š์„๊นŒ?
image

Q. ํ…Œ์ŠคํŠธ๋ฅผ ๋…๋ฆฝ์ ์œผ๋กœ ๊ตฌ๋™์‹œํ‚ค๊ธฐ ์œ„ํ•ด ์ž‘์„ฑํ–ˆ๋˜ ์„ค์ •๋“ค์„ ์†Œ๊ฐœํ•ด์ฃผ์„ธ์š”.
์œ„์—์„œ ์ž‘์„ฑํ•œ ๋‚ด์šฉ์ฒ˜๋Ÿผ server.use() resetHandlers()๋ฅผ ์‚ฌ์šฉํ•˜์˜€๋‹ค.

  • ex)
export const setupMockHandlerCreationError = () => {
  afterEach(() => {
    server.resetHandlers();
  });

  server.use(
    http.post('/api/events', () => {
      return HttpResponse.json({ message: 'Error' }, { status: 500 });
    })
  );
};

์‹ฌํ™” ๊ณผ์ œ

  • App ์ปดํฌ๋„ŒํŠธ ์ ์ ˆํ•œ ๋‹จ์œ„์˜ ์ปดํฌ๋„ŒํŠธ, ํ›…, ์œ ํ‹ธ ํ•จ์ˆ˜๋กœ ๋ถ„๋ฆฌํ–ˆ๋Š”๊ฐ€?
  • ํ•ด๋‹น ๋ชจ๋“ˆ๋“ค์— ๋Œ€ํ•œ ์ ์ ˆํ•œ ํ…Œ์ŠคํŠธ๋ฅผ 5๊ฐœ ์ด์ƒ ์ž‘์„ฑํ–ˆ๋Š”๊ฐ€?

ใ…Žใ…Žใ…Ž... ์•ˆํ–ˆ์Šต๋‹ˆ๋‹ค...
์•„๋‹ˆ.. ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค..

๊ณผ์ œ ์…€ํ”„ํšŒ๊ณ 

ํ…Œ์ŠคํŠธ์ฝ”๋“œ๋Š” ๋‚˜์˜ ๊ด€์‹ฌ์‚ฌ๋„ ์•„๋‹ˆ์˜€๊ณ , ์Šคํƒ€ํŠธ์—…์—์„œ ๊ณผ์—ฐ ํ•„์š”ํ•œ ๋‚ด์šฉ์ผ๊นŒ? ์‹ถ์€ ์˜๊ตฌ์‹ฌ๋„ ๊ฐ–๊ณ  ์žˆ์—ˆ๋‹ค.
๊ทธ๋Ÿฌ๋‹ค๋ณด๋‹ˆ ๋‹น์—ฐํžˆ ํ…Œ์ŠคํŠธ์ฝ”๋“œ ์ž์ฒด๋ฅผ ์ฒ˜์Œ ๊ณต๋ถ€ํ•ด๋ดค๋‹ค.

๊ณต๋ถ€ํ•ด๋ณธ ํ›„๊ธฐ๋กœ๋Š” ์ด๋…€์„.. ์šฐ๋ฆฌ ํšŒ์‚ฌ์—์„œ๋„ ๋‹น์žฅ ํ•˜๋‚˜์”ฉ ์‚ฌ์šฉํ•ด๋ด๋„ ๊ดœ์ฐฎ๊ฒ ๋Š”๋ฐ...? ๋ผ๋Š” ์ƒ๊ฐ์„ ํ–ˆ๋‹ค.
ํšŒ์‚ฌ์—๋Š” ํ•ต์‹ฌ๊ธฐ๋Šฅ์ด ์˜ทํŽธ์ง‘, ์˜ท๋“ฑ๋ก, ์ฝ”๋””๋“ฑ๋ก ๋“ฑ๋“ฑ ์•ฑ ์ดˆ๊ธฐ๋ถ€ํ„ฐ ์žˆ์—ˆ๋˜ ๊ธฐ์ดˆ๊ธฐ๋Šฅ์ด์žˆ๋‹ค.
ํ•ด๋‹น ๊ธฐ๋Šฅ๋“ค์„ ๊ฐœ์„ ํ•˜๊ฑฐ๋‚˜ ๊ณ ๋„ํ™”ํ•  ๋•Œ๋งˆ๋‹ค ๋ ˆ๊ฑฐ์‹œ ์ฝ”๋“œ๋“ค์ด ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๊ณ  ์žˆ๋Š”๊ฒƒ์ด๊ณ , ๊ธฐํš๋„ ์ž˜ ๋ชจ๋ฅด๊ฒ ๊ณ , ๊ธฐ๋Œ€๊ฐ’๋„ ๋ญ”์ง€ ๋ชจ๋ฅด๊ฒ ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค.
์ด๋Ÿฐ ๊ณณ์— ํ…Œ์ŠคํŠธ์ฝ”๋“œ๋ฅผ ๋„์ž…ํ•ด๋†“์œผ๋ฉด, ์•ˆ์ •์ ์œผ๋กœ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๊ณ  ํŒ€์›๋“ค์—๊ฒŒ ๋„์ž…์„ ๊ณ ๋ คํ•ด๋ณด์ž๊ณ  ์ „๋‹ฌํ•ด๋‘” ์ƒํƒœ์ด๋‹ค.

๊ณผ์ œ๋Š” ๋‚œ์ด๋„๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ์—ˆ๋Š”๋ฐ, ๋‚˜๋Š” hard๋ฅผ ์„ ํƒํ•˜์˜€๋‹ค.
ํ…Œ์ŠคํŠธ์ฝ”๋“œ๋Š” ์™„์ „ ์ฒ˜์Œ ์ ‘ํ•ด๋ณด๊ธดํ•˜์ง€๋งŒ, hard ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ „๋ถ€ ์ˆ˜ํ–‰ํ•ด์•ผ์ง€ ๊ณต๋ถ€ํ–ˆ๋‹ค๊ณ  ๋А๋‚„ ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์•˜๊ณ 
์‹ฌํ™”๊ณผ์ œ๋Š” ์ฒ˜์Œ๋ถ€ํ„ฐ ํฌ๊ธฐํ•˜๊ณ , ํ…Œ์ŠคํŠธ์ฝ”๋“œ๋ฅผ ํ•™์Šตํ•˜์ž๋Š” ๋ชฉํ‘œ๋ฅผ ๊ฐ–๊ณ  ๊ณผ์ œ์— ์ž„ํ–ˆ๋‹ค.
ํ…Œ์ŠคํŠธ์ฝ”๋“œ๋ฅผ ๋‹ค ์ž‘์„ฑํ•˜๊ณ  ๋ฆฌํŒฉํ† ๋งํ•˜๋Š” ๊ณผ์ •๋„ ๊ฒช์–ด๋ณด๊ณ  ์‹ถ์—ˆ์ง€๋งŒ, ํ…Œ์ŠคํŠธ์ฝ”๋“œ๋งŒ์œผ๋กœ๋„ ์‰ฝ์ง€ ์•Š์€ ์ฃผ๊ฐ„์ด์—ˆ๋‹ค.

๊ทธ๋ž˜๋„ ์˜ค๋žœ๋งŒ์— AI๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๊ตฌ๊ธ€๋งํ•˜๊ณ  ๋ฌธ์„œ๋ฅผ ์ฐพ์•„๊ฐ€๋ฉฐ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์˜ ์žฌ๋ฏธ๋„ ๋А๊ผˆ๋‹ค.
์˜ค๋žœ๋งŒ์— ๋ฐ‘๋ฐ”๋‹ฅ๋ถ€ํ„ฐ ๋ชจ๋ฅด๋Š” ๊ฒƒ์„ ํ•™์Šตํ•˜๋‹ˆ ์žฌ๋ฏธ์žˆ์—ˆ๊ณ , AI๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋ง๊ณ  ๊ณผ์ œํ•˜๋ผ๊ณ  ํ•˜์‹  ์ฝ”์น˜๋‹˜์˜ ๊นŠ์€ ๋œป์„ ๋А๋‚„ ์ˆ˜ ์žˆ์—ˆ๋˜ ์ฃผ๊ฐ„์ด์—ˆ๋‹ค.

๊ณผ์ œ ํƒˆ๋ฝ์„ ๋ณด๋Š” ๊ฒƒ์€ ๋„ˆ๋ฌด ์Šฌํ”„์ง€๋งŒ, hard๊ณ ๋ฅธ ๊ณณ์„ ํ›„ํšŒํ•˜์ง€ ์•Š๋Š”๋‹ค! ํ…Œ์ŠคํŠธ์ฝ”๋“œ๋ฅผ ํ•™์Šตํ–ˆ์œผ๋‹ˆ๊นŒ!!!

๊ธฐ์ˆ ์  ์„ฑ์žฅ

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์˜ ์ดํ•ด

Testing Library??? Jest?? Vitest??

์ด๋ฒˆ์— ๋ฐœ์ œ๋ฅผ ๋“ค์œผ๋ฉด์„œ ํ…Œ์ŠคํŒ… ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ๋ญ๊ณ , jest์™€ vitest๋Š” ๋ฌด์—‡์ด์ง€ ์ •๋ฆฌ๊ฐ€ ๋˜์ง€ ์•Š์•˜๋‹ค.

  • Vitest, Jest
    vitest์™€ jest๋Š” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋Ÿฌ๋„ˆ์ด๋‹ค.
    ํ…Œ์ŠคํŠธ์ฝ”๋“œ๋ฅผ ์‹คํ–‰์‹œํ‚ค๊ณ  ๊ฒฐ๊ณผ๋ฌผ์„ ์ถœ๋ ฅํ•ด์ฃผ๋Š” ์‹œ์Šคํ…œ์ด๋‹ค.

  • Testing Library?
    vitest์™€ jest๋ฅผ ์ด์šฉํ•˜์—ฌ ํ…Œ์ŠคํŠธ๋ฅผ ๋Œ๋ฆด ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๋„๊ตฌ์ด๋‹ค.

์•ฝ๊ฐ„ ์ง„๊ฒฉ์˜๊ฑฐ์ธ ์„ธ๊ณ„๊ด€์œผ๋กœ ๋น„๊ตํ•ด๋ณด์ž๋ฉด,,
testing library๋Š” ์ž…์ฒด๊ธฐ๋™์žฅ์น˜
test๋Š” ๊ฑฐ์ธ
vitest, jest๋Š” ์กฐ์‚ฌ๋ณ‘๋‹จ, ์ฃผ๋‘”๋ณ‘๋‹จ
์ด๋Ÿฐ ๋А๋‚Œ์ด๋ž„๊นŒ..?

ํ…Œ์ŠคํŠธ ์ž‘์„ฑ ๋ฐฉ๋ฒ•

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ์‹์—๋Š” ๋‘๊ฐ€์ง€ ๋ฐฉ์‹์ด ์žˆ๋‹ค.

  1. ๊ตฌํ˜„ ๊ธฐ๋ฐ˜ ํ…Œ์ŠคํŠธ
    ๊ตฌํ˜„ ๊ธฐ๋ฐ˜ ํ…Œ์ŠคํŠธ๋Š” ๊ตฌํ˜„ ์„ธ๋ถ€์‚ฌํ•ญ์— ๋”ฐ๋ผ์„œ ๊ฐœ๋ฐœ์ž ๊ด€์ , ์ฝ”๋“œ ๊ตฌ์กฐ ๊ธฐ๋ฐ˜์œผ๋กœ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.
    ๋‚ด๋ถ€ ๋กœ์ง์— ๋Œ€ํ•ด์„œ ์ปค๋ฒ„๋ฆฌ์ง€๊ฐ€ ๋†’๋‹ค.

  2. ๋ช…์„ธ ๊ธฐ๋ฐ˜ ํ…Œ์ŠคํŠธ
    ๋ช…์„ธ ๊ธฐ๋ฐ˜ ํ…Œ์ŠคํŠธ๋Š” ์‚ฌ์šฉ์ž ๊ด€์ , ์š”๊ตฌ์‚ฌํ•ญ ๋ฌธ์„œ์— ๋”ฐ๋ผ์„œ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด์„œ "์ดˆ๊ธฐ ์ƒํƒœ์—์„œ๋Š” ์•Œ๋ฆผ์ด ์—†์–ด์•ผ ํ•œ๋‹ค" ๋ผ๋Š” ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•  ๋•Œ ์•Œ๋žŒ์ด ์—†์–ด์•ผ ํ•œ๋‹ค๋Š” ๋ช…์„ธ ๊ธฐ๋ฐ˜ ํ…Œ์ŠคํŠธ์ผ๊นŒ ๊ตฌํ˜„ ๊ธฐ๋ฐ˜ ํ…Œ์ŠคํŠธ์ผ๊นŒ?

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ณด์•˜๋‹ค.

it('์ดˆ๊ธฐ ์ƒํƒœ์—์„œ๋Š” ์•Œ๋ฆผ์ด ์—†์–ด์•ผ ํ•œ๋‹ค', async () => {
  const { result: eventsResult } = renderHook(() => useEventOperations(false));

  await screen.findByText('์ผ์ • ๋กœ๋”ฉ ์™„๋ฃŒ!');

  const events = eventsResult.current.events;

  const { result } = renderHook(() => useNotifications(events));

  expect(result.current.notifications).toEqual([]);
});

useEventOperations, useNotifications ๋“ฑ์˜ hook ๋‚ด๋ถ€์—์„œ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„์ด ๋˜์–ด์žˆ๋Š”์ง€๋Š” ํ…Œ์ŠคํŠธํ•˜์ง€ ์•Š์•˜๋‹ค.
์ด๋Ÿฐ ๊ฒฝ์šฐ๊ฐ€ ๋ช…์„ธ ๊ธฐ๋ฐ˜ ํ…Œ์ŠคํŠธ์ด๋‹ค.

์˜ฌ๋ฐ”๋ฅธ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ

๋‹ต๋ณ€์€ ์ •์ ์ด์–ด์•ผํ• ๊นŒ? ๋™์ ์ด์–ด๋„ ๋ ๊นŒ?

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

it('holidays๋Š” ์˜ค๋Š˜ ๋‚ ์งœ์— ํ•ด๋‹นํ•˜๋Š” ๊ณตํœด์ผ ์ •๋ณด๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ์–ด์•ผ ํ•œ๋‹ค', async () => {
  const { result } = renderHook(() => useCalendarView());

  const holidays = HOLIDAY_RECORD_BY_MONTH[format('YYYY-MM')];

  expect(result.current.holidays).toEqual(holidays);
});

it(`currentDate๋Š” ์˜ค๋Š˜ ๋‚ ์งœ์ธ ${format('YYYY-MM-DD')}์ด์–ด์•ผ ํ•œ๋‹ค`, () => {
  const { result } = renderHook(() => useCalendarView());

  assertDate(result.current.currentDate, new Date());
});

์—ฌ๊ธฐ๊นŒ์ง€๋Š” ์•„๋งˆ ์ทจํ–ฅ์ฐจ์ด ์ •๋„๋กœ ๋„˜์–ด๊ฐˆ ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค. ๋ฌธ์ œ ์—†์„ ๊ฒƒ ๊ฐ™๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ "๊ฒ€์ƒ‰์–ด์— ๋งž๋Š” ์ด๋ฒคํŠธ๋งŒ ํ•„ํ„ฐ๋งํ•ด์•ผ ํ•œ๋‹ค" ๋ผ๋Š” ํ…Œ์ŠคํŠธ์˜ ๊ฒฐ๊ณผ๊ฐ’์„ ์ง์ ‘ filterํ•ด์„œ ๊ฒฐ๊ณผ๊ฐ’์„ ์ถ”๋ก ํ•œ๋‹ค๋ฉด..?

 expect(result).toEqual(data.filter(...))

์ด๋Ÿฐ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  data.filter()๋„.. ํ…Œ์ŠคํŠธ ๋Œ๋ ค์•ผํ•˜๋Š”๊ฑฐ์•„๋‹ˆ์•ผ...? ์ƒ๊ฐํ–ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ์•„์ฐจ ์‹ถ์—ˆ๋‹ค. ๋‚ด๊ฐ€ ๋ญ” ์ƒ๊ฐ์„ํ•œ๊ฑฐ์•ผ! ํ•˜๋ฉฐ ๋ฌดํ•œ ํ…Œ์ŠคํŠธ ๊ตด๋ ˆ์— ๋น ์ง€๋Š” ์ƒ์ƒ์„ ํ•˜๊ณ  ์ด๊ฑด ์ž˜๋ชป๋๋‹ค๊ณ  ๋А๊ผˆ๋‹ค.

๊ทธ๋ž˜์„œ ๋ฐ”๋กœ ์ฝ”์น˜๋‹˜๋“ค๊ป˜ ์—ฌ์ญค๋ดค๋‹ค.
์ทจํ–ฅ์ฐจ์ด๊ฐ€ ์žˆ๊ธดํ•˜์ง€๋งŒ ํ…Œ์ŠคํŠธ์ฝ”๋“œ์˜ ๋‹ต๋ณ€์€ ์ •์ ์œผ๋กœ ์ ๋Š” ๊ฒƒ์ด ์ข‹๋‹ค๊ณ  ํ•˜์…จ๋‹ค.

ํ…Œ์ŠคํŠธ์ฝ”๋“œ๋Š” ๋„ˆ๋ฌด ์ฝ”๋”ฉํ•˜๋“ฏ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์€ ์ข‹์ง€ ์•Š๊ตฌ๋‚˜๋ผ๊ณ  ๋А๊ผˆ๋‹ค.

๋™๋“ฑ ๋ถ„ํ•  ๊ทธ๋ฃน

ํ…Œ์ŠคํŠธ ์„ค๊ณ„ ๊ธฐ๋ฒ• ์ค‘ ํ•˜๋‚˜์ด๋‹ค.

์ž…๋ ฅ๊ฐ’๋“ค์„ ์˜๋ฏธ์ ์œผ๋กœ ๋™์ผํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋‚ด๋Š” ๊ทธ๋ฃน์œผ๋กœ ๋‚˜๋ˆ„๋Š” ๊ธฐ๋ฒ•์ด๋‹ค.

์•„๋ž˜ ์˜ˆ์‹œ๋ฅผ ๋ณด๋ฉด "์ผ์ •์ด ํ‘œ์‹œ๋˜์ง€ ์•Š๋Š”๋‹ค", "์ผ์ •์ด ํ‘œ์‹œ๋œ๋‹ค" ๋‘ ๊ทธ๋ฃน์œผ๋กœ ๋‚˜๋‰œ๋‹ค.
์ด ๋•Œ๋Š” ์˜๋ฏธ๊ฐ€ ์žˆ๋Š” ๋™๋“ฑ ๋ถ„ํ•  ๊ทธ๋ฃน์ด๋‹ค.

it('์ฃผ๋ณ„ ๋ทฐ๋ฅผ ์„ ํƒ ํ›„ ํ•ด๋‹น ์ฃผ์— ์ผ์ •์ด ์—†์œผ๋ฉด, ์ผ์ •์ด ํ‘œ์‹œ๋˜์ง€ ์•Š๋Š”๋‹ค.', async () => {
  const user = userEvent.setup();

  vi.setSystemTime(new Date('2025-09-01'));

  ...

  expect(screen.queryByText('ํŒ€ ํšŒ์˜')).not.toBeInTheDocument();
});

it('์ฃผ๋ณ„ ๋ทฐ ์„ ํƒ ํ›„ ํ•ด๋‹น ์ผ์ž์— ์ผ์ •์ด ์กด์žฌํ•œ๋‹ค๋ฉด ํ•ด๋‹น ์ผ์ •์ด ์ •ํ™•ํžˆ ํ‘œ์‹œ๋œ๋‹ค', async () => {
  const user = userEvent.setup();

  vi.setSystemTime(new Date('2025-09-12'));
  ...

  expect(within(weekViewContainer).getByText('ํŒ€ ํšŒ์˜')).toBeVisible();
});

๊ทธ๋Ÿฌ๋‚˜ ๋งŒ์•ฝ ์•„๋ž˜์ฒ˜๋Ÿผ ๊ฐ™์€ ๋ถ„ํ•  ๊ทธ๋ฃน์˜ ํ…Œ์ŠคํŠธ๋ฅผ ์—ฌ๋Ÿฌ๋ฒˆ ํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ์ž˜๋ชป๋œ ํ…Œ์ŠคํŠธ ์„ค๊ณ„๋‹ค

 it('์ฃผ๋ณ„ ๋ทฐ๋ฅผ ์„ ํƒ ํ›„ 9์›” 1์ฃผ์ฐจ์— ์ผ์ •์ด ์—†์œผ๋ฉด, ์ผ์ •์ด ํ‘œ์‹œ๋˜์ง€ ์•Š๋Š”๋‹ค.', async () => {
  const user = userEvent.setup();

  ...

  expect(screen.queryByText('ํŒ€ ํšŒ์˜')).not.toBeInTheDocument();
});

it('์ฃผ๋ณ„ ๋ทฐ๋ฅผ ์„ ํƒ ํ›„ 9์›” 2์ฃผ์ฐจ์— ์ผ์ •์ด ์—†์œผ๋ฉด, ์ผ์ •์ด ํ‘œ์‹œ๋˜์ง€ ์•Š๋Š”๋‹ค.', async () => {
  const user = userEvent.setup();

  ...

  expect(screen.queryByText('ํŒ€ ํšŒ์˜')).not.toBeInTheDocument();
});

๊ฒฝ๊ณ„๊ฐ’ ํ…Œ์ŠคํŠธ

ํ…Œ์ŠคํŠธ์˜ ๊ฒฝ๊ณ„๊ฐ’์—๋Š” ๊ฐœ๋ฐœ์ž์˜ ์‹ค์ˆ˜๊ฐ€ ๋งŽ์ด ์ผ์–ด๋‚  ์ˆ˜ ์žˆ๋Š” ์œ„์น˜์ด๋‹ค.
์•„๋ž˜์ฒ˜๋Ÿผ ๊ฒฝ๊ณ„๊ฐ’์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋ถ„๋ฅ˜๋˜๋Š”์ง€ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ฒƒ์€ ์˜๋ฏธ์žˆ๋‹ค.

it('์ฃผ์˜ ๋(์ผ์š”์ผ)์— ๋Œ€ํ•ด ์˜ฌ๋ฐ”๋ฅธ ์ฃผ์˜ ๋‚ ์งœ๋“ค์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค', () => {
  expect(getWeekDates(new Date('2025-07-07'))).toEqual([
    new Date('2025-07-06'),
    new Date('2025-07-07'),
    new Date('2025-07-08'),
    new Date('2025-07-09'),
    new Date('2025-07-10'),
    new Date('2025-07-11'),
    new Date('2025-07-12'),
  ]);
});

ํ•™์Šต ํšจ๊ณผ ๋ถ„์„

์‹ค๋ฌด ์ ์šฉ ๊ฐ€๋Šฅ์„ฑ

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

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

์˜คํ”„๋‹˜์ด Q&A ์„น์…˜์ค‘ ๋ˆ„๊ตฐ๊ฐ€ ๋น„ํšจ์œจ์ ์ธ ํ…Œ์ŠคํŠธ์ฝ”๋“œ ๊ฐ™๋‹ค๊ณ  ํ•ด๋„ ํ…Œ์ŠคํŠธ์ฝ”๋“œ๋กœ ์ธํ•ด ์‹ฌ๋ฆฌ์ ์ธ ์•ˆ์ •๊ฐ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค๋ฉด ๊ทธ๊ฑธ๋กœ๋„ ์˜๋ฏธ์žˆ๋‹ค๊ณ  ํ•˜์…จ๋‹ค.
์ด ๋ง์”€์ด ์ข€ ์™€๋‹ฟ๊ฒŒ ๋˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค. ์˜›๋‚  ๊ธฐ๋Šฅ์„ ๊ฑด๋“œ๋ฆด ๋•Œ๋งˆ๋‹ค ๋ฌด์Šจ ๋ฒ„๊ทธ๊ฐ€ ๋ฐœ์ƒํ• ์ง€ ๋ชจ๋ฅด๊ฒ ์œผ๋‹ˆ ๋ถˆ์•ˆํ•˜๊ณ  ์ž‘์—…ํ•˜๊ณ  ์‹ถ์ง€ ์•Š์•˜๋Š”๋ฐ, ํ…Œ์ŠคํŠธ์ฝ”๋“œ๋กœ ๋‚˜์—๊ฒŒ ์‹ฌ๋ฆฌ์ ์ธ ์•ˆ์ •๊ฐ์„ ์ค€๋‹ค๋ฉด ๊ฐœ๋ฐœํ•˜๊ธฐ๊ฐ€ ์ •๋ง ํŽธํ•  ๊ฒƒ ๊ฐ™๋‹ค.

ํ…Œ์ŠคํŠธ์ฝ”๋“œ๋ฅผ ํ•™์Šตํ•œ ํ›„ ์ƒ๊ฐ

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

๊ณผ์ œ ํ”ผ๋“œ๋ฐฑ

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ฒ˜์Œ ์ ‘ํ•˜๋‹ค๋ณด๋‹ˆ ๊ณผ์ œ์–‘์ด ๋ฒ…์ฐจ๊ฒŒ ๋А๊ปด์ง€๊ธด ํ–ˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋ž˜์„œ ๋‚œ์ด๋„๋ฅผ ๋‚˜๋ˆ ์ฃผ์‹œ๊ธด ํ•˜์…จ์ง€๋งŒ,
์‰ฌ์šด๊ฑธ ๊ณ ๋ฅด๊ณ  ์‹ถ์ง€ ์•Š์•˜๊ณ ... ์‹ฌํ™”๊ณผ์ œ ๋ฆฌํŒฉํ† ๋ง์€ ๊ณผ๊ฐํ•˜๊ฒŒ ํฌ๊ธฐํ•˜๊ณ  ํ…Œ์ŠคํŠธ์ฝ”๋“œ์— ์ง‘์ค‘ํ•˜์—ฌ ํ•™์Šตํ•˜๊ณ ์ž ํ•˜์˜€์Šต๋‹ˆ๋‹ค.
์ด๋Ÿฐ ๊ฒฝ์šฐ์— ์ œ๊ฐ€ ์„ ํƒํ•œ ๊ธธ์ด๊ธด ํ•˜์ง€๋งŒ ์‹ฌํ™”๊ณผ์ œ ์‹คํŒจํ•ด์„œ ์Šฌํ”„๋„ค์š” ใ…œ

๋ฆฌ๋ทฐ ๋ฐ›๊ณ  ์‹ถ์€ ๋‚ด์šฉ

1. handlersUtils ํ•จ์ˆ˜ ๋กœ์ง

๊ณผ์ œ์˜ ํ•ต์‹ฌ์ด ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰ํ–ˆ์„ ๋•Œ ๋ฌธ์ œ๊ฐ€ ์—†์–ด์•ผํ•œ๋‹ค๊ณ  ํ•˜์…จ๋Š”๋ฐ,
ํ…Œ์ŠคํŠธ๊ฐ€ ๋ณ‘๋ ฌ๋กœ ๋ˆ๋‹ค๋ฉด, ์—ฌ๋Ÿฌ๊ณณ์—์„œ ๋™์‹œ์— server.use๋กœ override๋ฅผ ํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ๋Š” ๊ฒƒ์ด ์•„๋‹Œ๊ฐ€? ํ•˜๋Š” ๊ฑฑ์ •์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ–ˆ์„ ๋•Œ๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋ฐ, ํ…Œ์ŠคํŠธ๊ฐ€ ๋ณ‘๋ ฌ๋กœ ๋ˆ๋‹ค๋Š” ์˜๋ฏธ๊ฐ€ ๋™์‹œ์— ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํ–‰๋œ๋‹ค๋Š” ๊ฒƒ์€ ์•„๋‹Œ๊ฑธ๊นŒ์š”?

server.resetHandlers()๋ฅผ ํ•ด์ฃผ์ง€ ์•Š์œผ๋ฉด ์™ธ๋ถ€ ํ…Œ์ŠคํŠธ์— ์˜ํ–ฅ์ฃผ๋Š” ๊ฒƒ์„ ๋ณด์•˜์„ ๋•Œ๋Š” ๊ทธ๋ ‡์ง€๋งŒ์€ ์•„๋‹Œ๊ฑฐ๊ฐ™๊ณ .. ์•ฝ๊ฐ„ ํ˜ผ๋ž€์Šค๋Ÿฌ์šด ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.

2. ํšŒ์‚ฌ์—์„œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ๋„์ž…ํ•˜๋Š” ๋ฐฉ๋ฒ•?

์œ„์— ํšŒ๊ณ ์— ์ ์€ ๊ฒƒ์ฒ˜๋Ÿผ ๋ ˆ๊ฑฐ์‹œ ๋กœ์ง๊ณผ ํ•จ๊ป˜ ๊ฐœ๋ฐœํ•  ๋•Œ ํ•„์š”์„ฑ์ด ๋А๊ปด์ง„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
ํ•ด๋‹น ํฌ์ธํŠธ๋กœ ํŒ€์›๋“ค๊ณผ ์–˜๊ธฐํ•ด์„œ ๋„์ž…์„ ํ•ด๋ณผ๊นŒ ์‹ถ์€๋ฐ, ์ค€์ผ๋‹˜์€ ์–ด๋–ป๊ฒŒ ์ƒ๊ฐํ•˜์‹œ๋‚˜์š”?
์ œ๊ฐ€ ์ƒˆ๋กœ์šด๊ฑฐ ๋ฐฐ์› ๋‹ค๊ณ  ์‹ ๋‚˜์„œ ํŽธํ˜‘๋œ ์‹œ๊ฐ์œผ๋กœ ์ง€๊ธˆ ์ƒํ™ฉ์„ ๋ฐ”๋ผ๋ณธ๊ฒŒ ์•„๋‹๊นŒ? ๊ฑฑ์ •๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

3. ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์˜ ๊ธฐ๋Œ€๊ฐ’์„ ์–ด๋””๊นŒ์ง€ ์ •์ ์œผ๋กœ ๋‘์–ด์•ผํ•˜๊ณ  ๋™์ ์œผ๋กœ ๋งŒ๋“ค์–ด์•ผํ• ์ง€? (์ด๋ฏธ ์˜คํ”„์ฝ”์น˜๋‹˜๊ป˜์„œ ๋‹ต๋ณ€์„ ํ•ด์ฃผ์…จ์ง€๋งŒ, ์ค€์ผ๋‹˜๊ป˜๋„ ๋“ค์–ด๋ณด๊ณ  ์‹ถ๋„ค์š” ใ…Žใ…Ž..)

์˜ˆ๋ฅผ ๋“ค์–ด์„œ
"๊ฒ€์ƒ‰์–ด์— ๋งž๋Š” ์ด๋ฒคํŠธ๋งŒ ํ•„ํ„ฐ๋งํ•ด์•ผ ํ•œ๋‹ค" ๋ผ๋Š” ํ…Œ์ŠคํŠธ์—์„œ์˜ ๊ฒฐ๊ณผ ๊ธฐ๋Œ€๊ฐ’์ด ์•„๋ž˜๋ผ๋ฉด,

[
  {
    id: '2',
    title: '์ค€์ผ๋‹˜ ์งฑ์งฑ๋งจ',
    date: '2025-10-15',
    startTime: '09:00',
    endTime: '10:00',
    description: '์ค€์ผ๋‹˜ ์งฑ์งฑ๋งจ',
    location: 'ํšŒ์˜์‹ค B',
    category: '์—…๋ฌด',
    repeat: { type: 'none', interval: 0 },
    notificationTime: 10,
  },
];

์ •๋‹ต์— ๋Œ€ํ•œ ๊ธฐ๋Œ€๊ฐ’์„ ์ •์ ์œผ๋กœ ๋ณด๊ด€ํ•ด์•ผํ• ์ง€
์•„๋ž˜์ฒ˜๋Ÿผ filter๋กœ ๋Œ์•„์•ผ๋˜๋‚˜ ๊ณ ๋ฏผํ•˜์˜€์Šต๋‹ˆ๋‹ค.

eventList.filter(...)

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

๊ทธ๋Ÿผ ๋ฌด์กฐ๊ฑด ์ •์ ์œผ๋กœ ๋‘์–ด์•ผํ•˜๋‚˜? ์‹ถ๋‹ค๊ฐ€๋„ ์•„์ฃผ ๊ฐ„๋‹จํ•œ ๊ฒฐ๊ณผ๊ฐ’์ธ๋ฐ๋„ ์ •์ ์œผ๋กœ ๋‘๋Š” ๊ฒƒ์€ ๋˜ ๋ถˆํ•„์š”ํ•œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์˜ˆ์‹œ๋กœ ๋“ค์–ด๋ณด๋ฉด,
"์ฃผ๊ฐ„ ๋ทฐ์—์„œ ๋‹ค์Œ์œผ๋กœ navigate" ํ•˜๋Š” ํ…Œ์ŠคํŠธ์ž…๋‹ˆ๋‹ค.

7์ผํ›„, 7์ผ์ „์œผ๋กœ ์ด๋™ํ•˜๋Š” ์•„์ฃผ ๊ฐ„๋‹จํ•œ ๋กœ์ง์ž„์—๋„ ์ด๊ฒƒ๋„ ์ •์ ์ธ ๋ฐ์ดํ„ฐ๋กœ ํ…Œ์ŠคํŠธ๊ฒฐ๊ณผ๊ฐ’์„ ์ž‘์„ฑํ•ด๋†”์•ผํ• ์ง€ ๊ณ ๋ฏผ์ž…๋‹ˆ๋‹ค.

์ •์ ์œผ๋กœ ๋‘๋ฉด mock ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๊ฐ’๋„ ๊ฐ™์ด ๋งค๋ฒˆ ์ˆ˜์ •ํ•ด์ค˜์•ผํ•œ๋‹ค๋Š” ๋ถˆํŽธํ•œ ์ ์ด ์žˆ์„ํ…๋ฐ, ๋ถˆํŽธํ•˜๋”๋ผ๋„ ์˜ฌ๋ฐ”๋ฅธ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•˜๋ ค๋ฉด ์ •์ ์ธ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ• ๊นŒ์š”?

- ๊ธฐ๋ณธ ๊ณผ์ œ์™€ ์‹ฌํ™” ๊ณผ์ œ ์ฒดํฌ๋ฆฌ์ŠคํŠธ ํฌํ•จ
- ๊ณผ์ œ ์…€ํ”„ํšŒ๊ณ  ๋ฐ ํ”ผ๋“œ๋ฐฑ ์š”์ฒญ ์„น์…˜ ์ถ”๊ฐ€
- Medium ๋ฐ Hard ๊ณผ์ œ์— ๋Œ€ํ•œ ์งˆ๋ฌธ ์„น์…˜ ํฌํ•จ
@realstone2 realstone2 changed the title [3ํŒ€ ์—ฌ์ง„์„] Chapter 3-1. ํ”„๋ก ํŠธ์—”๋“œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ [3ํŒ€ ์—ฌ์ง„์„] Chapter ๐Ÿฆ 3-1. ํ”„๋ก ํŠธ์—”๋“œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ๐Ÿฆ Aug 16, 2025
- MSW ํ•ธ๋“ค๋Ÿฌ์—์„œ ์‘๋‹ต ํ˜•์‹์„ ์ˆ˜์ •ํ•˜์—ฌ events ๊ฐ์ฒด๋ฅผ ํฌํ•จํ•˜๋„๋ก ๋ณ€๊ฒฝ
- ํ•ธ๋“ค๋Ÿฌ ์œ ํ‹ธ๋ฆฌํ‹ฐ์— ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ ๋ฐ ์ด๋ฒคํŠธ ์‚ญ์ œ ํ•ธ๋“ค๋Ÿฌ ์ถ”๊ฐ€
- useEventOperations ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์—์„œ ์ด๋ฒคํŠธ ๋กœ๋”ฉ ๋ฐ ์ €์žฅ, ์ˆ˜์ •, ์‚ญ์ œ์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค ์ถ”๊ฐ€
- ํ•ธ๋“ค๋Ÿฌ์—์„œ JSON ์ˆ˜์ • ๋ฌธ์ œ ๋ฐ ๋ณ‘๋ ฌ ํ…Œ์ŠคํŠธ ์‹คํ–‰ ์‹œ ๋…๋ฆฝ์„ฑ ํ™•๋ณด ๋ฐฉ์•ˆ์— ๋Œ€ํ•œ ๋…ผ์˜ ์ถ”๊ฐ€
- ์˜ฌ๋ฐ”๋ฅธ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ์— ๋Œ€ํ•œ ์ƒ๊ฐ ์ •๋ฆฌ ๋ฐ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์˜ ์ค‘์š”์„ฑ ๊ฐ•์กฐ
- ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ ๊ตฌ์„ฑ ๋ฐ ๋ชจํ‚น์— ๋Œ€ํ•œ ๊ตฌ์ฒด์ ์ธ ์„ค๋ช… ์ถ”๊ฐ€
- ์ด๋ฒคํŠธ ์ƒ์„ฑ ๋ฐ ์ˆ˜์ • ํ•ธ๋“ค๋Ÿฌ์— ์˜ค๋ฅ˜ ์‘๋‹ต ์ฒ˜๋ฆฌ ์ถ”๊ฐ€
- ํ•ธ๋“ค๋Ÿฌ ์ด๋ฆ„ ๋ณ€๊ฒฝ ๋ฐ ํ…Œ์ŠคํŠธ ํ›„ ํ•ธ๋“ค๋Ÿฌ ๋ฆฌ์…‹ ๋กœ์ง ํ†ต์ผ
- ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์˜ ๋…๋ฆฝ์„ฑ์„ ํ™•๋ณดํ•˜๊ธฐ ์œ„ํ•œ ๊ตฌ์กฐ ๊ฐœ์„ 
- ํ•ธ๋“ค๋Ÿฌ ์ด๋ฆ„์„ ๋ณ€๊ฒฝํ•˜๊ณ , ์ด๋ฒคํŠธ ๊ด€๋ จ ํ…Œ์ŠคํŠธ์—์„œ ํ•ธ๋“ค๋Ÿฌ ํ˜ธ์ถœ ๋ฐฉ์‹์„ ํ†ต์ผ
- ์ด๋ฒคํŠธ ๋กœ๋”ฉ ์‹คํŒจ ์‹œ ์—๋Ÿฌ ํ•ธ๋“ค๋ง์„ ์œ„ํ•œ ํ•ธ๋“ค๋Ÿฌ ์ˆ˜์ •
- ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค์—์„œ ํ•ธ๋“ค๋Ÿฌ ํ˜ธ์ถœ ๋ฐฉ์‹์„ ์ผ๊ด€๋˜๊ฒŒ ๋ณ€๊ฒฝํ•˜์—ฌ ์ฝ”๋“œ ๊ฐ€๋…์„ฑ ํ–ฅ์ƒ
- ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค์—์„œ ์ด๋ฒคํŠธ ๋‚ ์งœ๋ฅผ '2025-10-2'์—์„œ '2025-10-01'๋กœ ์ˆ˜์ •ํ•˜์—ฌ ์ผ๊ด€์„ฑ ํ™•๋ณด
- ํ•ธ๋“ค๋Ÿฌ ์œ ํ‹ธ๋ฆฌํ‹ฐ์—์„œ ๋ถˆํ•„์š”ํ•œ ์ฝ˜์†” ๋กœ๊ทธ ์ œ๊ฑฐ
- ์ด๋ฒคํŠธ ๋‚ ์งœ๋ฅผ '2025-10-01'๋กœ ์ˆ˜์ •ํ•˜์—ฌ ์ผ๊ด€์„ฑ ์œ ์ง€
- useNotifications ํ›…์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค ์ถ”๊ฐ€: ์ดˆ๊ธฐ ์ƒํƒœ, ์•Œ๋ฆผ ์ƒ์„ฑ, ์•Œ๋ฆผ ์ œ๊ฑฐ, ์ค‘๋ณต ์•Œ๋ฆผ ๋ฐฉ์ง€ ๊ฒ€์ฆ
- ์ผ์ • ์ถ”๊ฐ€, ์ˆ˜์ •, ์‚ญ์ œ ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค ๊ตฌํ˜„
- ์ฃผ๋ณ„ ๋ฐ ์›”๋ณ„ ๋ทฐ์—์„œ ์ผ์ • ํ‘œ์‹œ ์—ฌ๋ถ€ ๊ฒ€์ฆ
- ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค ์ถ”๊ฐ€ ๋ฐ ์•Œ๋ฆผ ๊ธฐ๋Šฅ ํ…Œ์ŠคํŠธ ๊ฐ•ํ™”
- ๊ฒน์น˜๋Š” ์ผ์ • ์ถ”๊ฐ€ ์‹œ ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€ ํ™•์ธ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€
- queryByText, findByText ๋ฉ”์„œ๋“œ์˜ ๋™๊ธฐ/๋น„๋™๊ธฐ ์‚ฌ์šฉ๋ฒ•์— ๋Œ€ํ•œ ์„ค๋ช… ์ถ”๊ฐ€
- ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ ์‹œ ๊ณ ๋ คํ•ด์•ผ ํ•  ์š”์†Œ๋“ค ์ •๋ฆฌ
- dayjs ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ œ๊ฑฐ ๋ฐ ๊ด€๋ จ ์ฝ”๋“œ ์ˆ˜์ •
- ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค์—์„œ ๋‚ ์งœ๋ฅผ ํ•˜๋“œ์ฝ”๋”ฉํ•˜์—ฌ ์ผ๊ด€์„ฑ ์œ ์ง€
- ๊ณตํœด์ผ ์ •๋ณด ๊ฒ€์ฆ ๋กœ์ง์„ ์—…๋ฐ์ดํŠธํ•˜์—ฌ ์ •ํ™•์„ฑ ํ–ฅ์ƒ
- package.json์— @eslint/js ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ถ”๊ฐ€
- pnpm-lock.yaml์— ํ•ด๋‹น ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๋ฒ„์ „ ๋ฐ ์˜์กด์„ฑ ์ •๋ณด ์—…๋ฐ์ดํŠธ
โ€ฆ-unused-vars' ๊ทœ์น™์„ ์ถ”๊ฐ€ํ•˜์—ฌ TypeScript์˜ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ๋ณ€์ˆ˜ ๊ฒฝ๊ณ ๋ฅผ ์˜ค๋ฅ˜๋กœ ์„ค์ •
- '@typescript-eslint/no-unused-vars' ๊ทœ์น™์„ ๊ฒฝ๊ณ ๋กœ ๋ณ€๊ฒฝ
- ํ•ธ๋“ค๋Ÿฌ ํŒŒ์ผ์—์„œ 'msw' ์ž„ํฌํŠธ ์œ„์น˜ ์ˆ˜์ •
- ํ…Œ์ŠคํŠธ ํŒŒ์ผ์—์„œ ๋ถˆํ•„์š”ํ•œ ์ž„ํฌํŠธ ์ •๋ฆฌ ๋ฐ ์ฝ”๋“œ ์ •๋ฆฌ
- JSON ์‘๋‹ต ํŒŒ์ผ์„ ์ƒˆ๋กœ์šด ์ด๋ฒคํŠธ ๋ฐ์ดํ„ฐ๋กœ ์—…๋ฐ์ดํŠธ
@BBAK-jun
Copy link

์ž…์ฒด๊ธฐ๋™์žฅ์น˜ ์ž˜ ๋ณด๊ณ  ๊ฐ‘๋‹ˆ๋‹ค

@realstone2
Copy link
Author

realstone2 commented Aug 22, 2025

@BBAK-jun. ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹์•„ ๋ถ€๋„๋Ÿฝ๋„ค ์ €๋ฒˆ์— qna ๋“ค์€๊ฑฐ ํ•„๊ธฐํ•œ๊ฑฐ๊ทธ๋Œ€๋กœ์žˆ๋„ค...

- pr.md์—์„œ ๊ธฐ๋ณธ๊ณผ์ œ ์™„๋ฃŒ ํ‘œ์‹œ ๋ฐ ๊ณผ์ œ ์…€ํ”„ํšŒ๊ณ  ์ถ”๊ฐ€
- ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์˜ ์ดํ•ด ์„น์…˜์— ๋™์ /์ •์  ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ์— ๋Œ€ํ•œ ๋…ผ์˜ ์ถ”๊ฐ€
- ๋ถˆํ•„์š”ํ•œ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค ์ฃผ์„ ์ฒ˜๋ฆฌ ๋ฐ ํ†ตํ•ฉ
- fetchHolidays.ts์—์„œ ๊ณตํœด์ผ ๋ฐ์ดํ„ฐ ์ œ๊ฑฐ ๋ฐ ๊ด€๋ จ ์ฝ”๋“œ ์ •๋ฆฌ
- ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค์—์„œ ์ผ์ • ๋ทฐ ๊ด€๋ จ ์„ค๋ช… ์ˆ˜์ •
@realstone2 realstone2 requested a review from JunilHwang August 22, 2025 13:50
@realstone2 realstone2 self-assigned this Aug 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants