카카오엔터테인먼트 스토리 FE팀이 시각적 회귀 테스트 도구 BackstopJS를 도입하고 6개월간 운영한 후기다. 실제 서비스 페이지 대신 스토리북 빌드 결과물을 대상으로 삼고, Atomic 디자인의 Organism 단위로만 테스트를 만들었다. 스토리북 7 업그레이드로 전체 테스트가 실패한 사고와 PR·머지 자동화까지 이어진다.
핵심 포인트- 서비스 페이지는 기획·디자인 변경으로 자주 바뀌므로 스토리북 빌드 결과물을 테스트 대상으로 삼았다.
- Atom은 잘 안 바뀌고 기획 변경으로 UI가 크게 바뀌는 단위는 Organism부터라 Organism만 테스트한다.
- 날짜 포맷 공통 함수를 고쳤다가 의도치 않게 깨진 다른 컴포넌트를 push 시점에 잡아냈다.
- 스토리북 7은 file URL 로딩을 더 이상 지원하지 않아 도커 안에서 http 서버를 띄우는 방식으로 바꿔야 했다.
- PR 봇과 젠킨스로 성공·실패 개수와 리포트 링크를 PR 코멘트에 자동으로 남긴다.
- develop에 머지되면 젠킨스가 reference 이미지를 교체하고 backstop approve 커밋을 자동으로 푸시한다.
상세 정리- 동작 방식: 설정 파일의 url로 헤드리스 브라우저를 직접 띄워 스크린샷을 찍고 비교하므로 서비스 페이지 단위 테스트도 가능하다.
- 대상 선택 이유: 서비스 페이지는 자주 바뀌어 기준 이미지가 계속 흔들리므로 스토리북 빌드 결과물 위에 테스트를 세웠다.
- 단위 선택 이유: button이나 input 같은 atom은 변경이 적고, 기획이 바뀌며 UI가 크게 달라지는 지점은 여러 컴포넌트를 품은 organism부터라고 판단했다.
- 시나리오 관리: backstop.json에 직접 쓰던 설정이 시나리오 증가로 감당이 안 돼, 목록을 만들어 반환하는 별도 파일을 두고 backstop 설정에서 불러 쓴다.
- 시나리오 형태: 스토리북 iframe url과 label을 넘기고 delay 500ms, misMatchThreshold 0, requireSameDimensions true 같은 공통 설정을 붙인다.
- 사이드이펙트 탐지 사례: 공지사항 날짜 표기만 바꾸려고 공통 포맷 함수를 고쳤는데, 같은 함수를 쓰던 다른 컴포넌트들이 push 시점 테스트에서 실패로 잡혔다.
- 문서 유지 효과: 스토리북이 깨지면 에러 화면 자체가 스크린샷으로 잡혀 테스트가 실패하므로 스토리북이 방치되거나 갱신되지 않는 상황도 막는다.
- 케이스 문서화: 배너 하나를 PC 반응형, PC 상단, 모바일 상단, 폴더블 상단 등 케이스별 스토리로 나눠 각각 시나리오를 만들면 뷰포트별 상태가 그대로 문서가 된다.
- 업그레이드 사고: 패키지 일괄 업데이트로 스토리북을 6에서 7로 올리자 테스트가 전혀 뜨지 않고 전부 실패로 처리됐다.
- 원인: 7버전 릴리스 노트에 file URL 지원 중단이 적혀 있었다. ESM이 HTTP 로딩을 요구하는데 file 스킴은 브라우저 CORS 설정과 충돌하기 때문이다.
- 기존 구조: 스토리북 빌드 산출물 디렉터리를 도커에 복사하고 컨테이너 내부 파일시스템 경로로 접근해 테스트했다.
- 수정: 도커 내부에서 http 서버를 띄우고 시나리오 url을 로컬 주소와 포트 기준으로 바꿨다.
- 자동화 1: 테스트 결과물이 담긴 폴더를 도커가 http-server로 노출하고, PR 봇과 젠킨스가 성공·실패 개수와 스토리북·리포트 링크를 PR 코멘트로 단다.
- 자동화 2: develop에 push되면 젠킨스가 도커 이미지를 받아 결과물을 꺼내고, 최신 테스트 비트맵으로 reference를 교체한 뒤 실패 diff와 report.json을 지우고 backstop approve 커밋을 푸시한다.
- 자동화의 효과: 의도적으로 바꾼 UI 때문에 기준 이미지와 달라져 실패하던 테스트가 머지 후 자동으로 갱신된다.
- 계속 쓰는 이유: 문서화는 유지보수가 어려운데, 시나리오를 추가하다 보면 스토리북 자체가 문서가 되고 그 문서가 깨지지 않도록 테스트가 지켜준다는 점을 든다.
왜 읽나스토리북은 있는데 회귀 테스트가 없어 리팩터링이 불안하다면 Organism 단위 시나리오 구성과 approve 자동화 파이프라인을 그대로 옮겨볼 수 있다.