QA Engineer
AI 에이전트를 직접 만들어 QA 파이프라인을 자동화한 엔지니어
0종
AI QA 에이전트 개발
0+
버그 식별
2h
30m
회귀테스트 단축
0%
토큰 비용 절감
Core
Tools & Infra
Education
단국대학교 응용컴퓨터공학과
2018.03 ~ 2022.08
Certifications
ISTQB CTFL 2023.02
컴퓨터활용능력 1급 2022.01
총 4년+ 경력 (2022.05 ~ 현재)
QA Engineer
2025.11 ~ 재직중
QA Engineer
2025.01 ~ 2025.10
QA Specialist
2024.01 ~ 2025.01
QA Manager
2022.05 ~ 2023.11
스킬 3종
qa-create-tc
tech-spec AC(GWT) + DesignSpec → tc.md 자동 생성
tc-auto-test
TC → E2ESpec YAML → spec 생성 → Playwright 실행 → 리포트
e2e-gen
자연어 시나리오 → E2ESpec YAML → BDD spec 생성
에이전트 4종
test-writer
E2ESpec → BDD spec 작성, POM 메서드 직접 추가
pom-writer
POM 작성/수정 (리팩토링 + 신규)
e2e-reviewer
spec/POM 의미적 검증 + 코드 리뷰 + 수정
e2e-rule-checker
grep 기반 규칙 위반 탐지 → 리포트
Phase 1 — TC 생성 (agentic-sd)
tech-spec + DesignSpec 읽기
AC(GWT) → TC 변환
Phase 2 — E2E 자동 실행 (web-app)
name: 링크서명 2인 서명 요청
domain: linkSignature
preconditions:
- 로그인 상태
- 문서 1건 업로드 완료
scenarios:
- name: 서명자 2명에게 이메일 서명 요청
steps:
- action: addSigners
params: { count: 2, method: email }
- action: addSignatureFields
params: { signerIndex: [0, 1] }
- action: sendRequest
expected:
- 서명 요청 완료 토스트 노출
- 문서 상태가 "서명 진행중"으로 변경
Canary 패턴
첫 번째 spec 1개를 먼저 실행하여 조기 실패 감지, 최대 2회 재시도 후 나머지 전체 실행
POM 충돌 방지
Phase 1에서 pom-writer로 필요한 POM 메서드를 한번에 추가, Phase 2에서 test-writer는 spec만 생성 (POM 읽기 전용)
토큰 최적화
reviewer에게 파일 내용을 프롬프트에 직접 삽입하여 Read tool call 최소화 (876K → 200K 토큰, 75% 절감)
크로스 레포 연동
agentic-sd에서 TC 생성 → web-app에서 E2E 실행, 절대경로로 tc.md 참조
| # | 섹션 | 내용 |
|---|---|---|
| 1 | AI 친화적 구조 원칙 | Self-describing, Predictable, Composable |
| 2 | Locator 사용 규칙 | 시맨틱 locator 우선순위 7단계, CSS/ID 금지 |
| 3 | 메서드 작성 규칙 | prefix 10종, 파라미터 규칙, 코드 배치 순서 |
| 4 | 공통 모듈 정의 | Page/Component/Flow 3계층 역할 분리 |
| 5 | 리팩토링 가이드 | 체크리스트 + 수정/삭제 백로그 |
| 6 | TC → Spec 자동 생성 | /e2e-gen, /tc-auto-test 스킬 연동 |
| 7 | AI 에이전트 | 4종 에이전트 역할 정의 + 자동 검증 규칙 |
| 8 | 도메인 레지스트리 | JSDoc 태그 분석 → 자동 갱신 스크립트 |
| 9 | 도메인 패턴 가이드 | 도메인별 기본 상태, gotcha, 사전 조건 |
1. getByRole() ← 최우선 (시맨틱)
2. getByText()
3. getByLabel()
4. getByPlaceholder()
5. getByAltText()
6. getByTitle()
7. getByTestId() ← 최후 수단
━━━━━━━━━━━━━━━━━━━━
✗ CSS selector ← 금지
✗ ID selector ← 금지
✗ XPath ← 금지
Page
URL 컨텍스트 대표, Component 생성/반환, spec의 진입점
Component
단일 UI 요소 래핑, spec에서 직접 생성 금지
Flow
여러 Page/Component 조합, 비즈니스 워크플로우 수행
바텀시트 열림
→ aria-busy="true" 감지
→ height 안정화 대기 (CSS transition 완료)
→ aria-busy="false" 확인
→ 버튼 클릭 가능
사인/도장 바텀시트 열기/닫기
이미지 첨부 바텀시트
체크박스 바텀시트
약관 동의 바텀시트
776줄 핵심 POM을 CLAUDE.md 규칙 기반으로 4단계 전면 리팩토링. 리팩토링 결과 CLAUDE.md 모범 예시로 지정됨.
| 항목 | Before | After |
|---|---|---|
| SignaturePage 역할 | Page + Flow 혼재 | Page만 (단일 액션) |
| Flow 메서드 | SignaturePage에 포함 | SignatureFlowPage 분리 |
| 미사용 locator | 다수 방치 | 제거 완료 |
| 모바일 지원 | 없음 | device 분기 구조 |
PDF 렌더링 검증 수단이 없어 수동 비교에 의존하던 문제를 해결. PDF 스냅샷 캡처 → 기준 스냅샷 비교, 필드 위치 스크린샷 비교를 CI/CD 품질 게이트에 통합.
PDF 스냅샷 비교
임계값 초과 시 자동 실패
필드 위치 스크린샷
리사이징 변경 자동 감지
CI/CD 통합
품질 게이트로 자동 차단
링크서명 플로우 전면 개선, 내부결재 비동기 대기 로직으로 flaky 해소, 외부 서버 의존을 로컬 파일 업로드로 전환하여 CI 안정성 확보.
링크서명
UX 변경 시 회귀 자동 감지
내부결재
flaky 테스트 완전 해소
CI 안정성
외부 의존 제거
1. 회원가입 → 로그인
SMS 인증 자동화 포함
2. 상품 구매 플로우
옵션 선택, 가격 계산, 결제
3. 마이페이지 검증
구매 내역, 수강 상태 확인
* 보안 정책상 실제 코드 대신 동일 패턴의 구현 예시입니다
export class PaymentPage {
constructor(private page: Page) {}
async selectOption(optionName: string) {
await this.page.click(`[data-option="${optionName}"]`);
}
async verifyPrice(expected: number) {
const price = await this.page
.locator('.total-price')
.textContent();
expect(Number(price?.replace(/[^0-9]/g, '')))
.toBe(expected);
}
async proceedPayment() {
await this.page.click('[data-testid="pay-button"]');
await this.page.waitForURL('**/payment/complete');
}
}
async function getVerificationCode(phone: string) {
const response = await request.get(
`${TEST_API}/sms/latest?phone=${phone}`
);
const { code } = await response.json();
return code;
}
// 테스트에서 사용
const code = await getVerificationCode('01012345678');
await page.fill('[data-testid="sms-code"]', code);
await page.click('[data-testid="verify-btn"]');
name: E2E Tests
on:
pull_request:
branches: [main]
jobs:
e2e:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- run: npm ci
- run: npx playwright install --with-deps
- run: npx playwright test
- uses: actions/upload-artifact@v4
if: failure()
with:
name: test-results
path: test-results/
E2E 테스트 결과 Slack 자동 알림
GitHub PR / 커밋 히스토리
1. SMS 인증 자동화
테스트 전용 API 엔드포인트를 활용하여 인증 코드를 프로그래밍 방식으로 조회, 수동 개입 없이 전체 인증 플로우 자동화
2. 결제 로직 검증
테스트 결제 게이트웨이를 통한 실제 결제 플로우 시뮬레이션, 옵션별 가격 계산 로직 검증
3. 테스트 데이터 관리
테스트 실행마다 독립적인 데이터 셋업/클린업으로 테스트 간 의존성 제거
Lambda A — 이벤트 라우터
이벤트 타입 분류 · 중복 요청 필터링
Lambda B
이슈 생성
Lambda C
댓글 동기화
Slack 메시지 → Jira 티켓 자동 생성 화면
* 보안 정책상 실제 코드 대신 동일 패턴의 구현 예시입니다
exports.handler = async (event) => {
const body = JSON.parse(event.body);
// Slack URL 검증
if (body.type === 'url_verification') {
return { statusCode: 200, body: body.challenge };
}
// 중복 이벤트 필터링
const eventId = body.event_id;
const isDuplicate = await checkDuplicate(eventId);
if (isDuplicate) return { statusCode: 200 };
const eventType = body.event?.type;
if (eventType === 'message' && !body.event.thread_ts) {
// 새 메시지 → 이슈 생성
await invokeLambda('issue-creator', body.event);
} else if (eventType === 'message' && body.event.thread_ts) {
// 스레드 댓글 → 댓글 동기화
await invokeLambda('comment-sync', body.event);
}
return { statusCode: 200 };
};
중복 처리
DynamoDB TTL을 활용한 이벤트 ID 기반 멱등성 보장으로 동일 이벤트 중복 처리 방지
사용자 매핑
Slack User ID ↔ Jira Account ID 매핑 테이블로 자동 리포터 할당
Jira 키 추출
Slack 메시지 내 Jira 이슈 키 정규식 추출로 기존 이슈 댓글 자동 연결
AWS Lambda
매일 자동 발송되는 배포 현황 Slack 메시지
* 보안 정책상 실제 코드 대신 동일 패턴의 구현 예시입니다
def get_deploy_issues(fix_version: str) -> list:
jql = (
f'fixVersion = "{fix_version}" '
f'AND status in (Done, "In Review") '
f'ORDER BY team ASC'
)
issues = jira.search_issues(jql, maxResults=100)
return categorize_by_team(issues)
에러 처리
Jira API 타임아웃 시 재시도(exponential backoff), 실패 시 Slack 에러 알림 자동 발송
빈 배포일 처리
배포 이슈가 없는 날에도 "오늘 배포 없음" 메시지를 전송하여 정보 공백 방지
메시지 상태 관리
DynamoDB에 메시지 ID 저장, 새로고침 버튼 클릭 시 기존 메시지 업데이트 (중복 메시지 방지)
커뮤니티 스쿼드 Slack 채널 버그 리포트 현황
| 활동 | 내용 |
|---|---|
| 상태 기반 TC 설계 | 게시글/댓글/유저 상태 조합별 TC 매트릭스 작성 |
| 기획 변경 대응 | 변경 사항 영향도 분석 → TC 즉시 업데이트 → 회귀 범위 재산정 |
| VOC 대응 루프 | VOC 수집 → 시나리오 추가 → 회귀 테스트 반영 |
| 릴리즈 QA | 스프린트 별 릴리즈 QA 일정 관리 및 실행 |
| 지표 | Before | After |
|---|---|---|
| QA 누락 | 빈번 | 0건 |
| 월간 핫픽스 | 3건 | 0~1건 |
| 릴리즈 지연 | 간헐적 | 0건 |
신규 웹 트레이딩 시스템(WTS)의 QA를 0부터 담당. 기존 문서화된 기준이 없는 상태에서 기획서, 디자인, API 명세를 분석하여 TC를 체계적으로 작성. 4차례에 걸친 이터레이션을 통해 TC를 지속적으로 보완하고, 개발자와 직접 소통하며 엣지 케이스를 발견.
1차
기본 기능 TC 작성
2차
엣지 케이스 추가
3차
회귀 TC 보완
4차
런칭 전 최종 검증
| 항목 | 수치 |
|---|---|
| 작성 TC | 1,000+건 |
| 탐지 이슈 | 4,000+건 |
| 이터레이션 | 4회 |
| 런칭 결과 | 오류 없는 정식 런칭 |
* 보안 정책상 실제 코드 대신 동일 패턴의 구현 예시입니다
class StockDetailPage {
constructor(page) {
this.page = page;
}
async navigateTo(stockCode) {
await this.page.goto(
`/stock/${stockCode}`
);
await this.page.waitForSelector(
'[data-testid="stock-price"]'
);
}
async getCurrentPrice() {
return await this.page
.locator('[data-testid="stock-price"]')
.textContent();
}
async clickBuyButton() {
await this.page.click(
'[data-testid="buy-button"]'
);
await this.page.waitForSelector(
'.order-modal'
);
}
async placeOrder(quantity) {
await this.page.fill(
'[data-testid="quantity"]',
String(quantity)
);
await this.page.click(
'[data-testid="confirm-order"]'
);
}
}
FROM mcr.microsoft.com/playwright:v1.40.0
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
# 비디오 증적 저장 디렉토리
RUN mkdir -p /app/test-results/videos
CMD ["npx", "playwright", "test", \
"--reporter=html,json"]
from fastapi import FastAPI
from datetime import datetime
app = FastAPI()
@app.get("/api/test/stock/{code}")
async def get_test_stock(code: str):
"""테스트용 주식 데이터 반환"""
return {
"code": code,
"price": 50000,
"change": 2.5,
"timestamp": datetime.now().isoformat()
}
@app.post("/api/test/order")
async def create_test_order(order: dict):
"""테스트 주문 생성 (실제 체결 없음)"""
return {
"orderId": f"TEST-{datetime.now().timestamp()}",
"status": "FILLED",
**order
}
1. 로그인 / 로그아웃
2. 종목 검색
3. 종목 상세 조회
4. 매수 주문
5. 매도 주문
6. 주문 취소
7. 잔고 조회
8. 주문 내역 조회
9. 차트 렌더링
10. 호가창 실시간 업데이트
11. 커뮤니티 댓글
12. 알림 설정
4년간 현장에서 얻은 관점
혼자서 전체 제품을 커버하려면 수동 반복을 제거하는 수밖에 없습니다. 처음엔 E2E 자동화로 회귀테스트를 2시간에서 30분으로 줄였고, 이후엔 TC 작성과 코드 생성까지 AI로 자동화했습니다. 결과적으로 "QA가 한 명이라 못 한다"는 말이 나오지 않는 환경을 만들었습니다.
핫픽스 월 3건 → 0건 | QA 누락 0건 | 스킬 3종 + 에이전트 4종
AI 에이전트가 TC를 자동 도출하고 E2E 코드를 생성해도, 어떤 시나리오가 중요한지, 어떤 엣지 케이스가 위험한지는 사람이 판단합니다. 저는 AI가 반복 작업을 맡게 하고, 그 시간에 리스크 분석과 테스트 전략에 집중합니다. 토큰 75% 절감도 "더 많이 쓰자"가 아니라 "더 똑똑하게 쓰자"의 결과입니다.
토큰 876K → 200K (75% 절감) | Canary 패턴으로 조기 실패 감지
480줄 POM 가이드를 쓴 이유는 단순합니다. 제가 없어도 같은 품질의 E2E 코드가 나와야 하니까요. AI 에이전트도 이 문서를 참조해서 코드를 생성합니다. 사람과 AI 모두 같은 기준으로 움직이는 것 — 그게 진짜 표준화입니다.
480줄 POM 가이드 | TC 작성 표준화 | 4종 에이전트가 동일 규칙 참조