개발

배포가 덜 무서워졌다: UI 테스트 자동화 이야기

배포 자신감을 높이는 테스트 자동화 프레임워크

배포가 덜 무서워졌다: UI 테스트 자동화 이야기배포가 덜 무서워졌다: UI 테스트 자동화 이야기

QA Automation Engineer

안녕하세요! 강남언니 DevOps 스쿼드에서 테스트 자동화를 담당하고 있는 엠마입니다.

QA 조직이 따로 없는 환경에서 어떻게 제품의 품질을 지켜낼 수 있을까?”

오늘은 이 질문에서 시작한 우리의 UI 기반 E2E 테스트 자동화 여정을 여러분과 함께 나눠보려 합니다.

강남언니팀에는 전통적인 QA 조직이 존재하지 않고, 각 스쿼드가 기획부터 개발, 테스트, 운영까지 책임지는 구조입니다. 이런 방식은 자율성과 빠른 실행 면에서 분명 강점이 있지만, 잠재적인 영향 범위에 대한 우려는 여전히 남아 있어 배포를 조심스럽게 진행해야 했습니다. “품질은 각 스쿼드가 알아서 챙긴다”는 원칙은 이상적이지만, 현실적으로 테스트 자동화 없이는 지속가능한 방식이 아니었습니다. 그래서 우리는 직접 테스트 자동화 프레임워크를 설계하고 도입하여 빠른 실행과 안정성을 동시에 확보하기로 했습니다.

이 글에서는 QA 조직이 없는 환경에서 테스트 자동화를 도입하게 된 배경과 과정을 살펴보고자 합니다. 우리가 직면한 도전 과제들과 그것을 해결하기 위해 선택한 기술적 접근 방식, 그리고 이러한 선택이 어떤 기준과 원칙에 따라 이뤄졌는지를 자세히 설명할 예정입니다. 또한 현재 우리의 테스트 자동화 시스템이 실제 개발 및 배포 과정에서 어떻게 활용되고 있는지, 그리고 이를 통해 어떤 가시적인 성과를 거두고 있는지도 함께 공유하려고 합니다. 특히, 테스트를 코드로 해결하며 조직의 품질 문화를 혁신적으로 변화시켜 나가는 QA 자동화 엔지니어의 핵심적인 역할과 그 중요성에 관심이 있는 분이라면, 이 글을 통해 실질적인 인사이트를 얻으실 수 있을 것입니다.

배경 살펴보기

처음엔 그럴듯해 보이던 자동화 테스트도 UI가 조금만 바뀌어도 깨지고, 테스트 코드 수정이 잦아지면 유지보수 부담에 허덕이다 중도에 포기하게 되는 경우가 많습니다. 이 문제를 피하고 싶어 작게 시작하더라도 꾸준히 확장해 나갈 수 있는 전략을 가져가기로 했고 다음과 같은 방향을 설정했습니다:

“유지 가능하고 점진적으로 확장할 수 있는 구조를 만들자.”

이 방향에 따라 사용자 경험에 직접적인 영향을 주는 기능부터 회귀 테스트 케이스를 만들어 자동화를 시작했고, iOS, Android에서 동일한 시나리오를 재사용할 수 있도록 구성했습니다. 나아가 이 테스트들이 CI/CD 파이프라인에 자연스럽게 통합되어 배포 전에 자동으로 실행되고 결과를 즉시 확인할 수 있도록 설계했습니다.

239d9338-d3d4-809a-86e2-d6a9f0de6f51.png239d9338-d3d4-809a-86e2-d6a9f0de6f51.png

이렇게 구축한 기본 골격 위에 어떤 기술 스택을 얹어 테스트 프레임워크를 완성했는지, 그리고 어떻게 조직 내에 정착시켜 갔는지에 대해 (모바일 중심으로) 아래에서 자세히 소개하겠습니다.

어떻게 풀었을까?

iOS도 Android도 한방에: 테스트 유지보수의 마법

테스트 자동화를 실제 서비스에 적용하다 보면 가장 먼저 부딪히는 벽 중 하나가 유지보수의 어려움입니다. 사소한 변경만으로도 테스트 스크립트가 쉽게 깨지고, iOS와 Android 같은 다중 플랫폼을 동시에 검증해야 할 경우 동일한 사용자 플로우라도 플랫폼별로 다른 locator를 써야하기 때문에 시나리오를 중복 작성하게 되는 경우가 많습니다. 특히 모바일 네이티브 앱 환경에서는 같은 기능이라도 iOS와 Android에서 다르게 구현된 화면 요소를 사용하기 때문에, 유지보수성 비용이 기하급수적으로 늘어나는 문제가 발생합니다.

이를 해결하기 위해 두 가지 핵심 패턴과 인터페이스를 도입했습니다:

POM(Page Object Model)

23ed9338-d3d4-801d-bf9e-e56467efc806.png23ed9338-d3d4-801d-bf9e-e56467efc806.png

Page Object Model은 애플리케이션의 각 화면을 독립된 객체로 모델링하는 디자인 패턴입니다. 모든 페이지가 상속하는 BasePage를 중심으로 로그인, 상담, 설정 등 화면 단위로 클래스를 나누고, 그 안에 화면 요소(버튼, 입력 필드, 리스트 등)의 locator와 해당 요소를 조작하는 메서드를 한데 모아둡니다. 스텝 클래스에서는 각 화면에서 검증할 수 있는 테스트 시나리오 흐름만 기술합니다. 이렇게 하면 UI 구조가 바뀌어도 오직 해당 페이지 클래스만 수정하면 되므로 유지보수가 훨씬 쉬워집니다.

PageFactory

PageFactory는 POM을 더욱 효율적으로 구현하기 위한 라이브러리입니다. 특히 강남언니처럼 iOS, Android, 그리고 Web을 모두 지원하는 크로스 플랫폼 환경에서 큰 힘을 발휘하는데, @iOSXCUITFinBy, @AndroidFindBy 같은 어노테이션을 이용해 플랫폼별 locator를 하나의 페이지 클래스에서 모두 관리할 수 있게 해줍니다. 예를 들어:

@FindBy(id = "nameLabel")
@iOSXCUITFindBy(iOSClassChain = "**/XCUIElementTypeTextField[`name == \"nameTitle\"`]")
@AndroidFindBy(uiAutomator = "new UiSelector().resourceId(\"nameText\")")
private WebElement nameTitle;

이렇게 설정하면 테스트 실행 시 플랫폼에 따라 자동으로 해당 locator가 선택됩니다. 결과적으로 시나리오는 하나, 페이지도 하나로 유지하면서, 플랫폼에 맞는 동작은 자동으로 처리되는 구조를 만들 수 있었습니다. 덕분에 중복되는 시나리오 코드 없이 플랫폼별 테스트를 일관된 방식으로 관리할 수 있게 되었고, 유지보수에 드는 비용을 크게 줄일 수 있었습니다.

IRetryAnalyzer

자동화 테스트가 간헐적으로 실패하는데, 같은 스크립트를 수동으로 재실행하면 아무 문제 없이 통과된 경험이 한 번쯤 있으실 겁니다. 네트워크 지연, 디바이스 응답 속도 차이, UI 렌더링 타이밍 이슈 등이 모두 자동화 환경에서 피하기 어려운 Flaky Test의 원인이 됩니다. 이런 불안정성 또한 테스트에 대한 신뢰도를 떨어뜨리고, 실제 버그인지 환경 문제인지 구분하기 어렵게 만들어 유지보수를 힘들게 하는 요소 중 하나입니다.

@Test(groups = "regression", retryAnalyzer = RetryAnalyzer.class)
public void eventWish() throws InterruptedException {
  ...
}
public class RetryAnalyzer implements IRetryAnalyzer {
  public int getRetryCount() {
    return retryCount;
  }

  public void resetRetryCount() {
    retryCount = 0;
  }

  @Override
  public boolean retry(ITestResult result) {
    if (retryCount < maxRetryCount) {
      retryCount++;
      return true; // 재시도
    }
    return false; // 더 이상 재시도하지 않음
  }
}

이를 해결하기 위해 우리는 TestNG라는 강력한 어노테이션 모델을 가진 테스트 프레임워크를 사용했습니다. 그리고 이 프레임워크에서 제공하는 IRetryAnalyzer라는 인터페이스를 도입해, 테스트가 실패하는 경우 최대 3회까지 자동으로 재시도하도록 했습니다. 그 결과 테스트의 안정성이 향상되었고 실제 버그를 조사해야 하는 시간도 크게 단축되었습니다

앱 심사 기다리는 사이, 디바이스가 혼자 테스트합니다

구현된 자동화 테스트를 실행할 환경은 어떻게 구성해야 할까요? 자동화 테스트가 단순히 “돌아간다”는 수준에 머물지 않고 유의미한 결과를 제공하려면, 먼저 실제 사용자 환경에서 발생할 수 있는 문제를 놓치지 않는 조건이 필요합니다. 또한 자동화 테스트 도입의 핵심 목적 중 하나인 효율성을 확보하고, 비 가시적으로 돌아가는 테스트의 진행 상황과 결과를 모든 구성원이 즉시 확인할 수 있어야 합니다. 이러한 요구사항을 충족하기 위해 우리는 다음과 같은 파이프라인을 구축했습니다.

실제 환경 재현부터 자동 실행까지

실제 사용자 환경과 최대한 유사한 조건에서 회귀 테스트를 수행하는 것은 매우 중요합니다. 그렇다면 사용자에게 배포되기 전의 운영 환경 앱을 어떻게 미리 테스트할 수 있을까요? 강남언니 앱은 매주 금요일에 심사용 빌드를 생성해 앱스토어와 구글 플레이에 제출하고, 월요일에 심사가 통과된 것을 확인한 후 점진적으로 프로덕션 배포를 시작하는 프로세스로 구성되어있습니다. 이러한 사이클에서 우리는 심사 대기 시간을 활용해 실 디바이스에서 테스트를 수행하는 플로우를 다음과 같이 설계했습니다.

239d9338-d3d4-8075-9bca-d9f33da914ca.png239d9338-d3d4-8075-9bca-d9f33da914ca.png
  1. iOS/Android Release Job이 돌아가면서 자동화 테스트 워크플로우 트리거
  2. 워크플로우가 맥 미니에 접속해, 연결된 모바일 디바이스에 자동으로 최신 심사용 빌드 다운로드 및 설치
  3. 각 디바이스에서 미리 설정해둔 회귀 테스트를 자동으로 수행
자동화 테스트 워크플로우
자동화 테스트 워크플로우

이 구조 덕분에 별도의 수작업 없이 테스트를 실행하고, 그 결과를 프로덕션 배포 전까지 충분히 검토할 수 있게 되었습니다.

실시간 공유와 데이터 축적

239d9338-d3d4-80c6-83d3-e62b608d0f29.png239d9338-d3d4-80c6-83d3-e62b608d0f29.png

자동으로 돌아가는 테스트의 진행 현황과 결과를 투명하게 공유하기 위해서는 Slack과 더불어 테스트 관리 플랫폼인 TestRail을 이용했습니다. 먼저 자동화 테스트 워크플로우가 트리거되면 곧바로 #sq-플랫폼-자동화테스트-리포트 채널에 앱 설치 메시지가 전송되고, 설치 후 테스트가 모두 완료되면 그 결과도 마찬가지로 슬랙에 전송되도록 했습니다.

239d9338-d3d4-8010-9683-d714a56a9c66.png239d9338-d3d4-8010-9683-d714a56a9c66.png

여기에는 플랫폼(iOS/Android), 테스트 환경, 앱 버전, 전체 소요 시간 등의 정보는 물론, 각 시나리오의 pass/fail 여부를 한눈에 파악할 수 있는 결과 요약 메시지도 포함되어 있습니다. 테스트가 실패하는 경우엔 해당 시점의 스크린샷이 쓰레드에 자동 첨부되어 빠른 원인 파악이 가능합니다.

?(물음표) 이미지가 동영상?(물음표) 이미지가 동영상
?(물음표) 이미지가 동영상

모든 상세 로그와 동영상은 TestRail에 기록됩니다. 이 데이터를 기반으로 QA 자동화 엔지니어가 실패 원인을 분석해 버그라면 담당자에게 즉시 리포팅하고, 스크립트 오류라면 빠르게 수정하여 테스트 코드를 유지보수 할 수 있습니다. 성공/실패 여부와 관계없이 TestRail에 축적되는 스크린샷과 동영상, 로그는 이후 품질 지표 분석과 회귀 이슈 추적에도 활용할 수 있는 데이터가 됩니다.

239d9338-d3d4-808b-b9fd-e9a117410ff5.png239d9338-d3d4-808b-b9fd-e9a117410ff5.png

이런 구조를 통해 우리는 “어떤 환경에서, 어떤 흐름으로, 어떻게 통과/실패했는지”를 모든 구성원이 확인할 수 있는 환경을 갖추게 되었습니다.

결과와 다음 단계

효과는 어땠을까? 그리고 실전에서의 한 방!

이렇게 자동화 테스트가 돌아가면서 배포 안정성 측면에서 큰 도움이 되고 있습니다. 운영 환경에서 발생할 수 있는 예기치 않은 문제들을 미리 검증하고, 잠재적인 오류를 사전에 발견함으로써 실제 사용자에게 전달되는 앱의 품질을 한층 높이고 있습니다. 또한 일부 시나리오는 Dev 환경에서도 실행되도록 하여, 새로운 기능 개발이나 변경 사항의 영향을 즉시 확인할 수 있도록 했습니다. 이를 통해 각 스쿼드가 기존에 수동 테스트로 보장하던 도메인 품질을 자동화로 보완하며, 개발 단계에서부터 안정성을 강화하는 효과를 거두고 있습니다.

(왼쪽부터) 웹, 웹뷰, 모바일 사례 (왼쪽부터) 웹, 웹뷰, 모바일 사례
(왼쪽부터) 웹, 웹뷰, 모바일 사례

이제는 배포 속도를 늦추지 않으면서도, 그동안 놓칠 수 있었던 기존 기능 테스트를 자동화로 커버해 side-effect의 위험을 크게 줄였습니다. 덕분에 배포 버튼을 누르는 손가락이 한결 가벼워졌고, 배포가 덜 무서워졌습니다. 처음에는 한 스쿼드에서 시작했던 테스트 자동화가 점차 다른 스쿼드로 자연스럽게 확산되는 긍정적인 변화도 있었습니다. 우리도 OO시나리오를 자동화해 달라는 요청이 들어오기 시작하면서, 테스트 자동화는 단순한 기술 도입을 넘어 조직 차원의 품질 향상과 안정적인 배포를 가능하게 하는 중요한 자산으로 자리 잡고 있습니다.

Next Up: 우리의 다음 챕터

회귀테스트 시나리오 작성부터 테스트 환경 구축, 그리고 모바일, 웹 테스트 자동화까지 숨가쁘게 달려왔지만 여전히 해결해야 할 과제가 많이 남아 있습니다. 강남언니 앱·웹 제품에 대한 테스트 자동화 커버리지를 높이는 것과 더불어 앞으로 더 잘하기 위해 이런 점들을 고민하고 있습니다.

239d9338-d3d4-805c-80f4-de667d695bf8.png239d9338-d3d4-805c-80f4-de667d695bf8.png

마지막 질문과 관련해, 우리는 React 기반의 QA 대시보드를 직접 개발해 더 나은 품질 관리와 빠른 의사결정을 지원하려 합니다. 하지만 어떤 지표를 보여주는 것이 가장 의미 있을지, 현 상황을 가장 잘 드러낼 그래프는 어떤 모습일지 등 풀어야 할 주제는 여전히 많습니다.

이처럼 개선과 도전의 여지는 끝이 없기에, 함께 문제를 해결하며 성장해 나갈 새로운 동료를 기다리고 있습니다. 테스트 자동화와 품질 혁신에 열정을 가진 분들은 아래 링크를 통해 지원해 주세요. 우리와 함께 더 나은 품질 문화를 만들어 갑시다!