Medium
7주차 과제 체크포인트
기본과제
Medium
- 총 11개의 파일, 115개의 단위 테스트를 무사히 작성하고 통과시킨다.
질문
Q. medium.useEventOperations.spec.tsx > 아래 toastFn과 mock과 이 fn은 무엇을 해줄까요?
나의 생각 : expect(enqueueSnackbarFn).toHaveBeenCalledWith('일정이 추가되었습니다.', { variant: 'success' });
토스트 알림 기능을 테스트하기 위한 모킹 설정입니다. notistack 라는 라이브러리를 모킹하여 실제 토스트 대신
가짜 함수를 사용 할 수 있도록 설정합니다.
이해를 쉽게 할 수 있게 비유 설명과 함께 AI에게 물어보았고 단번에 이해 할 수 있는 답변을 받았습니다.
toastFn은 무엇을 하나요?
vi.fn(): Vitest에서 제공하는 가짜 함수를 만듭니다
이 함수는 실제로는 아무것도 하지 않지만, 언제 호출되었는지 추적할 수 있습니다
비유:
실제 토스트 = 실제 알람벨 (소리가 남)
가짜 함수 = 무음 알람벨 (소리는 안 나지만 누가 눌렀는지 기록됨)
mock은 무엇을 하나요?
vi.mock('notistack'): notistack 라이브러리를 가짜로 바꿉니다
vi.importActual('notistack'): 실제 라이브러리의 다른 기능들은 그대로 유지
enqueueSnackbar: enqueueSnackbarFn: 토스트 함수만 가짜 함수로 교체
비유:
실제 notistack = 실제 알람 시스템
가짜 notistack = 테스트용 알람 시스템 (소리는 안 나지만 기록은 됨)
Q. medium.integration.spec.tsx > 여기서 Provider로 묶어주는 동작은 의미 있을까요? 있다면 어떤 의미일까요?
// ! HINT. 이 유틸을 사용해 리액트 컴포넌트를 렌더링해보세요.
const setup = (element: ReactElement) => {
const user = userEvent.setup();
const theme = createTheme();
return {
...render(
<ThemeProvider theme={theme}>
<CssBaseline />
<SnackbarProvider>{element}</SnackbarProvider>
</ThemeProvider>
),
user,
};
};
나의 생각 : Provider로 묶어주는 것은 실제 앱 환경과 동일한 컨텍스트를 제공하기 위함이고 theme를 app에서 설정 해줘야
theme를 하위에서 다 편하게 쓸 수 있기 때문입니다.
ThemeProvider: 올바른 스타일과 테마를 적용받도록 해줍니다.
CssBaseline: 브라우저 기본 스타일 리셋, 일관된 렌더링 보장 해줍니다.
SnackbarProvider: 알림 메시지 기능(toast) 정상 동작 하도록 해줍니다.
제일 중요한 건 실제 앱과 동일한 환경에서 테스트해야 정확한 결과를 얻을 수 있습니다.
Q. handlersUtils > 아래 여러가지 use 함수(?? setup 함수 아닌가요..?)는 어떤 역할을 할까요? 어떻게 사용될 수 있을까요?
나의 생각 : setupMockHandlerCreation, setupMockHandlerDeletion, setupMockHandlerUpdation
3가지 함수를 미디움 과제에서는 제공을 해주셨고 실제 서버 없이 가짜 서버로 API 호출을 할 수 있도록 해서
반환, 생성, 삭제, 수정을 테스트 시나리오에서 테스트 할 수 있게 해주는 역할을 해 주었습니다.
그 가짜 서버로 하면 실제 서버에서 발생 할 수 있는 사이드 이펙트들이 없는 환경이라 안정적인 테스트가
가능하다고 했었습니다!
Q. setupTests.ts > 왜 이 시간을 설정해주는 걸까요?
나의 생각 : 사실 이 파일이 존재하는지도 어디서 쓰는지도 모르고 과제를 진행 했었고 중간에 어? 하면서 알게 되었습니다.
그래서 사용해야 하는 테스트인데 사용하지 않은 테스트도 존재 할 것이라 예상이 들기도 합니다.
공부를 하고 난 뒤 vite.config.ts 파일에서 이 파일을 자동으로 실행을 시켜주고 있으며 테스트 환경이 실행 될 때
이 파일이 실행되어 코드가 실행된다는 것을 알았습니다.
beforeEach(() => {
expect.hasAssertions(); // ? Med: 이걸 왜 써야하는지 물어보자
vi.setSystemTime(new Date('2025-10-01')); // ? Med: 이걸 왜 써야하는지 물어보자
});
나의 생각 : expect.hasAssertions() 함수는 테스트에서 최소 하나 이상의 검증을 필요로 하게 해주는 함수입니다.
vi.setSystemTime(new Date('2025-10-01')) 함수는 가짜 서버의 시간을 고정 시켜 일관된 시간 테스트를 할 수 있도록
해주는 함수입니다.
이 것을 과제 중에 모르고 진행을 하다가 easy.useCalendarView.spec 테스트 코드를 작성하면서
나는 지금 8월인데 어떤 코드 때문에 한 달 후가 11월 1일이고 7일 전이 9월 24일일까.. 생각도 했지만
describe에 조건으로 명시되어 있으니 통과를 하고 넘어갔다가 통합 테스트 부분에서 파악을 했습니다 ㅎㅎ..
심화 과제
- App 컴포넌트 적절한 단위의 컴포넌트, 훅, 유틸 함수로 분리했는가?
- 해당 모듈들에 대한 적절한 테스트를 5개 이상 작성했는가?
과제 셀프회고
기술적 성장
- 이번 과제를 진행하면서 테스트 작성에 대한 전반적인 기본적 이해와 코드 작성에 대한 부분을 배웠습니다. 처음 시작 할 때는 단위 테스트부터 통합 테스트 그리고 리팩토링 후 커스텀 된 내용을 테스트 코드 작성까지 막막했지만 실제로 해보니 단계별로 진행을 하는 방법 때문에 훨씬 접근하기 쉬운 느낌도 들어서 좋았습니다.
- 특히 MSW를 활용한 API 모킹을 처음 해보았는데 실제 서버 없이도 API 시나리오를 테스트할 수 있다는 것을 배웠습니다. 이전에는 사실 테스트 코드가 어떻게 작성되고 사용 되는지 조차 몰랐기에 재미있는 과제였습니다.
- 항해 시작 전 방법론 사전 스터디를 진행하면서 테스트 코드에 대해 전혀 무지한 상태에서 이론과 뭘 해야 될 지 모르는 스터디를 하다가 7팀 강병준, 1팀 이의찬 두 분의 준비로 8팀 김민지, 6팀 김수현, 2팀 박소연 그리고 저까지 총 6명이서 테스트코드 작성하는 스터디를 했었습니다. https://github.com/Legitgoons/frontend-test https://www.notion.so/teamsparta/2252dc3ef514809eb043d32348c10270?source=copy_link
- 이렇게 생각했던 제가 이번 챕터를 진행하면서 그리고 항해 챕터를 진행하면서 테스트 코드가 있다면 확실히 내가 구현한 기능에 대한 검증이 쉽고 타인에게 검증하기가 쉽겠구나 생각이 들었고 그만큼 중요하다는 것도 알게 되었습니다.
- 기술적 도전이 있기보다는 오프 코치님이 작성한 코드를 기준으로 최대한 테스트 코드를 작성하는 것을 목표로 진행하였기에 기술적 도전이나 해결보다는 배움에 집중했습니다.
- 한 주 한 주 챕터에서 원하는 지식을 다 습득하진 못 하지만 테스트 코드에 Vitest와 Jest가 있다. 그리고 이 둘은 Vitest는 Vite 환경에 최적화되어 빠르고 설정이 간편하고 Jest는 오랜 기간 검증된 범용적인 테스트 도구라는 점에 차이가 존재하지만 사용되는 코드는 거의 비슷해서 정해신 코드? 라고 해야 하나 사용 규칙도 많이 알게 되었습니다.
코드 품질
- 이번 과제에서 가장 만족스러웠던 부분은 단계별로 테스트를 작성하면서 코드의 동작을 정확히 이해할 수 있었다는 점입니다. 특히
setupTests.ts에서 시간을 고정하는 설정을 통해 일관된 테스트 환경을 구축할 수 있었고, MSW를 활용한 API 모킹으로 실제 서버 없이도 안정적인 테스트가 가능했다는 점을 알게 된 것이 만족스러운 경험이였습니다. - 리팩토링이 필요한 부분으로는 테스트 코드의 중복을 줄이고 더 체계적인 구조로 개선할 수 있을 것 같습니다. 현재는 각 테스트 파일이 독립적으로 작성되어 있어서 공통 로직이나 헬퍼 함수들을 더 효율적으로 활용할 수 있을 것 같습니다.
학습 효과 분석
- 가장 큰 배움은 테스트 작성 시 실제 환경과 테스트 환경의 차이점을 이해한 것입니다. 처음에는 단순히 함수가 올바르게 동작 하는지만 확인하면 된다고 생각했는데, 실제로는 시간 처리, Provider 설정, 비동기 처리 등 다양한 환경적 요소들을 고려해야 한다는 것을 배웠습니다.
- unit 테스트를 지나 hooks easy 테스트를 작성하고 medium 파일로 넘어 왔을 때 medium 에서는 api를 사용하니까 데이터를 response 파일에서 가져와서 써야 하는 줄 알았는데 그렇게 하면 문제가 있었습니다. events.json, realEvent.json 파일은 실제 handlers에서 쓰는 데이터(DB)이기 때문에 테스트 환경에서 쓰면 문제가 생길 여부가 큰데 어떤 문제가 생기냐면 테스트 환경에서 데이터를 생성, 수정하면 실제 DB에도 추가되기 때문에 테스트 결과가 예상과 다르게 나올 수 있습니다.
- 추가로 학습이 필요한 부분으로는 전반적인 테스트 코드의 이론부터 봐야 하는 것이 사실이고 많은 것을 모르는 상태이다 보니 과제 진행하면서 휘발 되고 정확한 이해를 못 하는 부분들이 많았기도 해서 React Testing Library를 사용해서 컴포넌트와 훅을 테스트하는 방법은 다시 학습이 필요하다고 느꼈습니다.
- 테스트 코드가 describe에 따라 통과가 된다고 사실 진짜 통과가 된 것인지 아닌지 확인하는 것도 검증 해야 하는 것을 알게 되어 통과 처리가 되었지만 사실은 문제가 있는 코드들도 다시 파악을 해보는 시간을 가져야 합니다.
과제 피드백
- 과제에서 좋았던 부분은 단계별로 난이도가 올라가는 구조였습니다. Easy부터 시작해서 Medium으로 넘어가는 과정이 접근, 코딩하기 좋았고, 각 단계마다 새로운 개념을 배울 수 있어서 학습 효과가 컸습니다.
리뷰 받고 싶은 내용
궁금한 점
- 실제 현업에서의 테스트 전략이 궁금한데 제가 회사에서 다루고 있는 솔루션의 볼륨과 코드 로직을 보여드리면서 어떤 방식으로 테스트를 작성하고 관리 할 수 있는지 물어보면 너무 좋겠는데... PR쓰는 지금 회사 gitLab에 외부망이라 접근이 불가능 하는지 궁금합니다.
과제를 수행하면서 느낀점
과제 시작 전 생각
- 과제 시작 전에는 테스트 코드 작성이 매우 어렵고 복잡할 것이라고 생각했습니다. 특히 "왜 테스트를 작성해야 하는가?"라는 근본적인 질문에 대한 답을 찾지 못하고 있었고 실제 개발에서는 기능 구현에만 집중하면 되지 않나라는 생각도 했습니다.
- 테스트 프레임워크들의 차이점(Vitest vs Jest)이나 MSW 같은 도구들에 대한 이해가 부족해서 과제를 시작하기 전까지는 막막한 마음이 컸습니다.
과제 제출 후 생각
- 과제를 완료한 후에는 테스트 코드의 중요성과 필요성을 이해하게 되었습니다. 특히 "테스트가 있는 코드는 안전하고 반격(?)의 무기가 될 수 있다"라는 말의 의미를 체감할 수 있었고, 실제로 테스트를 작성하면서 코드의 동작을 더 정확히 이해할 수 있었습니다.
- 단계별 학습의 중요성도 깨달았습니다. Easy부터 시작해서 Medium으로 넘어가는 과정에서 기초를 다질 수 있었고, 각 단계마다 새로운 개념을 자연스럽게 습득할 수 있었습니다.
- 가장 큰 변화는 개발자로서의 마인드셋 변화입니다. 이제는 새로운 기능을 구현할 때 "이 기능을 어떻게 테스트할 수 있을까?"라는 생각을 자연스럽게 하게 되었고, 코드의 품질과 안정성에 대한 관심이 높아졌습니다.
기타
과제 난이도
medium 기준 4점/5점
- 단계별로 잘 구성되어 있어서 접근하기 어려운 난이도는 아니었습니다. 다만 테스트 코드 작성에 대한 사전 지식이 부족했던 상태에서 시작했기 때문에 초기에는 어려움이 있었습니다.
- 특히 MSW 설정과 API 모킹 부분에서 처음에는 복잡하게 느껴졌지만, 실제로 사용 되는 코드를 알게 되면서 점차 이해할 수 있었습니다. 하지만 아직 직접 구현 하라고 하면 못 할 것 같긴 합니다.
- 전체적으로는 적절한 난이도였고, 충분한 성취감을 느낄 수 있는 과제였다고 생각합니다.!! ( 다만 개인적인 역량과 투자 가능한 시간에 따라 느껴지는 부분은 차이가 있을 것 같아요.. ㅎ)
과제 피드백
수고했습니다. 이번 과제는 테스트를 하는 다양한 방법들을 접하면서 테스트 코드를 작성한다라는 그 심리적 장벽을 허물로 친숙해지는데 있었습니다. 회고를 보아하니 잘 수행해준 것 같아요.
"단계별로 진행을 하는 방법 때문에 훨씬 접근하기 쉬운 느낌도 들어서 좋았습니다." 다행이네요. 과제의 양에 대해서 압박을 느끼는 경우가 많은데 차근 차근 잘 따라와줬네요
"내가 구현한 기능에 대한 검증이 쉽고 타인에게 검증하기가 쉽겠구나 생각이 들었고 그만큼 중요하다는 것도 알게 되었습니다." 맞아요. 테스트 코드는 분명 작성하는데 허들도 있고 에너지가 있지만 또 그만큼의 가치는 만들어주죠.
Q) 실제 현업에서의 테스트 전략이 궁금한데 제가 회사에서 다루고 있는 솔루션의 볼륨과 코드 로직을 보여드리면서 어떤 방식으로 테스트를 작성하고 관리 할 수 있는지 물어보면 너무 좋겠는데... PR쓰는 지금 회사 gitLab에 외부망이라 접근이 불가능 하는지 궁금합니다.
=> "리팩토링이 필요한 부분으로는 테스트 코드의 중복을 줄이고 더 체계적인 구조로 개선할 수 있을 것 같습니다. 현재는 각 테스트 파일이 독립적으로 작성되어 있어서 공통 로직이나 헬퍼 함수들을 더 효율적으로 활용할 수 있을 것 같습니다."
=> 우선은 테스트 코드를 테스트의 목적을 벗어나 그냥 한번 작성해보려고 해보세요. 테스트 코드를 작성하기 쉬운 코드는 좋은 코드라는 명제에 따라서 테스트 코드를 만드려고 하는 시도를 하는 과정에서 자연스럽게 리팩토링을 하면 좋을 부분들이 보입니다. 우선 그렇게 조금씩 코드를 개선해 나가보세요. 그렇게 조금씩 테스트 코드를 쌓아 나가는 식으로 해보면 좋습니다.
=> 리팩토링이 어느 정도 진행이 되면서 디버깅을 해야할 때, console.log를 찍어야 한다거나 변경한 기능이나 구현한 기능을 확인하기 위해서 손으로 눈으로 확인을 한다고 느껴지면 한번 테스트 코드로도 만들어 보세요. 우선적으로 해야할 일은 '귀찮다. 어렵다' 하는 심리적 허들을 낮추는 것이니까요. 잘 만든 테스트 코드가 있어야 한다가 아니라 일단 하나라도 만들어 보자 정도로 써먹어 보기를 바래요.
"가장 큰 변화는 개발자로서의 마인드셋 변화입니다. 이제는 새로운 기능을 구현할 때 "이 기능을 어떻게 테스트할 수 있을까?"라는 생각을 자연스럽게 하게 되었고, 코드의 품질과 안정성에 대한 관심이 높아졌습니다." 아주 훌륭한 변화였습니다. 이 마음이 실무까지 이어져 꼭 하나라도 만들어 보면서 관점이 바뀌었다는 것을 스스로 확인해보길 바래요. 수고하셨습니다.