프로젝트 소개
최종 갱신 2026-09-28 — 09-18 코드 동결 기준, STT 경로·GPU 운영 표기를 실제 운영값으로 정정.
Arda
채용 지원자 관리 시스템(ATS) — 공고 등록부터 지원 접수, 단계별 심사·평가, 합불 통보까지
핵심 소주제
1. 채용 프로세스 통합 관리 파이프라인
‘최종 합불은 항상 사람이 확정한다’라는 원칙을 기반으로, [공고 등록 → 접수 → 단계별 심사 → 결과 통보]까지의 채용 전 과정을 하나의 시스템으로 통합한다. 메인 화면은 지원자 칸반 보드로, 카드를 드래그해 단계를 이동하면 이력이 자동 기록되고 안내 메일이 n8n 웹훅 + SMTP로 발송된다(실패 시 API가 5분마다 재발송). 서류 단계는 아르가 자격요건·우대사항·인재상 3축으로 100점 채점해 임계(기본 60) 기준으로 자동 이동하고(ADR-0034), 자료가 부족한 지원자도 자동 서류 탈락 처리한다 — 사람이 한 번 손대면 그 지원자는 이후 자동 판정에서 빠진다. JWT 기반 역할 접근 제어(권한 등급은 admin·member 둘, ADR-0017)와 더미 지원자 10만 건 기준 검색·필터 튜닝(111ms → 7.8ms)을 포함한다.
2. AI 모델 전략 — 온프레미스 자체학습으로 검증하고, 클라우드 + Claude로 확정
애초 목표는 경량 LLM(sLLM)과 STT 를 온프레미스에서 구동해 지원자 개인정보가 외부 API 로 나가지 않는 ‘데이터 반출 없는 채용 에이전트’였다. 이를 실측으로 검증했다 — Qwen3-8B 를 QLoRA 로 자체학습해 어댑터 3갈래(도구 호출·요약·면접)를 만들고, 같은 채점기(judge.py · 동일 23건)로 재니 학습 전 26.1% → v9 73.9% 로 Claude Haiku(69.6%)와 동급까지 올라왔다. 학원 PC 3대에 실제 온프레미스도 구축해 운영했다.
결정(2026-09-18) — 심사·운영 서빙은 클라우드(AWS) + Anthropic Claude 로 확정했다. 정확도가 아니라 수치 추론·형식 안정성(경력 연수 오차·프롬프트 예시 베끼기·JSON 깨짐)과 지연·동시성(콜드 스타트 78초 · 동시 접속 시 대기줄)에서 갈렸고, 그 오류들이 심사 직전에 누적됐기 때문이다. Qwen 자체학습은 “public API 없이도 갈 수 있는가”에 실측으로 답한 비용 절감 R&D 자산으로 보존한다. 개인정보 보호는 프롬프트에 연락처·주민번호를 넣지 않는 규칙과 표정·음성 신호를 AI 판정 입력에서 배제하는 정책(ADR-0029)으로 지킨다.
3. 지원자가 24시간 접근 가능한 면접 일정 자동화 서비스
면접관들의 가용 일정을 파악해 지원자에게 후보 시간을 제안하고, 선택을 받아 일정을 확정과 통보하는 조율 과정을 에이전트가 자동화한다. 지원자는 안내 이메일의 링크(일회성 토큰) 또는 이메일 + 생년월일 로그인(ADR-0033)으로 24시간 접속해 전형 현황·면접 일정·인적성 설문·AI 면접을 한 화면에서 진행하고, 궁금한 사항은 FAQ 챗봇이 답한다 — 인사·연봉·합격 가능성 같은 기본 질문은 규칙 응답($0), 나머지는 공고와 회사 프로필을 근거로 Claude가 답한다. 확정 및 변경 통보는 메일 파이프라인(n8n 웹훅 + SMTP · ADR-0030)을 재사용하며, 수 회의 메일 왕복에 걸리던 조율 시간을 단축하고 반복적인 문의 응대를 제거하는 것이 목표다.
4. LLM 도구 호출 에이전트 및 AI 면접 분석 — STT · 근거 대조 · 실시간 참고 지표
“김도현 찾아줘 → 면접 안내 이메일 만들어줘”처럼 자연어 대화만으로 지원자 검색/조회/단계 변경/이메일 초안을 수행하는 도구 호출(Tool-Use) 에이전트를 개발하며, 실행성 작업은 초안(pending_action)까지만 만들어 사람의 확인을 거친다. 면접 분석은 [STT → 근거 대조 → Claude] 파이프라인이다 — Whisper 가 면접 음성을 전사하면(업로드 답변은 whisper-1 API, 실시간 면접은 CPU 로컬 faster-whisper — ADR-0038), 해당 지원자의 이력서·자소서·직무 요건에서 관련 근거를 찾아 컨텍스트로 결합하고, Claude 가 그 근거를 인용하며 답변이 서류와 일치하는지 대조·요약해 평가 기록으로 전환한다. 서류 요약도 요약→평가→추천 3단 체인(ADR-0022)으로 자격요건·우대사항·인재상 3축을 채점한다. 담당자는 1:1 WebRTC 실시간 화면으로 면접을 보며 답변↔서류 대조 결과를 즉시 확인하고, 표정(ViT + MediaPipe)·음성 신호는 참고 지표로만 표시되며 점수·합불에 쓰지 않는다(ADR-0029). 채용과 무관한 질문은 “답의 근거가 우리 데이터냐”를 기준으로 내용 없이 거절한다. 근거 문서 없이 모델이 단독 판단하지 않는 구조이며, 채팅·요약·STT 전 기능에 토큰·비용 로깅을 통일해 AI 원가를 관측한다 — 실측 아르 호출당 평균 $0.0075, 인사·능력·기본 FAQ 는 규칙 라우터가 LLM 없이 $0 로 답하는 원가 관측 체계를 갖췄다.
5. 웹/모바일 멀티 클라이언트 및 운영 체계
React(Vite/TS) 웹과 Flutter 모바일 앱이 동일한 FastAPI API를 사용하는 계약 중심 설계로, API/ERD 문서를 코드와 같은 커밋에서 갱신하는 규칙으로 4인 병렬 개발의 정합성을 유지한다. Docker, AWS(EC2/S3) + n8n·SMTP 메일, GitHub Actions 기반 CI 와 자동 CD(main 머지 → 2분 폴링 배포)와 함께 도메인별 파트 분담, ADR 36건, 헥사고날 재편(Bounded Context 4개 · ADR-0035), 팀원별 소유 파일 기반 무충돌 칸반 운영까지 — 산출물뿐 아니라 협업 체계 자체도 확장 가능한 구조로 설계한다.
주요 기능
| 기능 | 설명 |
|---|---|
| 지원자 칸반 보드 | 카드를 드래그해 단계 이동(지원 접수 → 서류 검토 → 면접 → 최종 합격/불합격). 모든 이동은 단계 이력으로 기록 |
| 단계 변경 자동 메일 | 단계 이동 시 지원자에게 메일 자동 발송. API 가 n8n 웹훅으로 넘기고 SMTP 로 발송 — n8n 이 죽어도 API 가 5분마다 밀린 메일을 재발송(최대 3회). 자동 서류 탈락 메일은 즉시 안 나가고 마감 뒤 담당자가 일괄 발행(번복 여지) |
| 공고 관리 · 공개 지원 링크 | 채용 공고 등록·관리. 지원자는 로그인 없이 외부 공개 링크로 지원서 제출 |
| 이력서 S3 업로드 | presigned URL로 브라우저에서 S3에 직접 업로드 — 파일이 API 서버를 거치지 않는다 |
| 지원자 검색·필터 | 이름·학교·기술스택 검색과 필터(10만 건 기준 인덱스 튜닝) + 임베딩 기반 시맨틱 검색으로 의미가 비슷한 지원자 탐색(ADR-0021) |
| 평가 · 면접관 배정 | 면접관 배정, 단계별 점수·코멘트 평가 기록 |
| AI 이력서 요약 | 제출된 이력서·자소서를 3단계 체인(추출→요약→검증)으로 요약해 담당자 화면에 표시. 근거가 부족하면 지어내는 대신 ‘판단 불가’로 표시하고, 어떤 모델이 만들었는지 태그로 기록한다(ADR-0022) |
| 아르 — 채용 에이전트 채팅 | 담당자가 자연어로 지원자 조회·검색·단계 변경을 요청하는 도구 호출 에이전트. 실행 전 확인 카드로 사람이 승인하고, 호출 비용을 관측하며, 뻔한 요청은 의도 라우터가 LLM 없이 코드로 처리한다 |
| 면접 일정 조율 | 면접관 가용 시간과 지원자 선택을 맞춰 확정하는 공개 링크 흐름. 지원자는 대화형 페이지에서 일정을 확인·확정하고, FAQ 챗봇이 문의에 즉답한다 |
| AI 면접 · 실시간 1:1 화상 | 지원자가 로그인해 이력서·자소서 기반 맞춤 질문에 음성으로 답하는 사전 면접. 담당자는 WebRTC 로 실시간 화면을 보며 답변이 서류와 일치하는지 대조 결과를 즉시 확인한다. 표정(ViT + MediaPipe)·음성 신호는 담당자 참고 지표로만 화면에 표시되고 점수·합불 판정에는 쓰지 않는다(ADR-0029 · 0032). 음성은 Whisper 로 전사해(업로드 답변은 API, 실시간은 로컬 — ADR-0038) 같은 파이프라인으로 분석 |
| 자동 서류 심사 | 아르가 자격요건·우대사항·인재상 3축으로 100점 채점, 임계(기본 60) 이상은 면접으로·미만은 서류 탈락으로 자동 이동(ADR-0034). 자료가 부족한 지원자(자소서 1줄·미기재)도 자동 탈락. 사람이 한 번 손대면 이후 자동 판정에서 빠진다 — 수동이 항상 이긴다 |
| 인적성(사전 성향) 설문 | 접수·서류 검토 단계의 지원자에게 메일로 발송하는 10문항 설문(5점 척도). 카테고리 통계는 코드가 계산하고, 아르는 응답을 관찰 문장으로 재서술만 한다 — 성격 유형 판정·점수화·합불 의견은 만들지 않으며, 미응답 불이익도 없다(ADR-0027) |
| 제출물 무결성 원장 (블록체인) | 이력서·자소서의 파일 지문(SHA-256)을 추가 전용 원장에 해시 사슬로 쌓고, DB 트리거가 수정·삭제·TRUNCATE를 거부한다. 사슬 머리는 이더리움 테스트넷(Sepolia — Amoy 무료 가스 고갈로 전환)에 앵커링해 위·변조를 외부에서 검증 가능하게 한다(ADR-0028). 서명 개인키는 서버 밖(GitHub Actions)에 둔다. 체인 발행은 환경변수로 온·오프한다 |
| 면접 보조 신호 (표정·시선) | 면접 영상의 얼굴 랜드마크 신호(시선·표정 변화)를 분석해 답변-서류 일관성 대조를 돕는 보조 신호를 제공하는 lie-detection 서비스(운영은 t3.large CPU · GPU 이미지는 09-17 Tesla T4 벤치로 검증 · GPU 가동은 10-14~27 계획). 판정이 아니라 담당자 참고용 보조 지표다 |
| 인증 · 권한 | 담당자는 JWT(12시간) · 역할은 admin(조작) / member(조회) 2종(ADR-0017), 비활성 계정은 발급된 토큰도 401. 지원자는 이메일 + 생년월일 8자리 로그인(ADR-0033) 또는 링크 안 일회성 토큰. n8n·판정 워커는 서비스 토큰(/internal/*) |
기술 스택
BACKEND — Python · FastAPI · SQLAlchemy · PostgreSQL 16 + pgvector · alembic
FRONTEND — React · Vite · TypeScript / APP — Flutter (Android APK)
INFRA — Docker Compose · AWS (EC2 · S3) · n8n + SMTP 메일 · Caddy · GitHub Actions(CI + 2분 폴링 자동 CD) · Vercel
AI — Anthropic Claude(claude-haiku-4-5) 서빙 — 서류 요약·평가·추천 3단 체인 · 아르 도구 호출 · FAQ · Qwen3-8B QLoRA 어댑터 3갈래(chat v9 73.9% · summary · interview — 비용 절감 R&D 자산, Ollama 스위치로 교체 가능) · ko-sroberta 임베딩(로컬) · Whisper STT — 업로드 답변·재전사·아르 음성은 OpenAI whisper-1 API, 실시간 면접은 CPU 로컬 faster-whisper(ADR-0038) · ViT + MediaPipe 표정(담당자 참고용)
아키텍처
지원자는 공개 지원 링크(로그인 없음) 또는 앱 로그인(이메일 + 생년월일 8자리, ADR-0033)으로, 담당자는 JWT(admin · member 2종, ADR-0017)로 접근한다. React(Vercel) 프론트와 Flutter 앱이 같은 FastAPI(EC2 · Docker · Caddy 뒤) API를 호출하고, 이력서는 presigned URL로 브라우저에서 S3에 직접 업로드된다. 단계 변경 메일은 API 가 n8n 웹훅으로 넘기고 SMTP 로 발송한다 — n8n 이 죽어도 API 가 5분마다 밀린 메일을 재발송한다(최대 3회). AI 면접의 실시간 전사·표정 참고 지표는 별도 lie-detection 컨테이너(/ai/*)가 담당하고, 이력서·자소서 해시 사슬은 GitHub Actions 가 주기적으로 Sepolia 테스트넷에 앵커한다(ADR-0028). AWS 는 8종에서 3종(EC2·S3·IAM)으로 줄였고(ADR-0031·0036), 메일·큐·스토리지는 환경변수 스위치(MAIL_DISPATCH · QUEUE_BACKEND · S3_ENDPOINT_URL)로 공급자를 바꿀 수 있다.
2026-09-03 다이어그램과 달라진 점 — SQS 큐 + 메일 워커 컨테이너 + SES 발송 경로가 사라지고 n8n + SMTP 로 바뀌었다(ADR-0030·0036). 443 앞에 Caddy 리버스 프록시가 들어와 FastAPI · lie-detection · n8n 을 경로로 나눈다. AI 면접용 lie-detection 컨테이너(실시간 면접 로컬 faster-whisper 전사 · ViT/MediaPipe 표정)와 외부 AI API 2종(Anthropic Claude · OpenAI Whisper — 업로드 답변·아르 음성 전사), Sepolia 무결성 앵커, CI/CD 자동 배포 경로(main 머지 → systemd 2분 폴링), 매일 S3 백업이 새로 그려졌다. 역할 3종은 admin · member 2종 + 지원자 로그인으로 정리됐다.
| 계층 | 기술 | 배포 |
|---|---|---|
| Frontend | React + TypeScript + Vite | Vercel (seuk.suvisdev.cloud) |
| Backend API | FastAPI (Python) · 헥사고날 4 컨텍스트 | EC2 · Docker (api.seuk.suvisdev.cloud) |
| Database | PostgreSQL 16 + pgvector | EC2 · Docker 컨테이너 (매일 S3 백업) |
| 파일 저장 | S3 (presigned URL 업로드, SSE 암호화) | AWS S3 |
| 메일 발송 | n8n 웹훅 + SMTP (실패 시 5분 재발송) | EC2 · n8n 컨테이너 |
| AI 판단 | Anthropic Claude API | 사용량 과금 · 확장은 벤더 쪽(서버는 단일 EC2) |
| STT · 표정 | OpenAI Whisper API(업로드 답변·아르 음성) · faster-whisper 로컬(실시간 면접, 09-17 운영 실측) · ViT + MediaPipe(lie-detection) | API · EC2 컨테이너(운영 t3.large CPU · GPU 이미지는 09-17 T4 벤치, 가동은 10-14~27 계획) |
| CI/CD | GitHub Actions (ruff → alembic → 드리프트 → pytest → 프론트 → AI·앱) | main 머지 → 2분 폴링 자동 배포 |
ERD — 테이블 28개 (v2.8 · 2026-09-18)
다이어그램은 핵심 9테이블(v1.0 기준). 28개 전체 정의는 저장소 docs/00_overview/01-erd.md(v2.8) 가 진실이며, 아래 문단이 확장분을 요약한다
지원서(applications)를 축으로 한 28개 테이블(alembic 리비전 26개 · API 라우트 107개). 핵심 9개 — 공고(job_postings)·내부 사용자(users)와, 단계 이력·평가·담당자 메모·이력서 파일·메일 발송 로그·면접관 배정. 이후 확장 — 메일 템플릿, 면접관 가용 시간, 일정 제안/슬롯, 시맨틱 검색 임베딩(768차원), AI 면접 3종, 인적성 설문 2종. 지원서에는 접수 시 1회 생성되는 AI 요약 컬럼(ai_summary·생성 시각·모델명)이 함께 저장되고, 스키마 이행은 alembic 리비전 26개로 관리하고, CI 가 모델↔이행 결과를 비교해 이행 누락을 잡는다. 이후 확장 — 회사 프로필·자동 심사 규칙, 면접 세션·실시간 분석·채점, 에이전트 추적(agent_traces), 제출물 무결성 원장. 복합 UNIQUE 2건 — applications(job_posting_id, email) · interviewer_assignments(application_id, interviewer_id).
화면 (실서비스 · 2026-09-22)
seuk.suvisdev.cloud 실운영 화면 — 심사위원 데모 계정으로 캡처. 지원자·회사는 전부 가상 데이터(fit-check·리허설용). 2026-09-04 다크 딥네트워크 테마 개편 이후의 현재 UI다.
대시보드 — 전체 현황(접수·서류·면접 / 합격·불합격 누적) · 공고별 심사 적체 막대 · 이번 주 면접 · 지금 면접 중(실시간 분석 화면으로 바로 진입)
지원자 — 단계 필터(접수·서류·면접·종료) · 이름 검색 · 단계 배지(최종 합격 · 면접 · 불합격) · 「종합 →」로 종합평가 진입. 서류 단계는 아르가 자동 판정해 이 목록의 「서류 0」이 정상 상태다
종합 평가 — 공고별 지원자 수 · 평가 완료 · 평균 종합 점수(서류 + 면접 자동 점수 · 등급). 담당자가 여기서 최종 합격·불합격을 확정한다
아르 에이전트 패널(Ctrl+K) — 자연어로 지원자 검색·단계 변경·면접 일정·메일 초안/발송·이력서 드롭 접수. 쓰기 작업은 확인 카드로 사람이 승인하고, 인사·능력 같은 기본 질문은 규칙 응답($0)으로 처리한다
AI 면접(지원자) — 이력서·자소서 기반 맞춤 질문에 음성으로 답한다. 담당자는 1:1 WebRTC 실시간 화면에서 답변↔서류 대조 결과와 표정·음성 참고 지표(점수 미반영)를 본다. 얼굴은 모자이크 처리
캘린더 — 확정된 면접 일정만 표시(「내 면접만」 필터). 데모 데이터는 면접 일정이 과거 주간에 몰려 있어 이 달은 비어 있다
채용 공고 — 등록 · 마감 · 다시 열기 · 공개 지원 링크 생성 · 공고별 지원자
설정 — 내 계정(이름·비밀번호) · 사용자·권한(admin/member) · 메일 템플릿 · 면접 가능 시간