brunch

You can make anything
by writing

C.S.Lewis

by 이지원 Feb 03. 2024

데이터 정합성을 검증하고 재현 반복 가능하게 구성하기

안녕하세요, 기술로 수면 문제를 잠재우는 에이슬립의 플랫폼 백엔드 개발팀에서 Mobile SDK와 API 시스템 그리고 웹 대시보드 품질을 보증하고 있는 지원입니다. Data API 검증 간에 4000개의 데이터 정합성을 검증하고 재현 반복 가능하게 구성한 뒤 배포 전후 리그레션 테스트에서 유의미한 결함을 검출했던 경험을 공유합니다.


요구사항 분석 과정  

담당 중인 프로덕트는 크게 Backend API, Customer API, Data API 그리고 해당 API를 사용하는 Mobile SDK와 웹 대시보드입니다. 서버 아키텍처를 살펴보면 각 기술들이 서로 유기적으로 얽히면서 동작하는 모습인데요. 수면 결과 메트릭을 표현하는 Data API에 대한 신규 기능이 추가되었고 Data API에 대한 신규 스펙 및 회귀 테스트가 필요한 상황이었습니다.


담당 중인 다른 프로덕트도 검증 방법이 꽤나 까다롭고 어렵지만 사실 Data API는 에이슬립에 합류할 당시 초기부터 이걸 대체 어떻게 검증해야 할까?라는 고민이 더욱 많았던 기능이었습니다. Data API에 문제가 생기면 수면 데이터의 정확성을 내세우는 에이슬립의 가치가 고객께 전달되기 힘들기 때문이죠. 데이터를 다루다 보니 최소한 보장된 범위 내에서 조금의 오차도 허용하지 않으면서도 대규모 데이터를 쉽고 빠르게 검증하는 E2E 테스트 전략이 필요했습니다. 웹 대시보드에서 수면 결과 지표를 확인하는 고객께서 느낄 수 있는 부정적인 영향을 사전에 최소화시키기 위해서죠. 문제가 발생하면 고객 이탈에 영향을 끼칠 만큼 중요한 영역이기도 했습니다.


고민 끝에 Data API에 해당되는 E2E 테스트를 2가지로 분류하게 되었어요. 지금까지 해왔던 방식으로 테스트를 접근하면 Data API에 대한 품질 보증이 원활히 될 수 없겠다는 판단이었죠. 프론트에서 UI를 통해 검증할 항목과 서버 응답 관점에서 검증할 항목을 E2E 관점으로 조금 더 세분화 시켜서 분류하게 되었습니다. 분류하는 과정에서 프론트에서 서버 응답 데이터를 처리하는 방식에 대한 명확한 파악이 필요했어요. 응답 데이터를 프론트에 바로 뿌려주는 형태라면 해당 데이터들은 서버 응답 데이터만 확실히 검증하면 프론트 로직이 변경되지 않는 이상 버그가 발생하기 힘든 구조이기 때문이죠.


서버 응답을 바로 처리하는 경우와 그렇지 않은 특이한 데이터가 있다는 사실을 알게 되었고 해당 과정을 통해 테스트 전략을 세분화 시켰어요. 그리고 반드시 지켜야 할 1가지 원칙을 정하게 되었는데, Mock과 같은 가짜 객체를 생성해서 테스트 된 결과는 해당 테스트 계층에서 확인해야 할 테스트 커버리지 측면에서는 신뢰하되 최종 릴리스 여부에는 반영하지 않기로 했고 다양한 경우의 수가 포함된 실제 데이터를 검증하는 방향으로 테스트 전략을 세웠습니다.


검증 환경 구성  

신규 수면 메트릭 DB/API 데이터 정합성 검증에 필요한 테스트 케이스 개수는 4000개 정도 되었어요.

서버 응답을 하나씩 확인해서 데이터 정합성 검증에 필요한 관계식으로 계산하여 프론트에서 보여지는 값이 동일한지 테스트하는 방식은 비효율과 추후 반복 재현 가능한 환경 구성이 불가했죠. 무엇보다 회귀 테스트 간에 해당 테스트를 동일한 과정을 거쳐 수동으로 검증하는 것은 휴먼 에러와 비효율적인 검증으로 인해 품질과 속도의 균형이 필요한 성장하는 스타트업에서는 맞지 않는 방식이었습니다. 제가 추구하지 않는 방향이기도 했고요.


사람이 잘하는 영역과 코드가 잘하는 영역을 구분해서 리소스를 적절히 분배해야만 시프트 레프트와 시프트 라이트의 균형감 있는 접근이 가능하므로 편하고 익숙한 Axios 라이브러리를 사용하여 검증 환경을 구성하게 되었습니다.


관계식 검증 과정  

우선 포스트맨으로 다양한 데이터로 요청을 보내면서 신규 기능이 어떠한 구조인지 파악했어요. Axios로 API 테스트를 어떻게 구성해야 할지 살펴보는 과정이었죠.

모든 데이터에 대한 정합성 검증이 필요했기에 모든 Session의 데이터 검증이 필요했어요. 하지만 검증이 필요하지 않는 데이터도 섞여있어서 데이터를 구분하는 작업이 필요했어요. sleep_session_list 존재 유무를 체크하여 filter로 session.state가 “COMPLETE”이고 session.time_in_bed가 1200 이상인 조건을 만족하는 session_id를 찾아서 새로운 배열을 생성한 뒤 데이터 정합성 검증 코드가 실행되도록 구현했습니다.

그런데 검증 조건을 통과한 세션 중에서 간혹 검증 로직이 동작하지 않는 경우가 있었어요. 디버깅 결과 특정 케이스에서만 발생하는 현상이었죠. 서버에서 의도된 구현이므로 해당 부분이 검증 로직에서 발견될 경우 검증을 건너 뛰도록 처리했습니다. 하지만 나중에 문제가 발생할 경우 어떠한 Session ID였는지 파악이 필요하기 때문에 로그를 남기도록 했어요. 이후 16개 관계식을 로직으로 구현했고 로깅 및 Mocha 테스트 프레임워크로 검증하도록 처리했죠.


이로써 검증 필요한 모든 테스트 데이터에 대한 서버 응답 데이터가 관계식과 일치하게 구현되어 있는지 E2E 테스트 계층에서 사람이 아닌 코드로 검증할 수 있게 되었습니다.


산술 평균 검증 과정

관계식 검증과 마찬가지로 산술 평균 검증에 필요한 API 요청을 포스트맨으로 빠르게 확인했어요. 서버 응답 구조를 살펴보며 어떤 식으로 API 로직 검증을 구현해야 할지 고민하는 과정이었죠.

모든 테스트 데이터를 검증해야 했기 때문에 userID를 동적 매개변수로 처리했고 테스트 필요한 userID 개수만큼 순회하도록 처리했어요.

그리고 산술 평균이 가능하도록 reduce 함수를 사용하여 값을 누적하여 slept_sessions 배열의 길이로 나눈 값과 average_stats.time_in_stable_breath 값을 비교하여 동일한지 검증하도록 구현했습니다. 이로써 검증 필요한 모든 테스트 데이터에 대한 서버 응답 데이터가 산술 평균과 일치하게 구현되어 있는지 E2E 테스트 계층에서 사람이 아닌 코드로 검증할 수 있게 되었습니다.


배포 전 발견한 문제  

관계식과 산술 평균 코드를 실행하면 위와 같이 모든 테스트 과정이 로그로 남기도록 되어있어요. 이로 인해 어떠한 데이터에서 어떠한 검증 과정이 문제가 있었는지 바로 파악할 수 있었죠. 배포 전 테스트 환경에서 4000개의 E2E 테스트케이스를 코드 레벨에서 수행하면서 발견된 문제는 크게 3가지였어요.  


특정 관계식 검증 과정에서 특정 케이스에 대해서만 허용 오차 범위를 0.02로 검증해야 성공하는 현상

API 테스트 결과와 서버 응답 데이터의 값 차이 발생

특정 값의 산술 평균이 서버 응답 산술 평균으로 계산되지 않는 현상


위 3가지 문제를 팀에 공유하였고 서버 수정 후 수정 확인까지 테스트 코드 레벨에서 진행하여 문제가 모두 해결되었어요. 이로써 데이터 정합성 검증에 필요한 테스트 케이스 4000개를 배포 전 반복 재현 가능하도록 구성하여 배포 전 다양한 문제를 발견할 수 있었습니다.


배포 후 발견한 문제  

테스트 환경에서 검증을 끝마친 뒤 라이브 배포가 진행되었어요. 테스트 환경과 라이브 환경의 테스트 데이터에 차이가 있다 보니 배포 후에는 라이브 환경에 구성된 테스트 데이터 검증이 필요했습니다. 설마 문제가 있을까 싶었는데 CI에 구성된 Data API 회귀 테스트가 실패되었어요.

라이브 환경에서만 위와 같은 실패가 발생하게 되었어요. 디버깅 결과 라이브 환경에 존재하는 오래된 세션에서 관계식을 통과하지 못한 케이스가 1건 발견되어 배포 후 테스트가 실패된 케이스였어요. 서버 수정 완료 후 라이브 환경에서 다시 한번 4000개의 회귀 테스트를 실행하여 수정 확인 테스트까지 빠르게 마무리하게 되었습니다.


CI 자동화 환경 구성

QA Engineering repo를 관리하고 있고 웹 모바일 API 테스트 모두 Node 환경에서 코드 베이스로 관리하고 있어요. 일부 API는 Postman과 Newman을 활용하여 Collection id로 구성했어요. 제가 없어도 개발자분들께서 직접 필요한 테스트를 개발 과정 또는 배포 후 필요할 때마다 빠르게 실행하여 결과 확인이 가능하도록 GitAction에서 테스트 환경을 선택하여 실행 가능토록 구성했어요.

CI 테스트 결과는 슬랙으로 리포팅 되도록 구성했어요. 테스트 상세 로그는 CI 로그를 직접 살펴봐도 괜찮지만 편의성을 위해 테스트가 종료되면 로그가 기록된 json 파일을 슬랙 채널로 리포팅 되도록 slackUpload 함수를 별도로 구현하여 활용했어요. main 브랜치를 항상 최신 테스트 환경으로 유지하면 제가 없어도 개발자분들께서 얼마든지 필요한 리그레션 테스트를 실행할 수 있는 환경이 갖춰진 것이죠. 이와 같은 방식으로 웹 모바일 API에 대한 모든 리그레션 테스트 커버리지를 구성하여 시프트 레프트 접근과 시프트 라이트 접근의 균형을 유지하고 품질과 속도의 균형을 맞춰가고자 노력하고 있습니다.


마치며

지금까지 Data API 검증 간에 4000개의 데이터 정합성을 검증하고 재현 반복 가능하게 구성한 뒤 배포 전후 리그레션 테스트에서 유의미한 결함을 검출했던 경험을 공유하게 되었어요.


에이슬립의 플랫폼 백엔드 개발팀은 QA가 Tech 영역에서 활동하는 상황을 적극적으로 지지해 주고 응원해 주는 동료분들로 가득 차있어요. QA Engineering에 필요한 사항들을 공유할 때면 적극적으로 확인해 주시고 높은 수준의 품질 문화가 정착될 수 있도록 노력하는 팀 문화가 정착되어 있어요. 결이 맞는 동료분들과 함께하고 있는 덕분에 앞으로의 커리어가 기대되는 요즘이에요.


어디까지나 기술 블로깅인지라 많은 내용을 상세하게 담을 순 없었지만 저와 비슷한 QA 및 테스트가 필요한 엔지니어 분께서는 위와 같은 접근을 통해 유의미한 결과와 경험을 만들어가시길 바라는 마음으로 해당 포스팅 마무리하도록 하겠습니다.


감사합니다.


지원 드림.

매거진의 이전글 API 기능 테스트, 무엇을 어떻게 검증할 것인가?
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari