← スキル䞀芧に戻る
eco2-team

postgres-schema

by eco2-team

🌱 읎윔에윔(Eco²) BE

⭐ 0🍎 0📅 2026幎1月25日
GitHubで芋るManusで実行

SKILL.md


name: postgres-schema description: PostgreSQL 슀킀마 섀계 가읎드. DDL 작성, 테읎랔 섀계, 읞덱슀 전략, 마읎귞레읎션 시 ì°žì¡°. "schema", "ddl", "table", "migration", "index", "constraint" 킀워드로 튞늬거.

PostgreSQL Schema Design Guide

Quick Reference

┌─────────────────────────────────────────────────────────────────┐
│                     Schema Design Principles                     │
├──────────────────────────────────────────────────────────────────
│                                                                  │
│  1. TEXT Ʞ볞 → VARCHAR 예왞 (RFC 표쀀만)                         │
│  2. TIMESTAMPTZ 필수 (타임졎 볎졎)                                │
│  3. ENUM 선택적 (고정 값 집합만)                                   │
│  4. Partial Index 활용 (NULL 제왞)                                │
│  5. CASCADE 명시적 섀정                                           │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Naming Conventions

TypePatternExample
Schema도메읞 소묞자chat, users, auth
Tablesnake_case 복수형sessions, social_accounts
Columnsnake_caseuser_id, created_at
PKidid UUID PRIMARY KEY
FK Column{entity}_idsession_id, user_id
Indexidx_{table}_{columns}idx_sessions_user_updated
Constraint{type}_{table}_{column}fk_user, chk_role

Column Type Strategy

1. TEXT Ʞ볞 원칙

-- 좋은 예: Ꞟ읎 불확싀한 컬럌은 TEXT
content TEXT NOT NULL,
title TEXT NOT NULL,
description TEXT,

-- 나쁜 예: 임의 Ꞟ읎 제한
title VARCHAR(255) NOT NULL,  -- 왜 255읞가?

2. VARCHAR 예왞 (RFC/표쀀 Ʞ반만)

-- 읎메음: RFC 5321 (64 + 1 + 255 = 320)
email VARCHAR(320) NOT NULL,

-- 전화번혞: E.164 표쀀 (최대 15자늬 + 국가윔드)
phone_number VARCHAR(20) UNIQUE,

-- ISO 윔드류
country_code CHAR(2),        -- ISO 3166-1 alpha-2
currency_code CHAR(3),       -- ISO 4217
language_code VARCHAR(5),    -- BCP 47 (ko-KR)

3. ENUM 사용 Ʞ쀀

-- 좋은 예: 값 집합읎 고정되고 변겜읎 드묞 겜우
role VARCHAR(10) NOT NULL CHECK (role IN ('user', 'assistant')),
type VARCHAR(20) NOT NULL CHECK (type IN ('text', 'image', 'generated_image')),

-- 대안: PostgreSQL ENUM 타입 (마읎귞레읎션 죌의)
CREATE TYPE message_role AS ENUM ('user', 'assistant');

ENUM vs CHECK 비교:

방식장점닚점
CHECK마읎귞레읎션 쉬움, 값 추가 간닚였타 가능성
ENUM TYPE타입 안전성, 저장 공간 횚윚값 추가 시 ALTER TYPE 필요

Timestamp Rules

-- 필수: TIMESTAMPTZ 사용 (타임졎 볎졎)
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),

-- ꞈ지: TIMESTAMP WITHOUT TIME ZONE
created_at TIMESTAMP NOT NULL,  -- 타임졎 정볎 손싀

SQLAlchemy에서 자동 갱신:

updated_at: Mapped[datetime] = mapped_column(
    TIMESTAMP(timezone=True),
    server_default=func.now(),
    onupdate=func.now(),
)

Constraint Patterns

Foreign Key

-- CASCADE: 부몚 삭제 시 자식도 삭제 (1:N 종속 ꎀ계)
CONSTRAINT fk_session FOREIGN KEY (session_id)
    REFERENCES chat.sessions(id) ON DELETE CASCADE,

-- SET NULL: 부몚 삭제 시 NULL로 섀정 (선택적 ì°žì¡°)
CONSTRAINT fk_assignee FOREIGN KEY (assignee_id)
    REFERENCES users.accounts(id) ON DELETE SET NULL,

-- RESTRICT: 자식 있윌멎 부몚 삭제 방지 (볎혞)
CONSTRAINT fk_owner FOREIGN KEY (owner_id)
    REFERENCES users.accounts(id) ON DELETE RESTRICT,

Check Constraints

-- 값 검슝
CONSTRAINT chk_role CHECK (role IN ('user', 'assistant')),
CONSTRAINT chk_type CHECK (type IN ('text', 'image', 'generated_image')),

-- 범위 검슝
CONSTRAINT chk_message_count CHECK (message_count >= 0),

Unique Constraints

-- 닚음 유니크
email VARCHAR(320) UNIQUE NOT NULL,

-- 복합 유니크 (명명된 제앜조걎)
CONSTRAINT uq_social_provider UNIQUE (provider, provider_user_id),

Index Strategy

Ʞ볞 읞덱슀

-- 조회 팹턮 êž°ë°˜ 읞덱슀
CREATE INDEX idx_sessions_user_updated
    ON chat.sessions(user_id, updated_at DESC);

-- 히슀토늬 조회용
CREATE INDEX idx_messages_session_ts
    ON chat.messages(session_id, timestamp DESC);

Partial Index (조걎부 읞덱슀)

-- NULL 제왞로 읞덱슀 크Ʞ 최적화
CREATE INDEX idx_accounts_nickname
    ON users.accounts(nickname)
    WHERE nickname IS NOT NULL;

-- Soft delete 지원
CREATE INDEX idx_sessions_active
    ON chat.sessions(user_id, updated_at DESC)
    WHERE is_deleted = FALSE;

Soft Delete Pattern

-- 권장: Boolean 플래귞
is_deleted BOOLEAN NOT NULL DEFAULT FALSE,

-- 대안: 삭제 시간 Ʞ록
deleted_at TIMESTAMPTZ,

-- 읞덱슀에서 삭제된 행 제왞
CREATE INDEX idx_sessions_user_updated
    ON chat.sessions(user_id, updated_at DESC)
    WHERE is_deleted = FALSE;

Standard DDL Template

-- 1. Schema 생성
CREATE SCHEMA IF NOT EXISTS {schema_name};

-- 2. Table 생성
CREATE TABLE {schema_name}.{table_name} (
    -- PK
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),

    -- FK
    {parent}_id UUID NOT NULL,

    -- Data columns
    {column} {TYPE} [NOT NULL] [DEFAULT value],

    -- Timestamps
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),

    -- Soft delete (선택)
    is_deleted BOOLEAN NOT NULL DEFAULT FALSE,

    -- Constraints
    CONSTRAINT fk_{parent} FOREIGN KEY ({parent}_id)
        REFERENCES {parent_schema}.{parent_table}(id) ON DELETE CASCADE,
    CONSTRAINT chk_{column} CHECK ({column} IN ('val1', 'val2'))
);

-- 3. Index 생성
CREATE INDEX idx_{table}_{columns}
    ON {schema_name}.{table_name}({columns})
    [WHERE condition];

-- 4. Comment (선택)
COMMENT ON TABLE {schema_name}.{table_name} IS '테읎랔 섀명';
COMMENT ON COLUMN {schema_name}.{table_name}.{column} IS '컬럌 섀명';

Migration Structure

migrations/schemas/
├── 001_users_schema.sql      # users 슀킀마
├── 002_auth_schema.sql       # auth 슀킀마
├── 003_chat_schema.sql       # chat 슀킀마 (신규)
└── README.md                 # 마읎귞레읎션 가읎드

Review Checklist

DDL 늬뷰 시 확읞할 항목:

  • TEXT vs VARCHAR: VARCHAR는 RFC 표쀀 Ʞ반읞가?
  • TIMESTAMPTZ: 몚든 시간 컬럌읎 타임졎 포핚읞가?
  • FK CASCADE: 삭제 동작읎 명시적윌로 섀정되었는가?
  • Index: 죌요 조회 팚턎에 읞덱슀가 있는가?
  • Partial Index: Soft delete나 NULL 컬럌에 조걎부 읞덱슀 적용?
  • Naming: 컚벀션을 따륎는가?
  • NOT NULL: 필수 컬럌에 NOT NULL 제앜읎 있는가?
  • DEFAULT: 적절한 Ʞ볞값읎 섀정되었는가?

Reference Files

Eco² Project Notes

スコア

総合スコア

60/100

リポゞトリの品質指暙に基づく評䟡

✓SKILL.md

SKILL.mdファむルが含たれおいる

+20
✓LICENSE

ラむセンスが蚭定されおいる

+10
○説明文

100文字以䞊の説明がある

0/10
○人気

GitHub Stars 100以䞊

0/15
○最近の掻動

3ヶ月以内に曎新がある

0/10
○フォヌク

10回以䞊フォヌクされおいる

0/5
✓Issue管理

オヌプンIssueが50未満

+5
✓蚀語

プログラミング蚀語が蚭定されおいる

+5
○タグ

1぀以䞊のタグが蚭定されおいる

0/5

レビュヌ

💬

レビュヌ機胜は近日公開予定です