이번 과제를 진행하면서 "왜 이런 설정들이 필요한가?"라는 근본적인 질문부터 시작했다.
Mock에 대한 고민과 깨달음
처음에는 "왜 실제 함수를 쓰지 않고 가짜를 만드는거지?"라는 의문이 들었다. 하지만 실제로 사용해보니:
toastFn
: 실제 토스트를 표시하면 테스트 환경에서 UI가 복잡해지고, 정작 확인하고 싶은 건 "호출되었는지"이지 "실제 토스트가 보이는지"가 아니라는걸 깨달았다enqueueSnackbarFn
: 함수 호출을 추적하고 기록하는 것만으로도 충분히 기능을 검증할 수 있다는 점notistack mock
: 실제 라이브러리 의존성 없이도 테스트가 가능하다는 것이 얼마나 큰 장점인지 체감했다Provider 사용에 대한 의문과 해답
통합 테스트에서 ChakraProvider
로 컴포넌트를 감싸는 부분을 보고 "이게 정말 의미가 있을까?"라고 의문을 가졌다. 하지만 실제로는:
ThemeProvider
, SnackbarProvider
, CssBaseline
등이 단순한 스타일링이 아니라 컴포넌트의 핵심 기능 작동에 필요하다는걸 알게 되었다handlersUtils 활용에서 느낀 효율성
각 이벤트 생성/수정/삭제를 위한 mock API 설정을 보면서 "이미 짜여져 있는 함수를 가져다 쓰는거였지만 미디움에서 편리하게 사용했다"고 생각했다. 실제 API 호출은 너무 많은 리소스를 사용한다고 생각이 들었고, 가짜 서버와 데이터를 만들어 사용하는 것이 얼마나 효율적인지 몸소 체험할 수 있었다.
시간 고정에 대한 이해
vi.setSystemTime
을 보고 "왜 이 시간을 설정해주는 걸까?"라는 궁금증에서 시작했다. 고정된 시간 설정이 날짜/시간 의존 로직의 예측 가능성과 재현성을 보장한다는걸 이해하고 나니, 테스트의 안정성이 얼마나 중요한지 깨달았다.
act
와 waitFor
를 처음 접했을 때 "언제 뭘 써야 하는거지?"라는 혼란이 컸다.
초기 고민들
실제 경험을 통한 깨달음
act
는 동기/비동기 모두 사용 가능하며, React의 상태 업데이트를 즉시 처리한다는걸 체험했다waitFor
은 항상 비동기이며, 실제 시간이 흘러야 하는 상황에서 사용한다는걸 이해했다// 동기 act - "이거 정말 즉시 처리되나?" 의심하며 사용했는데 실제로 즉시 처리됨!
act(() => {
vi.advanceTimersByTime(1000);
});
// waitFor - "정말 2초를 기다려야 하나?" 걱정했는데 필요한 경우였음
await waitFor(() => {
expect(screen.getByText('1초 지남')).toBeInTheDocument();
}, { timeout: 2000 });
두 가지 데이터 로딩 방식을 보고 "어떤게 더 좋은 방법일까?"라는 고민이 들었다.
1번 방법에 대한 의문
await act(async () => {
await new Promise((resolve) => setTimeout(resolve, 0));
});
"이게 왜 작동하는거지? setTimeout을 0으로 설정하는게 무슨 의미가 있을까?"라는 의문에서 시작했다.
2번 방법의 명확성
await act(async () => {
await result.current.fetchEvents();
});
"이게 더 직관적이고 명확한 것 같은데, 2번 방법을 택한게 맞을까?"라고 고민했다.
코치님 피드백을 통한 이해
몇 시간 동안 MUI Icons 모킹 문제로 삽질했던 경험이 가장 큰 깨달음을 줬다. AI에게 계속 에러를 고쳐달라고 했지만, 답이 수렴되지 않고 오히려 더 복잡해지기만 했다.
결국 직접 구글링해서 찾은 해결책은 단순했다:
// 기존
import { LocationCity } from "@mui/icons-material";
// 수정
import LocationCity from "@mui/icons-material/LocationCity";
코치님의 팁처럼, AI를 사용했을 때 답이 수렴되지 않는다면 AI가 방향성을 제대로 짚지 못한 징조로 받아들이고, 직접 문제 해결에 나서야 한다는 것을 체감했다.
코치님의 피드백을 통해 테스트 코드 작성의 기준을 명확히 할 수 있었다:
경계값 테스트의 경우, 달력 Form을 사용한다면 큰 문제가 없을 수 있지만, 코드로 입력하는 엑셀 같은 환경이라면 반드시 검증해야 한다는 관점이 인상적이었다.
처음엔 막막했던 통합 테스트가 오히려 단위 테스트보다 재미있었다. 상태를 기반으로 기획서와 코딩을 맞춰가는 과정에서 전체적인 플로우를 이해할 수 있었고, 실제 사용자 관점에서 기능을 검증하는 느낌이 들었다.
git reset --hard HEAD~1
명령어로 커밋하지 않은 파일들이 모두 날아간 경험... 정말 뼈아픈 교훈이었다. 스테이징에 올려두지 않은 것이 화근이었지만, 덕분에 git 명령어의 위험성과 중요성을 체감할 수 있었다.
이번 과제는 단순히 테스트 코드 작성법을 배우는 것을 넘어서, 문제 해결 접근법, 도구 사용의 균형, 그리고 실패로부터 배우는 것의 중요성을 깨닫게 해준 의미있는 경험이었다.
"내가 웃는게 웃는게 아니야.. ㅠ"라고 해주신 코치님의 따뜻한 피드백처럼, 실패와 삽질의 경험도 결국 성장의 밑거름이 된다는 것을 느꼈다. 테스트 코드에 대한 심리적 장벽은 확실히 허물어졌고, 다음 과제에서는 더 체계적이고 효율적인 접근을 해보고 싶다.
화이팅입니다!