Skip to content

Latest commit

 

History

History
238 lines (178 loc) · 12.5 KB

File metadata and controls

238 lines (178 loc) · 12.5 KB

Dev-Sync: Git 기반 AI 이력서 & 커뮤니티 플랫폼

1. 개요

Dev-Sync는 개발자의 GitHub 활동과 기본 프로필 정보를 기반으로, AI가 이력서/포트폴리오를 자동 생성하고 커뮤니티 피드백까지 연결해 주는 서비스입니다.

  • 목표
    • 코드와 GitHub 활동만 잘 관리해도 이력서가 자동으로 생성되도록 하는 것
    • 생성형 AI를 명확한 도메인 모델과 트랜잭션 안에 안전하게 통합하는 것

2. 주요 기능 요약

  • AI 이력서 생성: GitHub 레포지토리/커밋/PR/릴리즈 데이터를 기반으로 OpenAI가 한국어 이력서를 자동 생성
  • 블록 기반 이력서 편집기: 프로필/소개/프로젝트/스킬/경력/업적/커스텀 섹션을 블록 단위로 관리 및 정렬
  • 커뮤니티 게시판: 카테고리, 검색, 좋아요, 댓글/대댓글이 있는 개발자 커뮤니티
  • 문의(컨택트) 시스템: 비밀번호 기반 비공개 문의 + 관리자 이메일 알림
  • OAuth 로그인: Google/GitHub OAuth 2.0 기반 세션 로그인, 프로필 관리, GitHub 연동

3. 아키텍처 한눈에 보기

  • 백엔드: NestJS 모노리식 API 서버
    • 도메인 모듈: auth, user, resume, post, contact, upload, queue, worker, common, cache
    • 데이터: MySQL + TypeORM (RDB 기반 도메인 모델)
    • 캐시/큐/세션: Redis + cache-manager + BullMQ
  • 프론트엔드: React + Vite + TypeScript SPA
    • 상태: React Query(서버 상태) + Redux Toolkit(이력서 편집 상태)
    • UI: MUI + Emotion, Quill 기반 에디터
  • AI & 외부 연동
    • GitHub REST API로 활동 데이터 수집
    • OpenAI(gpt-4o-mini)로 이력서 JSON 생성 (schema 강제)
    • Nodemailer + Gmail로 문의 메일 전송

4. 핵심 기능 상세

4.1 GitHub 연동 & 리포지토리 분석

  • 데이터 수집 범위
    • 사용자 githubUrl에서 username 추출
    • /users/:username/repos 로 레포 목록 로드
    • 각 레포마다
      • /languages 로 언어 비율 수집
      • /commits 로 최근 커밋 메시지 및 타임라인 수집
      • /contributors 로 사용자 기여도 확인
      • /pulls 로 사용자 PR 내역 수집
      • /releases 로 릴리즈 정보 수집
      • /contents/README.md 로 README 텍스트 추출
  • 이력서 관점의 스코어링 로직
    • 별도의 resume_relevance_score를 계산해 이력서에 넣을 레포를 선별
      • 스타/포크/워처 수: 외부 관심도 지표
      • 기여 횟수 및 PR 수: 본인 기여도 지표
      • 릴리즈 수: 배포 경험 지표
      • 레포 크기·최근 커밋 여부: 프로젝트의 성숙도와 최신성 반영
    • 점수 기반으로 상위 레포만 선별해 AI에 전달

4.2 AI 기반 이력서 자동 생성 파이프라인

  • 입력: GitHub 분석 결과 JSON (상위 레포들의 활동/메트릭/README 요약)
  • OpenAI 프롬프트 설계
    • 모델에 정확한 JSON 스키마를 제시하고, response_format: json_object 사용
    • 제약 조건을 명시:
      • 모든 텍스트는 한국어로 작성
      • 자기소개/프로젝트 설명/성과는 글자 수 범위를 명시해 과도한 장문 방지
      • 데이터에 근거 없는 내용은 빈 문자열/빈 배열로 두도록 규칙화
      • 역할/성과는 커밋/PR/릴리즈/README에 근거가 있을 때만 작성
    • 프롬프트 본문은 영어로 작성하고, 출력 언어만 한국어로 강제:
      • LLM이 이해하기 쉬운 구조적 요구사항과 JSON 스키마를 짧고 일관된 영어 문장으로 표현해 토큰 사용량과 혼동 가능성을 동시에 줄임
      • 프롬프트 수정·디버깅 시, 팀원 간 공유와 재현이 용이하도록 한글 설명 대신 영문 스펙 중심으로 관리하는 전략
  • 출력 스키마 예시
    • introduction: 헤드라인, 자기소개 본문
    • skills: 핵심 스킬, 서브 스킬 목록
    • projects: 프로젝트별 설명/기간/역할/성과 리스트
  • 저장 로직
    • 결과 JSON을 파싱해 아래와 같이 블록 단위 엔티티로 매핑
      • 프로필(ProfileModel)
      • 소개(IntroductionModel)
      • 스킬(SkillModel + ManyToMany)
      • 프로젝트(ProjectModel + ProjectOutcomeModel)
    • 스킬 문자열은 DB 내 기존 SkillModel 과 이름 매칭 후 ID 기반으로 연결

4.3 블록 기반 이력서 편집 & 정렬

  • 블록 타입
    • PROFILE, INTRODUCTION, PROJECTS, SKILLS, CAREERS, ACHIEVEMENTS, CUSTOM
  • 데이터 모델링
    • 각 블록은 독립적인 엔티티로 분해 (예: resume_profile, resume_introduction, resume_project, resume_career 등)
    • 이력서 상세 조회 시, 각 블록을 개별 쿼리로 가져온 후 정렬 정보에 따라 조합하여 응답
  • 정렬 관리(블록 순서)
    • OrderModel(resumeId, blockType, blockId?, order) 형태로 순서를 별도 저장
    • 새 블록 생성 시 가장 뒤에 order 부여, 삭제 시 나머지 order를 재정렬하여 gap 없는 순번 유지
  • 프론트 UX 연계
    • Redux Toolkit + Immer를 사용해 section 단위 수정/순서 변경을 optimistic update로 처리
    • 서버 sync 실패 시 원본으로 롤백하는 트랜잭션 유사 패턴으로 구현

4.4 커뮤니티 게시판 & 댓글/좋아요

  • 게시글 목록 조회
    • 카테고리(질문/자유/공지 등), 검색어, 정렬 옵션, 페이지 번호를 입력으로 받습니다.
    • TypeORM QueryBuilder 로 작성자/카테고리 조인 및 좋아요/댓글 count를 relation count로 함께 조회
  • 게시글 작성/수정
    • Quill 에디터를 사용해 이미지/서식이 포함된 글을 작성
    • 이미지 업로드는 2단계로 분리:
        1. 프론트: base64 미리보기 + 파일명 관리
        1. 백엔드: /post/uploadFormData로 전송 → 업로드된 파일 URL 반환 → 에디터 HTML 내 src 교체 후 /post에 최종 HTML 저장
  • 댓글/대댓글 구조
    • Comment 엔티티에서 parent 필드로 대댓글을 표현
    • 상위 댓글은 페이지네이션 + hasReplies 플래그 제공
    • 대댓글은 별도의 커서 기반 API로 제공해, 긴 쓰레드에도 퍼포먼스를 유지
  • 좋아요 토글
    • (userId, postId) 조합에 유니크 제약을 걸어 중복 좋아요를 DB 레벨에서 방지
    • 좋아요/취소를 단일 토글 API로 제공해 프론트 구현을 단순화

4.5 문의 시스템 & 관리자 알림

  • 문의 등록
    • 사용자가 이름/이메일/제목/내용을 제출하면
      • DB에 저장 후,
      • Nodemailer + Gmail SMTP로 관리자 메일 발송
  • 비공개 문의
    • 4자리 비밀번호를 설정하면, 비밀번호 검증이 통과할 때만 상세 조회/수정/삭제가 가능
  • 문의 목록 조회
    • 이메일 + 페이지네이션 기반으로 "내가 남긴 문의" 목록을 조회
    • 비공개 문의는 메타 정보만 노출하고, 실제 본문은 보호

5. 기술 스택 및 선택 이유

5.1 백엔드

  • NestJS

    • 선택 이유
      • 인증, 캐시, 큐, 설정, 유효성 검증 등 서버에서 반복되는 concern들을 일관된 모듈/데코레이터 기반 패턴으로 제공
      • 도메인 모듈별로 코드를 나누기 쉬워, 기능 확장 시 코드 베이스가 무너지지 않도록 유지
    • 대안 대비
      • Express/Fastify를 직접 사용하는 경우, 아키텍처를 개발자가 일일이 설계해야 하는데, 본 프로젝트 규모에서는 Nest의 규칙적인 구조가 더 적합하다고 판단
  • TypeORM + MySQL

    • 선택 이유
      • 이력서/프로젝트/성과/스킬/커뮤니티(게시글/댓글/좋아요) 등 관계형 데이터가 많아 정규화된 RDB 모델이 자연스러움
      • QueryBuilder를 통해 복잡한 조인과 페이지네이션, 카운트 쿼리를 직관적으로 작성 가능
    • 대안 대비
      • Prisma 역시 고려했으나, 복잡한 서브쿼리/집계에 있어서 QueryBuilder 기반 ORM이 더 유연하다고 판단
  • Redis + cache-manager-redis-yet

    • 선택 이유
      • 빈번히 조회되는 유저/카테고리 정보는 Redis에 캐싱해 DB 부하를 낮추고 응답 시간을 단축
      • CacheService로 네임스페이스(user:email, category:categories)를 추상화해 캐시 사용 코드를 정돈
  • BullMQ + Worker 프로세스

    • 선택 이유
      • OpenAI API 호출과 이력서 저장은 수 초 이상 걸릴 수 있는 작업이므로, HTTP 요청/응답 흐름에서 분리
      • BullMQ를 통해 재시도, 작업 상태 모니터링, 백오프 정책 등 백그라운드 작업에 필요한 기능을 손쉽게 사용
  • Passport (Google/GitHub OAuth) + 세션 기반 인증

    • 선택 이유
      • 브라우저 기반 서비스에서 세션 쿠키는 보안과 편의성의 균형이 좋은 선택지
      • Access Token은 서버에만 보관하고, GitHub API 호출 시에만 사용해 토큰 노출 위험을 줄임

5.2 프론트엔드

  • React + Vite + TypeScript

    • 선택 이유
      • Vite는 빠른 HMR과 가벼운 번들 환경을 제공하여 개발 속도와 DX가 우수
      • TypeScript를 통해 도메인 모델(이력서 섹션/게시글/댓글 등)의 타입을 명확히 모델링
  • React Query

    • 선택 이유
      • 게시글/댓글/좋아요/이력서 목록/유저 정보 등은 모두 서버 상태이므로, 캐싱/리페치/에러/로딩 상태를 컴포넌트에서 분리하고 싶었음
      • 쿼리 키(userKeys, postKeys, resumeKeys)를 중앙에서 관리해, API 계층을 정돈
  • Redux Toolkit + redux-persist

    • 선택 이유
      • 이력서 편집 상태는 서버와 1:1로 즉시 동기화되지 않는 작업 중 상태(draft) 가 존재
      • 섹션 추가/삭제/정렬/부분 업데이트를 Immer 기반으로 쉽게 다루기 위해 Redux Toolkit 사용
      • 이력서 편집 도중 새로고침해도 상태가 유지되도록, redux-persist로 로컬 스토리지에 저장
  • MUI + Emotion

    • 선택 이유
      • 빠르게 일관성 있는 UI를 제공하면서도, Emotion으로 세밀한 스타일 커스터마이징이 필요했음
      • 이력서/커뮤니티/문의 등 여러 화면의 공통 컴포넌트를 재사용하기 좋음
  • Quill 에디터

    • 선택 이유
      • 이미지/리스트/강조 등 블로그 수준의 서식을 지원해야 했고, HTML 저장이 가능한 검증된 에디터가 필요했음
      • 이미지 리사이즈 모듈과 조합하여 모바일에서도 읽기 좋은 게시글 화면을 구현

6. 안정성, 확장성, 유지보수 고려 사항

  • 환경 변수 검증

    • ConfigModule + Joi로 env 스키마를 정의해, 필수 값이 없거나 잘못된 경우 애플리케이션이 부팅 단계에서 바로 실패하도록 설계
  • 민감 정보 보호

    • ClassSerializerInterceptor@Exclude()를 사용해 githubAccessToken 등 민감 필드를 API 응답에서 숨김
    • OAuth Access Token은 DB에 AES로 암호화해 저장, 서버 내부에서만 복호화
  • 확장성

    • 세션/캐시/큐 모두 Redis를 사용해, 멀티 인스턴스 환경에서도 세션 일관성을 유지할 수 있도록 설계
    • 모듈화된 도메인 구조 덕분에, 기능 추가 시 영향을 받는 영역을 명확히 파악 가능
  • 에러 처리 및 롤백

    • 이력서 블록 sync/업데이트는 typeorm-transactional을 도입해 트랜잭션 단위로 처리
    • 프론트에서는 optimistic update 후 실패 시 원본으로 롤백하는 패턴을 적용해 사용자 경험과 데이터 정합성을 함께 확보

7. 개선 여지 및 향후 계획

  • 이력서 공유 링크 & 공개 프로필 페이지

    • 현재는 편집/관리 중심이라, 공개용 이력서 뷰와 링크 공유 기능을 추가하면 채용/포트폴리오 활용성이 높아질 예정입니다.
  • GitHub Actions 기반 포트폴리오 자동 갱신

    • main 브랜치에 변경이 머지될 때마다 GitHub Actions로 테스트/빌드를 수행하고, 성공 시 정적 포트폴리오 페이지(README, 관련 문서)를 자동으로 빌드·배포하는 파이프라인을 추가해, 코드 변경과 포트폴리오 상태가 항상 동기화되도록 할 계획입니다.
  • 테스트 커버리지 보강

    • 도메인 서비스 레벨의 유닛 테스트와, Resume 생성 플로우에 대한 E2E 테스트를 추가해 회귀를 막을 계획입니다.