3-way 교차 검증
이날은 잠금 기능을 검증하다가 치명적인 버그를 찾은 날이었다.
기획 문서, 디자인, 코드를 서로 교차 검증했다.
그 과정에서 잠금 상태가 API 응답에서 누락되어 있었다는 걸 발견했다.
그리고 픽셀 퍼펙트까지 밀어붙였다.
검증 방법은 3-way 교차 검증이었다.
기획 문서랑 디자인, 코드를 서로 비교하는 거다.
세 가지를 따로 보면 놓치는 게 있다.
근데 서로 비교하면 어긋나는 게 드러난다.
기획 문서에는 이렇게 적혀 있고 디자인에는 이렇게 그려져 있고 코드에는 이렇게 구현되어 있다.
이 셋이 일치해야 한다.
하나라도 어긋나면 버그다.
이 검증으로 불일치 7개를 찾았다.
완료율 계산 오류, 모달 타이포그래피, 툴팁 위치, 부제목 조건 누락, 진행률 바 색상이랑 높이, 모달 닫기 버튼, 잠금 아이콘 크기. 전부 기획이나 디자인이랑 어긋나 있었다.
치명적 버그 발견
그리고 더 심각한 걸 찾았다.
잠금 상태가 화면에 전달되지 않는 문제였다.
순차 수강 잠금 필드가 커리큘럼 API에는 있었다.
근데 대시보드 API에는 빠져 있었다.
그러니까 대시보드에서는 잠금 상태를 모른다.
잠금 상태를 모르니까, “다음 강의” 버튼이 잠긴 파트로 그냥 넘어가버린다.
잠금 모달이 안 뜬다.
이건 프론트엔드 버그가 아니다.
API 응답에 필드가 없으면, 프론트엔드에서 아무리 처리해도 소용없다.
백엔드 계약의 누락이었다.
이런 버그는 프론트엔드만 보면 절대 못 잡는다.
화면이 잘못 나오는 것처럼 보이지만, 원인은 데이터에 있다.
3-way 교차 검증을 했기 때문에 찾을 수 있었다.
“잠금이 안 먹힌다”는 증상을 보고, 기획 문서의 잠금 정책이랑 코드의 API 응답을 비교하니까 필드 누락이 보였다.
픽셀 퍼펙트
불일치 7개를 두 번에 걸쳐 잡았다.
첫 번째는 구조적인 것 세 개. 모달 레이아웃, 잠금 툴팁, 진행률 바.
이건 기능이 안 되거나 크게 어긋나는 것들이었다.
두 번째는 픽셀 퍼펙트 패스였다.
폰트 굵기, 줄 높이, 자간, 패딩, 마진, 간격, 색상까지 전부 디자인 토큰에 맞췄다.
그리고 화면을 캡처해서 디자인이랑 나란히 놓고 비교했다.
마지막으로 Playwright로 픽셀 단위 비교를 돌려서 불일치가 0개가 될 때까지 다듬었다.
테스트 데이터 세팅
테스트하려면 잠금 상태를 재현할 수 있어야 한다.
그래서 테스트 데이터베이스에 잠금 필드를 심었다.
완전 잠금, 부분 잠금, 임계값 초과 같은 시나리오를 만들 수 있게 했다.
테스트 데이터가 없으면 잠금 상태를 확인할 수 없다.
어떤 상태에서 어떻게 보여야 하는지 검증하려면, 그 상태를 만들 수 있어야 한다.
깃 하위 정리
잠금 작업 외에 깃 정리도 했다.
타입스크립트 컴파일 결과물이 깃에 잡히고 있었다.
원인은 설정 불일치였다.
컴파일 출력 디렉토리 설정이 깃이그노어랑 맞지 않았다.
그래서 컴파일 결과물이 소스 트리 안에 생기고, 깃이 그걸 추적하고 있었다.
깃이그노어에 컴파일 결과물 패턴을 추가하고, 이미 커밋된 결과물을 깃에서 추적 해제했다.
그러니까 작업 트리가 깨끗해졌다.
추적되지 않은 파일이 0개가 됐다.
이 정리는 다음 날로 이어진다. 다음 날에 타입스크립트 결과물 290개를 더 쓸어냈다.
설정 불일치로 쌓인 결과물이 그만큼 있었던 거다.
마무리
3-way 교차 검증이 이날의 핵심이었다.
기획이랑 디자인, 코드를 서로 비교하니까 혼자서는 안 보이는 버그가 보였다.
특히 API 필드 누락은, 프론트엔드만 보면 절대 못 잡는다.
기획 문서의 잠금 정책이랑 API 응답을 비교해야 보인다.
3-way 검증이 왜 효과적인가. 하나만 보면 “이게 맞나?”를 못 한다.
기준이 하나면 검증이 안 된다.
근데 세 가지를 비교하면, 어긋나는 게 명확히 드러난다.
기획은 A라고 하는데 디자인은 B고 코드는 C다.
그러면 셋 중 하나가 틀린 거다.
이렇게 교차해서 보는 게 가장 확실한 검증 방법이다.
그리고 픽셀 퍼펙트도 같은 맥락이다.
디자인이 기준이다.
화면을 캡처해서 디자인이랑 비교한다.
불일치가 0개가 될 때까지 다듬는다.
“대충 비슷하다”가 아니라, 픽셀이 정확히 일치할 때까지 간다.