사주 소개팅 API https://api.saju.croninc.com 마크다운 원문 서비스 홈

사주 소개팅 API

사주 궁합으로 인연을 잇는 소개팅 서비스의 백엔드 API 문서입니다.

이 문서는 서버의 api.md 파일을 요청할 때마다 읽어 렌더링합니다. 문서를 고치면 새로고침만으로 반영됩니다. 원문은 /api.md 에서 그대로 받을 수 있습니다.


인증 방식

가입·로그인에 성공하면 토큰 두 개를 함께 돌려줍니다.

토큰 유효기간 쓰임
access_token 7일 모든 인증 API 호출에 사용
refresh_token 60일 액세스 토큰이 만료됐을 때 재발급

리프레시 토큰은 saju_sessions 테이블에 기록되며, 한 번 쓰면 폐기되고 새 토큰 쌍으로 교체됩니다(회전). 로그아웃하면 그 자리에서 삭제됩니다.

오류 응답

모든 오류는 HTTP 상태 코드와 함께 아래 형태로 돌아옵니다.

{ "detail": "이메일 또는 비밀번호가 올바르지 않습니다." }
코드
400 요청 형식이 잘못됨
401 인증 실패 · 토큰 만료
403 탈퇴한 회원 등 접근 불가
409 이미 가입된 이메일
422 입력값 검증 실패(형식·필수값)

POST /api/auth/signup

이메일로 회원가입합니다. 생년월일(+ 태어난 시각)으로 사주 기둥을 계산해 함께 저장합니다.

요청

{
  "email": "user@example.com",
  "password": "8자 이상",
  "name": "홍길동",
  "gender": "male",
  "birth_date": "1994-03-21",
  "birth_time": "07:30",
  "calendar": "solar",
  "region": "서울 강남",
  "marketing_agree": false
}
필드 필수 설명
email 로그인 아이디. 소문자로 정규화해 저장합니다.
password 8자 이상 128자 이하. pbkdf2_sha256(210,000회)으로 해시해 저장합니다.
name 1~30자
gender male 또는 female
birth_date YYYY-MM-DD. 만 19세 이상만 가입할 수 있습니다.
birth_time HH:MM. 모르면 비워 둡니다 — 시주 없이 저장합니다.
calendar solar(기본) 또는 lunar
region 활동 지역, 40자 이내
marketing_agree 마케팅 수신 동의 여부

응답 201

{
  "user": {
    "user_id": "u_3f9a2c1d5b7e8a04",
    "email": "user@example.com",
    "name": "홍길동",
    "gender": "male",
    "birth_date": "1994-03-21",
    "birth_time": "07:30",
    "birth_time_known": true,
    "calendar": "solar",
    "region": "서울 강남",
    "saju": {
      "year_pillar": "갑술",
      "day_pillar": "병오",
      "day_stem": "병",
      "day_element": "화",
      "day_yinyang": "양",
      "animal": "개",
      "hour_pillar": "임진",
      "month_pillar": null,
      "month_pillar_note": "월주는 절기(입춘·경칩 등) 기준이라 정확한 천문 계산이 필요해 아직 제공하지 않습니다.",
      "year_pillar_caveat": false
    },
    "email_verified": false,
    "status": "active",
    "created_at": "2026-08-30T18:20:11+09:00"
  },
  "access_token": "eyJhbGciOiJIUzI1NiIs...",
  "refresh_token": "eyJhbGciOiJIUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 604800
}

응답의 user 에는 password_hash 가 절대 포함되지 않습니다.

사주 계산 범위year_pillar(연주) · day_pillar(일주) · hour_pillar(시주) 세 기둥만 계산합니다.


POST /api/auth/login

요청

{ "email": "user@example.com", "password": "..." }

응답 200signup 과 같은 형태(user + 토큰 4종)입니다.

가입되지 않은 이메일과 비밀번호 오류는 같은 401 메시지로 응답합니다. 가입 여부가 새어 나가지 않게 하기 위한 것입니다.


POST /api/auth/refresh

액세스 토큰이 만료됐을 때 새 토큰 쌍을 받습니다. 쓴 리프레시 토큰은 즉시 폐기됩니다.

요청

{ "refresh_token": "eyJhbGciOiJIUzI1NiIs..." }

응답 200

{
  "access_token": "...",
  "refresh_token": "...",
  "token_type": "Bearer",
  "expires_in": 604800
}

이미 쓴 토큰을 다시 보내면 401 입니다.


POST /api/auth/logout

요청

{ "refresh_token": "eyJhbGciOiJIUzI1NiIs..." }

응답 200

{ "ok": true }

세션 기록을 지우므로 그 리프레시 토큰은 더 이상 쓸 수 없습니다. 액세스 토큰은 자체 만료(최대 7일)까지 유효합니다.


GET /api/auth/me

로그인한 회원의 정보를 돌려줍니다.

요청 헤더

Authorization: Bearer <access_token>

응답 200

{ "user": { "user_id": "u_3f9a2c1d5b7e8a04", "email": "user@example.com", "...": "..." } }

GET /health

서버 상태 확인용. 인증이 필요 없습니다.

{ "status": "ok", "app": "saju", "version": "1.0.0" }

데이터 저장소

DynamoDB(서울 리전 ap-northeast-2)를 쓰며, 테이블 이름은 모두 saju_ 로 시작합니다.

saju_users

항목 내용
파티션 키 user_id (u_ + 16자리 hex)
GSI email-index email — 로그인 시 이메일로 회원을 찾습니다
GSI status-index status + created_ts — 가입일순 조회용
과금 온디맨드(PAY_PER_REQUEST)

주요 속성: email, password_hash, name, gender, birth_date, birth_time, birth_time_known, calendar, region, saju(계산된 기둥), marketing_agree, email_verified, status, created_at, created_ts

saju_sessions

항목 내용
파티션 키 jti (리프레시 토큰 ID)
GSI user-index user_id — 한 회원의 세션 전체 조회
TTL expires_at — 만료된 세션은 DynamoDB 가 자동 삭제

아직 구현되지 않은 것

솔직하게 적어 둡니다. 아래는 이 문서에 없는 기능이며 서버에도 없습니다.

문서 최종 수정: 2026-08-30 18:26 (KST)