Mobile Parallel Testing
안녕하세요, 에이슬립에서 Quality Engineering Lead를 맡고 있는 이지원입니다. 과거, 2000개가 넘는 모바일 테스트케이스를 검증해야 했습니다. 당시에는 Appium이나 Selenium을 추상화한 프레임워크 없이 Appium Python-Client와 Pytest를 직접 사용해 설계된 상태였습니다. 초기에는 간단한 구조로 빠르게 시작할 수 있겠지만, 대규모 병렬화를 구현해야 할 시점에서 복잡성이 크게 증가했습니다.
특히, FastAPI로 자체 프록시 서버를 구현해 테스트 요청을 분산하고, 각 디바이스별로 Appium 서버를 관리하는 과정에서 많은 개발 및 유지보수 부담이 발생했습니다. FastAPI 프록시는 테스트 요청을 라우팅 하고 세션 충돌을 방지하는 역할을 했지만, 오류 처리와 확장성 관리에서 한계를 드러냈습니다. 이 과정에서 저는 “이미 더 나은 방법이 존재하는데 이렇게까지 해야 할 필요가 있을까?”라는 의문을 품게 되었습니다.
기술적으로 더 효율적인 대안이 있다고 판단해 새로운 아키텍처를 제안했지만, 기존 방식에 이미 많은 리소스가 투자된 상황에서 이를 전환하기에는 팀의 추가적인 협조와 설득이 필요했습니다. 결국 제가 제안했던 새로운 아키텍처는 실행되지 않았습니다. 당시에는 아쉬움이 컸지만, 그 경험을 통해 배우고 성장할 수 있는 계기가 되었습니다.
1. 병렬화의 어려움
각 디바이스별로 독립된 Appium 서버를 설정하고 관리해야 했습니다. FastAPI 기반 프록시 서버로 요청 라우팅과 세션 충돌 문제를 해결했지만, 오류 처리와 유지보수 부담이 커지면서 한계에 직면했습니다.
2. 유지보수의 복잡성
테스트 코드에 로케이터와 테스트 로직이 섞여 있어, 플랫폼(Android/iOS) 간 로케이터 변경 시 수정 작업이 중복적으로 광범위하게 발생했습니다. 테스트 데이터 관리도 분산되어 있어 환경별 데이터 전환이 어려웠고 뿐만 아니라 코드 간 불필요한 의존 관계가 많아, 단일 코드베이스로 온프레미스와 클라우드 환경 전환이 어려웠습니다.
3. 디자인 패턴의 부재
2천개가 넘는 대규모 테스트케이스를 구현하면서도 Page Object Pattern이나 Screenplay Pattern과 같은 구조화된 디자인 패턴을 적용하지 않았습니다. 결과적으로 테스트 코드가 중복되고 비효율적으로 설계되어, 작은 변경에도 광범위한 수정이 필요했습니다. 테스트 로직과 UI 요소가 분리되지 않아, 코드가 복잡하고 유지보수가 어려운 상태였습니다.
4. 자동화의 부재
CI/CD 파이프라인과 완전히 통합되지 않아, 테스트 실행과 결과 확인까지 많은 수작업이 필요했습니다. 결과 리포팅 역시 비효율적인 방식으로 운영되고 있어서 디버깅과 분석이 어려웠습니다.
위 문제들을 해결하기 위해, 저는 WebdriverIO와 Appium Grid Relay 4를 기반으로 한 대규모 병렬화 아키텍처를 제안했습니다. 병렬화 지원과 자동화된 파이프라인 통합을 통해 QA가 테스트 작성과 품질 분석에만 집중할 수 있는 환경을 목표로 했습니다.
대규모 병렬 테스트 환경을 안정적이고 확장 가능하게 설계하기 위해
1. Appium Grid 기반 병렬화 설계
Appium Grid Relay 4를 통해 테스트 요청을 중간에서 라우팅 하고, 디바이스 풀을 관리하도록 제안했습니다. 또한 Relay 노드와 Appium 서버를 Docker 컨테이너로 배포해 확장성과 유연성을 강화하도록 제안했으며 각 디바이스마다 독립된 Appium 서버를 구성해 병렬 실행 중 세션 충돌을 방지하고 Capabilities를 활용해 플랫폼(Android/iOS), OS 버전, 디바이스 속성에 따라 테스트 요청을 분배하도록 제안했습니다.
테스트 코드의 유지보수성과 재사용성을 높여 QA 생산성을 극대화하기 위해
2. 테스트 코드의 플랫폼 간 통합
Page Object Pattern(POM) 페이지 단위로 테스트 로직과 로케이터를 분리해 코드 중복을 줄이고 유지보수를 단순화하도록 제안했습니다. 동적 로케이터 처리를 위해 복잡한 코드를 간소화시키고 Capabilities 정보를 기반으로 적합한 로케이터를 동적으로 선택하도록 제안했습니다.
자동화된 파이프라인으로 QA 리소스를 최적화하고 빠른 피드백 루프를 지원하기 위해
3. CI/CD 파이프라인과의 통합
병렬 실행 스케줄링 Jenkins Pipeline과 Docker 컨테이너를 활용해 일관된 환경에서 테스트를 병렬로 실행하도록 제안했습니다. Allure 리포트를 생성하여 스크린샷과 실패 지점의 동영상을 자동으로 첨부하는 과정을 보다 간편한 방식으로 제안했습니다. Prometheus와 Grafana로 디바이스 상태와 실행 현황을 실시간 시각화하도록 제안했습니다.
지금도 여전히 기술적으로 유의미했다고 생각합니다. 이미 WebdriverIO와 Appium Grid 4 Relay 아키텍처는 기존 대규모 병렬 자동화의 문제점을 해결하기 위해 등장한 기술이기 때문입니다. 하지만 실행되지 못했습니다. 새로운 인원이 합류해서 지금까지 해왔던 방식에 의문을 품고 새로운 방식으로 전환하자는 제안 또한 크게 와닿지 않았던 것 같습니다. 개발 언어부터 모든 것들을 갈아엎는 과정에 있어서 거부감이 있었을지도 모릅니다. 하지만 무작정 새로운 방식으로의 전환을 제시한 것만은 아니었습니다. 기존 방식을 점진적으로 리팩터링 하는 비용보다 새로운 아키텍처를 기반으로 운영하는 것이 리소스 측면에서 더욱 효율적이고 효과적이라는 생각이 경험에서 느낄 수 있었기 때문입니다. 하지만 기존 방식에 이미 많은 리소스가 투자되어 있었고, 새로운 방식으로 전환하려면 추가적인 교육과 설득이 필요했고 끝내 실행되지 않았습니다. 이 경험을 통해 저는 다음과 같은 교훈을 얻었습니다.
기술만으로 모든 문제를 해결할 수 없고 아무리 좋은 기술적 해결책이라도 조직의 리소스와 상황을 충분히 고려하지 않으면 실행 가능성을 높이기 어렵다는 점을 배웠습니다.
제안의 기술적 우수성뿐만 아니라, 조직이 얻을 수 있는 구체적인 이점과 전환 비용을 명확히 제시하는 것이 중요하다는 것을 깨달았습니다.
실현되지 않은 제안도 가치가 있음을 배웠습니다. 이 경험은 이후 에이슬립에서 더 나은 테스트 환경을 설계하는 데 큰 밑거름이 되었습니다.
현재 저는 에이슬립에서 1인 QA로서 5개 이상의 모바일 웹 SDK 프로덕트를 책임지고 있습니다. 비록 과거의 제안이 실행되지 못했지만, 그때의 경험은 현재 WebdriverIO 기반의 효율적이고 유지보수성 높은 테스트 환경을 구축하는 데 큰 도움이 되었습니다.
이 경험을 통해 제안이 실현되지 않았다고 해서 그것이 실패라고 생각하지 않게 되었습니다. 기술은 목표를 달성하기 위한 수단이고, 실현되지 않은 제안도 더 나은 미래를 위한 밑거름이 될 수 있다는 것을 배웠습니다.