Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .agents/skills/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Skills (Codex)

OpenAI Codex 호환 스킬 디렉토리입니다. 스킬 설명은 [.claude/skills/README.md](../../.claude/skills/README.md)를 참고하세요.

각 서브디렉토리의 `SKILL.md`가 스킬 본문입니다.
32 changes: 32 additions & 0 deletions .agents/skills/api-design/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
name: api-design
description: REST API design guide for new endpoints — RESTful URL structure, query parameter binding rules (@RequestParam vs @ModelAttribute), OpenAPI annotations, and CommonApiResponse usage.
---

# REST API Design Guide

## URL Design

- RESTful principles: `/v1/auth/api-keys`
- Use plural: `/students`, `/clubs`
- Hierarchy: `/students/{id}/projects`

## Query Parameters

- Filtering: `?status=active`
- Pagination: `?page=0&size=20`
- Sorting: `?sort=createdAt,desc`

## OpenAPI Documentation

```kotlin
@Operation(summary = "Create API key", description = "...")
@ApiResponse(responseCode = "200", description = "Success")
@PostMapping("/api-keys")
fun create(@Valid @RequestBody reqDto: CreateApiKeyReqDto): ApiKeyResDto
```

## Response Format

- Success: `CommonApiResponse(data = ...)`
- Error: `ExpectedException` → Global Handler
126 changes: 126 additions & 0 deletions .agents/skills/database-schema/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
---
name: database-schema
description: Database schema design guide — table naming, column conventions, index strategy, and JPA entity mapping patterns.
allowed-tools: AskUserQuestion
---

# Database Schema Design Guide

Before providing schema guidance, ask the user about their migration tooling:

```
AskUserQuestion: "DB 마이그레이션 도구로 무엇을 사용하고 있나요?"
options:
- Flyway
- Liquibase
- 사용하지 않음 (JPA DDL auto)
```

Then provide the relevant migration section below along with the core conventions.

---

## Naming Conventions

- Tables: `snake_case`, plural (`users`, `api_keys`)
- Columns: `snake_case` (`created_at`, `is_active`)
- FK columns: `{referenced_table_singular}_id` (`user_id`, `club_id`)
- Index names: `idx_{table}_{columns}` (`idx_users_email`)
- UK names: `uq_{table}_{columns}` (`uq_users_email`)

## Standard Columns

Include in every entity table:

```sql
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
updated_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6)
```

## Index Strategy

- Single column used frequently in WHERE: simple index
- WHERE + ORDER BY combination: composite index (WHERE column first)
- Low-cardinality columns (`is_active`, `status` enum): indexing rarely helps

```sql
-- Composite index example
CREATE INDEX idx_posts_user_created ON posts (user_id, created_at DESC);
```

## Migration — Flyway

_(Include this section if the user selected Flyway)_

File naming: `V{version}__{description}.sql`

```
db/migration/
V1__create_users.sql
V2__add_api_keys.sql
V3__add_index_users_email.sql
```

```sql
-- V2__add_api_keys.sql
CREATE TABLE api_keys (
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT NOT NULL,
key_value VARCHAR(64) NOT NULL,
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
updated_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
CONSTRAINT fk_api_keys_user FOREIGN KEY (user_id) REFERENCES users (id),
CONSTRAINT uq_api_keys_value UNIQUE (key_value)
);
```

## Migration — Liquibase

_(Include this section if the user selected Liquibase)_

File naming: `db/changelog/{version}-{description}.yaml`

```yaml
# db/changelog/002-add-api-keys.yaml
databaseChangeLog:
- changeSet:
id: 002-add-api-keys
author: dev
changes:
- createTable:
tableName: api_keys
columns:
- column:
name: id
type: BIGINT
autoIncrement: true
constraints:
primaryKey: true
- column:
name: user_id
type: BIGINT
constraints:
nullable: false
- column:
name: key_value
type: VARCHAR(64)
constraints:
nullable: false
unique: true
```

## JPA Entity Mapping

```kotlin
@Entity
@Table(name = "api_keys")
class ApiKey(
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
val user: User,

@Column(name = "key_value", nullable = false, unique = true, length = 64)
val keyValue: String,
) : BaseEntity()
```
70 changes: 70 additions & 0 deletions .agents/skills/docker/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
name: docker
description: Dockerfile and docker-compose authoring guide — multi-stage builds, layer caching, security best practices, and compose service wiring.
---

# Docker Guide

## Dockerfile

### Multi-stage build

```dockerfile
FROM eclipse-temurin:21-jdk AS builder
WORKDIR /app
COPY gradlew settings.gradle.kts build.gradle.kts ./
COPY gradle gradle
RUN ./gradlew dependencies --no-daemon
COPY src src
RUN ./gradlew bootJar --no-daemon

FROM eclipse-temurin:21-jre
WORKDIR /app
COPY --from=builder /app/build/libs/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
```

### Layer caching rules

- `COPY` dependency manifests first, run install, then `COPY` source
- Only invalidate layers that actually changed

### Security

- Use specific digest tags, not `latest`
- Run as non-root: `RUN adduser --disabled-password app && USER app`
- Never `COPY . .` before installing dependencies

## docker-compose.yml

```yaml
services:
app:
build: .
ports:
- "8080:8080"
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://db:3306/mydb
depends_on:
db:
condition: service_healthy

db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: mydb
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
retries: 5
```

## .dockerignore

```
.git
build/
.gradle/
*.log
```
59 changes: 59 additions & 0 deletions .agents/skills/git-commit/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
name: git-commit
description: Split working tree changes into logical commits following this project's convention (`<type> :: <한글 요약>`), auto-detect Git Flow (warn before committing directly to develop/main), and commit without pushing.
compatibility: Requires git
---

## Step 1 — Inspect Changes

```bash
git status --short
git diff
git diff --staged
```

If there are no changes (staged or unstaged), report that and exit.

## Step 2 — Git Flow Check

```bash
git branch --show-current
```

If the current branch is `main`, `master`, or `develop`, warn the user before committing directly and ask for confirmation. Prefer committing on a feature/fix branch.

## Step 3 — Group Into Logical Commits

Read the diff and group changed files by concern (one feature, one fix, one config change, etc.). If the working tree mixes unrelated concerns, split into multiple commits using targeted `git add <files>` instead of `git add -A`. Do not bundle unrelated changes into a single commit just for convenience.

## Step 4 — Write Commit Messages

Format (see `AGENTS.md`):

```
<type> :: <한글 요약>
```

- `type`: `feat`, `fix`, `refactor`, `chore`, `docs`, `test`, `style`, `perf` 중 하나
- 요약은 한글로, 무엇을 했는지 간결하게

Example: `feat :: JWT 인증 필터 추가`, `fix :: API 키 조회 NPE 수정`

**어트리뷰션 주의**: 커밋 메시지에 "Co-Authored-By", "Generated by Codex" 같은 트레일러나 서명을 추가하지 않는다. 커밋 작성자는 로컬 `git config user.name`/`user.email`(사용자 본인 계정)을 그대로 따른다 — 별도로 identity를 바꾸지 않는다.

## Step 5 — Commit

```bash
git add <grouped-files>
git commit -m "<type> :: <한글 요약>"
```

여러 그룹이 있으면 그룹마다 반복. **`git push`는 실행하지 않는다** — 푸시는 `write-pr` 스킬 또는 사용자가 직접 수행한다.

## Step 6 — Report

생성된 커밋 목록을 보여준다:

```bash
git log --oneline -n <생성한 커밋 수>
```
Loading
Loading