Arda 개발 보고서
2026. 09. 29. github.com/Seuk-Team/Arda

목차 › 3. 요구사항 분석

요구사항 분석

엑셀·메일함으로 굴러가던 채용을 하나의 파이프라인으로 — 필수 27기능과 그 검수 기준 · 최종 갱신 2026. 09. 22.

전체 기능 목록 80개
필수 27개 · 27/27 구현
권장 / 여유 30 / 23개
개발 범위 요구 ID SFR 9 + SEC 2 + PER 2 + QUA 3
QA 시나리오 27+ 실패 7

1. 기존 채용 프로세스의 문제점

요구사항을 기능 목록에서 시작하지 않고 "인사팀이 왜 이걸 사는가"에서 시작했다 (docs/04_planning/01-시장조사-방향성.md, 2026. 08. 27.). 그 답이 없으면 기능을 아무리 쌓아도 우선순위를 정할 근거가 없기 때문이다. 조사에서 확인된 pain 은 다섯 가지이고, 각각을 그것을 받아내는 기능 영역에 대응시켰다.

PAIN 1

엑셀 + 메일함 + 채용플랫폼 3중 관리

지원자가 늘고, 담당자가 2인 이상이 되고, 개인정보 규정이 겹치는 세 조건이 동시에 걸리는 순간 엑셀이 무너진다. 지원자 정보가 세 곳에 흩어져 어느 것이 최신인지 알 수 없게 된다.

→ 단일 파이프라인 (B · C · D)

PAIN 2

행정 업무가 시간을 잡아먹는다

채용 코디네이터 업무의 46%가 일정 조율 등 행정이다. 면접 1건을 수동으로 조율하는 데 평균 243분, 이력서 1장을 훑는 데 30~90초, 지원자 1명에게 연락하는 데 5~15분이 든다.

→ 자동 메일 (G1) · 자동 서류 심사 · 일정 자동화

PAIN 3

협업이 안 된다

"누가 언제 어느 단계로 옮겼나", "면접관 3명의 평가가 어디 있나" — 엑셀에는 이 두 질문의 답이 없다. 기록이 없으니 나중에 아무도 설명할 수 없다.

→ 단계 이력 (D5) · 평가 (E1 · E2)

PAIN 4

응답 지연 = 후보 이탈 = 회사 평판

단계가 바뀌었는데 지원자가 모르면 기다리다 이탈하고, 무응답은 그대로 회사 평판이 된다. 사람이 한 통씩 보내는 구조에서는 지원자가 늘수록 지연도 같이 는다.

→ 단계 변경 자동 메일 (G1 · G2 · G3)

PAIN 5

컴플라이언스

채용절차법 · 개인정보보호법상 서류 보관 · 파기 의무가 있고, EU AI Act 는 채용을 고위험으로 분류하고, 사람 검토 없는 자동 합불을 문제 삼는다. 엑셀로는 이 의무를 이행했다는 것을 증명할 수 없다.

→ 접근 제어 (A3) · 이력 · 사람 확정 원칙

pain 이 실재한다는 가장 강한 증거는 정부가 중소기업 ATS 도입에 연간 이용료의 80%(최대 40만 원)를 지원하는 사업을 운영 중이라는 사실이다. 국가가 돈을 대는 문제라는 뜻이다. 시장 조사에 따르면 채용담당자의 71%가 이미 ATS 를 쓰고 있고, 79%가 채용의 일부를 자동화하고 있다. 즉 "ATS 가 필요한가"는 이미 끝난 질문이고, 남은 질문은 "AI 를 켜도 사고가 안 나는가"다.

그래서 이 프로젝트의 요구사항은 기능 개수가 아니라 한 문장의 정체성에서 파생됐다 — 반복 업무는 에이전트가 대신하고, 판단의 근거는 사람에게 보여주는 ATS. 비싼 것(기록 · 정리 · 취합 · 발송)은 자동화하고, 위험한 것(합불 판단)은 사람에게 남긴다. 이 원칙이 아래 기능 요구사항 전체를 관통하고, "최종 합불은 사람이 확정한다"(ADR-0003 → 0034)는 제약으로 박혀 있다.

2. 기능 요구사항

2-1. 개발 범위 — 요구 ID 9건

사업 단위의 개발 범위다. 각 항목에 검수 기준을 수치로 붙였다 — "구현했다"가 아니라 "무엇을 보면 됐다고 할 수 있는가"를 먼저 정하지 않으면 완료 판정이 사람마다 달라지기 때문이다.

요구 ID기능검수 기준
SFR-001 이력서 파싱 — PDF/DOCX 업로드 시 이름 · 학력 · 경력 · 기술스택 자동 추출 주요 필드 추출 정확도 90% 이상
SFR-002 칸반 보드 — 지원자 카드를 드래그하여 채용 단계 전환 상태 전환 시 DB 반영 200ms 이내
SFR-003 Tool-Calling Agent — 자연어 명령으로 지원자 검색 · 조회 · 단계 변경 · 면접관 배정 · 일정 제안 · 메일 초안/발송 · 이력서 드롭 접수 도구 12종 · 쓰기 도구는 확인 카드 필수 · 회귀 하네스 40시나리오 · 동일 채점기 23건 기준 Claude 69.6% / 자체학습 v9 73.9% (2026-09-17)
SFR-004 RAG 질의응답 · 시맨틱 검색 — 이력서 · 자소서 · 공고 기반 의미 검색 (ko-sroberta + pgvector, ADR-0021) 키워드 폴백 병행 · search_mode 로 벡터 가동 여부를 응답에 노출
SFR-005 지원자 관리 — 지원자 CRUD, 검색 · 필터링, 채용 단계별 목록 조회 전체 CRUD 정상 동작, 커서 페이지네이션 · 10만 건 111ms → 7.8ms
SFR-006 이메일 알림 — 채용 단계 변경 시 자동 이메일 발송 (n8n 웹훅 + SMTP, ADR-0030) n8n 장애 시 API 가 5분마다 재발송(최대 3회) · SES · SQS 는 폐기(ADR-0031 · 0036)
SFR-007 자동 서류 심사 — 3축(자격요건 · 우대사항 · 인재상) 100점 채점 → 임계 기준 자동 단계 이동 (ADR-0034) 자료 부족 자동 탈락 · 사람 개입 시 자동 판정 제외 · fit-check 24명 정확성 분석으로 가중치 개정
SFR-008 AI 면접 · 실시간 분석 — 맞춤 질문 · 음성 STT · 답변↔서류 대조 · 1:1 WebRTC · 표정/음성 참고 지표 (ADR-0029 · 0032 · 0038) 참고 지표는 점수 · 합불에 미반영 · 실시간 STT 는 서버 내 로컬 전사
SFR-009 제출물 무결성 원장 — SHA-256 해시 사슬 · DB 트리거 수정/삭제 거부 · Sepolia 앵커 (ADR-0028) 트리거 상태 변경은 감사 로그 · 서명 키는 서버 밖

2-2. 필수 27기능

전체 기능 목록은 80개이고, 이를 ● 필수 27 / ○ 권장 30 / △ 여유 23으로 나눴다. 필수 27은 기획 시점(2026. 08. 24.)에 판단한 4주의 현실적 상한이다 — "다 하고 싶다"가 아니라 "이것만 되면 제품이라 부를 수 있다"의 선이고, 게이트 판정과 QA 시나리오가 이 27개를 그대로 쓴다. 아래가 그 전체 목록이다.

영역번호기능비고
A. 인증 · 권한 A1 회원가입 / 로그인 (JWT) 토큰 12시간 · 비활성 계정은 발급된 토큰도 401
A2 역할 구분 — 관리자 / 멤버 개정 원안은 관리자/채용담당자/면접관 3종, 2026. 08. 31. ADR-0017 로 2종화
A3 역할별 조작 제어 개정 원안의 "면접관은 배정된 지원자만 조회" 폐지 — 조회는 로그인 전체 허용, 제한은 조작에만(ADR-0017)
B. 채용 공고 B1 공고 생성 / 수정 / 삭제 —
B2 공고 상태 — 임시저장 / 진행중 / 마감 진행중 공고만 공개 지원 링크가 활성화된다
B3 공고별 지원자 수 집계 —
C. 지원 (지원자용) C1 지원서 제출 폼 (로그인 없이) 공개 링크 /public/postings/{id}
C2 이력서 파일 업로드 presigned URL 로 브라우저 → S3 직접 업로드
C3 개인정보 수집 동의 미체크 시 제출 거부
D. 지원자 관리 D1 지원자 목록 (테이블 뷰) 이름 · 단계 · 경력 · 스펙 · 평점 · 지원일
D2 칸반 보드 (단계별 컬럼) 접수 / 서류 / 면접 / 최종 합격 / 불합격 5컬럼
D3 드래그로 단계 이동 실패 시 원위치 복귀 + 토스트 (낙관적 업데이트 롤백)
D4 지원자 상세 페이지 —
D5 단계 변경 이력 기록 (누가 / 언제 / 어디서 어디로) changed_by=NULL 은 시스템 자동 판정
D6 담당자가 지원자 직접 등록 —
E. 평가 E1 평가 코멘트 작성 (점수 + 텍스트) 멤버는 배정된 건만 작성 가능 (미배정 403)
E2 평가 목록 조회, 평균 점수 계산 —
F. 파일 F1 이력서 업로드 → S3 저장 API 서버를 경유하지 않는다
F2 presigned URL 다운로드 —
G. 알림 · 메일 G1 단계 변경 시 지원자에게 메일 발송 —
G2 메일 발송 비동기 처리 개정 원안 SQS + 워커 → n8n 웹훅 + SMTP (ADR-0030 · 0036). 화면 응답이 메일을 기다리지 않는다는 요구는 동일
G3 발송 실패 시 재시도 API 가 5분마다 재발송, 최대 3회 초과는 failed
H. 검색 · 필터 H1 이름 / 이메일 검색 더미 10만 건 기준 인덱스 튜닝 대상
H2 단계별 필터 —
J. 시스템 · 운영 J1 Docker 컨테이너 구성 docker compose up 으로 API · DB 기동, /health 응답
J2 AWS 배포 공개 URL 접속 + 헬스체크 정상
J3 API 문서 (Swagger) /docs 에서 전체 엔드포인트 조회 · Try it out

영역 I(통계) 에는 필수가 하나도 없다. 통계 5개는 전부 권장 · 여유로 밀었다 — I1 · I2 가 권장, I3 · I4 · I5 가 여유이고 "통계 대시보드는 여유가 생기면 여기부터 착수"가 기획 시점의 명시적 결정이었다.

2-3. 구현 현황 (2026. 09. 22. 기준)

구분개수현황
● 필수 27 27/27 구현 달성 — 2026. 09. 03. 달성 이후 유지
○ 권장 30 09. 03. 기준 22/30. 이후 ADR 편입 범위로 확장 진행
△ 여유 23 09. 03. 기준 0/23. 이후 ADR 편입 범위로 확장 진행

필수 27이 09. 03. 에 전부 끝났기 때문에, 이후의 개발은 기획서 밖의 범위를 ADR 로 정식 편입하는 방식으로 진행됐다. 그렇게 편입되어 배포까지 끝난 것은 — 도구 호출 에이전트(확인 카드 · 비용 관측 · 규칙 라우터 $0), 요약→평가→추천 3단 체인과 자동 서류 심사(ADR-0034), RAG 시맨틱 검색(ADR-0021), 면접 일정 자동화와 FAQ 챗봇, AI 면접(1:1 화상 · STT · 표정/음성 참고 지표, ADR-0029 · 0032 · 0038), 인적성 설문(ADR-0027), 지원자 로그인(ADR-0033), 제출물 무결성 원장과 Sepolia 앵커(ADR-0028), 헥사고날 재편(ADR-0035), 심사위원 데모 계정이다.

2-4. 명시적으로 제외한 요구사항

"안 한 것"에도 문서를 남겼다. 못 만들어서 뺀 것과 안 만드는 게 맞다고 판단해서 뺀 것은 완전히 다른 결정이고, 후자는 근거를 남기지 않으면 증명할 방법이 없기 때문이다. 아래 열 건 중 일곱은 ADR 이고, 실시간 화상면접 · SNS 크롤링 · 면접관 모방 모델 셋은 ADR 번호 없이 기획 문서(docs/04_planning/)에 근거가 남아 있다. 개정할 때도 원문을 지우지 않고 절을 덧붙인다.

항목원 결정과 근거현재
Kubernetes 제외 — "한 달 안에 실제로 굴렸다고 말할 수 없는 것은 넣지 않는다" (ADR-0001) 제외 유지 EC2 1대 + Docker Compose
표정 분석 제외 — 직무성과 예측 기여 0.25% 미만, 차별 위험, HireVue 가 2021. 03. 폐기 (ADR-0002) 개정 도입 ADR-0029 — 담당자 참고 지표까지만, 점수 재료 아님. 원 근거는 문서에 그대로 남김
AI 자동 합불 판정 AI 는 추천까지만 (ADR-0003) 개정 ADR-0034 — 서류 단계는 AI 자동 판정, 최종 합불만 사람. 안전장치 셋(이력 · 일괄 메일 · 수동 우선)
실시간 화상면접 제외 — 견적(시그널링 + TURN + SFU 4주)은 3인 이상이 전제였다 1:1 만 도입 둘이면 SFU 없이 P2P. 3인 이상 다자 화상면접은 그대로 제외이고, 집단 면접(지원자 여러 명 + 면접관 1명)은 시연 뒤 ADR 로 다시 본다
음성 감정 분석 ·
인적성 성격 판정
재서술 · 전사까지만 (ADR-0026 · 0027) 음성 신호는 참고 지표로 표시(점수 미반영) · 성격 판정 금지 유지
지원자 SNS 크롤링 제외 — 채용절차법 제4조의3 · 개인정보보호법 제15조 위반, 플랫폼 약관 위반도 별도로 발생 제외 유지
실시간 공동 편집 제외 (ADR-0005) — 메모는 행 추가 방식으로 대체 제외 유지
면접관 모방 모델 제외 — 면접관 성향 학습은 그 사람의 편향까지 복제한다. Amazon 이 2018년 같은 구조로 만든 채용 AI 를 폐기한 사례가 있고, 면접관 1명의 연간 면접 수로는 표본도 안 된다 (docs/04_planning/01-시장조사-방향성.md §5) 제외 대신 성향을 드러내는 캘리브레이션 (기능 목록 I5) 방향으로 뒤집음
SQS 워커 · SES 초기 메일 경로 폐기 ADR-0031 · 0036 — n8n + SMTP 로 전환, 스위치 3개로 공급자 교체 가능
온프레미스 자체 서빙 계획 (ADR-0024) 구축 후 폐쇄 로컬 sLLM 의 도구 오호출 · 예시 베끼기 · JSON 깨짐이 심사 직전 누적. Qwen 어댑터는 R&D 자산으로 보존

3. 비기능 요구사항

성능 · 보안 · 가용성 · 확장성 네 축이다. 축마다 검수 기준을 수치나 동작으로 정의했고, 실측값이 있으면 실측값을 적었다 — "빠르다" · "안전하다"는 판정할 수 없는 문장이기 때문이다. 가용성 항목은 대부분 설계가 아니라 실제 사고가 남긴 장치다.

3-1. 성능 (PER)

요구 ID항목검수 기준 · 실측 (2026. 09. 22.)
PER-001 지원자 검색 · 필터 더미 10만 건 기준 인덱스 튜닝 실측 111ms → 7.8ms
PER-002 실시간 면접 STT 오디오 청크 1.5초 예산 안에 전사 (GPU 실측 275ms / 3초 음성 · API 경로)
SFR-002 칸반 단계 전환 상태 전환 시 DB 반영 200ms 이내
G2 메일 발송 비동기 단계 변경 API 가 메일 발송 완료를 기다리지 않고 즉시 응답
성능 부하를 만들어 놓고 재는 것이 요구사항이다
  • 성능 요구는 더미 지원자 10만 건을 먼저 만들고(J7) 그 위에서 측정하는 것을 전제로 했다. 데이터가 수십 건일 때는 인덱스가 있으나 없으나 같은 속도가 나오므로 요구사항이 성립하지 않는다.
  • 목록 조회는 offset 이 아니라 커서 페이지네이션을 요구한다 — 뒤 페이지로 갈수록 느려지는 구조를 애초에 만들지 않기 위함이다.
  • AI 원가도 성능 지표로 관측한다 — 호출마다 모델명 · 토큰을 로깅하고, 실측 아르 호출당 $0.0075, 인사 · 능력 · 기본 FAQ 는 규칙 라우터가 LLM 없이 $0 로 처리한다. 대량 더미 데이터에는 AI 호출을 금지한다.
  • 실시간 면접의 성능 요구는 CPU 에서 충족되지 않았다 — t3.large(2 vCPU)에서 44초 발화가 180초를 넘겼고, 8명 동시 부하에서 STT 대기가 15초 → 42초로 늘었다. GPU 이관과 API 경로 전환(ADR-0038)으로 대기줄 0을 만들었다.

3-2. 보안 · 개인정보 (SEC)

요구 ID항목검수 기준
SEC-001 인증 · 인가 — JWT 기반 인증, CORS 설정, 개인정보 암호화 미인증 요청 401/403 차단, 개인정보 AES-256 암호화
SEC-002 데이터 보안 — 이력서 파일 S3 암호화 저장, 접근 권한 IAM 기반 제어 S3 SSE 활성화, IAM 정책 적용

권한 모델 (RBAC) — 등급은 둘뿐이고(ADR-0017), 위계가 아니라 조작 권한의 유무다. 조회는 로그인만 하면 전부 허용된다 — 옛 "면접관은 배정된 지원서만" 규칙은 폐지됐다.

등급권한 범위
admin 면접관 배정 · 해제 / 계정 생성 / 메일 템플릿 / 타인 가용 시간 — 이 넷이 admin 전용
member 그 외 전부 — 단 평가 작성은 배정된 건만
지원자 링크 안 일회성 토큰 또는 이메일 + 생년월일 8자리 로그인(ADR-0033) — 담당자 화면과 분리
시스템 · n8n 서비스 토큰(/internal/*) — 없으면 아예 호출하지 않는다
보안 · 개인정보 적용된 통제
  • JWT 12시간 · 비활성 계정은 이미 발급된 토큰도 401 — 퇴사자 토큰이 만료까지 살아 있는 구멍을 막기 위함이다.
  • APP_ENV=production 에서 공개 회원가입 차단 · 기본 시크릿 사용 불가. 오타나 미설정도 production 으로 잠기게 했다 — 안전한 쪽이 기본값이어야 한다.
  • 심사 데모 계정은 비밀번호 · 역할 변경이 403 — 공유 계정을 서로 잠그지 못하게.
  • 이력서 파일은 presigned URL 로 브라우저에서 S3 로 직접 올라간다 — 파일이 API 서버를 거치지 않아 서버 부담과 유출 접점이 함께 줄어든다.
  • 시크릿은 서버 .env 에만 두고 .env.example 에는 키 이름만 남긴다. IAM 은 콘솔용 · 서버 전용 유저로 분리하고 서버 유저는 최소 권한이다(ADR-0025).
  • AI 프롬프트에 연락처 · 주민번호를 넣지 않는다. 음성 경로는 STT_BACKEND 로 명시한다 — openai 면 외부 API 전송, faster_whisper 면 서버 내 로컬 전사(ADR-0038).
  • 사용자는 물리 삭제하지 않고 비활성화만 한다 — changed_by · evaluator_id 로 박힌 이력을 삭제가 부수기 때문이다.
  • 제출물 무결성 — 이력서 · 자소서의 SHA-256 을 추가 전용 원장에 해시 사슬로 쌓고, DB 트리거가 UPDATE · DELETE · TRUNCATE 를 거부한다. 사슬 머리는 매일 Sepolia 에 앵커하고 서명 개인키는 서버에 두지 않는다(ADR-0028).

3-3. 가용성

가용성 대부분 설계가 아니라 사고가 남긴 장치다
  • 메일 단일 장애점 제거 — n8n 이 웹훅을 받고 죽어 메일이 queued 로 남은 사고 이후, API 가 스스로 5분마다 밀린 메일을 SMTP 로 재발송한다(최대 3회, 초과는 failed). 경로가 하나뿐일 때 n8n 이 멈추면 합불 통보가 통째로 멎었다.
  • 백업 — 매일 04:00 KST DB pg_dump → gzip 검증 → S3(최소 권한 PutObject), 30일 자동 만료.
  • 경보 · 외부 감시 — CloudWatch 사용자 지정 지표(디스크 · 백업 나이 · API 헬스)를 SNS 메일로 받고, GitHub Actions 가 15분마다 외부에서 헬스체크해 실패 시 이슈를 자동으로 열고 닫는다.
  • 디스크 고갈 재발 방지 — 컨테이너 로그 상한 20MB × 3, 배포 때 이미지 · 캐시 prune, EBS 29 → 50GB. 디스크가 차서 배포가 멎은 사고의 후속이다.
  • 자동 복구 — EC2 시스템 상태 검사 실패 시 자동 복구 알람, 컨테이너 restart: unless-stopped.
  • 부분 실패 허용 — pgvector 확장을 못 켜면 API 전체가 죽는 대신 경고만 남기고 시맨틱 검색만 꺼진 채 기동한다. 확장 하나 때문에 API 가 재시작 루프에 빠져 /health 가 502 였던 사고의 후속이다.
  • 멈춤을 실패로 — Docker 가 죽어 pytest 가 24분간 조용히 멈춘 뒤 pytest-timeout 60초를 넣었다. 침묵은 성공도 실패도 아니라서 가장 늦게 발견된다.
  • 배포 안전망 — main 직접 push 는 브랜치 보호가 차단하고, CI 5잡이 전부 초록이어야 머지한다. main 머지 2분 뒤 자동 배포되므로 CI 빨간불 = 머지 불가가 유일한 게이트다.

3-4. 확장성

확장성 바꿔 끼울 수 있게 만드는 것이 요구사항이다
  • 클라이언트 추가가 서버 변경을 부르지 않는다 — React 웹 · Flutter 앱이 같은 FastAPI API 를 쓰는 계약 중심 설계다. ERD · API 문서를 코드와 같은 커밋에서 갱신하는 규칙이 이 계약을 지킨다.
  • 공급자 교체 가능 — 메일 · 큐 · 스토리지 · STT · 모델을 환경변수 스위치로 바꾼다 — MAIL_DISPATCH · QUEUE_BACKEND · S3_ENDPOINT_URL · STT_BACKEND · AGENT_*_BACKEND. AWS 의존을 8종에서 3종(EC2 · S3 · IAM)으로 줄인 것도 "AWS 를 떠나도 돌게" 하기 위함이다(ADR-0031 · 0036).
  • 구조 확장 — 헥사고날 부분 적용 — Bounded Context 4개(hiring · talent · application · interview) + 포트/어댑터(ADR-0035). models.py 를 71개 파일이 직접 참조하던 상태를 해소한 것이 목적이다. Full DDD 는 하지 않는다.
  • 스키마 확장 — 이행은 alembic 리비전 26개로 관리하고, CI 가 모델 ↔ 이행 결과를 비교해 이행 누락을 잡는다(2026. 09. 17.). git pull 로는 DB 가 따라오지 않으므로 uv run alembic upgrade head 한 줄로 전원이 따라올 수 있는 것이 규칙이다.
  • 현재 확인된 확장 제약 — 실시간 면접의 방 상태가 프로세스 메모리에 있어 API 워커를 1개로 묶어 둔 상태다. Redis 이관으로 이 제약을 푸는 것이 프리즈 뒤 계획으로 남아 있다. 집단 면접(지원자 여러 명 + 면접관 1명)도 ADR 단계다.

3-5. 품질 · 문서화 (QUA)

요구 ID항목검수 기준 · 현황 (2026. 09. 22.)
QUA-001 테스트 — 자동화 CI 에서 push · PR 마다 백엔드 pytest(실제 PostgreSQL + pgvector, alembic 이행 후) · 프론트 oxlint + tsc + build · 앱 flutter test · AI 서버 pytest 가 전부 초록이어야 머지. 백엔드 pytest 1,165건 통과
QUA-002 문서화 — API FastAPI Swagger /docs 에서 전체 API 명세(107 라우트) 조회 가능
QUA-003 문서화 — 스키마 모델 ↔ alembic 이행 결과를 CI 가 비교해 이행 누락을 잡는다. ERD 테이블 28개(v2.8)가 전원의 계약이다

4. 사용자 시나리오

필수 27기능을 전제 → 절차 → 기대 결과 형식의 시나리오 27건으로 풀어 docs/00_overview/qa-scenarios.md 에 정리했고, 여기에 실패 케이스 7건을 더했다. 시나리오는 게이트 판정과 통합 리허설의 체크리스트로 쓰인다 — "구현했다"는 주장 대신 "이 절차를 밟으면 이것이 보인다"로 완료를 판정하기 위함이다. 아래는 행위자별 대표 시나리오 넷이다.

C1 · C2 · C3 · F1 지원자가 로그인 없이 지원서를 낸다 행위자 — 지원자 (외부, 비로그인)
전제

진행중 상태인 공고의 공개 지원 링크(/public/postings/{id})를 브라우저에 열었다. 로그인하지 않은 상태이고, PDF 이력서(5MB 이하)를 준비했다.

절차

공고 정보를 확인하고 이름 · 연락처 · 이메일 · 최종학력을 입력한다. 이력서 첨부 영역에 파일을 끌어 놓는다. 개인정보 수집 동의를 체크하고 "지원서 보내기"를 누른다.

기대

파일은 presigned URL 로 브라우저에서 S3 로 직접 올라가고(API 서버 미경유) 진행률과 파일명 · 용량이 표시된다. 제출 완료 화면이 뜨고, 담당자가 해당 공고의 지원자 목록을 열면 방금 낸 지원자가 "지원 접수" 단계로 나타난다. 동의를 체크하지 않으면 제출 자체가 되지 않는다.

D2 · D3 · D5 · G1 담당자가 칸반에서 카드를 끌어 단계를 옮긴다 행위자 — 채용담당자
전제

지원자 목록 화면에서 보기 방식을 "칸반"으로 전환했다. 접수 / 서류 / 면접 / 최종 합격 / 불합격 다섯 컬럼이 가로로 나열되고, 각 지원자가 현재 단계 컬럼에 카드로 있다. 지원자의 이메일이 등록되어 있다.

절차

"서류 검토" 컬럼의 카드를 "면접" 컬럼으로 끌어 놓는다. 이어서 해당 지원자의 상세 화면에서 단계 이력을 확인한다.

기대

카드가 옮겨지고 변경 이력이 누가 / 언제 / 어디서 어디로 형태로 시간순 기록된다. 지원자에게 안내 메일이 발송되고 발송 기록이 남는다. 실패하면 카드가 원래 위치로 돌아가고 토스트 알림이 뜬다 — 낙관적 업데이트의 롤백이다. 전진은 한 칸씩만 가능하고, 역행은 항상 허용된다 — 사람이 AI 판정을 되돌리는 안전장치이기 때문이다. 불합격으로 옮길 때 사유가 없으면 422 다.

E1 · E2 · A3-2 면접관이 배정된 지원자에게 평가를 남긴다 행위자 — member 등급 사용자
전제

member 계정으로 로그인했다. 본인에게 배정된 지원자가 2명, 배정되지 않은 지원자가 10명 있다.

절차

지원자 목록 · 평가 현황 · 검색 화면을 확인하고, 배정되지 않은 지원자의 상세도 연다. 배정된 지원자와 배정되지 않은 지원자 각각에서 점수(1~5)와 코멘트 입력을 시도한다.

기대

조회는 12명 전원이 열린다 — 배정되지 않은 지원자의 상세 · 이력 · 평가 · 메모 · 이력서도 정상 열람된다(ADR-0017 로 조회 제한 폐지). 평가 작성은 배정된 건만 저장되고, 배정되지 않은 건은 403 과 "본인에게 배정된 지원자만 평가할 수 있습니다" 안내가 나온다. 점수를 고르지 않으면 등록 버튼이 비활성이다. 면접관 2명이 4점 · 5점을 남기면 상세에 두 건과 평균 4.5가 표시된다. 로그아웃 상태에서 같은 URL 을 열면 401 이다.

A2 · A3-3 관리자만 할 수 있는 조작을 확인한다 행위자 — admin / member
전제

admin 계정과 member 계정이 각각 있다.

절차

member 계정으로 ① 면접관 배정 · 해제 ② 남의 가용 시간 등록 · 삭제 를 시도한다. 같은 조작을 admin 계정으로 다시 한다. admin 계정에서는 설정 → 사용자 관리로 한 사용자의 역할을 멤버에서 관리자로 바꾼다.

기대

member 는 둘 다 403, admin 은 성공한다. 단 본인 가용 시간은 member 도 등록 · 삭제할 수 있다 — 자기 일정은 자기 것이기 때문이다. 역할은 관리자 / 멤버 2종뿐이고 변경한 역할이 목록에 반영된다.

4-1. 실패 케이스 7건

정상 흐름만 확인하면 거절해야 할 것을 거절하는지는 알 수 없다. 실패 케이스는 기대 결과를 "에러가 난다"가 아니라 안내 문구까지, 정해진 것은 상태 코드까지 적었다.

번호상황기대 결과
F-1 같은 공고에 같은 이메일로 중복 지원 "이미 지원한 공고입니다" 안내 후 제출 거부(409). 기존 지원 기록은 변경되지 않는다
F-2 .exe 등 허용되지 않는 파일 형식 업로드 업로드 거부 + 허용 형식(pdf · docx · hwp) 안내를 함께 표시
F-3 50MB PDF 등 용량 초과 파일 업로드 업로드가 시작되지 않고 최대 허용 용량을 함께 안내
F-4 미배정 지원자 상세 URL 직접 입력 폐지 ADR-0017 로 조회 제한이 없어져 이 케이스는 더 이상 유효하지 않다. 대체 확인 항목은 A3-2(평가 작성 403)
F-5 마감된 공고에 지원 시도 "마감된 공고입니다" 안내 후 제출 불가. 폼 자체가 비활성이거나 접수 불가 화면
F-6 잘못된 비밀번호로 로그인 "이메일 또는 비밀번호가 올바르지 않습니다" — 어느 항목이 틀렸는지 구분하지 않는다(계정 존재 여부 노출 방지)
F-7 필수 항목(이름)을 비우고 지원서 제출 누락 항목을 지목한 안내 표시 후 제출 차단

4-2. 시나리오 문서와 현재 구현의 차이

QA 시나리오 문서는 2026. 08. 24. 작성된 초안이고, 화면이 없던 시점이라 확정되지 않은 UI 디테일에 "(화면 확정 후 갱신)" 표식이 붙어 있다. 그 뒤 결정이 개정되면서 시나리오 자체가 낡은 항목이 셋 있다 — 이것을 지우지 않고 남겨 두는 이유는, 무엇이 왜 바뀌었는지가 요구사항 이력이기 때문이다.

항목초안 (08. 24.)현재
A2 역할 3종 — 관리자 / 채용담당자 / 면접관 2종 — admin / member (ADR-0017, 08. 31.)
A3 · F-4 면접관은 배정된 지원자만 조회 조회 제한 폐지 — 제한은 조작에만. 확인 항목이 A3-1 · A3-2 · A3-3 으로 쪼개졌다
G2 SQS 큐에 메시지가 들어가고 워커가 처리 n8n 웹훅 + SMTP (ADR-0030 · 0036). "화면 응답이 메일을 기다리지 않는다"는 요구 자체는 동일하고, 그것을 만족시키는 수단만 바뀌었다

시나리오와 실제 배포본이 어긋나지 않는지는 사람 눈이 아니라 스크립트로 대조한다 — check_public_contract.py 가 배포본 OpenAPI 와 main 의 경로 · 스키마 · 인증을 비교하고, 08. 31. 실측에서 35/35 · 62/62 일치를 확인했다.

← 목차로