UnitTest 방치에서 MCP 시나리오 테스트까지 — AI로 갈아탄 테스트 자동화
안녕하세요. 물먹고하자입니다.
이번 글은 테스트 자동화를 여러 번 갈아탄 이야기예요. (AI테스트 활용기네요)
UnitTest → 명세 대조 → XCUITest → MCP 시나리오 테스트까지,
한 방에 정답을 찾은 게 아니라 계속 벽에 부딪히며 방향을 바꿔온 과정을 정리해봤어요.
1. AI 도입 전 — 손으로 짠 UnitTest, 결국 방치됐어요
처음엔 정석대로 UnitTest 코드를 직접 짜서 돌렸어요. 문제는 유지보수였습니다. 기능이 바뀌면 테스트도 같이 업데이트돼야 하는데, 바쁘다 보면 그 갱신이 스멀스멀 누락되더라고요. 깨진 테스트가 하나둘 쌓이면 신뢰가 떨어지고, 결국 "나중에 고치자" → 안 보게 되는" 전형적인 흐름을 탔어요.
2. 그래서 코드 대신 "명세 대조"로 (spec-test)
그래서 유닛 레벨 검증은 테스트 코드를 짜는 대신, 명세(Given / When / Then)를 마크다운으로 적어두고 AI에게 "현재 코드가 이 명세를 지키는지" 정적으로 대조시키는 방식으로 바꿨어요. 코드는 안 건드리고 리포트만 뽑으니 부담이 확 줄었죠.
유지보수 대상이 "테스트 코드"가 아니라 "명세 문서"로 바뀌니, 갱신 누락 스트레스가 훨씬 덜했어요.
3. UITest는 시작도 못했는데… XCUITest의 벽
사실 UI 테스트는 솔직히 시작도 못한 케이스였어요. 손이 많이 가서 계속 미뤄뒀죠. AI를 도입하고 나서야 "이참에 해보자" 하고 XCUITest를 구성하게 했는데, 여기서 또 벽을 만났어요.
아시다시피 XCUITest로 요소를 클릭하려면 접근성 식별자 세팅(예: accessibilityIdentifier / setupAccessibility())이
되어 있어야 잡히거든요. 그 말은 지금 만들어진 화면 + 앞으로 만들어질 화면 전부가 그 세팅을 고려해야 한다는 뜻이었어요.
4. 방향 전환 — MCP로 앱을 "밖에서" 조작
그래서 다른 방법을 찾다가 MCP(에이전트가 외부 도구를 쓰게 해주는 연결 규격)를 활용하게 됐어요. 핵심은 앱 코드에 손대지 않고(접근성 세팅 없이) 밖에서 화면을 조작하는 거예요. 두 개를 붙였어요.
특히 하이브리드(WebView) 화면은 네이티브 접근성 트리로는 안이 텅 비어 보여서,
Appium으로 웹뷰 컨텍스트에 붙어 textarea에 입력하고 응답 DOM을 읽는 식으로 풀었어요.
프로덕션 코드에 테스트용 세팅을 심을 필요가 없다는 게 XCUITest 대비 가장 큰 해방감이었어요.
rlawldnr → 김지욱), IME 상태가 어긋나면 지우고 다시 치는 보정까지 해야 했거든요. 한 글자 넣는 데 몇 배씩 걸렸죠.
그래서 네이티브도 Appium 한 컨텍스트(NATIVE_APP)로 통일했더니, set_value로 한글이 그냥 바로 들어갔어요. 같은 시나리오가 수 분 → 약 1분으로 줄었어요.
5. 시나리오 테스트, 그리고 시간을 줄이는 반복 학습
이렇게 해서 드디어 시나리오 단위 테스트가 가능해졌어요. "이 화면 들어가서 → 입력하고 → 결과 확인" 같은 흐름을 명세로 적어두면 AI가 그대로 실행하고 판정해요.
처음엔 시나리오 하나에 약 16분이나 걸렸어요. 근데 뜯어보니 앱이 실제로 일한 시간은 몇 초뿐이고, 대부분이 자동화 오버헤드(스크린샷을 매번 찍어 눈으로 판독 · 매번 재로그인 · 스텝마다 왕복)였어요. 그래서 반복 학습으로 이 부분을 계속 줄여나갔어요.
※ 앱 실제 동작 시간(서버 응답 등)은 그대로고, 줄인 건 전부 자동화 오버헤드예요.
줄인 방법은 크게 세 가지였어요.
- 한글 입력을 HID 두벌식 → Appium
set_value직접 : 네이티브에선 이게 제일 컸어요(두벌식 조합·IME 보정 통째로 제거) - 스크린샷 판독 → 텍스트 판정 : 화면을 눈으로 보는 대신 DOM·접근성 트리 텍스트로 판정
- 재로그인 제거 : 자동로그인 켜두고 세션 재활용 → AI가 로그인 조작을 아예 안 함
- 스텝 체이닝 : 로그인·진입 같은 결정적 스텝은 스크립트로 한 번에 묶어 AI 왕복 제거
6. 실측하며 만난 함정 — 특히 오판하기 쉬운 것
- 롱프레스가 탭으로 오인식 — HID 터치로 길게 누르면 탭으로 먹혀 엉뚱한 화면이 열렸어요. Appium
long_press에 duration을 명시(1.3초)하니 선택 모드 진입이 안정됐어요. - 조작이 이상하면 코드 탓 전에 "세션/서버"부터 의심 — 삭제·읽음이 자꾸 안 먹혀서 좌표 조작을 의심했는데, 진짜 원인은 같은 계정이 다른 기기에서 로그인(중복 로그인)돼 세션이 만료된 거였어요. 서버가 요청을 거부하는 중이라 화면만 봐선 오판하기 딱 좋았죠. UI 자동화에서 제일 헷갈리는 지점이에요.
- 좌표 조작은 상태 검증을 꼭 같이 — 각 조작 뒤 "예상한 화면이 됐는지"를 확인 안 하면 오탭 한 번에 통제를 잃어요. 게다가 좌표는 기기 해상도가 바뀌면 어긋나서, 가능하면 좌표보다 셀렉터를 우선해야 해요.
마무리
아직 완성형은 아니에요. 대신 "시나리오를 글로 적으면 실행된다"는 방향이 마음에 들어서, 실측하며 발견한 함정을 명세에 계속 쌓아가는 중이에요.
오늘은이만
즐거운코딩 되세요~
끝.


댓글
댓글 쓰기