SkillGap: AI 기반 커리어 어시스턴트 구축
Source: Dev.to
(번역할 텍스트가 제공되지 않았습니다. 번역이 필요한 본문을 알려주시면 한국어로 번역해 드리겠습니다.)
문제
직무 설명은 읽기 어렵습니다. 길고, 전문 용어가 가득하며, 자신이 자격이 되는지 진정으로 알기 힘듭니다. 대부분의 사람들은:
- 스스로 얻을 수 있는 직업을 포기하거나, 혹은
- 준비되지 않은 역할에 지원합니다.
직무가 실제로 필요로 하는 기술과 자신의 기술을 빠르고 정직하게 비교할 방법이 없습니다. 이것이 우리가 해결하고자 했던 문제입니다.
우리의 솔루션
SkillGap이(가) 비교를 대신 수행합니다.
- Paste a job description into the app. → 1. 앱에 직무 설명을 붙여넣기 합니다.
- The app checks it against your saved skill profile. → 2. 앱이 저장된 기술 프로필과 대조합니다.
- You receive a match score, a breakdown of your skills into three groups (Have / Missing / Bonus), and a personalized AI learning roadmap. → 3. 매치 점수, 기술을 세 그룹(보유 / 부족 / 보너스)으로 나눈 분석, 그리고 맞춤형 AI 학습 로드맵을 받게 됩니다.
You get a clear, actionable plan instead of a guess. As you learn and update your profile, your results improve too. → 추측이 아닌 명확하고 실행 가능한 계획을 얻습니다. 학습하고 프로필을 업데이트할수록 결과도 개선됩니다.
팀 구분
| 멤버 | 기여 내용 |
|---|---|
| Jing | • JWT 인증 • 스킬 프로필 CRUD • 키워드 추출 엔진 • 애니메이션 매치 링 |
| Liuyi | • 학습 로드맵을 위한 Claude API 통합 • TDD 테스트 프레임워크 • Framer‑motion UI 애니메이션 • 스켈레톤 UI 로딩 상태 • AI 평가 스위트 |
사용한 AI 도구
| 도구 | 역할 |
|---|---|
| Claude Web | 계획 및 산출물 생성. • 징은 이를 사용해 초기 아이디어를 우선순위가 매겨진 계획으로 전환했습니다. • 리우이는 이를 사용해 손으로 그린 와이어프레임을 UI 레퍼런스로 변환하고, 이후 실제 테스트 데이터로 평가 결과 웹페이지를 생성했습니다. |
| Antigravity | IDE 내부에서 코딩. 우리 둘 다 이를 사용해 프론트엔드와 백엔드 전반에 걸쳐 코드를 작성하고, 리팩터링하며, 디버깅했습니다. |
분담: Claude Web는 계획을, Antigravity는 구축을 담당했습니다.
Source: …
Core Architecture
Authentication
SkillGap의 모든 기능은 사용자가 누구인지 아는 것에 기반합니다.
- JWT 기반 인증을 구현했습니다 (회원가입, 로그인, 로그아웃, 보호된 라우트).
- 비밀번호는 소금(salt)과 해시 처리를 거쳐 데이터베이스에 저장됩니다.
- 보호된 요청마다 JWT 토큰을 검증합니다.
다른 모든 기능이 이에 의존하기 때문에 가장 먼저 구축했습니다.
Skill Profile CRUD
인증 위에 스킬 프로필에 대한 전체 CRUD 작업을 구현했습니다.
- 사용자는 언제든지 스킬을 추가, 편집, 삭제할 수 있습니다.
- 변경 사항은 즉시 반영되어 새로운 분석마다 최신 프로필 버전을 사용합니다.
Database Design
- SQLAlchemy 스키마는 사용자, 스킬 프로필, 분석 히스토리를 포함합니다.
- 히스토리 테이블을 통해 사용자는 과거 분석을 조회하고 시간에 따른 매치 스코어 향상을 추적할 수 있습니다.
- Alembic이 마이그레이션을 담당하며, 각 스키마 변경은 검토·테스트·롤백이 가능한 마이그레이션 파일로 관리됩니다.
매칭 엔진
이것은 제품의 핵심 알고리즘입니다.
- 입력: 직무 설명 + 사용자의 스킬 프로필.
- 프로세스: 두 항목을 선별된 기술 스킬 목록과 비교합니다.
- 출력:
- 보유: 사용자가 가지고 있으며 직무가 요구하는 스킬.
- 부족: 직무가 요구하지만 사용자가 보유하지 않은 스킬.
- 보너스: 사용자가 가지고 있지만 직무에서 요구하지 않은 스킬.
- 키워드 정규화는 변형(예: “React”, “ReactJS”, “React.js”)을 하나의 항목으로 매핑합니다.
- 어휘는 프론트엔드, 백엔드, 인프라스트럭처, 데이터 도구를 포함합니다.
- 엔진은 인증 및 프로필 모듈과 별개의 자체 모듈에 존재하여 단위 테스트와 향후 확장이 용이합니다.
시각적 피드백
- 애니메이션 SVG 링이 매칭 점수를 표시합니다:
- 초록색 → 강한 매치
- 노란색 → 부분 매치
- 빨간색 → 큰 차이
- 링은 페이지 로드 시 점진적으로 그려져 “계산” 느낌을 줍니다.
- 링 아래에 3열 뷰가 점수에 해당하는 정확한 스킬을 나열합니다.
Claude Web를 활용한 설계 및 계획
코드를 작성하기 전에 Jing은 Claude Web을 사용해 프로젝트 설계를 자연어로 진행했습니다. 대화를 통해 다음을 정리했습니다:
- 핵심 사용자 흐름을 확정한다.
- 어떤 기능을 먼저 구축할지 결정한다.
- 답변되지 않은 PRD 질문을 도출한다 (예: 알 수 없는 기술 처리, 신규 사용자를 위한 온보딩).
이러한 결정을 일찍 내림으로써 나중에 디버깅에 소요되는 시간을 크게 절약할 수 있었다.
AI 기반 학습 로드맵
- Extraction engine가 누락된 기술을 식별합니다.
- FastAPI backend가 해당 기술과 원본 직무 설명을 Claude API에 전송합니다.
- Claude가 구조화된 JSON 로드맵을 반환합니다:
{
"steps": [
{
"skill": "Docker",
"resources": ["Docker Docs", "Docker for Beginners (Udemy)"],
"estimated_time": "4h",
"explanation": "Docker is required for containerizing the microservices mentioned in the JD."
}
// …
]
}- React frontend가 JSON을 파싱하고 카드 행을 렌더링합니다. 주제당 하나씩, 읽기 쉽고 실행 가능한 계획을 만듭니다.
일반적인 링크 목록이 아니라, 특정 직무 요구에 맞춘 개인화된 순서형 계획입니다.
테스트 전략
추출 엔진 (결정론적)
- 엄격한 TDD: 구현 전에 테스트를 작성합니다.
server/tests/의 각 모듈은 대응되는test_.py를 가집니다.- CI 파이프라인은 pytest 커버리지가 80 % 이하로 떨어지는 모든 병합을 차단합니다.
Claude 로드맵 (비결정론적)
- AI 평가 테스트 스위트를 구축하여 각 응답을 세 가지 차원으로 평가합니다:
- 관련성 – 리소스가 부족한 기술과 일치합니까?
- 구체성 – 단계가 모호하지 않고 구체적입니까?
- 완전성 – 모든 부족한 기술을 다루고 있습니까?
- 점수는 평가 대시보드에 입력됩니다.
Security Challenges
- Client‑side score spoofing – The match score was being calculated on the React side, allowing manipulation.
- (Second issue omitted in original excerpt – placeholder for completeness).
Both issues were addressed by moving critical calculations to the backend and enforcing strict token validation.
Summary
SkillGap는 robust authentication, dynamic skill‑profile management, smart matching engine, 그리고 AI‑generated learning roadmaps를 결합하여 구직자에게 원하는 역할을 향한 명확하고 실행 가능한 경로를 제공합니다. Claude Web를 계획에 활용하고 Antigravity를 구현에 활용함으로써, 팀은 TDD와 전용 AI 평가 프레임워크를 통한 높은 코드 품질을 유지하면서 일관된 제품을 제공했습니다.
Overview
우리는 원래 구현에서 두 가지 중요한 문제를 식별하고 수정했습니다:
클라이언트‑측 점수 조작 – 프런트엔드가 계산된 점수를 FastAPI 백엔드에 전송했으며, 사용자가 값을 변조하여 저장될 수 있었습니다.
해결책: 계산을 완전히 서버 측으로 옮겨 클라이언트가 제공하는 점수는 무시하도록 합니다.Unhandled SQLAlchemy exceptions – 데이터베이스 오류가
500응답을 발생시켜 전체 스택 트레이스를 노출, 내부 구현 세부 정보가 유출되었습니다.
해결책: 전역 오류 처리기를 추가하여 전체 트레이스백을 서버 측에 로그하고, 클라이언트에는 깔끔하고 안전한 오류 메시지만 반환합니다.
두 문제 모두 프로덕션에 도달하기 전에 코드 리뷰 과정에서 발견되었습니다.
UI 개선
- Responsive feel: 앱이 빠르게 반응하도록 집중적인 UI 개선을 추가했으며, 특히 몇 초가 걸리는 Claude API 호출 중에 스냅한 느낌을 줍니다.
- Staggered animations: 스킬 컬럼과 로드맵 카드를 차례로 애니메이션하기 위해 framer‑motion을 사용하여, 갑작스러운 표시 대신 점진적인 공개를 제공합니다.
- Skeleton UI: Claude API 호출이 진행 중일 때, 결과 패널은 최종 콘텐츠의 형태와 일치하는 스켈레톤 플레이스홀더를 표시하여 인지된 대기 시간을 줄입니다.
디자인 워크플로우
Sketch → Claude Web → Production
- Liuyi는 손으로 그린 대시보드 스케치로 시작했습니다.
- 그 스케치는 Claude Web에 입력되어 컴포넌트 제안 및 레이아웃 논리를 포함한 상세 와이어프레임을 생성했습니다.
- 와이어프레임은 IDE 내부의 Antigravity를 사용해 구현된 프로덕션 구현을 위한 디자인 사양이 되었습니다.
결과: React 코드를 작성하기 전에 구체적인 레퍼런스를 갖게 되어 디자인 추측이 줄어들고 재작성도 감소했습니다.
CI/CD 파이프라인
모든 풀 리퀘스트는 병합되기 전에 다단계 GitHub Actions 파이프라인을 실행합니다:
- Lint –
ruff(Python) 및ESLint(JS/TS) - Security scan
- Pytest
- Build
- Lint –
Coverage gate: 백엔드 테스트 커버리지는 ≥ 80 %를 유지해야 하며, 그렇지 않으면 파이프라인이 실패하고 PR이 차단됩니다.
Secrets management: API 키, JWT 시크릿, DB 연결 문자열은 GitHub Secrets에만 저장되고 런타임에 주입됩니다.
Deploy:
main이 업데이트될 때 앱이 Render에 자동 배포됩니다.
이렇게 하면 문서에만 존재할 때 쉽게 넘어갈 수 있는 품질 기준을 강제할 수 있습니다.
Source:
AI‑생성 로드맵 자동 평가
- Claude가 로드맵을 만든 후, 두 번째 LLM 호출이 이를 평가합니다.
- 평가자는 로드맵, 원본 누락 기술 목록, 그리고 직무 설명을 받아 관련성, 구체성, 완전성에 대해 고정된 루브릭을 사용해 점수를 매깁니다.
왜? AI가 AI 출력을 평가하도록 하면 비결정적 결과를 테스트하는 확장 가능한 방법을 제공하며, 일관되고 구조화된 점수를 제공해 시간이 지남에 따라 추적할 수 있습니다. 인간 검토도 여전히 가치가 있지만, 이 자동화는 정량적인 품질 신호를 제공합니다.
- Liuyi는 실제 테스트 데이터에 전체 평가 스위트를 실행하고 결과를 Claude Web에 다시 입력했습니다.
- Claude Web은 평가 웹페이지 아티팩트를 생성했습니다: 모든 점수의 깔끔한 요약과 높은 점수와 낮은 점수를 설명하는 메모가 포함된 페이지.
이 페이지는 두 가지 목적을 가집니다:
- Claude API 통합에 대한 구체적인 품질 신호를 제공합니다.
- AI 출력이 어떻게 측정되었는지와 결과가 무엇인지 정확히 보여주는 공유 가능한 문서를 생성합니다.
Tooling: Claude Web vs. Antigravity
| Tool | Strength |
|---|---|
| Claude Web | 대화형 브레인스토밍, 개방형 사고, 산출물 생성, 정의되지 않은 문제에 대한 의사결정. |
| Antigravity | IDE 내부에서 실제 코드를 작성, 리팩토링, 디버깅하는 직접 파일 조작. |
두 역할을 혼합하면 속도가 느려졌을 것입니다. 채팅 창에서 코드를 복사‑붙여넣는 것은 마찰을 발생시키고, 구현을 위해 대화형 도구를 사용하면 더 나은 결정을 이끌어내는 반복 루프가 사라집니다. 각 도구를 최적의 역할에 맞게 유지함으로써 두 도구 모두 더 효과적이었습니다.
향후 기술 업그레이드
- Semantic skill matching – 키워드 추출을 sentence‑transformer embeddings 로 교체합니다. 현재 엔진은 정확히 일치하는 키워드만 매칭합니다; 의미 임베딩을 사용하면 “component‑based UI development”가 React와 매핑된다는 것을 인식하여 일반 영어 직무 설명까지 적용 범위를 확대할 수 있습니다.
- Resume parsing – 사용자가 이력서를 업로드하면 자동으로 스킬 프로필을 구축하도록 합니다.
- Reverse analysis mode – 고용주가 후보자의 프로필을 채용 공고와 대조하여 확인할 수 있게 합니다.
SkillGap에 대한 회고
- 출처: 수업 프로젝트로 시작했으며, 이제는 쇼케이스 작품입니다.
- 모듈식 아키텍처: 서로의 코드를 방해하지 않고 독립적으로 작업할 수 있게 했습니다.
- 공유 규칙:
.antigravityrules파일이 규칙을 문서화하여 충돌이 발생하기 전에 정리했습니다. - AI 작업 분담: Claude Web으로 계획하고 Antigravity로 구현함으로써 속도를 높였으며, 결과물 품질은 유지했습니다.
핵심 교훈: AI 도구는 견고한 엔지니어링 프로세스를 가속화하지만, 체계적인 개발 관행의 필요성을 대체하지는 못합니다.
프로젝트 요약
SkillGap — 기술 스택 스킬 격차 분석기
구직자가 채용 공고에서 필요한 스킬 격차를 파악하도록 도와주는 웹 앱.
- 채용 공고를 붙여넣기 → 매치 점수 확인 → AI가 생성한 학습 로드맵 받기.
팀
- Jing Ng
- Liuyi Yang
기술 스택
| 레이어 | 기술 |
|---|---|
| 프론트엔드 | React 18, TypeScript, Vite, Tailwind CSS, Zustand |
| 백엔드 | FastAPI, Python 3.11, SQLAlchemy, PostgreSQL |
| AI | Claude API (claude‑sonnet‑4‑20250514) |
기능
- 채용 공고 파싱 및 스킬 격차 점수 산출
- AI가 생성한 학습 로드맵
- 애니메이션 UI가 포함된 인터랙티브 대시보드
- 린팅, 보안 스캔, 테스트, 커버리지 강제 적용이 포함된 자동 CI/CD
- 비밀 키 안전 관리 및 Render 배포
스크린샷
- 로그인 페이지
- 회원가입 페이지
- 프로필 설정 페이지
- 메인 대시보드 – 스킬 매치 분석
시스템 아키텍처
(여기에 아키텍처 다이어그램을 삽입하세요)
사용자가 직무 설명을 제출할 때 요청 흐름
- 사용자 행동 – 사용자가 UI에 직무 설명을 붙여넣습니다.
- 서버 처리 –
- 서버가 직무 설명을 사용자가 저장한 기술 프로필과 비교합니다.
- 매치 점수를 계산합니다.
- 갭 정보를 Claude AI에 전송합니다.
- AI 생성 – Claude AI가 식별된 기술 격차를 메우기 위한 맞춤형 학습 계획을 생성합니다.
- 결과 – 학습 계획이 프런트엔드에 반환되어 사용자에게 표시됩니다.
관련 기술: 프런트엔드 (React), 백엔드 (FastAPI), 데이터베이스, Claude API
프로젝트 구조
SkillGap/
├── client/ # React frontend (Vite, Tailwind, Zustand)
├── server/ # FastAPI backend
│ ├── tests/ # pytest test suite
│ └── … # other backend modules
└── … # additional top‑level files (README, .gitignore, etc.)GitHub에서 보기 ( # 를 실제 저장소 URL로 교체하세요)