Skip to content

Latest commit

 

History

History
204 lines (108 loc) · 11.1 KB

File metadata and controls

204 lines (108 loc) · 11.1 KB

job_wiki — 캡스톤 최종발표 대본

12조 · 2026-1 · 발표 7분


슬라이드 1: 표지 (30초)

안녕하십니까. 12조입니다.

저희는 job_wiki — 공공기관 채용공고 자동 수집, 위키 변환, AI 매칭 시스템을 개발했습니다.

팀원 소개 드리면, 백엔드 담당 강현모, 프론트엔드 담당 양병현, QA 담당 권오규입니다.


슬라이드 2: 문제 정의 (40초)

캡스톤 수업에서 가장 먼저 배운 것이 있습니다. "만들고 싶어서"가 아니라 "이런 문제가 있어서" 만들어야 한다는 것.

저희가 주목한 타겟 사용자는 자신의 진로를 명확히 탐색하지 못한 사용자입니다. 예를 들어 의공학을 전공했지만, 자신의 경험을 어떤 직무와 연결해야 할지 모르는 상황이죠.

이런 사용자가 본인의 경험과 흥미를 비정형적으로 작성하면, 그걸 바탕으로 맞춤형 채용 공고를 추천해주는 시스템. 이것이 저희의 목표입니다.

구체적인 문제는 세 가지입니다. 첫째, 공공기관 채용공고가 ALIO에 분산되어 있어 개인이 모니터링하기 어렵고, 둘째, 자신의 경험을 어떤 직무와 연결해야 할지 모르며, 셋째, 이력서는 비정형 텍스트라 자동 분석이 어렵다는 점입니다.


슬라이드 3: 5Whys — 진짜 문제 찾기 (30초)

저희는 5Whys 기법을 적용해서 진짜 문제를 찾아냈습니다.

왜 사용자가 공고를 못 찾을까? → 경험과 직무를 연결하지 못해서. 왜 연결이 어려울까? → 비정형 텍스트 vs 제각각인 공고 형식. 왜 자동 분석 시스템이 없을까? → 연결하는 매칭 시스템 자체가 없음. 왜 만들기 어려울까? → 공고와 사용자 경험을 같은 분류 체계로 정규화해야 하기 때문.

이를 통해 도출한 진짜 문제 정의문입니다. "진로를 탐색 중인 사용자의 비정형 경험을 분석하여, 구조화된 채용 데이터와 자동으로 매칭하는 시스템이 필요하다."


슬라이드 4: 요구사항 및 제약조건 (20초)

시스템의 입력은 ALIO API의 공공기관 채용공고 원문이고, 출력은 맞춤형 Top-5 추천입니다.

제약조건으로는 3인 팀, API 호출 제한, 무료 LLM 티어 한계, 15주 개발 기간이 있었고, 이에 맞춰 설계를 진행했습니다.


슬라이드 5: 전체 아키텍처 (30초)

저희 시스템은 3단계 파이프라인으로 구성됩니다.

Step 1은 ALIO API에서 채용공고를 수집하고 마크다운으로 저장합니다. Step 2는 수집된 공고를 NCS 분류 체계 기반의 Facet Wiki로 구조화합니다. Step 3는 LLM 기반 매칭 엔진이 사용자 프로필과 위키 데이터를 매칭하여 결과를 제공합니다.


슬라이드 6: 수집 · Wiki 변환 상세 (30초)

Step 1은 fetcher.py가 ALIO API를 호출하고, formatter.py가 마크다운으로 변환, writer.py가 00_Raw에 날짜별로 저장합니다. 크롤링 대신 공식 API를 직접 사용해서 안정성을 확보했습니다.

Step 2는 wiki_generator.py가 이 데이터를 NCS 24개 분류, 17개 지역, 7개 학력 등 8개 축의 Facet Wiki로 구조화합니다.

여기서 중요한 점은, 초기에는 임베딩 방식으로 접근했다가 Wiki 방식으로 전환했다는 겁니다. 임베딩은 '유사하다'는 것만 알려주지만, Wiki는 '왜 유사한지'를 NCS 분류 체계로 설명할 수 있습니다.


슬라이드 7: 역량 추출 (35초) ⭐

역량 추출부터 설명드리겠습니다.

INPUT으로 사용자가 "의공학 전공, 의료기기 인턴 6개월, 파이썬 데이터분석 프로젝트 경험"이라고 입력합니다.

PROCESS는 두 단계를 거칩니다. 첫째, LLM이 프롬프트에 따라 키워드를 추출합니다. 실제 코드 레벨의 프롬프트를 보여드리면, NCS 분류 체계에 맞춰 ncs, skills, regions, education을 최대 15개 키워드로 추출하도록 되어 있습니다. 둘째, 추출된 키워드는 WikiReadOnlyTool을 통해 표준 Wiki 키워드로 정규화됩니다. _normalize_keyword()로 불필요한 문자를 제거하고, Facet_Index.json과 매칭하여 표준화한 뒤, 중복을 제거합니다.

|OUTPUT으로 이렇게 구조화된 키워드 셋이 나옵니다.


슬라이드 7b: 기업 매칭 (25초) ⭐

다음으로 기업 매칭입니다. 여기에 추가로, LLM 추출 전 관련성 검증 게이트를 도입했습니다. 사용자 프로필이 채용이나 직무와 전혀 무관한 내용이면 빈 결과를 반환해서 불필요한 API 호출과 매칭을 차단합니다. 품질 필터 역할을 하는 거죠.

저희는 가중치 점수화 방식을 사용합니다. 실제 코드 상수값을 보여드리면, CORE_PROFILE_TERM_WEIGHT는 6.0 (핵심 의도 6배), PROFILE_TERM_WEIGHT는 3.0 (사용자 직접 입력 3배), SUPPLEMENTAL_TERM_WEIGHT는 1.0 (보조 추출 1배)입니다. 즉, LLM이 core/support/follow_up 3단계로 키워드를 분류하고 각각 6배, 3배, 1배의 가중치를 적용합니다.

점수화는 4단계로 이루어집니다.

  1. _build_weighted_scoring_terms()로 가중치 적용
  2. Wiki_Index.json에서 각 키워드별 매칭 기관 수집
  3. _match_strength_for_entry()로 기관별 일치율 계산
  4. _score_index_entries_with_file_scores()로 최종 점수 산출 → Top-5 추천

실제 출력 예시로는 충남대병원 92%, 분당서울대병원 88%와 같이, 각 매칭된 키워드까지 함께 보여줍니다.



슬라이드 9: 기술 스택 선정 근거 (20초)

기술 스택 선정에도 근거가 있습니다.

데이터 소스는 크롤링 대신 ALIO API를 선택해 안정성을 확보했고, LLM은 OpenCode Go API를 주력으로, Groq를 폴백으로 사용합니다. 데이터 저장소는 초기에 검토했던 Vector DB 대신 Facet Wiki를 선택했습니다.

임베딩이 "의료기기 연구개발"과 "의공학"의 관계를 설명하지 못하는 반면, Wiki는 "보건의료"라는 NCS 분류로 명확히 설명 가능하기 때문입니다.


슬라이드 10: 아키텍처 진화 (40초) ⭐⭐

교수님께서 결과물보다 과정을 중요시한다고 말씀하셨습니다. 저희가 가장 많은 것을 배운 부분이기도 합니다.

Phase 1은 CrewAI 프레임워크 기반으로 시작했습니다. 하지만 Multi-Agent 구조가 과도한 추상화를 가져왔고, 응답 속도 저하와 디버깅 어려움을 겪었습니다. 이때 배운 교훈은 **"Over-engineering은 오히려 독이다"**라는 것입니다.

|Phase 2에서는 CrewAI를 완전히 제거하고 자체 LLM 클라이언트로 전환했습니다. 이 과정에서 Input Token을 60% 절감했고, Groq 폴백 모델 6개로 안정성을 확보했으며, server.py를 OS 환경 독립적으로 만들었습니다.

Phase 3에서는 GitHub Actions CI/CD를 구축해 주간 자동 수집을 안정화했고, LLM 프롬프트 관련성 검증 게이트를 도입했습니다. 프론트엔드도 다크모드, 로딩 상태, 에러 UI, 접근성 등 UI/UX를 전반적으로 개선했습니다.


슬라이드 11: 리팩토링 결정 과정 (20초)

Before와 After를 비교해보면, Token 사용량 60% 감소, 의존성 단순화, 디버깅 용이성, 폴백 모델 도입, 환경 독립성 등 모든 측면에서 개선이 있었습니다.

Git 커밋 로그와 PROJECT_CHANGELOG.md로 이 과정을 증빙할 수 있습니다.


슬라이드 12: 수집 데이터 현황 (20초)

현재까지의 성과입니다. 200개 이상의 채용공고를 수집했고, 150개 이상의 기관 프로필, 400개 이상의 역량 정의를 구축했습니다.

NCS 24개 대분류, 17개 지역, 7개 학력 분류로 데이터를 구조화했습니다.

실제 데이터 예시로 분당서울대병원, 부산대병원, 충남대병원 등의 채용공고가 00_Raw에 저장되어 있습니다.


슬라이드 13: Facet Wiki + Obsidian 그래프 뷰 (30초)

저희 위키는 8개 축, 총 87개의 세부 분류로 구성된 다차원 분류 체계입니다.

예를 들어 사용자가 "의료기기 연구개발"을 검색하면, NCS: 보건의료, 지역: 대전, 경력: 신입+경력으로 필터링되어 충남대병원, 분당서울대병원 등이 매칭됩니다.

오른쪽 영상은 실제 Obsidian 그래프 뷰의 10배속 타임랩스입니다. 98초 분량의 실제 Obsidian Graph View 녹화를 10초로 압축했으며, 공고, NCS 분류, 역량, 기관 간의 연결 관계를 실제 Obsidian에서 표현한 모습을 보여줍니다.


슬라이드 14: 매칭 엔진 데모 (20초)

실제 매칭 예시입니다.

의공학 전공, 의료기기/데이터분석 관심, 대전 희망 사용자의 경우, 충남대병원 의료기기연구개발 92%, 분당서울대병원 데이터분석 88% 등 Top-5가 추천됩니다.


슬라이드 15: 성능 측정 결과 (20초)

수집 파이프라인은 매주 월요일 09시 KST에 자동 실행되며, 수집 성공률 99%, 3주 이상 무중단 운영 중입니다.

매칭 정확도는 키워드 기반 85% 이상, LLM 추출 정확도 78%, 평균 응답 시간 2.3초입니다.

리팩토링 전후 비교를 보면, Input Token 사용량이 100%에서 40%로 60% 감소했습니다.


슬라이드 16: 개선 전후 비교 (20초)

종합 비교표를 보면, 모든 항목에서 개선이 있었습니다.

이 경험을 통해 얻은 가장 큰 교훈은 **"처음에는 CrewAI라는 유명 프레임워크를 사용하는 것이 정답이라고 생각했지만, 직접 필요한 만큼만 구현하는 것이 더 효율적"**이라는 것을 배웠습니다.


슬라이드 17: 리스크 관리 (20초)

식별된 주요 리스크와 대응 전략입니다.

ALIO API 변경에는 모의 모드와 캐싱으로, LLM 비용 문제는 OpenCode Go API와 Groq 폴백으로 대응했고, 이 중 CrewAI 오버엔지니어링 리스크를 조기에 인지하고 자체 클라이언트로 전환한 것이 가장 효과적인 대응이었습니다.


슬라이드 18: 개인 기여도 (20초)

팀원별 역할을 말씀드리면,

백엔드 담당인 저 강현모는 전체 파이프라인 설계 및 구현, CrewAI 리팩토링, CI/CD 구축, 매칭 엔진 알고리즘 개발, 그리고 LLM 프롬프트 최적화를 통한 관련성 검증 게이트 도입을 담당했습니다.

양병현은 웹 UI 개발과 사용자 경험 설계를, 권오규는 테스트 및 검증과 데이터 품질 관리를 담당했습니다.


슬라이드 19: 향후 계획 (20초)

향후 계획으로는 사용자 피드백 루프 도입, 사람인·잡코리아 등 사기업 채용정보 API 연계를 통한 공공+민간 통합 매칭, RESTful API 제공, 그리고 Vector DB와 Wiki를 결합한 하이브리드 검색을 고려하고 있습니다.

현재는 공공기관에 한정되어 있지만, 사람인·잡코리아 API를 추가로 연동하면 더욱 강력한 통합 채용 매칭 플랫폼으로 확장할 수 있을 것으로 기대합니다.


이상으로 발표를 마치겠습니다. 감사합니다.