개발자를 위한 지능형 팀 빌딩 플랫폼
머신러닝 기반 추천 시스템으로 토이 프로젝트, 해커톤, 스터디를 위한 최적의 팀원을 자동으로 매칭합니다.
개발자들이 토이 프로젝트, 해커톤, 스터디 등을 위해 최적의 팀원을 찾을 수 있도록 돕는 AI 기반 매칭 플랫폼입니다.
- 온라인 커뮤니티에서 적합한 팀원 찾기의 어려움
- 포지션, 기술 스택, 프로젝트 목표, 협업 스타일 등 다차원적 고려 사항
- 수동 검색의 비효율성과 미스매치로 인한 프로젝트 실패
머신러닝 기반 다차원 벡터 매칭으로 개인-팀 간 최적 조합을 자동 추천하며, 추천 근거를 제공하여 설명 가능한 AI(XAI) 구현
- 토이 프로젝트: 사이드 프로젝트를 함께 진행할 팀원 모집
- 해커톤: 단기 집중 개발을 위한 팀 빌딩
- 스터디/독서: 기술 스터디 그룹 구성
- 오픈소스: 오픈소스 프로젝트 기여자 모집
- 스타트업: 공동 창업자 또는 초기 팀원 탐색
Content-Based Filtering + Collaborative Filtering 결합
# 팀 벡터 = 팀 요구사항 + 기존 멤버 프로필의 가중 평균
combined_team_vector = α × team_requirements + (1-α) × mean(member_vectors)- α (alpha): 팀 요구사항과 멤버 특성의 균형 조절 (기본값: 0.5)
- 팀 요구사항: 모집 포지션, 프로젝트 목표, 선호 분위기
- 멤버 평균: 현재 팀원들의 프로필 벡터 평균
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: 편한분위기, 합의중심희소한 특성에 높은 가중치 부여로 구별력(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_vector ⊙ weight_vector # 원소별 곱셈기본 유사도 계산
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% 가산문제: 상위 추천이 모두 유사한 프로필 (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까지 반복모든 추천에 해석 가능한 이유 제공으로 사용자 신뢰도 확보
reasons = [
"포지션 일치(main:backend)",
"목표 겹침: 취업우선, 실무경험",
"분위기 겹침: 편한분위기, 합의중심"
]응답 예시
{
"user_id": 42,
"name": "김철수",
"similarity": 0.8734,
"reasons": [
"포지션 일치(main:backend)",
"목표 겹침: 취업우선, 포트폴리오중심",
"분위기 겹침: 애자일방식"
]
}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[최종 추천 결과 반환]
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 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 | 분산 캐싱, 세션 관리 |
- 양방향 추천: 개인 → 팀, 팀 → 후보자 추천 모두 지원
- 실시간 추천: 프로필 업데이트 시 즉시 재계산
- 다양성 보장: 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
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
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 3Framework: 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.7Containerization: Docker + Docker Compose
CI/CD: Gitlab CI/CD Pipeline
Monitoring: Spring Actuator + Prometheus
Logging: SLF4J + Logback (Backend), FastAPI Logger (ML)# 개발 환경 실행 (Backend: :8081, Frontend: :8080, RecSys: :8000)
docker-compose up --build
# 백그라운드 실행
docker-compose up -d
# 로그 확인
docker-compose logs -f recsysRecSys (AI Engine)
cd RecSys
pip install -r requirements.txt
python main.py
# http://localhost:8000/docs → FastAPI Swagger UIBackend (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후보자 추천 (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)",
"목표 겹침: 취업우선",
"분위기 겹침: 편한 분위기"
]
}
]
}positions = ["pm", "backend", "frontend", "design", "ai"]
main_position: 가중치 0.7 (주포지션)
sub_position: 가중치 0.3 (부포지션)
예: PM(주) + Backend(부) → [0.7, 0.3, 0, 0, 0]
목표 8가지: 취업우선, 수상목표, 포트폴리오중심, 학습중심,
아이디어실현, 실무경험, 빠른개발, 완성도추구
예: [취업우선, 실무경험] → [1, 0, 0, 0, 0, 1, 0, 0]
분위기 10가지: 반말지향, 존대지향, 편한분위기, 규칙적분위기,
리더중심, 합의중심, 새로운주제, 안정적주제,
애자일방식, 워터폴방식
예: [편한분위기, 합의중심] → [0, 0, 1, 0, 0, 1, 0, 0, 0, 0]
user_vector = [pos_vec(5dim) || goal_vec(8dim) || vibe_vec(10dim)]
= 23차원 벡터
# 팀 벡터 (팀이 모집하는 포지션/목표/분위기)
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기본 유사도 = cosine_similarity(weighted_combined_team, weighted_candidate)
= (A·B) / (||A|| × ||B||)
범위: 0~1 (높을수록 유사)
포지션 수요 부스트:
- 모집 중인 포지션(주): +0.06
- 모집 중인 포지션(부): +0.03
최종 점수 = 기본 유사도 + 포지션 부스트
문제점: 많은 사람이 "새로운 주제"를 선택하면, 이 항목의 구별력이 낮음 해결책: 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 (원소별 곱셈)문제점: 상위 k개 추천이 모두 유사한 프로필일 수 있음 해결책: 유사도와 다양성의 균형
MMR_score = lambda × 유사도 - (1-lambda) × 최대중복도
(lambda=0.7 기본값)
알고리즘:
1. 유사도가 가장 높은 후보 선택
2. 나머지 중에서 MMR_score가 최고인 후보 선택
(유사도는 높지만, 이미 선택된 후보들과는 차이가 있어야 함)
3. 반복하여 k개 선택_explain_overlap() 함수:
- 포지션 일치: "포지션 일치(main:backend)" 또는 "포지션 부분일치(sub:design)"
- 목표 겹침: "목표 겹침: 실무경험, 포트폴리오중심"
- 분위기 겹침: "분위기 겹침: 편한분위기, 합의중심"
반환: 상위 3가지 이유-
하이브리드 추천 시스템 구현
- Content-Based + Collaborative Filtering 결합
- 팀 요구사항과 멤버 특성을 가중 평균으로 통합
- α(alpha) 하이퍼파라미터로 두 특성 간 균형 조절
-
TF-IDF 기반 Feature Weighting
- 단순 빈도가 아닌 희소성 기반 가중치 부여
- 구별력 높은 특성(예: 워터폴 방식)에 높은 가중치
- 동적 가중치 계산으로 데이터 분포 변화에 자동 대응
-
MMR 알고리즘 최적화
- 유사도와 다양성의 균형 (λ=0.7)
- O(K²) 복잡도로 실시간 추천 가능
- 탐욕 알고리즘으로 효율적 Top-K 선택
-
Explainable AI (XAI) 구현
- 벡터 차원별 overlap 분석으로 추천 이유 도출
- 사용자 신뢰도 향상 및 피드백 수집 용이
- 디버깅 및 모델 개선에 활용
-
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)# 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)
)- Multi-Armed Bandit: α, λ 동적 조정
- Thompson Sampling: 탐험-활용 균형
# 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