테스트 코드 정리
1. SSR에서 테스트 코드 의미 있나?
REST API(CSR) 방식과 비교하면 가성비가 떨어지는 건 사실이다.
| 구분 | REST API (CSR) | SSR (Thymeleaf) |
|---|---|---|
| 응답 데이터 | JSON (구조화된 데이터) | HTML (거대한 문자열) |
| 검증 편의성 | 특정 필드 값만 딱 집어서 확인 가능 | HTML 태그 안을 찾아야 함 |
| 검증 대상 | 데이터 정확성, HTTP 상태 코드 | Model 객체, 뷰 이름, 렌더링 텍스트 |
2. SSR 테스트가 불편한 이유
- JSON은
$.name == 'James'처럼 명확하게 검증 가능 - SSR은
body().string(containsString("James"))→ HTML 문자열 검색 - 디자인이 바뀌어 태그 구조만 변경돼도 테스트가 깨질 수 있음
- 서버 테스트인데 HTML/CSS/JS가 섞여 있어 순수 비즈니스 로직 검증이 번거로움
3. SSR에서 테스트한다면 무엇을 검증하나?
HTML 내용 전체를 뜯어보는 테스트는 가성비가 낮다.
대신 아래 3가지만 확인하는 것이 효율적이다.
| 검증 대상 | 설명 |
|---|---|
| View Name | 정확히 community/list.html 로 보내주는가? |
| Model Attributes | 화면에 그려줄 데이터가 Model에 제대로 담겼는가? ← 가장 중요 |
| Redirection | 로그인 성공 후 메인 페이지로 리다이렉트 되는가? |
// SSR 방식의 전형적인 MockMvc 테스트
mockMvc.perform(get("/community/1"))
.andExpect(status().isOk())
.andExpect(view().name("community/detail")) // 뷰 이름 확인
.andExpect(model().attributeExists("community")) // 데이터 담겼는지 확인
.andExpect(model().attributeExists("comments")); // 댓글 담겼는지 확인
4. 실무에서 쓰는 전략
| 계층 | REST API | SSR |
|---|---|---|
| Service / Repository | 단위 테스트 빡빡하게 | 단위 테스트 빡빡하게 (동일) |
| Controller | JSON 응답값 검증 위주로 꼼꼼하게 | 중요한 리다이렉션, Model 데이터 정도만 가볍게 |
핵심: Service/Repository 단위 테스트를 잘 짜두면
“데이터는 문제없다” 를 확신하고 화면(HTML) 수정에만 집중할 수 있다.
5. 결론
- SSR에서 HTML 응답 전체를 검증하는 테스트 → 가성비 낮음, 굳이 X
-
Controller가 Model에 데이터를 제대로 담는지 → 가볍게 확인
- CSR에서는 API별 응답이 잘 오면 전체 로직이 잘 돌아간다고 확신할 수 있음. 그래서 테스트코드 굳(통합테스트). 결국엔 SSR은 테스트코드 굳이??
6. CSR 프로젝트에서의 테스트 전략 (이 프로젝트 기준)
이 프로젝트는 CSR (REST API) 방식이므로, API 응답 JSON을 검증하는 테스트가 효과적
service, repository, controller 단위테스트도 좋지만 너무 힘듦. API 요청했을 때 원하는 결과가 오는지 안 오는지 통합테스트로만 해도 충분
테스트코드 정리 (강의용)
1) 이 프로젝트에서 테스트를 왜 하는가
- 기능이 동작하는지 “눈으로만” 확인하면 놓치는 경우가 많다.
- API 계약(상태코드, JSON 구조, 인증 필요 여부)을 자동으로 검증해야 유지보수가 쉬워진다.
- 리팩터링(코드 정리)할 때 기존 동작이 깨졌는지 빠르게 확인할 수 있다.
2) 단위테스트 vs 통합테스트 (이 강의의 선택)
- 단위테스트: 메서드/클래스 단위로 아주 작게 검증.
- 통합테스트: 실제 스프링 컨텍스트 + DB + 보안 필터까지 포함해서 API 호출 흐름을 검증.
이 강의 프로젝트는 CSR + REST API 중심이므로,
단위테스트를 많이 쪼개기보다 API 통합테스트를 우선으로 가져간다.
3) TDD를 아주 간단히 이해하기
TDD 사이클은 3단계만 기억하면 된다.
- Red: 실패하는 테스트를 먼저 작성한다.
- Green: 테스트를 통과시키는 최소 코드만 작성한다.
- Refactor: 중복 제거/가독성 개선을 한다(테스트는 계속 통과).
핵심은 “완벽한 설계 먼저”가 아니라
작은 테스트 -> 작은 구현 -> 정리를 반복하는 것이다.
4) 이 프로젝트에서의 실전 적용 방식
/api/**엔드포인트를 기준으로 테스트를 묶는다.- 각 API는 최소한 아래를 검증한다.
- 성공 상태코드 (
200,201) - 실패 상태코드 (
401,400,404등) - 응답 JSON 필드 (
success,data,message) - 인증이 필요한 API는 토큰 없을 때 실패하는지
- 성공 상태코드 (
- 생성 API는 가능하면
Location헤더까지 확인한다.
5) 추천 테스트 작성 순서 (강의 실습용)
- 인증 API (
/api/login,/api/users/me, 토큰 재발급) - 커뮤니티 API (목록/상세/생성/수정/삭제)
- 댓글 API (목록/생성/수정/삭제)
- 파일 API (업로드/조회/다운로드/삭제)
- 채팅방 REST API (목록/상세/생성)
6) 테스트 코드 작성 팁
- 테스트 이름은 “무엇을 보장하는지”가 보이게 쓴다.
- 예:
communities_create_update_delete_work
- 예:
Given-When-Then흐름으로 읽히게 작성한다.- 하나의 테스트에서 검증 포인트를 너무 많이 넣지 않는다.
- 테스트 데이터는 재사용하되, 충돌 가능 값(username 등)은 랜덤값을 섞는다.
7) 강의용 한 줄 결론
이 프로젝트에서는
“단위테스트를 깊게 파기”보다 “API 통합테스트로 실제 사용자 흐름을 보장”하는 전략이 더 효율적이다.