
안녕하세요! 원티드랩 QA팀 김명관입니다. 전에 공유드린 파파라치를 개선하는 과정에서 파이썬으로 이미지를 다루는 모듈 중에 opencv2라는 모듈도 있다는 사실을 알게 되었고 이 모듈을 사용해 미리 찍어둔 웹 페이지와 현재 상태의 유사도를 비교하고, 어디가 어떻게 달라졌는지 표시할 수 있는 스크립트를 만들게 되었습니다.

네이밍에 재미가 들려서인지 이번엔 숨은그림찾기 계의 대명사 같은 게임인 “히든캐치” 라는 이름을 짓게 되었습니다. opencv2를 이용해 전체 웹 페이지의 UI 상태를 한방에 점검할 수 있는 “히든캐치” 스크립트를 만들어본 과정을 공유해 드리겠습니다!

시작
히든캐치의 시작은 파파라치를 개선하는 작업이었습니다. 점검이 필요한 UI 요소를 스크린샷으로 따두고 Selenium으로 해당 페이지에 접속해 해당 요소가 렌더링 까지 모두 정상적으로 완료 되었는지 스크린샷으로 확인하도록 개선하고 있었어요.
스크립트를 작성하는 중 문득 들었던 생각이 있었습니다.
‘필요한 요소를 모두 스크린샷 따는게 과연 맞을까? 60개에 달하는 주요 페이지의 요소들을 수십, 수백 장 따놓고 변경 사항이 생기면 한 장 한 장 새로운 이미지로 교체하는 방식은 너무 손이 많이 가지 않나?’
이런 생각이 들며 파파라치의 방식과는 달리 화면에 표시되는 전체 웹 페이지를 통째로 비교할 수는 없는지 궁금해졌고 파이썬으로 이미지 유사도를 측정하는 방법을 조사하게 되었습니다.
요구사항
제 스스로 원한 기능들은 이랬습니다.
- 원하는 웹 페이지에 접속할 수 있어야 한다.
- 웹 페이지의 원본 사진과 비교용 사진을 촬영할 수 있어야 한다.
- 원본 사진과 비교용 사진을 서로 비교한다.
- 비교 결과 유사도를 측정해서 알려준다.
- 원본과 비교본이 다르다면 어디가 다른지 표시해준다.
이런 조건을 만족하는 방법을 찾기 시작했고, 오래 걸리지 않아 opencv2 라는 모듈에서 제가 원하는 기능을 모두 제공한다는 것을 알게 되었습니다.
구현하기
Selenium으로 웹 페이지에 접속해 전체화면을 한 번에 찍고싶었습니다. 브라우저를 띄우고 브라우저의 스크롤 최대 길이를 반환받아 세로 길이로 지정했습니다.
하지만 브라우저의 높이는 스크롤 길이만큼 길어졌으나 스크린샷을 찍으면 모니터에 표시되는 영역까지만 찍히게 된다는 것을 알게 되었습니다.
구글링을 통해 Headless 모드로 Selenium을 실행하여 전체 웹 페이지의 스크린샷을 찍도록 해결할 수 있었습니다. 이렇게 원본 웹 페이지의 사진이 없다면 원본용으로 쓰일 사진도 자동으로 찍도록 구현했고, 이어서 비교용 사진도 같은 영역을 촬영합니다.
이미지 비교하기
원본과 비교용 이미지를 비교하는 과정은 처음엔 바로 이해가 가진 않았습니다. 간단하게 요약하자면
원본 이미지와 비교용 이미지를 회색조 처리한다.

- 회색조 처리한 이미지는 음영 정보만 남게되고 이 상태로 이미지의 픽셀 정보를 unit8 데이터로 변환하여 달라진 부분을 찾는다.
- 달라진 부분을 표시하기 위해 비교한 이미지 결과를 흑백 상태로 변환한다.
- 흑백 상태에서 달라진 부분으로 포착된 영역의 값을 저장한다.
- unit8 데이터에서 찾은 달라진 영역의 퍼센티지를 계산한다.
- 검사 결과를 원본 사진에 그린다.
- 원본과 비교본을 좌우로 합쳐 한번에 볼 수 있는 이미지로 만들어 저장한다.
One more thing
원티드 페이지는 유동적인 영역이 많아 항상 같은 컨텐츠를 보여주는 경우가 적습니다. 따라서 위의 스크립트를 그냥 실행한다면 분명 정상적인 상태임에도 유사도가 낮게 측정되죠. 심하면 60%대의 유사도를 보이기도 합니다. 이를 보완하기 위해서 이미지 비교 시 제외 영역을 설정할 수 있는 기능을 추가했습니다.
Selenium은 엘리먼트를 인식한 뒤 인식한 엘리먼트의 위치와 크기를 반환받을 수 있는 기능을 제공합니다.
element.location()으로 해당 엘리먼트의 위치를 x, y좌표로 받을 수 있고 element.size()로 해당 엘리먼트의 width, height를 받을 수 있습니다.
이 값을 이용하여 제외하려는 엘리먼트 위에 파란색 사각형을 그려 해당 영역을 가릴 수 있었습니다.

이것이 제외영역을 가린 상태입니다. 제외영역을 가린 상태에서 비교한 뒤 비교 결과를 원본에 그려내 최종 결과물에는 해당 마스킹 영역에 파란 사각형은 보이지 않게 됩니다.

이렇게 나온 결과가 위의 사진입니다. 왼쪽 부분이 원본으로 비교본 사진이 원본과 얼마나 달라졌는지 퍼센티지를 표시하고 있습니다. 오른쪽 부분이 비교본으로 어떤 부분이 달라졌는지 빨간 사각형으로 표시하고 있습니다.
유사도를 값으로 측정하기 때문에 특정 수치 이하로 떨어졌을 때 트리거를 발생시켜 알림을 보낼 수도 있고, 결과 사진만 보고 어디가 어떻게 달라서 문제가 발생했는지 한 눈에 파악하기가 쉽습니다.
UI 상에서 많이 바뀌게 되는 프로젝트에서 배포를 진행할 때 배포 상태를 아주 빠르고 간단하게 모니터링 할 수 있는 툴로 유용하게 쓸 수도 있겠네요.
마무리
최근 계속해서 자동화 관련 글을 작성했기 때문에 이번엔 반드시 자동화 관련 글을 쓰지 않겠다(?) 라고 결심했었는데 또 자동화 글이 되었네요..
저는 테스트 자동화 엔지니어가 아니기도 하고 자동화는 그저 저를 도와주는 도구일 뿐 결국 QA 개개인의 QA 업무 능력이 훨씬 더 중요하다 생각하는 편입니다. 그래서 인지 누군가 저를 자동화에만 몰두하는 사람으로 보게 되지 않을지 걱정하기도 해요.. (최근 들어 주변 분들이나 주변 분들의 주변 분들이 제 글을 꽤 많이 보고 계시다는걸 알게되고 주위의 시선이 신경쓰이기 시작했어요 😅)
그래도 히든캐치를 만들어 팀 내에 사용법도 공유해 드리고 실제로 바로 사용하시려는 분도 계시다는 것에 유의미한 결과물을 얻었다고 생각해 글을 작성하게 되었습니다.
다음번엔 자동화가 아닌 QA 업무 개선이나 프로세스 관련한 글을 작성하려고 준비하고 있습니다. 자동화 글거리가 있더라도 나중으로 미루려고 해요.
제 업무 성과나 공부하면서 알게된 바를 정리하기 위해 작성하기 시작한 글을 좋게 봐주시는 분들이 계시다는 사실에 너무 감사드립니다.
좋아요 많이 눌러주세요!
'서비스 신뢰성 확보' 카테고리의 다른 글
웹 페이지 모니터링 스크립트를 3년 만에 개선한 이유 (0) | 2024.12.31 |
---|---|
파이썬 + 슬랙으로 에러 통계 데일리 요약 받아보기 (0) | 2024.02.29 |
UI, 프론트, 서버를 모두 한방에 점검하는 스크립트 만들기 (0) | 2024.01.29 |
Python으로 Wanted 서비스의 헬스 체크하기 (1) | 2024.01.29 |