운명이라 부르던 것을,
데이터로 계산했다

마인드매치(MindMatch)는 외모 스와이프 대신 성향 호환성으로 인연을 찾는 매칭 플랫폼입니다. Big Five 심리학·MBTI라는 현대 과학과, 사주팔자·별자리라는 전통 명리학을 하나의 가중치 알고리즘으로 융합했습니다. 분석 → 매칭 → 실시간 채팅까지, 1인 풀스택으로 만들고 운영합니다.

5요소
융합 호환성 알고리즘
34문항
Big Five 성향 분석
3단계
하이브리드 점수 갱신
1인
기획 → 개발 → 배포 운영
mindmatch.vision
MindMatch 랜딩 화면

※ 화면 이미지는 실제 서비스 코드(React)의 디자인을 재현한 UI 미리보기이며, 등장 인물·수치는 모두 가상 예시입니다.

스와이프는 빠르지만, 관계는 남지 않는다

외모 사진 2초 스와이프로 시작한 관계는 그만큼 빨리 끝납니다. 오래 가는 관계를 예측하는 건 첫인상이 아니라 성격 호환성이라는 문제의식에서 출발했습니다. "잘 맞는 사람"을 어떻게 수치로 정의할 것인가 — 이 질문이 프로젝트의 전부입니다.

🔬

직감 → 검증된 심리학

성격심리학에서 가장 검증된 Big Five(5대 성격 요인) 모델을 분석의 뼈대로 삼았습니다. 34개 문항으로 개방성·성실성·외향성·친화성·신경증을 정량화하고, 레이더 차트로 시각화합니다.

🔮

전통 명리학의 재해석

한국 사용자에게 "궁합"은 문화 그 자체입니다. 사주팔자의 오행 상생상극·천간합·십성을 직접 계산 엔진으로 구현해, 재미 요소가 아닌 알고리즘의 정식 변수(25%)로 편입했습니다.

⚖️

점수에는 이유가 있다

"87점"이라는 숫자만 던지지 않습니다. 어떤 요소가 잘 맞았는지 호환성 근거(인사이트)를 요소별로 분해해 함께 보여줍니다. 납득할 수 있는 점수가 신뢰를 만듭니다.

분석 → 매칭 → 대화, 하나의 여정

회원가입부터 첫 대화까지, 모든 화면이 "왜 이 사람인가"를 설명하는 데 집중합니다.

ANALYZE34문항이 나를 5개의 축으로 그린다

5단계 리커트 척도 설문이 끝나면 Big Five 레이더 차트와 성향 리포트가 생성됩니다. 설문 이탈을 막기 위해 진행률·마일스톤·XP 게이미피케이션을 설계했습니다.

  • Big Five 5요인 측정 — 개방성·성실성·외향성·친화성·신경증
  • 취향 확장 문항 — 음악·영화·도서·예술·가치관까지 프로필화
  • 키보드 단축키(1–5) — 응답 속도를 높이는 마이크로 UX
  • Canvas 레이더 차트 — 라이브러리 없이 직접 렌더링
mindmatch.vision/survey
Big Five 성향 설문 화면
Big Five 성향 분석 설문

MATCH호환성 점수로 만나는 사람들

성향 분석을 완료한 사용자만 매칭 풀에 들어옵니다. 5요소 융합 알고리즘이 산출한 점수로 천생연분(90+) · 최상위 · 좋은 매칭 등급을 나누고, 점수의 근거를 함께 제시합니다.

  • 검증된 매칭 풀 — 분석 미완료 사용자는 추천에서 제외
  • 호환성 근거 제시 — 성격 보완성·가치관 일치 요소 자동 추출
  • 디스커버리 큐 — 상위 호환 파트너 우선 추천
  • 상호 좋아요 → 매칭 성사 — 받은/보낸 좋아요 관리
mindmatch.vision/matches
매칭 목록 화면
호환성 점수 기반 매칭 목록

CONNECT대시보드에서 대화까지

내 성향·매칭 현황·받은 좋아요를 한 화면에 모은 대시보드에서, 매칭이 성사되면 WebSocket 실시간 채팅으로 바로 이어집니다.

  • 실시간 1:1 채팅 — WebSocket 연결 상태·온라인 표시
  • 읽지 않은 메시지 배지 — 채팅 이력 페이지네이션
  • 실시간 알림 — 새 좋아요·매칭 성사·메시지 도착
  • 신고·차단 시스템 — 안전한 소통 장치
mindmatch.vision/dashboard
대시보드 화면
성향·매칭 현황 대시보드

과학 65 : 운명 35, 호환성의 공식

하나의 이론에 기대지 않았습니다. 검증된 심리학(Big Five·MBTI)에 무게를 싣되, 전통 명리학(사주·별자리·혈액형)을 보조 변수로 융합해 한국적 맥락의 호환성 점수를 만들었습니다.

Big Five30%
MBTI30%
사주팔자25%
별자리10%
혈액형5%
Big Five — 5차원 성격 프로필 유사도 MBTI — 차원별 보완성 사주 — 오행 상생상극·천간합·십성 별자리 — 4원소 조화 혈액형 — 성격론 기반
🧠

Big Five — 유사성과 보완성의 균형

모든 요인이 "비슷할수록 좋은" 건 아닙니다. 가치관 축은 유사도를, 에너지 축은 보완성을 평가하도록 요인별 비교 전략을 다르게 설계했습니다.

호환성 = Σ wᵢ × compare(meᵢ, youᵢ) // 요인별 전략 분리
🀄

사주팔자 — 명리학을 코드로

양력 생년월일시에서 천간지지를 자동 변환하고, 오행 분포·일간 천간합·지지 육합/육충·십성 관계를 가중 합산합니다. 미신의 영역을 결정론적 계산 엔진으로 옮겼습니다.

사주점수 = 오행조화 40% + 천간합 20% + 지지관계 15% + 십성 10% + ⋯
년주조상 · 초년운
월주부모 · 청년운
일주본인 · 배우자궁
시주자녀 · 말년운

네 기둥(四柱)의 천간·지지 8글자(八字)를 계산해 오행 분포와 용신을 도출합니다.

// FOR DEVELOPERS

여기서부터는 기술 이야기입니다

1인 풀스택으로 기획부터 알고리즘 설계·배포·운영까지. 아래는 이 서비스를 실제로 굴러가게 만드는 구조와, 그 과정에서 내린 설계 결정의 기록입니다.

타입 안전한 풀스택 단일 저장소

client / server / shared 구조로 API 타입과 도메인 상수를 프론트·백엔드가 단일 소스로 공유합니다.

FRONTEND

  • React 18SPA + 함수형 컴포넌트
  • TypeScriptstrict mode
  • Vite빌드 · HMR
  • TanStack Query서버 상태 · 캐싱
  • Wouter경량 라우팅
  • Tailwind CSS디자인 토큰
  • shadcn/uiUI 컴포넌트
  • Canvas API레이더 차트 직접 렌더링

BACKEND

  • Node.js 20런타임
  • ExpressREST API
  • Drizzle ORM타입 안전 쿼리
  • PostgreSQL메인 데이터베이스
  • WebSocket(ws)실시간 채팅 · 알림
  • Passport.jsGoogle · Kakao OAuth
  • JWT토큰 기반 인증
  • node-cron배치 점수 갱신

INFRA / OPS

  • Docker Composedev · prod 환경 분리
  • Nginx리버스 프록시 · SSL
  • Hostinger VPSUbuntu 운영 서버
  • Let's EncryptSSL 자동 갱신
  • GitHub Actionspush → 자동 배포
  • Drizzle Kit스키마 마이그레이션
  • mindmatch.vision도메인 운영

성향 엔진을 품은 레이어드 아키텍처

성향 분석 1건이 저장되면 Big Five 프로필 갱신 → 5요소 호환성 재계산 → 매칭 점수 반영 → 실시간 알림까지, 트레이트 시스템 서비스들이 연쇄 처리됩니다.

Client — React 18 + ViteTanStack Query(서버 상태) · Wouter · Tailwind · shadcn/ui
▼ HTTPS / WebSocket (Nginx Reverse Proxy · SSL Termination)
Express — Routes → Services → Trait EnginePassport OAuth · JWT 미들웨어 · WebSocket Hub
compatibility/
5요소 가중 합산
four-pillars/
사주 계산 엔진
mbti-calculator/
천간합 · 차원 분석
batch-update/
cron 점수 갱신
▼ Drizzle ORM (타입 안전 쿼리 빌더)
PostgreSQL — Docker Container
Users · Profiles
PersonalityTraits
Matches · Likes
Messages · Reports
5
융합 트레이트 시스템
14
페이지 컴포넌트
3-Tier
점수 갱신 전략
78%
대시보드 코드 감량

10,000명이 써도 버티는 3단계 점수 갱신

사용자가 성향을 재분석하면 관련된 모든 매칭 점수가 낡은 값이 됩니다. 100명이면 99건, 10,000명이면 9,999건 — 매번 전부 재계산하면 느리고, 안 하면 틀립니다. 중요도에 따라 갱신 시점을 셋으로 분리해 실시간성과 성능을 동시에 잡았습니다.

TIER 01
즉시 갱신
setImmediate() · 1초 이내

상호 매칭(mutual) 상대 5~10명만 분석 직후 바로 재계산합니다. 사용자가 가장 먼저 확인할 화면이 가장 먼저 최신화됩니다.

TIER 02
배치 갱신
node-cron · 매일 03:00

전체 매칭을 사용량이 가장 낮은 새벽에 일괄 동기화합니다. 24시간 이내 갱신된 매칭은 스킵하는 스마트 캐싱으로 작업량을 줄입니다.

TIER 03
Lazy 갱신
조회 시 실시간 계산

매칭 화면을 열 때는 DB 점수 대신 최신 프로필로 즉석 계산합니다. 배치 사이 공백이 있어도 사용자 눈에는 항상 최신값이 보입니다.

// 성향 분석 완료 직후 — mutual 매칭만 비동기 즉시 갱신 (응답 블로킹 없음)
setImmediate(async () => {
  const mutualMatches = userMatches.filter(m => m.status === 'mutual');
  for (const match of mutualMatches) {
    const compatibility = await calculateUserCompatibility(me, partner);
    await storage.updateMatch(match.id, {
      compatibilityScore: compatibility.totalScore,  // 점수 + 근거를 함께 저장
      reasons: compatibility.insights,
    });
  }
});

설계 결정과 문제 해결의 기록

튜토리얼에는 없는 문제들입니다. 도메인 지식을 코드로 옮기고, 성능과 정확성 사이의 트레이드오프를 결정한 과정입니다.

01

사주팔자 계산 엔진 — 명리학을 결정론적 코드로 옮기기

PROBLEM사주는 표준 라이브러리가 없는 도메인이다. 천간지지 변환, 오행 상생상극, 천간합, 육합/육충, 십성 — 서로 얽힌 규칙 체계를 정확하고 테스트 가능한 형태로 구현해야 했다.
SOLUTION명리학 규칙을 데이터 테이블(천간 10 × 지지 12 매핑)과 순수 함수로 분리해 결정론적 엔진으로 구현. 호환성은 오행 조화 40% + 천간합 20% + 지지 관계 15% + 십성 10% 가중 합산으로 점수화하고, 근거(breakdown)를 함께 반환한다.
export function calculateFourPillarsCompatibility(p1: FourPillars, p2: FourPillars) {
  const elementHarmony = calculateElementHarmony(p1.elementDistribution, p2.elementDistribution); // 오행 상생상극
  const dayStem = checkHeavenlyStemCombination(p1.dayStem, p2.dayStem);   // 천간합 (갑기합토 등)
  const branch = analyzeBranchRelations(p1.day.branch, p2.day.branch);    // 배우자궁 육합/육충
  return { totalScore: elementHarmony * 0.4 + dayStem * 0.2 + branch * 0.15 + /* 십성 0.1 ⋯ */, breakdown };
}
02

이질적인 5개 체계를 하나의 점수로 — 정규화와 가중치 설계

PROBLEMBig Five는 연속 점수, MBTI는 16개 이산 유형, 사주는 규칙 기반 판정, 별자리·혈액형은 범주형 — 스케일과 분포가 전혀 다른 체계를 합산하면 특정 요소가 점수를 지배하는 왜곡이 생긴다.
SOLUTION각 체계를 독립 모듈로 두고 0~100으로 정규화한 뒤 가중 합산(30/30/25/10/5). 검증된 심리학에 65%를 싣고 전통 요소는 보조로 제한해, 재미와 신뢰의 균형점을 가중치로 명문화했다. 모듈 분리 덕에 가중치 실험·요소 추가가 한 줄 변경으로 끝난다.
const totalScore =
  bigFiveScore   * 0.30 +  // 5차원 성격 프로필 (유사성·보완성 혼합 전략)
  mbtiScore      * 0.30 +  // 차원별 보완성
  fourPillarsScore * 0.25 +  // 오행·천간합·십성
  zodiacScore    * 0.10 +  // 4원소 조화
  bloodTypeScore * 0.05;   // 성격론 기반
03

766줄 대시보드 — 도메인 단위 분해 리팩토링

PROBLEMdashboard.tsx 한 파일이 766줄 — 통계·성향 분석·좋아요 프리뷰·빠른 액션·다이얼로그가 한 컴포넌트에 엉켜 API 로직과 UI가 분리되지 않았고, 작은 수정에도 전체 파일을 읽어야 했다.
SOLUTION화면을 도메인 단위 7개 모듈(quick-stats, personality-analysis, likes-preview 등)로 분해하고, API 호출은 use-dashboard 커스텀 훅으로 추출. 본체는 165줄(-78%)로 줄고, 각 섹션이 독립적으로 수정·테스트 가능해졌다.
// Before: dashboard.tsx 766줄 (UI + API + 상태가 한 파일)
// After:  dashboard.tsx 165줄 + 도메인 모듈 7개
components/dashboard/
  ├─ quick-stats.tsx            // 퀵 스탯
  ├─ personality-analysis.tsx   // 성향 분석 섹션
  ├─ likes-preview.tsx          // 좋아요 프리뷰
  └─ survey-results-dialog.tsx  // 결과 다이얼로그
hooks/use-dashboard.ts          // API 로직 분리 — UI와 데이터 경계 확정
04

WebSocket 채팅 — 연결 상태와 메시지 정합성

PROBLEM실시간 채팅은 연결이 끊기는 순간이 본질이다. 끊김 중 도착한 메시지 유실, 재연결 시 중복 수신, 읽음 상태 불일치가 사용자 신뢰를 직접 깎는다.
SOLUTION메시지는 DB 영속화를 단일 진실로 삼고 WebSocket은 전달 채널로만 사용. 재연결 시 마지막 수신 이후를 REST로 동기화하고, 연결 상태를 UI에 명시해 사용자가 현재 상태를 항상 알 수 있게 했다. 읽지 않은 배지·페이지네이션도 서버 기준으로 계산한다.
05

운영 환경 — Docker · Nginx · SSL을 VPS 한 대에서

PROBLEM관리형 PaaS 없이 Hostinger VPS 한 대에서 프론트·백엔드·DB·SSL을 모두 직접 운영해야 했다. 환경 차이로 인한 "로컬에선 되는데" 문제와 인증서 만료 사고를 막아야 한다.
SOLUTIONdev/local/prod를 docker-compose 파일로 분리해 환경 차이를 코드화. Nginx 리버스 프록시에서 SSL 종료·WebSocket 업그레이드를 처리하고, Let's Encrypt 자동 갱신 + GitHub Actions push 배포로 수동 운영 작업을 제거했다.

push 한 번이 배포가 되기까지

GitHub push → Actions 빌드 → Docker 이미지 → VPS 배포. Nginx가 SSL을 종료하고 WebSocket을 프록시하며, 인증서는 자동 갱신됩니다.

git pushmain branch
GitHub Actionsbuild · test
Docker Buildcompose prod
VPS DeployHostinger Ubuntu
Live 🌐mindmatch.vision
HTTPS
Let's Encrypt 자동 갱신
3 env
dev · local · prod 분리
03:00
일일 배치 점수 동기화
24/7
실서비스 운영

화면 미리보기

실제 서비스 디자인을 재현한 UI 미리보기입니다. 클릭하면 크게 볼 수 있습니다.