
일단 죄송합니다, 다들.
이번 주 과제를 전혀 하지 못했다. 사실 이유는 간단한데, 바빴다. 이런저런 일이 있어서 목요일 저녁에 1일의 전사 한다고 밤샘까지 했는데.. 난이도 조절 실패로 그냥 PR도 작성하지 못한 사람이 되었다.
하지만 뭐 어쩌겠나. 이미 시간은 흘러간걸. 그래도 회고는 써야 하기 때문에 감히 ㅋㅋ 작성한다.
이번 주차부터 오프 코치님의 테스트 코드 작성인데, 살면서 테스트 코드니 TDD니 들어 본 적만 있지 실제로 작성한 건 처음이라, 기대가 조금 되었던 주차이기도 하고,
챕터 1에서 준일 코치님께서 과제 진행을 위해 테스트 코드랑 e2e 코드를 작성하셔서, 자세히 들여다 보지는 않았지만 이런 식으로 흘러가는구나는 이미 깨달은 상태였다.
하지만..
잘 작동했던 것, 효과가 있었던 것, 계속 유지하고 싶은 습관이나 방식
난이도가 총 세 개였는데, 테스트 코드를 처음 작성해 보는 사람은 이지 모드를, 이지 모드를 작성하고 좀 괜찮으면 미디움이나 하드 난이도를 하면 되는데, 우선 이지 모드는 과제 자체가 통과가 되지 않는다. 그리고 미디움은 BP를 받을 수가 없다. 그래서 하드를 선택했는데, 내가 왜 그랬는지 모르겠다.
하드 난이도에서는 handlers.ts를 직접 구현해야 하는데, handlers.ts는 MSW 관련 코드를 작성하는 것이다. MSW? 처음 들었다. ㅜㅜ
그래서 과제를 진행하기 전(이미 진행한 팀원이 있음에도 불구하고), 페어 팀 노션에 MSW와 관련해서 페이지를 하나 작성했다.

아래는 전문이다. 틀린 내용 있으면 말해 달라고 부탁을 했지만 아직까지는 안 썼다. 나 꽤 잘 쓴 걸지도?!
Mock Service Worker라는 라이브러리예요. API 호출을 가짜로 만들어 주는 라이브러리입니다. 테스트 진행 시 진짜로 API를 호출할 수 없으니 그냥 가짜로 호출하는 거예요.
easy 브랜치에 있는 handlers.ts를 봅시다. (이지 브랜치에서 핸들러는 이미 구현되어 있어요)
http.get('/api/events', () => {
return HttpResponse.json({ events });
}),
http 와 HttpResponse ? 처음 들어 보는 단어예요.
http 는 HTTP 메서드(get, post, put, delete)를 모킹하는(가짜로 만드는) 함수,HttpResponse 는 가짜 응답을 만드는 클래스예요.http와 HttpResponse를 알고 다시 코드 블록을 보니 무슨 동작을 하는 함수인지 이해되시죠?
http 함수로 /api/events API를 가짜로 처리합니다. 그러면 응답값이 있을 거예요. 그 응답값을 HttpResponse.json으로 events 객체를 리턴합니다.
브라우저 → fetch(’/api/events’) → MSW가 홀랑 가로챔 → 가짜 응답 반환
http.post('/api/events', async ({ request }) => {
const newEvent = (await request.json()) as Event;
newEvent.id = String(events.length + 1);
return HttpResponse.json(newEvent, { status: 201 });
})
이번에는 get이 아닌 post네요. 이벤트 생성 (가짜) 함수예요.
POST는 아래와 같은 코드로 요청을 보냅니다.
fetch('/api/events', {
method: 'POST',
body: JSON.stringify({ title: '뚜민이 응원하기', date: '2025-08-19' })
})
그러면 request에는 이런 정보들이 담겨졌을 거예요.
{
method: 'POST',
url: '/api/events',
headers: { ... },
body: "{ title: '뚜민이 응원하기', date: '2025-08-19' }"
}
그러면 newEvent 는 누군가가 새로 생성한 일정 정보가 담겼겠죠?
그리고 newEvent에 임의의 id를 생성합니다. → 201 상태로 생성 성공!
handlers.ts에 있는 http 함수들은 모든 테스트에 기본적으로 깔려 있는 MSW예요. 그런데 테스트를 하다 보면 다른 상황에서의 API 호출 (가짜지만)도 필요할 순간이 올 수 있어요. 그때! server.use를 사용합니다.
즉, server.use는 handlers.ts에 적혀 있는 MSW를 덮어 씌우는 역할을 해요. 그리고 특정 상황에서만 사용되니, export를 한 거고요.
확실히 배운 걸 정리하고, 피드백을 초조해하면서 공유를 하니 나름의 학습 효과로 handlers.ts부터 작성했다. 무슨 자신감인지는 아직까지도 잘 모르겠다.
export const handlers = [
http.get('/api/events', () => {
// 조회
// status 값을 생략하면 명시적으로 200
return HttpResponse.json({ events });
}),
http.post('/api/events', async ({ request }) => {
// 생성
try {
const newEvents = (await request.json()) as Event;
newEvents.id = String(events.length + 1); // id 타입이 string
events.push(newEvents);
return HttpResponse.json({ newEvents }, { status: 201 });
} catch (err) {
return HttpResponse.json({ error: '이벤트 생성에 실패했습니다.' }, { status: 400 });
}
}),
http.put('/api/events/:id', async ({ params, request }) => {
// 업데이트
const { id } = params;
const updateEvent = (await request.json()) as Event;
const index = events.findIndex((event) => event.id === id); // 업데이트할 이벤트 찾기
if (index !== -1) {
// 수정하고자 하는 이벤트가 (findIndex로) 잘 찾아졌으면
events[index] = { ...events[index], ...updateEvent };
return HttpResponse.json({ ...events[index], ...updateEvent }, { status: 200 });
}
// 수정하고자 하는 이벤트가 없으면
return HttpResponse.json(null, { status: 404 });
}),
http.delete('/api/events/:id', ({ params }) => {
// 삭제
const { id } = params;
const index = events.findIndex((event) => event.id === id); // 삭제할 이벤트 찾기
if (index !== -1) {
// 삭제하고자 하는 이벤트가 잘 찾아졌으면
events.splice(index, 1);
return HttpResponse.json(null, { status: 204 });
}
// 삭제하고자 하는 이벤트가 없으면
return HttpResponse.json(null, { status: 404 });
}),
];
어려웠던 점, 막혔던 부분, 아쉬웠던 점
그리고 handlers.ts를 작성하면서 고민이 생겼다. PR을 작성하지 못해서, 이 부분은 이 글을 보는 누군가가 알려 줬으면 한다........................ 단골 손님 정석 님, 찬규 님, 창준 님, 유진 님 모십니다.

events 데이터를 한 번 더 new Map으로 감싸면 더 좋을 것 같은데.. 누가 좀 알려 주세요..
다음 주에 시도해 보고 싶은 것, 개선하고 싶은 점, 새로운 도전
벌써 8주차다. 쓰읍. 시간 생각보다 빨리 가는 것 같다. 아무튼 다음 주 주차는 거의 팀전이라고 봐도 무방할 정도 같은데, 다음 주에도 시간..을 못 쓸 것 같아서 걱정된다.
그래도 페어 코딩으로라도 (리딩은 못 하겠지만?!) 팀원들이랑 같이 과제 해결해 나가고 싶다.
단골 손님 왔읍니다... 답변은 .. 음... 테스트 데이터를 조금 복잡한 구조로 바꾼다는 생각이 듭니다... 그리고 데이터 수도 적을 거 같아서 저는 불필요하다고 생각해요. 그리고 "콩"