Skip to content

Burgerliker/TeamRecSys

Repository files navigation

AI 기반 개발자 팀 매칭 플랫폼

개발자를 위한 지능형 팀 빌딩 플랫폼

머신러닝 기반 추천 시스템으로 토이 프로젝트, 해커톤, 스터디를 위한 최적의 팀원을 자동으로 매칭합니다.

Tech Stack ML Spring Boot React


🎯 프로젝트 개요

개발자들이 토이 프로젝트, 해커톤, 스터디 등을 위해 최적의 팀원을 찾을 수 있도록 돕는 AI 기반 매칭 플랫폼입니다.

💡 문제 정의

  • 온라인 커뮤니티에서 적합한 팀원 찾기의 어려움
  • 포지션, 기술 스택, 프로젝트 목표, 협업 스타일 등 다차원적 고려 사항
  • 수동 검색의 비효율성과 미스매치로 인한 프로젝트 실패

🚀 해결 방안

머신러닝 기반 다차원 벡터 매칭으로 개인-팀 간 최적 조합을 자동 추천하며, 추천 근거를 제공하여 설명 가능한 AI(XAI) 구현

🎪 주요 사용 사례

  • 토이 프로젝트: 사이드 프로젝트를 함께 진행할 팀원 모집
  • 해커톤: 단기 집중 개발을 위한 팀 빌딩
  • 스터디/독서: 기술 스터디 그룹 구성
  • 오픈소스: 오픈소스 프로젝트 기여자 모집
  • 스타트업: 공동 창업자 또는 초기 팀원 탐색

🤖 AI/ML 핵심 기술

1. 하이브리드 추천 시스템 (Hybrid Recommendation System)

Content-Based Filtering + Collaborative Filtering 결합

# 팀 벡터 = 팀 요구사항 + 기존 멤버 프로필의 가중 평균
combined_team_vector = α × team_requirements + (1-α) × mean(member_vectors)
  • α (alpha): 팀 요구사항과 멤버 특성의 균형 조절 (기본값: 0.5)
  • 팀 요구사항: 모집 포지션, 프로젝트 목표, 선호 분위기
  • 멤버 평균: 현재 팀원들의 프로필 벡터 평균

2. Multi-Hot Encoding 기반 프로필 벡터화

23차원 Feature Vector 구성

차원 설명 인코딩 방식 차원 수
Position 주/부 포지션 (PM, Backend, Frontend, AI, Design) Weighted One-Hot (0.75/0.25) 5
Goals 프로젝트 목표 (취업, 수상, 학습, 포트폴리오 등) Multi-Hot 8
Vibes 팀 분위기 (반말/존대, 편한/규칙적, 애자일/워터폴 등) Multi-Hot 10
# 예시: Backend(주) + AI(부) 개발자, 목표=[취업우선, 실무경험]
person_vector = [0, 0.75, 0, 0, 0.25,  # Position: Backend(0.75), AI(0.25)
                 1, 0, 0, 0, 0, 1, 0, 0,  # Goals: 취업우선, 실무경험
                 0, 0, 1, 0, 0, 1, 0, 0, 0, 0]  # Vibes: 편한분위기, 합의중심

3. TF-IDF 기반 가중치 (Feature Importance)

희소한 특성에 높은 가중치 부여로 구별력(Discriminative Power) 향상

# IDF (Inverse Document Frequency) 계산
IDF(feature) = log((N + 1) / (DF(feature) + 1)) + 1

# 예시:
# - "취업 우선" 선택 비율 80% → IDF 낮음 (구별력 낮음)
# - "워터폴 방식" 선택 비율 5% → IDF 높음 (구별력 높음)

가중치 벡터 적용

weight_vector = [
    position_weight(0.5),          # 포지션 가중치
    goal_idf_weight(0.3),          # TF-IDF 기반 목표 가중치
    vibe_idf_weight(0.2)           # TF-IDF 기반 분위기 가중치
]

weighted_vector = original_vectorweight_vector  # 원소별 곱셈

4. Cosine Similarity + Position Boosting

기본 유사도 계산

similarity(A, B) = (A · B) / (||A|| × ||B||)  # 범위: [0, 1]

포지션 수요 부스팅

if candidate.main_position in team.recruit_positions:
    similarity += 0.06  # 주포지션 일치 시 6% 가산
elif candidate.sub_position in team.recruit_positions:
    similarity += 0.03  # 부포지션 일치 시 3% 가산

5. MMR (Maximal Marginal Relevance) - 다양성 재랭킹

문제: 상위 추천이 모두 유사한 프로필 (e.g., 전부 Backend 개발자) 해결: 유사도와 다양성의 균형

# MMR Score 계산
MMR(i) = λ × similarity(i, query) - (1-λ) × max_diversity(i, selected)
       = 0.7 × 유사도 - 0.3 × 이미 선택된 후보와의 최대 유사도

# 알고리즘:
1. 가장 높은 유사도 후보 선택
2. 남은 후보  MMR 점수 최고인 후보 선택 (유사도 높지만 기존 선택과 다른 후보)
3. Top-K까지 반복

6. Explainable AI (XAI) - 추천 근거 제공

모든 추천에 해석 가능한 이유 제공으로 사용자 신뢰도 확보

reasons = [
    "포지션 일치(main:backend)",
    "목표 겹침: 취업우선, 실무경험",
    "분위기 겹침: 편한분위기, 합의중심"
]

응답 예시

{
  "user_id": 42,
  "name": "김철수",
  "similarity": 0.8734,
  "reasons": [
    "포지션 일치(main:backend)",
    "목표 겹침: 취업우선, 포트폴리오중심",
    "분위기 겹침: 애자일방식"
  ]
}

📊 AI 추천 알고리즘 Pipeline

graph TD
    A[사용자/팀 입력] --> B[Multi-Hot Vectorization<br/>23차원 벡터 생성]
    B --> C[TF-IDF 가중치 계산<br/>희소 특성 부스팅]
    C --> D[후보 풀 벡터화<br/>전체 후보 벡터 준비]
    D --> E[Cosine Similarity<br/>유사도 계산]
    E --> F[Position Boosting<br/>수요 포지션 가산점]
    F --> G[1차 정렬<br/>유사도 순]
    G --> H{Top-K > 1?}
    H -->|Yes| I[MMR 재랭킹<br/>다양성 고려]
    H -->|No| J[결과 선택]
    I --> J
    J --> K[XAI 근거 생성<br/>추천 이유 설명]
    K --> L[최종 추천 결과 반환]
Loading

🏗️ 시스템 아키텍처

┌─────────────────┐      ┌─────────────────┐      ┌─────────────────┐
│  React Frontend │◄────►│ Spring Boot API │◄────►│  PostgreSQL DB  │
│   (TypeScript)  │      │   (Java 17)     │      │                 │
└─────────────────┘      └────────┬────────┘      └─────────────────┘
         │                         │
         │                         │ REST API
         │                         ▼
         │              ┌─────────────────────┐
         │              │   FastAPI RecSys    │
         │              │   (Python ML)       │
         └─────────────►│                     │
           WebSocket    │  • scikit-learn     │
                        │  • NumPy/Pandas     │
                        │  • Cosine Similarity│
                        │  • MMR Algorithm    │
                        └─────────────────────┘

주요 컴포넌트

계층 기술 스택 역할
Frontend React 19, TypeScript, Zustand, Tailwind CSS 사용자 인터페이스, 프로필 관리
Backend API Spring Boot 3.5, Java 17, JWT, WebSocket 비즈니스 로직, 인증, 실시간 채팅
AI Engine FastAPI, scikit-learn, NumPy, Pandas ML 추천 알고리즘, 벡터 연산
Database PostgreSQL (prod), H2 (dev) 사용자/팀 데이터 영속성
Cache Hazelcast 분산 캐싱, 세션 관리

✨ 주요 기능

🎯 AI 기반 매칭

  • 양방향 추천: 개인 → 팀, 팀 → 후보자 추천 모두 지원
  • 실시간 추천: 프로필 업데이트 시 즉시 재계산
  • 다양성 보장: MMR 알고리즘으로 다양한 후보 제시
  • 설명 가능성: 모든 추천에 구체적 이유 제공

💬 실시간 커뮤니케이션

  • WebSocket 채팅: STOMP 프로토콜 기반 실시간 메시징
  • 팀 채팅방: 팀 생성 시 자동 채팅방 생성
  • 메시지 영속성: 채팅 히스토리 저장 및 조회

👥 팀 관리 시스템

  • 팀 생성/수정/삭제: 완전한 CRUD 기능
  • 멤버십 관리: JOIN(지원) / INVITE(초대) 양방향 요청
  • 리더 관리: 팀 리더 권한 위임 기능

📈 대시보드 & 분석

  • 매칭 통계: 성공률, 평균 유사도 등
  • 사용자 활동: 프로필 완성도, 팀 참여 이력
  • 팀 현황: 모집 중인 포지션, 팀 구성 현황

📂 프로젝트 구조

TeamRecSys/
├── RecSys/                              # 🤖 AI/ML 추천 엔진 (FastAPI)
│   ├── app/
│   │   ├── api/
│   │   │   └── routes.py               # REST API 엔드포인트
│   │   │       ├── POST /recommend/candidates  # 후보자 추천
│   │   │       ├── POST /recommend/teams       # 팀 추천
│   │   │       └── GET  /recommend/health      # 헬스체크
│   │   ├── services/
│   │   │   └── recommender.py          # 핵심 ML 알고리즘
│   │   │       ├── person_vector()            # 개인 프로필 벡터화
│   │   │       ├── team_vector()              # 팀 요구사항 벡터화
│   │   │       ├── combined_team_vector()     # 하이브리드 팀 벡터
│   │   │       ├── recommend_candidates()     # 후보자 추천 (MMR)
│   │   │       └── recommend_teams()          # 팀 추천 (MMR)
│   │   ├── schemas/
│   │   │   └── models.py               # Pydantic 데이터 모델
│   │   └── core/
│   │       └── config.py               # CORS, 로깅 설정
│   ├── main.py                          # FastAPI 애플리케이션 엔트리
│   ├── requirements.txt                 # Python 의존성
│   └── Dockerfile                       # 컨테이너 이미지
│
├── back_end/                            # 🔧 Spring Boot 백엔드
│   ├── src/main/java/com/example/demo/
│   │   ├── auth/                        # JWT + OAuth2 인증
│   │   ├── user/                        # 사용자 프로필 관리
│   │   ├── team/                        # 팀 CRUD, 멤버십 관리
│   │   ├── chat/                        # WebSocket 채팅
│   │   └── dashboard/                   # 분석 대시보드
│   ├── build.gradle                     # Gradle 빌드 설정
│   └── application-{profile}.yml        # 환경별 설정 (local/prod)
│
├── front_end/                           # 🎨 React 프론트엔드
│   ├── src/
│   │   ├── components/
│   │   │   ├── common/                  # 공통 컴포넌트
│   │   │   ├── layout/                  # 레이아웃
│   │   │   ├── features/                # 기능별 컴포넌트
│   │   │   │   ├── auth/               # Google OAuth
│   │   │   │   ├── profile/            # 프로필 설정
│   │   │   │   ├── matching/           # 매칭 UI
│   │   │   │   └── chat/               # 채팅 UI
│   │   │   └── ui/                      # Shadcn/ui 라이브러리
│   │   ├── pages/                       # 라우트 페이지
│   │   ├── store/                       # Zustand 스토어
│   │   ├── api/                         # Axios API 클라이언트
│   │   ├── hooks/                       # Custom React Hooks
│   │   └── types/                       # TypeScript 타입 정의
│   ├── package.json
│   └── vite.config.ts
│
├── docker-compose.yml                   # 개발 환경 오케스트레이션
└── README.md

🛠 기술 스택

🤖 AI/ML (Python 3.x)

Framework: FastAPI 0.116.1          # 고성능 비동기 API 서버
ML Library: scikit-learn 1.7.1      # Cosine Similarity, 벡터 연산
Data Processing:
  - NumPy 2.3.2                     # 다차원 배열 연산
  - Pandas 2.3.1                    # 데이터 전처리
Validation: Pydantic 2.11.7         # 입력 데이터 검증
Server: Uvicorn 0.35.0              # ASGI 서버

주요 알고리즘

  • Multi-Hot Encoding for feature vectorization
  • TF-IDF weighting for feature importance
  • Cosine Similarity for matching score
  • MMR (Maximal Marginal Relevance) for diversity

🔧 Backend (Java 17 + Spring Boot 3.5.3)

Framework: Spring Boot 3.5.3
Authentication:
  - JWT (io.jsonwebtoken 0.11.5)
  - OAuth2 (Google)
Real-time: WebSocket (STOMP)
Database:
  - PostgreSQL (Production)
  - H2 (Development)
Cache: Hazelcast 5.5.0              # 분산 캐싱
Documentation: Swagger/OpenAPI 3

🎨 Frontend (React 19 + TypeScript 5.8)

Framework: React 19 + Vite 7.0
Language: TypeScript 5.8
UI Library: Shadcn/ui + Radix UI    # Accessible components
Styling: Tailwind CSS 3.4
State Management: Zustand 5.0
Form Handling: React Hook Form 7.61 + Zod 4.0
HTTP Client: Axios 1.11
Routing: React Router 7.7

🐳 DevOps

Containerization: Docker + Docker Compose
CI/CD: Gitlab CI/CD Pipeline
Monitoring: Spring Actuator + Prometheus
Logging: SLF4J + Logback (Backend), FastAPI Logger (ML)

🚀 빠른 시작

1. 전체 서비스 실행 (Docker Compose)

# 개발 환경 실행 (Backend: :8081, Frontend: :8080, RecSys: :8000)
docker-compose up --build

# 백그라운드 실행
docker-compose up -d

# 로그 확인
docker-compose logs -f recsys

2. 개별 서비스 실행

RecSys (AI Engine)

cd RecSys
pip install -r requirements.txt
python main.py
# http://localhost:8000/docs → FastAPI Swagger UI

Backend (Spring Boot)

cd back_end
./gradlew bootRun
# http://localhost:8080/swagger-ui.html → API 문서

Frontend (React)

cd front_end
npm install
npm run dev
# http://localhost:3000

3. API 테스트

후보자 추천 (Team → Person)

curl -X POST "http://localhost:8000/recommend/candidates" \
  -H "Content-Type: application/json" \
  -d '{
    "team_info": {
      "team_id": 1,
      "team_name": "AI 스터디팀",
      "recruit_positions": ["backend", "ai"],
      "goals": ["취업우선", "실무경험"],
      "vibes": ["편한 분위기", "합의 중심"]
    },
    "member_infos": [],
    "candidate_pool": [
      {
        "user_id": 101,
        "name": "김철수",
        "main_pos": "backend",
        "sub_pos": "ai",
        "goals_": ["취업우선", "포트폴리오중심"],
        "vibes_": ["편한 분위기", "애자일 방식"]
      }
    ],
    "alpha": 0.5,
    "top_k": 5
  }'

응답 예시

{
  "status": "success",
  "message": "Recommended 1 candidates",
  "results": [
    {
      "user_id": 101,
      "name": "김철수",
      "main_pos": "backend",
      "sub_pos": "ai",
      "similarity": 0.8945,
      "reasons": [
        "포지션 일치(main:backend)",
        "목표 겹침: 취업우선",
        "분위기 겹침: 편한 분위기"
      ]
    }
  ]
}

🔬 AI 추천 엔진 상세

1. 프로필 벡터화 (Vectorization)

포지션 벡터 (Position Vector)

positions = ["pm", "backend", "frontend", "design", "ai"]
main_position: 가중치 0.7 (주포지션)
sub_position: 가중치 0.3 (부포지션)
예: PM(주) + Backend(부) → [0.7, 0.3, 0, 0, 0]

목표 벡터 (Goal Vector) - Multi-hot Encoding

목표 8가지: 취업우선, 수상목표, 포트폴리오중심, 학습중심,
           아이디어실현, 실무경험, 빠른개발, 완성도추구
예: [취업우선, 실무경험] → [1, 0, 0, 0, 0, 1, 0, 0]

분위기 벡터 (Vibe Vector) - Multi-hot Encoding

분위기 10가지: 반말지향, 존대지향, 편한분위기, 규칙적분위기,
             리더중심, 합의중심, 새로운주제, 안정적주제,
             애자일방식, 워터폴방식
예: [편한분위기, 합의중심] → [0, 0, 1, 0, 0, 1, 0, 0, 0, 0]

최종 사용자 벡터

user_vector = [pos_vec(5dim) || goal_vec(8dim) || vibe_vec(10dim)]
             = 23차원 벡터

2. 팀 벡터 = 팀 요구조건 + 기존 멤버 정보

# 팀 벡터 (팀이 모집하는 포지션/목표/분위기)
team_vector = [recruit_pos_vec(5dim) || team_goal_vec(8dim) || team_vibe_vec(10dim)]

# 멤버들의 평균 벡터
member_mean = mean([member1_vec, member2_vec, ...])

# 결합 벡터 (alpha=0.5 기본값)
combined_team_vec = 0.5 * team_vec + 0.5 * member_mean

3. 유사도 계산 (Cosine Similarity)

기본 유사도 = cosine_similarity(weighted_combined_team, weighted_candidate)
           = (A·B) / (||A|| × ||B||)
           범위: 0~1 (높을수록 유사)

포지션 수요 부스트:
  - 모집 중인 포지션(주): +0.06
  - 모집 중인 포지션(부): +0.03

최종 점수 = 기본 유사도 + 포지션 부스트

4. TF-IDF 기반 가중치 (희소성 보정)

문제점: 많은 사람이 "새로운 주제"를 선택하면, 이 항목의 구별력이 낮음 해결책: TF-IDF로 희소한 목표/분위기에 높은 가중치 부여

goal_idf = log((N+1) / (df+1)) + 1
vibe_idf = log((N+1) / (df+1)) + 1

weight_vector = [pos_weight(0.5) || goal_idf_weighted(0.3) || vibe_idf_weighted(0.2)]

가중 벡터 = 원본벡터 * weight_vector (원소별 곱셈)

5. MMR (Maximal Marginal Relevance) - 다양성 고려

문제점: 상위 k개 추천이 모두 유사한 프로필일 수 있음 해결책: 유사도와 다양성의 균형

MMR_score = lambda × 유사도 - (1-lambda) × 최대중복도
          (lambda=0.7 기본값)

알고리즘:
1. 유사도가 가장 높은 후보 선택
2. 나머지 중에서 MMR_score가 최고인 후보 선택
   (유사도는 높지만, 이미 선택된 후보들과는 차이가 있어야 )
3. 반복하여 k개 선택

6. 추천 근거 제공

_explain_overlap() 함수:
- 포지션 일치: "포지션 일치(main:backend)" 또는 "포지션 부분일치(sub:design)"
- 목표 겹침: "목표 겹침: 실무경험, 포트폴리오중심"
- 분위기 겹침: "분위기 겹침: 편한분위기, 합의중심"

반환: 상위 3가지 이유

💡 핵심 성과 및 차별점

🎯 기술적 성과

  1. 하이브리드 추천 시스템 구현

    • Content-Based + Collaborative Filtering 결합
    • 팀 요구사항과 멤버 특성을 가중 평균으로 통합
    • α(alpha) 하이퍼파라미터로 두 특성 간 균형 조절
  2. TF-IDF 기반 Feature Weighting

    • 단순 빈도가 아닌 희소성 기반 가중치 부여
    • 구별력 높은 특성(예: 워터폴 방식)에 높은 가중치
    • 동적 가중치 계산으로 데이터 분포 변화에 자동 대응
  3. MMR 알고리즘 최적화

    • 유사도와 다양성의 균형 (λ=0.7)
    • O(K²) 복잡도로 실시간 추천 가능
    • 탐욕 알고리즘으로 효율적 Top-K 선택
  4. Explainable AI (XAI) 구현

    • 벡터 차원별 overlap 분석으로 추천 이유 도출
    • 사용자 신뢰도 향상 및 피드백 수집 용이
    • 디버깅 및 모델 개선에 활용
  5. Cold Start 문제 해결

    • 멤버가 없는 신규 팀: 자동으로 Content-Based Filtering만 사용
    • combined_team_vector() 함수에서 빈 멤버 리스트 처리 로직 구현
    • 별도의 폴백 로직 없이 하이브리드 시스템에서 자연스럽게 처리

🚀 확장 가능성

  • 실시간 학습: 사용자 피드백(좋아요/싫어요)을 통한 개인화 가중치 학습
  • 딥러닝 확장: Embedding Layer + Neural Collaborative Filtering
  • A/B 테스팅: 다양한 α, λ 값의 성능 비교 실험

📈 기대 효과

  • 매칭 효율성: 다차원 벡터 매칭으로 수동 검색 대비 빠른 후보 추천
  • 매칭 품질: 프로필 유사도 기반 정량적 스코어링
  • 사용자 신뢰도: XAI 기반 추천 근거 제공으로 의사결정 지원

🧪 알고리즘 설정 및 검증

하이퍼파라미터 튜닝

파라미터 기본값 설명 영향
α (alpha) 0.5 팀 요구사항 vs 멤버 평균 비율 α↑: 팀 요구사항 중시
α↓: 멤버 궁합 중시
λ (lambda) 0.7 MMR 유사도 vs 다양성 비율 λ↑: 유사도 우선
λ↓: 다양성 우선
group_weights (0.5, 0.3, 0.2) Position, Goal, Vibe 가중치 도메인 중요도 반영
main_sub (0.75, 0.25) 주/부 포지션 가중치 주포지션 우선도
pos_need_boost (0.06, 0.03) 수요 포지션 부스팅 팀 니즈 반영 강도

성능 메트릭

# 추천 품질 평가
Precision@K = (추천된 K개  실제 선택된 ) / K
Recall@K = (추천된 K개  실제 선택된 ) / (전체 선택 가능한 )
NDCG@K = DCG@K / IDCG@K  # 순위 고려 평가
Diversity@K = 평균 pairwise distance in Top-K

# 응답 시간
Latency = 벡터화 + 유사도 계산 + MMR (목표: <100ms)

🔮 향후 개선 방향

1. 딥러닝 기반 Embedding

# Neural Collaborative Filtering
class UserEmbedding(nn.Module):
    def __init__(self, num_users, embedding_dim=32):
        self.user_embedding = nn.Embedding(num_users, embedding_dim)
        self.fc = nn.Sequential(
            nn.Linear(embedding_dim + 23, 64),
            nn.ReLU(),
            nn.Linear(64, 32)
        )

2. 강화학습 기반 최적화

  • Multi-Armed Bandit: α, λ 동적 조정
  • Thompson Sampling: 탐험-활용 균형

3. 피드백 학습

# Implicit Feedback
positive_signal = [view, click, apply, accept]
negative_signal = [skip, reject]

# Learning-to-Rank
RankNet, LambdaMART 적용

👨‍💻 개발자

AI/ML Engineer

  • RecSys 아키텍처 설계 및 구현
  • 하이브리드 추천 알고리즘 개발
  • TF-IDF + MMR 최적화
  • FastAPI 서버 구축 및 성능 튜닝

Tech Stack Proficiency

  • Python (NumPy, Pandas, scikit-learn)
  • Machine Learning (Recommendation Systems, NLP)
  • FastAPI / RESTful API Design
  • Docker / Microservices Architecture

About

팀 프로젝트 매칭 추천시스템

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors