Data Model
users, roles 테이블과 필드를 정리합니다.
가장 먼저 구현하는 테이블은 users, roles, 둘을 잇는 user_roles입니다. 한 사람이 여러 역할을 가질 수 있도록 연결 테이블로 나눴습니다. 전체 컬럼은 저장소의 docs/MeerKit_테이블명세서.xlsx를 보세요.
users
| 컬럼 | 타입 예시 | 필수 | 설명 |
|---|---|---|---|
id | BIGINT | 필수 | 사용자 고유 식별자 (PK). 자동 생성 |
login_id | VARCHAR(30) | 필수 | 로그인 ID. UNIQUE. API에서는 user_id 라는 이름으로 주고받음 |
hashed_password | VARCHAR(255) | 필수 | 비밀번호 해시값 (argon2). 응답에 넣지 않음 |
email | VARCHAR(255) | 필수 | 이메일. UNIQUE |
name | VARCHAR(50) | 필수 | 사용자 이름 |
is_active | BOOLEAN | 필수 | 계정 활성화 여부 |
email_verified_at | TIMESTAMPTZ | 선택 | 이메일 인증 시각 (API: email_verified) |
created_at | TIMESTAMPTZ | 필수 | 회원가입 일시 |
updated_at | TIMESTAMPTZ | 필수 | 마지막 정보 수정 일시 |
deactivated_at | TIMESTAMPTZ | 선택 | 탈퇴(관리자 삭제 포함) 시각. 값이 있으면 탈퇴한 계정 |
deleted_at | TIMESTAMPTZ | 선택 | 보관 기간이 지나 개인정보를 지운 시각 |
id와 user_id의 차이
id: 데이터베이스 내부에서 사용자를 구분하는 고유 번호입니다.user_id: 사용자가 로그인할 때 입력하는 ID입니다. 중복되지 않아야 합니다.
roles
| 컬럼 | 타입 예시 | 설명 |
|---|---|---|
id | BIGINT | PK |
code | VARCHAR(30) | 역할 이름 (MASTER 등). API에서는 name |
name | VARCHAR(50) | 화면 표시용 설명 |
user_roles
| 컬럼 | 타입 예시 | 설명 |
|---|---|---|
user_id | INTEGER | users.id (PK, FK) |
role_id | INTEGER | roles.id (PK, FK) |
Relationship
┌───────────────────┐ ┌──────────────┐ ┌──────────────┐ │ users │ 1 N │ user_roles │ N 1 │ roles │ │ id (PK) ├────────┤ user_id (FK) ├────────┤ id (PK) │ │ login_id (UNIQUE) │ │ role_id (FK) │ │ code │ │ hashed_password │ └──────────────┘ │ name │ │ email, name │ └──────────────┘ │ is_active │ │ deactivated_at │ │ deleted_at │ └───────────────────┘
사용자와 역할은 다대다입니다. 한 사람이 VIEWER와 WRITER를 함께 가질 수 있고, VIEWER가 100명이어도 roles에는 VIEWER가 한 번만 있습니다.
Frontend type
API가 돌려주는 사용자는 역할이 배열로 펼쳐진 형태입니다. 비밀번호 해시는 포함되지 않습니다.
src/meerkit/types.ts
export interface User {
id: number;
user_id: string;
email: string;
name: string;
email_verified: boolean;
roles: { id: number; name: RoleName }[]; // 여러 개일 수 있음
is_active: boolean;
created_at: string;
updated_at: string;
deactivated_at: string | null; // 탈퇴 시각
deleted_at: string | null; // 개인정보 파기 시각
}Optional columns
가입 폼의 선택 항목(Signup Form 참고)을 켜면 users에 같은 컬럼이 필요합니다. 기본 스키마에는 포함되어 있지 않습니다.
| 컬럼 | 타입 예시 | 필수 여부 | 설명 |
|---|---|---|---|
nickname | VARCHAR(30) | 선택 | 닉네임 (UNIQUE 권장). 있으면 이름 대신 표시 |
phone | VARCHAR(20) | 선택 | 전화번호 |
postcode | VARCHAR(10) | 선택 | 우편번호 (addressType이 postcode일 때) |
address | VARCHAR(255) | 선택 | 주소 (검색으로 채워짐) |
address_detail | VARCHAR(255) | 선택 | 상세 주소 (동·호수 등 직접 입력) |
birth_date | DATE | 선택 | 생년월일 |
gender | VARCHAR(10) | 선택 | 성별 (male, female, none) |
email_verified_at | TIMESTAMPTZ | 선택 | 이메일 인증 완료 시각 (인증 기능 도입 시) |
Terms agreements
약관 동의는 누가 어떤 약관에 언제 동의했는지 남겨야 분쟁 때 증빙할 수 있습니다. 가입 요청의 agreed_terms를 받아 서버가 별도 테이블에 저장하는 방식을 권장합니다.
| 컬럼 | 타입 예시 | 설명 |
|---|---|---|
user_id | BIGINT | users.id 참조 |
term_id | VARCHAR(30) | 약관 식별자 (terms, privacy, marketing …) |
agreed_at | TIMESTAMPTZ | 동의한 시각 |
version | VARCHAR(20) | 동의 당시 약관 버전 (약관 개정 대응) |
Email verifications
이메일 인증(signup.emailVerification)을 켰다면 인증번호와 증표를 저장할 곳이 필요합니다.
| 컬럼 | 타입 예시 | 설명 |
|---|---|---|
email | VARCHAR(255) | 인증 대상 이메일 |
code_hash | VARCHAR(255) | 인증번호의 해시 |
expires_at | TIMESTAMPTZ | 인증번호 만료 시각 (예: 3분) |
verified_token_hash | VARCHAR(255) | 인증 성공 시 발급한 증표의 해시 (가입 때 확인) |
attempts | INT | 확인 시도 횟수 (무차별 대입 방지) |
Password reset tokens
| 컬럼 | 타입 예시 | 설명 |
|---|---|---|
user_id | BIGINT | users.id 참조 |
token_hash | VARCHAR(255) | 토큰의 해시 (원본은 저장하지 않음) |
expires_at | TIMESTAMPTZ | 만료 시각 |
used_at | TIMESTAMPTZ | 사용된 시각 (단일 사용) |
AI usage (planned)
멤버 AI 사용량 화면(Member AI Usage, Member AI Usage History)은 현재 프론트 UI만 작업된 상태입니다. 사용량을 기록·집계하는 테이블과 API는 추후 적용 예정입니다.
Future extensions
permissions,role_permissions: 세부 기능별 권한이 필요할 때 추가합니다.projects: Owner가 여러 프로젝트를 소유하는 구조가 필요할 때 추가합니다.refresh_tokens: 토큰 해시, 만료, 폐기 시각을 저장합니다.
