개념
스크립트 20개까지는 아무 구조나 된다
자동화를 시작할 때는 구조가 문제가 되지 않는다. 스크립트 20개면 어떻게 짜도 굴러간다. 문제는 200개가 됐을 때 드러난다.
로그인 화면에 필드 하나가 추가됐다. 147개 스크립트를 고쳐야 한다.
레슨 4에서 자동화 부채를 배웠다. 그 부채가 쌓이는 가장 큰 원인이 구조 없이 늘린 스크립트 다. 이 레슨은 그 구조 — 자동화 프레임워크의 유형 — 를 다룬다.
여기서 '프레임워크'는 Playwright나 Selenium 같은 도구 가 아니라, 그 도구 위에 우리가 만드는 코드 조직 방식 을 말한다. 같은 Playwright로도 전혀 다른 구조를 만들 수 있다.
다섯 가지 유형
발전 순서대로 보면 이해가 쉽다. 뒤로 갈수록 초기 비용이 크고 유지보수 비용이 작다.
1) 선형(Linear) — 기록·재생
동작을 순서대로 나열한 스크립트다. 도구의 레코딩 기능으로 만든 결과물이 대개 이 형태다.
test('로그인 후 주문', async ({ page }) => {
await page.goto('https://shop.example.com')
await page.fill('#email', 'test@example.com')
await page.fill('#password', 'pass1234')
await page.click('#login-btn')
await page.click('#product-1')
await page.click('#add-to-cart')
// ... 계속
})| 장점 | 만들기 가장 쉽다. 배울 것이 없다 |
| 단점 | 중복이 폭발한다. 로그인 절차가 스크립트마다 복사된다 |
| 적합 | 일회성 검증, PoC, 몇 개 안 되는 스모크 |
2) 모듈 기반(Modular)
반복되는 절차를 함수로 뽑는다. 프로그래밍의 기본을 적용한 것이다.
async function login(page, email, password) { /* ... */ }
async function addToCart(page, productId) { /* ... */ }
test('로그인 후 주문', async ({ page }) => {
await login(page, 'test@example.com', 'pass1234')
await addToCart(page, 'product-1')
})로그인 절차가 바뀌면 함수 하나만 고치면 된다. 대부분의 팀이 여기까지는 자연스럽게 도달한다.
3) 페이지 객체 모델(Page Object Model)
모듈 13(레슨 4)에서 자세히 다룬 그것이다. 화면 단위로 클래스를 만들어 로케이터와 동작을 한곳에 모은다. 모듈 기반의 UI 특화 버전이라고 보면 된다.
class LoginPage {
constructor(page) { this.page = page }
async login(email, password) { /* 로케이터는 이 안에만 */ }
}로케이터가 한 곳에만 있다는 것 이 핵심 이득이다. 화면이 바뀌어도 고칠 곳이 하나다.
4) 데이터 주도(Data-Driven)
로직은 하나이고 데이터만 바꿔가며 반복 실행 한다.
const cases = [
{ email: 'valid@test.com', password: 'pass1234', expect: 'success' },
{ email: 'valid@test.com', password: 'wrong', expect: 'fail' },
{ email: 'notanemail', password: 'pass1234', expect: 'validation' },
{ email: '', password: 'pass1234', expect: 'required' },
]
for (const c of cases) {
test(`로그인: ${c.email} / ${c.expect}`, async ({ page }) => {
await loginPage.login(c.email, c.password)
await expect(resultOf(page)).toBe(c.expect)
})
}모듈 3에서 배운 설계 기법이 여기서 데이터가 된다. 동등분할·경계값 분석으로 뽑은 케이스 표가 그대로 이 배열이 된다. 케이스를 추가하려면 줄 하나만 더하면 되므로, 테스트 설계와 구현이 분리 되는 효과가 있다.
데이터를 외부 파일(CSV·JSON·스프레드시트)에 두면 코드를 모르는 사람도 케이스를 추가 할 수 있다.
5) 키워드 주도(Keyword-Driven)
한 걸음 더 나아가, 동작 자체를 데이터로 만든다.
| 키워드 | 인자1 | 인자2 | 기대결과 |
|---------------|--------------------|-----------|-----------|
| 페이지열기 | /login | | |
| 입력 | 이메일 | a@b.com | |
| 입력 | 비밀번호 | pass1234 | |
| 클릭 | 로그인버튼 | | |
| 검증_텍스트포함 | 환영합니다 | | 표시됨 |키워드(페이지열기, 입력, 클릭, 검증_텍스트포함)의 구현은 코드에
있고, 테스트 케이스는 표로 작성 된다. 비개발자도 케이스를 만들 수
있다는 것이 최대 장점이다.
| 장점 | 비개발자가 케이스 작성 가능, 테스트 케이스가 곧 문서 |
| 단점 | 키워드 엔진을 만들고 유지해야 한다. 복잡한 로직 표현이 어렵다 |
| 적합 | 도메인 전문가가 케이스를 많이 만드는 조직, 대규모 반복 시나리오 |
6) 하이브리드와 BDD
실무에서 순수한 한 유형만 쓰는 경우는 드물다. 대개 페이지 객체 + 데이터 주도 조합이 기본이고, 필요한 영역에만 키워드 주도를 얹는다.
BDD(모듈 7 레슨 5)의 Given-When-Then도 넓게 보면 키워드 주도의 한
형태다. Given 로그인한 사용자가 라는 문장이 하나의 키워드이고, 그
구현이 스텝 정의에 있다.
유형별 비교
| 유형 | 초기 비용 | 유지보수 | 비개발자 참여 | 표현력 |
|---|---|---|---|---|
| 선형 | 매우 낮음 | 매우 나쁨 | 불가 | 낮음 |
| 모듈 기반 | 낮음 | 보통 | 불가 | 보통 |
| 페이지 객체 | 중간 | 좋음 | 불가 | 보통 |
| 데이터 주도 | 중간 | 좋음 | 부분 가능 | 보통 |
| 키워드 주도 | 높음 | 좋음 | 가능 | 낮음~보통 |
| 하이브리드 | 상황에 따라 | 좋음 | 부분 가능 | 높음 |
'표현력' 열을 눈여겨보라. 추상화를 올릴수록 복잡한 조건이나 예외 처리를 표현하기 어려워진다. 키워드 주도로 "응답 시간이 3초를 넘으면 재시도하되 3회까지만" 같은 로직을 표현하려면 키워드가 계속 늘어나고, 결국 표로 프로그래밍을 하는 상태 가 된다.
무엇을 고를 것인가
판단 기준은 팀의 조건에서 나온다.
| 질문 | 답이 이렇다면 |
|---|---|
| 코드를 쓸 수 있는 사람이 몇 명인가 | 적다 → 데이터 주도·키워드 주도 쪽 |
| 케이스를 만드는 사람이 누구인가 | 도메인 전문가 → 키워드 주도 검토 |
| 케이스 수가 얼마나 늘 것인가 | 수백 이상 → 페이지 객체 필수 |
| 화면이 얼마나 자주 바뀌는가 | 잦다 → 로케이터 집중(페이지 객체) |
| 검증 로직이 복잡한가 | 복잡 → 코드 기반(표현력 필요) |
| 유지보수할 인력이 몇 명인가 | 1명 → 키워드 엔진은 위험 |
마지막 줄이 실무에서 가장 중요하다. 키워드 주도는 프레임워크 자체가 하나의 제품이 된다. 만든 사람이 떠나면 아무도 손대지 못하는 자산 이 남는다. 모듈 7(레슨 9)에서 다룬 버스 팩터 문제가 그대로 적용된다.
실무 권장 순서: 페이지 객체 + 데이터 주도로 시작한다. 대부분의 팀에게 이 조합이 비용 대비 이득이 가장 크다. 키워드 주도는 비개발자가 케이스를 대량으로 만들어야 하는 명확한 필요 가 있을 때만 검토한다.
프레임워크에 함께 들어가야 하는 것들
유형과 별개로, 쓸 만한 자동화 프레임워크에는 공통으로 갖춰야 할 요소가 있다.
| 요소 | 없으면 |
|---|---|
| 테스트 데이터 관리 | 하드코딩된 계정이 만료돼 전부 깨진다(모듈 7 레슨 2) |
| 환경 설정 분리 | URL·계정이 코드에 박혀 다른 환경에서 못 돈다 |
| 명확한 실패 리포트 | 왜 실패했는지 모르는 빨간 불만 남는다 |
| 스크린샷·트레이스 수집 | 실패 원인 분석에 재현부터 다시 해야 한다 |
| 재시도 정책 | 플래키가 신호를 죽인다(모듈 13 레슨 6) |
| 병렬 실행 | 케이스가 늘수록 실행 시간이 선형으로 는다 |
| CI 연동 | 사람이 눌러야 도는 자동화가 된다(모듈 14) |
두 번째와 세 번째가 자주 빠진다. 특히 실패 리포트가 부실하면 자동화의 신뢰가 무너진다. 모듈 14(레슨 5)에서 다룬 false alarm 문제와 같은 뿌리다 — 원인을 알 수 없는 실패가 반복되면 사람들은 결과를 무시하기 시작한다.
구조를 바꿔야 할 때의 신호
이미 만든 자동화의 구조를 바꿀지 판단하는 신호들이다.
- 화면 하나가 바뀌었는데 수정할 파일이 열 개를 넘는다
- 새 케이스를 추가하는 데 기존 코드를 복사 한다
- 같은 로직이 세 곳 이상에 중복 돼 있다
- 케이스 추가를 특정 한 사람에게만 부탁한다
- 실패를 분석하는 시간이 테스트를 만드는 시간보다 길다
두세 개가 동시에 보이면 구조 개선을 백로그에 올릴 때다. 다만 모듈 11(레슨 4)에서 배운 대로, 전면 재작성은 대개 실패한다. 새로 만드는 케이스부터 새 구조로 쓰고, 기존 것은 손댈 일이 생길 때 옮기는 점진적 방식이 현실적이다.
실무에서 왜 필요한가
자동화 채용 면접에서 자주 나오는 질문이 있다 — "어떤 프레임워크 구조로 짜셨나요?" 이때 도구 이름(Playwright, Selenium)을 답하는 사람과 구조(페이지 객체 + 데이터 주도, 왜 그렇게 골랐는지)를 답하는 사람은 층이 다르다. 도구는 배우면 되지만 구조 판단은 경험에서 나오기 때문 이다.
실무적으로는 유지보수 비용이 갈린다. 같은 200개 케이스라도 구조에 따라 화면 개편 시 하루가 걸리기도 하고 2주가 걸리기도 한다. 그리고 그 차이가 자동화가 살아남느냐 방치되느냐를 결정한다.
키워드 주도를 아는 것도 실익이 있다. 국내 SI·금융권에서 이 방식을 쓰는 조직이 있고, 상용 도구(모듈 15에서 다룬 계열) 중 키워드 방식을 채택한 것들이 있다. 처음 보는 도구도 "이건 키워드 주도구나"라고 분류할 수 있으면 적응이 빠르다.