Communitygithub.com

EgoDZB/claude-skills

PostgreSQL 네이밍 및 스키마 규칙 (테이블, 컬럼, 키, 제약 조건, 인덱스, 관계, 타입) for .NET/EF Core, Node.js (Drizzle, Prisma, TypeORM, Knex) 및 Go (sqlc). 스키마 설계 또는 리뷰, 마이그레이션 작성, 엔티티 구성, sqlc 쿼리 또는 SQL 작성 시, 또는 데이터베이스 객체 이름 지정 방법에 대한 질문을 받았을 때 사용합니다. 사용자에게 변경 사항을 알리지 않고 자동으로 수정하지 않고 편차를 보고합니다.

claude-skills란 무엇인가요?

이 스킬은 PostgreSQL 데이터베이스 스키마 설계 및 리뷰에 대한 종합적인 규칙과 모범 사례를 제공합니다. 테이블, 컬럼, 키, 제약 조건, 인덱스, 관계, 타입 등 데이터베이스 객체의 명명 규칙을 정의하며, .NET/EF Core, Node.js (Drizzle, Prisma, TypeORM, Knex) 및 Go (sqlc)와 같은 주요 ORM 및 개발 스택과의 통합 방법을 설명합니다. 이 스킬은 두 가지 모드로 작동합니다: 사용자가 이름을 직접 지정하는 경우(A)와 기존 코드나 데이터베이스에 이미 이름이 있는 경우(B)입니다. 모드 B에서는 자동으로 이름을 변경하지 않고 사용자에게 편차를 보고하고 수정 여부를 질문합니다. 또한 동시성 제어, 키셋 페이지네이션, 스네이크 케이스 ORM 설정 등 고급 주제를 다루며, Go sqlc에 대한 특별 섹션을 포함합니다. 이 스킬은 코드베이스 일관성을 유지하고, 잠재적인 버그를 방지하며, 개발자에게 명확한 지침을 제공하는 데 유용합니다.

지원 대상✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/EgoDZB/claude-skills/tree/HEAD/skills/postgres-conventions

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

PostgreSQL 규칙

적용 방법

두 가지 모드가 있습니다. 무언가를 작성하기 전에 어떤 모드를 적용할지 결정하십시오.

모드 A — 사용자가 이름을 선택합니다. 사용자가 스키마, 엔티티 또는 마이그레이션을 요청했지만 이름을 지정하지 않았습니다. 아래 규칙을 직접 적용하십시오.

모드 B — 이름이 이미 존재하거나 지정되었습니다. 사용자가 이름을 지정했거나, 기존 코드, 마이그레이션 또는 데이터베이스에 이러한 규칙에서 벗어난 이름이 포함되어 있습니다. 자동으로 이름을 변경하지 말고 보고하고 질문하십시오.

변경하기 전에 사용자 언어로 된 보고 형식:

Naming:
Must fix
- `"UserProfile"` (table) → `user_profiles` — quoted PascalCase는 모든 쿼리에서 따옴표로 묶어야 함
- `created` timestamp DEFAULT (CURRENT_TIMESTAMP AT TIME ZONE 'UTC') → `created_at timestamptz DEFAULT now()` — 세션 TimeZone이 UTC가 아닐 때 값이 변경됨
Recommended
- `users.user_email` → `users.email` — 테이블 이름이 이미 컨텍스트를 제공함

그런 다음 한 가지 질문을 합니다: 모두 적용, "Must fix"만 적용, 또는 현재 상태 유지. 답변을 기다리십시오.

보고 규칙:

  • Must fix = 버그를 유발하거나 쿼리 또는 도구를 손상시킵니다: 따옴표로 묶인 혼합 대소문자 식별자, 예약어, 63바이트를 초과하는 이름, 시간대가 없는 timestamp, 잘못된 시간 기본값, jsonb/numeric이 필요한 데이터에 json/float/money, FK 인덱스 누락, 트랜잭션 외부의 잠금.
  • Recommended = 스타일 및 일관성.
  • 현재 작업에서 다루는 객체만 보고합니다. 다른 곳에서 다른 편차를 발견한 경우, 한 줄을 추가하십시오: "<장소>에 유사한 편차 N개 더 있음 — 목록을 표시할까요?"
  • 적용된 마이그레이션 또는 라이브 데이터베이스의 객체: 이름 변경은 호환성을 깨는 변경입니다. 제안만 하고; 승인되면 새 마이그레이션으로 구현하십시오. 적용된 마이그레이션을 편집하지 마십시오.
  • 코드베이스가 일관되게 다른 규칙을 사용하는 경우, 해당 규칙이 우선합니다. 차이점을 한 번 언급한 다음, 각 발생을 플래그 지정하지 않고 프로젝트 규칙을 따르십시오.
  • ORM 명명 규칙(예: EFCore.NamingConventions)으로 생성된 이름은 그대로 허용됩니다.
  • 사용자가 규칙을 따르지 않는 이름을 확인하면, 해당 이름을 사용하고 이 세션에서 다시 언급하지 마십시오.

일반 규칙

  • snake_case, 소문자, 따옴표로 묶이지 않은 식별자.
  • 식별자당 최대 63바이트; 더 긴 이름은 자동으로 잘립니다. 자르지 말고 의미 있게 줄이십시오.
  • 테이블 복수형: users, orders, order_items.
  • 컬럼 단수형, 테이블 접두사 없음: users.email, users.user_email 아님.
  • 일반적인 약어를 제외한 전체 단어: id, url, ip, sku.
  • 예약어 또는 모호한 단어를 이름으로 사용하지 마십시오: user, order, group, table, limit, offset, desc, end, date, time, timestamp.
  • 형식 또는 객체 접두사 없음: tbl_users, str_name 사용 금지.
  • 부울은 긍정적으로: is_deleted, is_not_deleted 사용 금지.

표준 컬럼

용도이름형식
기본 키idbigint generated always as identity 또는 uuid v7
생성 / 수정created_at, updated_attimestamptz not null default now()
소프트 삭제deleted_attimestamptz null
감사created_by, updated_byFK to users.id
플래그is_active, is_verified, has_children, can_editboolean not null default false
상태statustext + check, enum, 또는 참조 테이블
날짜 전용birth_date, due_ondate
유효성expires_at, valid_from, valid_totimestamptz
금액amount, unit_price, total_amount + currency_codenumeric(19,4) + char(3), 또는 amount_minor bigint
카운터items_count, retry_countinteger / bigint
정렬sort_orderinteger
비즈니스 키code, slug, external_idtext + unique
테넌트tenant_idFK
동시성version 또는 시스템 xmininteger / xid
자유 형식 데이터metadata, payload, settingsjsonb

접미사는 의미를 전달합니다: _at 순간, _on/_date 달력 날짜, _id 참조, _count 카운터, _url, _path, _hash.

키 및 제약 조건

객체패턴예제
기본 키pk_<table>pk_orders
외래 키fk_<table>_<ref_table>_<column>fk_orders_customers_customer_id
고유 제약 조건uq_<table>_<cols>uq_users_email
대체 키 (EF Core)ak_<table>_<cols>ak_products_sku
검사ck_<table>_<rule>ck_orders_amount_positive
배타ex_<table>_<cols>ex_bookings_room_id_period
인덱스ix_<table>_<cols>ix_orders_customer_id_created_at
고유 인덱스ux_<table>_<cols>ux_users_email
부분 인덱스ix_<table>_<cols>_<condition>ix_users_email_not_deleted
메서드별 인덱스ix_<table>_<col>_<method>ix_products_tags_gin
트리거trg_<table>_<action>trg_orders_set_updated_at
트리거 함수동사 + 객체set_updated_at()
시퀀스PostgreSQL 기본값orders_id_seq
  • FK 컬럼: <참조 테이블, 단수형>_id, 또는 역할이 중요할 때 역할 이름: author_id, sender_id, recipient_id, parent_id.
  • FK 패턴에는 컬럼이 포함되므로, 하나의 테이블에 대한 여러 FK는 고유하게 유지됩니다: fk_messages_users_sender_id, fk_messages_users_recipient_id.
  • PostgreSQL은 FK 컬럼을 인덱싱하지 않습니다. 모든 FK는 복합 인덱스가 이미 FK로 시작하지 않는 한 인덱스가 필요합니다. EF Core는 기본적으로 이를 생성합니다. Drizzle, Prisma, TypeORM, Knex 및 sqlc는 그렇지 않습니다.

관계

종류형태예제
일대다자식의 FKorder_items.order_id → orders.id
일대일FK + unique, 또는 PK = FKuser_profiles.user_id
다대다접합 <a>_<b>, 복합 PKuser_roles (user_id, role_id), pk_user_roles
속성이 있는 다대다의미 있는 엔티티 이름memberships, enrollments
자기 참조parent_id 또는 역할categories.parent_id, employees.manager_id

다형성 쌍(commentable_type + commentable_id)은 FK를 가질 수 없습니다. 정확히 하나가 설정되었는지 확인하는 검사가 있는 별도의 nullable FK 컬럼 또는 별도의 테이블을 선호하십시오.

스키마, 뷰, 함수, 타입

객체패턴예제
스키마도메인 또는 모듈auth, billing, catalog, audit
뷰v_<name>v_active_users
구체화된 뷰mv_<name>mv_daily_sales
함수 / 프로시저동사 + 객체get_user_balance, calculate_order_total
열거형 타입<entity>_<attribute>order_status
열거형 값소문자 snake_casepending, paid, refunded
데이터베이스 역할<app>_<access>shop_app_rw, shop_app_ro, shop_migrator

열거형 값은 타입을 다시 생성하지 않고는 삭제할 수 없습니다. 변경되는 집합의 경우 text + 검사 또는 참조 테이블을 선호하십시오.

타입 및 기본값

  • 순간을 위한 timestamptz, 기본값 now(). timestamptz 컬럼의 CURRENT_TIMESTAMP AT TIME ZONE 'UTC'는 버그입니다.
  • 길이가 비즈니스 규칙이 아닌 이상 varchar(n) 대신 text; 이를 위해 check (char_length(col) <= n)을 선호하십시오.
  • jsonb, 절대 json 사용 금지.
  • 금액은 numeric; 절대 real, double precision 또는 money 사용 금지.
  • 새 identity 컬럼은 serial/bigserial이 아닌 generated always as identity를 사용합니다.
  • UUID 기본 키는 v7 사용: PostgreSQL 18 uuidv7(), .NET 9 Guid.CreateVersion7(), Node uuid 패키지 v7(), Go github.com/google/uuid uuid.NewV7(). 무작위 v4 키는 B-트리 인덱스를 조각화합니다.
  • gen_random_uuid()는 PostgreSQL 13부터 내장되어 있습니다. 이를 위해 uuid-ossp 및 pgcrypto는 필요하지 않습니다.
  • 대소문자 구분 없는 고유성을 위해 citext 또는 lower(email) 고유 인덱스를 사용합니다.

동시성 및 쿼리 패턴

  • 낙관적 동시성, EF Core + Npgsql: IsRowVersion()로 구성된 uint 속성은 xmin에 매핑됩니다.
  • 낙관적 동시성, Node 및 Go: version integer not null default 0, where id = $1 and version = $2 및 version = version + 1로 업데이트됨; 영향을 받은 행이 0이면 충돌을 의미합니다. sqlc에서는 :execrows를 사용하여 영향을 받은 행 수를 가져옵니다.
  • select ... for update 및 for update skip locked은 명시적 트랜잭션 내에서만; 자동 커밋에서는 잠금이 즉시 해제됩니다.
  • 어드바이저리 잠금: 트랜잭션 내 pg_try_advisory_xact_lock. 세션 수준 pg_advisory_lock은 잠금 해제될 때까지 열려 있는 전용 연결에서만; 풀링을 사용하면 잠금 및 잠금 해제가 다른 연결에 할당될 수 있습니다.
  • 크거나 무한한 목록은 키셋 페이지네이션을 사용합니다: where (created_at, id) < ($1, $2) order by created_at desc, id desc limit $3. offset은 작고 제한된 목록에만 사용합니다.
  • 미래 테이블에 대한 권한 부여는 grant ... on all tables뿐만 아니라 alter default privileges가 필요합니다.

스네이크 케이스를 위한 ORM 설정

스택설정
EF Core + NpgsqlEFCore.NamingConventions, UseSnakeCaseNamingConvention()
Drizzlecasing: 'snake_case'
Prisma필드에 @map, 모델에 @@map
TypeORMtypeorm-naming-strategies의 SnakeNamingStrategy
Knex / ObjectionknexSnakeCaseMappers()
Go + sqlc없음; Go 이름은 snake_case에서 자동으로 생성됨

프로젝트가 스네이크 케이스로 구성되지 않은 ORM을 사용하는 경우, 첫 번째 마이그레이션 전에 Must fix로 보고하십시오. 마이그레이션이 존재한 후에는 마이그레이션 비용과 함께 Recommended로 보고하십시오.

Go + sqlc

sqlc는 SQL 우선입니다: 스키마는 마이그레이션 파일에서 비롯되므로 위의 모든 규칙이 직접 적용됩니다.

  • sqlc.yaml의 schema를 마이그레이션 디렉토리로 지정하십시오 (goose, golang-migrate, dbmate 및 atlas 형식이 지원됨; down 마이그레이션은 무시됨). 마이그레이션 옆에 별도의 수동 작성 스키마 파일을 유지하지 마십시오.
  • 복수 snake_case 테이블은 단수 Go 구조체를 제공합니다: order_items → OrderItem. Enum order_status → 타입 OrderStatus와 상수 OrderStatusPending.
  • sql_package: pgx/v5를 사용하십시오. uuid → github.com/google/uuid.UUID 및 원하는 경우 timestamptz → time.Time을 pgtype 래퍼 대신 재정의하십시오.
  • 컬럼 이름을 바꾸지 않고 rename (url: URL, ip: IP)으로 두문자어를 수정하십시오.
  • 쿼리 이름은 PascalCase 동사 + 객체이며, 결과 종류를 포함합니다:
용도예제
한 행-- name: GetUserByEmail :one
여러 행-- name: ListOrdersByCustomer :many
삽입-- name: CreateOrder :one + returning *
업데이트-- name: UpdateOrderStatus :execrows
삭제-- name: DeleteSession :exec
대량 로드-- name: CreateOrderItems :copyfrom
  • 매개변수 이름은 @name 또는 sqlc.arg(name)으로 지정하고, nullable 매개변수는 sqlc.narg(name)으로 지정하십시오. 위치 기반 $1은 Column1 스타일의 Go 필드를 생성합니다.
  • 조인의 경우 임시 별칭으로 컬럼을 선택하는 대신 sqlc.embed(table)를 사용하십시오.
  • 쓰기에서 returning *을 제외하고 스키마 변경에도 살아남아야 하는 쿼리에서는 select *를 사용하지 마십시오.

관련 스킬