ecole42

matcha

matcha

matcha는 ecole42의 웹 프로젝트로, Tinder 같은 데이팅 웹사이트를 만드는 것이 목표다. Nuxt.js와 Express.js를 사용하여 SSR 기반 풀스택 웹 애플리케이션을 구축하며, JWT 인증, 실시간 채팅(Socket.IO), 위치 기반 매칭, 지능형 추천 시스템 등 다양한 기능을 제공한다. ORM과 외부 validator 사용이 금지되어 있기에 순수 SQL 쿼리와 직접 구현한 검증 로직을 사용하여 데이터베이스와 백엔드 로직을 완전히 이해하여야 한다

Nuxt.js
Vue.js
Express.js
TypeScript
MySQL
Socket.IO

개요

Matcha는 ecole42의 웹 프로젝트 중 하나로, Tinder와 유사한 데이팅 웹사이트를 구현한 프로젝트다.

⚠️ 제약사항: 이 프로젝트에서는 ORM, validators, User Accounts Manager, NoSQL Database 사용이 엄격히 금지되어 있다.

스크린샷

Light ModeDark Mode
ChatNotification
MobileMap
Scroll Pagination

주요 기능

인증 및 보안

  • JWT 인증: Access Token과 Refresh Token을 사용한 인증 플로우
  • 이메일 인증: 회원가입 시 이메일 검증 링크 발송
  • 비밀번호 재설정: 이메일을 통한 비밀번호 재설정 기능
  • Google OAuth2 로그인: 소셜 로그인 지원

사용자 매칭

  • 지능형 추천 시스템: 사용자의 관심사, 나이, 언어, 성적 지향(이성애, 동성애, 양성애)을 기반으로 한 매칭 추천
  • 위치 기반 매칭: GPS 좌표를 이용한 거리 기반 매칭
  • IP 기반 위치 추적: 브라우저 GPS 허용이 없는 경우 IP 주소 기반 위치 추적
  • 고급 검색: 나이, 명성 점수, 위치, 태그를 기반으로 한 필터링 및 정렬

소셜 기능

  • 실시간 채팅: Socket.IO를 활용한 실시간 메시징
  • 좋아요 시스템: 사용자 간 좋아요 및 상호 좋아요 알림
  • 프로필 방문 추적: 프로필 방문 기록 및 알림
  • 차단 기능: 사용자 차단 기능
  • 신고 기능: 부적절한 사용자 신고 기능

사용자 프로필

  • 다중 이미지 업로드: 프로필 사진 여러 장 업로드
  • 태그 시스템: 관심사 태그 추가 및 관리
  • 자기소개: 프로필 소개글 작성
  • 명성 점수: 사용자 활동 기반 명성 점수 시스템

UI/UX

  • 다크 모드: 라이트/다크 테마 전환 지원
  • 반응형 디자인: 모바일 및 데스크톱 최적화
  • Google Maps 통합: 인터랙티브 지도를 통한 위치 표시
  • 무한 스크롤: 스크롤 이벤트 기반 페이지네이션
  • 알림 시스템: 실시간 알림 수신 및 관리

개발 도구

  • 시드 데이터: 자동 생성된 500명의 테스트 사용자 데이터

기술 스택

Frontend

  • Nuxt.js 2.15: Server Side Rendering (SSR)
  • Vue.js: 프론트엔드 프레임워크
  • Vuetify: Material Design 컴포넌트 라이브러리
  • Vuex: 상태 관리
  • Socket.IO Client: 실시간 통신
  • Vue2 Google Maps: 지도 통합

Backend

  • Express.js: RESTful API 서버
  • TypeScript: 타입 안정성
  • Socket.IO: 실시간 웹소켓 통신
  • MySQL 8.0: 관계형 데이터베이스 (Docker)
  • JWT: 인증 토큰 관리
  • bcrypt: 비밀번호 해싱
  • Multer: 파일 업로드 처리
  • Mailgun: 이메일 서비스

DevOps

  • Docker & Docker Compose: 데이터베이스 컨테이너화
  • Node.js: 런타임 환경

프로젝트 구조

matcha/
├── api/                    # Backend API 서버
│   ├── controller/        # 컨트롤러 (비즈니스 로직)
│   │   ├── Authentification.ts
│   │   ├── Chat.ts
│   │   ├── Like.ts
│   │   ├── Profile.ts
│   │   ├── Search.ts
│   │   └── ...
│   ├── models/            # 데이터 모델
│   │   ├── User.ts
│   │   ├── Chat.ts
│   │   ├── UserLike.ts
│   │   └── ...
│   ├── routes/            # API 라우트
│   │   ├── auth.ts
│   │   └── api/
│   │       ├── profile.ts
│   │       ├── chat.ts
│   │       ├── search.ts
│   │       └── ...
│   ├── middleware/        # 미들웨어
│   │   ├── authToken.ts
│   │   ├── validator.ts
│   │   └── ...
│   ├── services/          # 서비스 레이어
│   │   ├── Socket.ts
│   │   ├── Token.ts
│   │   ├── Mailing.ts
│   │   └── Location.ts
│   ├── init/              # 데이터베이스 초기화
│   │   ├── Database.ts
│   │   ├── InitDB.ts
│   │   └── SeedDB.ts
│   └── index.ts           # Express 서버 진입점
│
├── app/                    # Frontend Nuxt 애플리케이션
│   ├── components/        # Vue 컴포넌트
│   │   ├── App/          # 앱 내부 컴포넌트
│   │   │   ├── chat/
│   │   │   ├── notifications/
│   │   │   ├── profile/
│   │   │   └── search/
│   │   └── Home/         # 홈페이지 컴포넌트
│   ├── pages/            # 페이지 라우트
│   │   ├── app/          # 인증 필요 페이지
│   │   └── index.vue     # 홈페이지
│   ├── store/            # Vuex 스토어
│   ├── middleware/       # Nuxt 미들웨어
│   ├── plugins/          # Nuxt 플러그인
│   └── nuxt.config.js    # Nuxt 설정
│
├── docker-compose.yml     # Docker Compose 설정
├── eval.sh               # 자동 실행 스크립트
└── package.json          # 루트 패키지 설정

설치 및 실행

사전 요구사항

  • DockerDocker Compose (>= 1.27)
  • Node.js (권장: v14 이상)
  • npm 또는 yarn

필요한 API 키

다음 API 키를 사전에 준비해야 한다:

  1. Google Maps API Key (Places API)
  2. Google OAuth API Key
  3. Mailgun API Key

환경 변수 설정

apiapp 폴더에 각각 .env 파일을 생성해야 한다. .env.example 파일을 참고하여 다음 변수들을 설정한다:

api/.env

# Database
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=root
DB_NAME=matcha
DB_PORT=3306

# Server
PORT=5000
API=http://localhost:5000
APP=http://localhost:3000
ENVIRONMENT=build

# JWT
JWT_SECRET=your-secret-key
JWT_REFRESH_SECRET=your-refresh-secret-key

# Mailgun
MAILGUN_API_KEY=your-mailgun-api-key
MAILGUN_DOMAIN=your-mailgun-domain

# Google OAuth
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret

app/.env

# API Server
API=http://localhost:5000

# Server
PORT=3000
ENVIRONMENT=build

# Google Maps
GOOGLE_MAPS_API_KEY=your-google-maps-api-key

# Google OAuth
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret

빠른 시작

자동 실행 스크립트를 사용하여 한 번에 모든 것을 설정하고 실행할 수 있다:

sh ./eval.sh

이 스크립트는 다음 작업을 수행한다:

  1. Docker로 MySQL 데이터베이스 시작
  2. 루트 및 서브 프로젝트 의존성 설치
  3. 프로젝트 빌드
  4. 데이터베이스 초기화 및 시드 데이터 생성
  5. API 서버 및 프론트엔드 서버 시작

수동 실행

1. 데이터베이스 시작

npm run db
# 또는
docker-compose up -d

2. 의존성 설치

npm run install

3. 프로젝트 빌드

npm run build

4. 데이터베이스 초기화 및 시드 데이터 생성

npm run init_seed

5. 서버 시작

npm run start

개별 서버 실행:

# API 서버만 실행
npm run start-api

# 프론트엔드 서버만 실행
npm run start-app

개발 모드

개발 중에는 각 디렉토리에서 직접 실행할 수 있다:

# API 서버 (개발 모드)
cd api
npm run server

# 프론트엔드 서버 (개발 모드)
cd app
npm run dev

API 엔드포인트

인증 (/auth)

  • POST /auth/register - 회원가입
  • POST /auth/login - 로그인
  • POST /auth/refresh - 토큰 갱신
  • DELETE /auth/logout - 로그아웃
  • GET /auth/me - 현재 사용자 정보
  • POST /auth/social - 소셜 로그인
  • GET /auth/email-verification/:jwt - 이메일 인증
  • POST /auth/reset-password - 비밀번호 재설정 요청
  • GET /auth/reset-password/:jwt - 비밀번호 재설정 확인

프로필 (/api/profile)

  • GET /api/profile - 프로필 목록 조회
  • GET /api/profile/:id - 특정 프로필 조회
  • PUT /api/profile - 프로필 수정
  • POST /api/profile/picture - 프로필 사진 업로드
  • DELETE /api/profile/picture/:id - 프로필 사진 삭제

검색 (/api/search)

  • GET /api/search - 사용자 검색
  • POST /api/search - 고급 검색

좋아요 (/api/like)

  • POST /api/like/:id - 사용자 좋아요
  • DELETE /api/like/:id - 좋아요 취소

채팅 (/api/chat)

  • GET /api/chat - 채팅 목록 조회
  • GET /api/chat/:id - 특정 채팅 메시지 조회
  • POST /api/chat/:id - 메시지 전송

알림 (/api/notifications)

  • GET /api/notifications - 알림 목록 조회
  • PUT /api/notifications/:id - 알림 읽음 처리
  • PUT /api/notifications - 모든 알림 읽음 처리

차단 (/api/block)

  • POST /api/block/:id - 사용자 차단
  • DELETE /api/block/:id - 차단 해제
  • GET /api/block - 차단 목록 조회

신고 (/api/report)

  • POST /api/report/:id - 사용자 신고

태그 (/api/tags)

  • GET /api/tags - 태그 목록 조회
  • POST /api/tags - 태그 추가
  • DELETE /api/tags/:id - 태그 삭제

데이터베이스 구조

주요 테이블

users

  • 사용자 기본 정보 (이메일, 사용자명, 비밀번호, 이름 등)
  • 성별, 성적 지향, 자기소개
  • 위치 정보 (GPS 좌표)
  • 명성 점수, 온라인 상태, 마지막 로그인 시간

user_pictures

  • 사용자 프로필 사진 정보

user_tags

  • 사용자 관심사 태그

user_likes

  • 사용자 간 좋아요 관계

user_blocks

  • 사용자 차단 관계

chats

  • 채팅방 정보

chat_messages

  • 채팅 메시지 내용

user_notifications

  • 알림 정보 (좋아요, 메시지, 프로필 방문 등)

tags

  • 태그 마스터 데이터

자세한 데이터베이스 구조는 api/models/DATA.md를 참고한다.

보안 기능

  • JWT 토큰 기반 인증: Access Token (15분) 및 Refresh Token (7일)
  • 비밀번호 해싱: bcrypt를 사용한 안전한 비밀번호 저장
  • CORS 설정: 허용된 도메인만 접근 가능
  • 쿠키 기반 인증: HttpOnly 쿠키를 통한 토큰 관리
  • 이메일 인증: 회원가입 시 이메일 검증 필수
  • IP 기반 위치 추적: GPS 미허용 시 IP 기반 위치 추적

테스트

# 프론트엔드 테스트
cd app
npm test

# API 테스트
cd api
npm test

주요 제약사항

이 프로젝트는 ecole42의 교육 목적으로 다음 도구 사용이 금지되어 있다:

  • ❌ ORM (Object-Relational Mapping)
  • ❌ 외부 Validator 라이브러리
  • ❌ User Accounts Manager
  • ❌ NoSQL Database

대신 순수 SQL 쿼리와 직접 구현한 검증 로직을 사용한다.

기여자