목차
- Claude Code 자동화의 전체 아키텍처
- 커스텀 스킬 설계: 슬래시 커맨드 만들기
- 훅 시스템으로 자동 전후처리 붙이기
- 에이전트 서브프로세스 활용법
- 역할
- 사용 도구
- 출력 형식
- CLAUDE.md로 프로젝트 컨텍스트 주입하기
- 프로젝트 개요
- 코드 컨벤션
- 디렉토리 구조
- 금지 사항
- 배치 처리: 대량 작업 자동화
- MCP 서버 연동으로 Claude Code 확장하기
- Claude Code 자동화 시스템 구축 시 비교: 접근 방식별 트레이드오프
- 실전 파이프라인 예시: PR 자동 리뷰 시스템
- 트러블슈팅과 운영 팁
- 이 자동화 구조가 실무에 남긴 것
결론부터 말하면, Claude Code 자동화 시스템 구축은 생각보다 진입장벽이 낮고 실무 효과는 꽤 크다. 커스텀 스킬 몇 개 만들고, 훅으로 파이프라인 엮고, 배치 API로 대량 처리 붙이면 혼자서 반복 업무의 절반 이상을 자동화할 수 있다.
나는 서버를 혼자 관리하는 입장이라 자동화에 민감한 편이다. Claude Code 자동화 시스템 구축을 본격적으로 시작한 건 매일 똑같은 코드 리뷰, 로그 분석, 문서 생성 작업에 시간을 너무 많이 쓰고 있다는 걸 깨달았을 때다. 지금은 .claude/ 디렉토리 하나에 스킬, 에이전트, 훅 설정을 모아두고 프로젝트마다 재사용하고 있다. 이 글에서 그 구조를 처음부터 풀어본다.
Claude Code 자동화의 전체 아키텍처
자동화 시스템을 만들기 전에 큰 그림부터 잡아야 한다. Claude Code는 단순한 코드 어시스턴트가 아니라 하나의 에이전트 런타임이다. 스킬, 훅, 에이전트, MCP 서버라는 네 가지 축이 있고, 이걸 조합하면 꽤 다양한 파이프라인이 나온다.
graph TB
A[사용자 입력 / 스케줄 트리거] --> B[Claude Code CLI]
B --> C{라우팅}
C --> D[커스텀 스킬]
C --> E[에이전트 서브프로세스]
C --> F[MCP 서버]
D --> G[훅 pre/post]
E --> G
G --> H[배치 API]
H --> I[결과 출력 / 파일 저장]
핵심은 진입점을 하나로 통일하는 거다. CLI에서 슬래시 커맨드 하나 치면 스킬이 실행되고, 훅이 전후처리를 하고, 필요하면 에이전트가 서브태스크를 처리한다. 이 흐름을 이해하면 나머지는 설정 파일 작성이다.
`.claude/` 디렉토리 아래에 `commands/`, `agents/`, `skills/` 폴더를 만들어 관리한다. 프로젝트 루트의 `CLAUDE.md`가 전체 컨텍스트를 제공하고, `settings.json`이 훅과 권한을 제어한다.
| 구성 요소 | 역할 | 트리거 방식 | 적합한 작업 |
|---|---|---|---|
| 커스텀 스킬 | 슬래시 커맨드로 실행하는 프롬프트 묶음 | /skill-name 입력 |
코드 리뷰, 문서 생성, 설정 변경 |
| 에이전트 | 독립 서브프로세스로 복잡한 태스크 처리 | Agent 도구 호출 |
멀티스텝 분석, 병렬 탐색 |
| 훅 | 특정 이벤트 전후에 자동 실행 | settings.json 설정 | 린트, 포맷팅, 검증 |
| MCP 서버 | 외부 API/DB를 도구로 노출 | 도구 호출 시 자동 | DB 조회, API 연동, 파일 시스템 |
사실 처음에는 이 네 가지가 어떻게 다른 건지 좀 헷갈렸다. 스킬이랑 에이전트가 비슷해 보이는데, 차이는 실행 컨텍스트다. 스킬은 현재 대화 안에서 실행되고, 에이전트는 별도 프로세스로 떠서 독립적으로 돌아간다.
커스텀 스킬 설계: 슬래시 커맨드 만들기
Claude Code 자동화 시스템 구축의 첫 단계는 커스텀 스킬이다. .claude/commands/ 디렉토리에 마크다운 파일을 만들면 그게 바로 슬래시 커맨드가 된다.
기본 스킬 파일 구조
# .claude/commands/review.md
코드 리뷰를 수행한다. 변경된 파일을 분석하고 아래 기준으로 피드백한다:
1. 보안 취약점 (SQL Injection, XSS, 인증 우회)
2. 성능 이슈 (N+1 쿼리, 불필요한 루프)
3. 에러 핸들링 누락
4. 네이밍 컨벤션 위반
출력 형식:
- 파일명: 이슈 설명 (심각도: high/medium/low)
- 수정 제안 코드 포함
이렇게 만들면 Claude Code에서 /review라고 입력하면 해당 프롬프트가 실행된다. 단순해 보이지만, 이게 쌓이면 팀 전체의 워크플로우가 된다.
인자를 받는 스킬
스킬에 $ARGUMENTS 플레이스홀더를 넣으면 동적으로 입력을 받을 수 있다.
# .claude/commands/deploy-check.md
$ARGUMENTS 환경에 배포하기 전 체크리스트를 실행한다.
1. 해당 환경의 설정 파일 확인 (config/{environment}.yaml)
2. 마이그레이션 스크립트 누락 여부
3. 환경 변수 diff 확인
4. 의존성 버전 충돌 체크
문제 발견 시 배포 차단 사유를 명확히 출력한다.
/deploy-check staging이라고 치면 $ARGUMENTS에 "staging"이 들어간다. 환경별 배포 전 검증을 자동화할 때 쓰기 좋다.
파일명이 곧 커맨드명이다. `review.md`는 `/review`, `deploy-check.md`는 `/deploy-check`가 된다. 팀 프로젝트면 접두사를 붙여서 `team-review.md`, `team-deploy.md`처럼 네임스페이스를 나누는 게 좋다.
스킬은 두 군데에 둘 수 있다:
- 프로젝트 스킬:
.claude/commands/— Git에 커밋해서 팀 공유 - 개인 스킬:
~/.claude/commands/— 내 머신에서만 동작
나는 코드 리뷰, 배포 체크 같은 건 프로젝트 스킬로, 개인적인 메모 생성이나 로그 분석은 개인 스킬로 분리해 두고 있다. 근데 솔직히 개인 스킬은 자주 안 쓰게 되더라. 프로젝트마다 맥락이 달라서 결국 프로젝트 스킬로 옮기는 경우가 많다.
훅 시스템으로 자동 전후처리 붙이기
스킬이 "뭘 할지"를 정의한다면, 훅은 "언제 자동으로 뭘 할지"를 정의한다. settings.json에서 설정하며, 특정 이벤트 발생 시 셸 명령을 자동 실행한다.
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit",
"command": "echo 'Checking lint before edit...'"
}
],
"PostToolUse": [
{
"matcher": "Write",
"command": "npx eslint --fix $CLAUDE_FILE_PATH"
}
],
"Notification": [
{
"matcher": "",
"command": "terminal-notifier -message '$CLAUDE_NOTIFICATION'"
}
]
}
}
PreToolUse는 도구 실행 전, PostToolUse는 실행 후에 트리거된다. matcher로 어떤 도구에 반응할지 필터링한다.
개인적으로 이 훅 시스템이 Claude Code 자동화에서 제일 과소평가된 기능이다. 파일을 수정할 때마다 자동으로 린트를 돌리고, 테스트를 실행하고, 포맷팅을 맞춘다. 사람이 까먹을 수 있는 걸 시스템이 잡아주니까.
실전에서 쓰는 훅 조합
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"command": "sh -c 'if echo \"$CLAUDE_FILE_PATH\" | grep -q \"\\.py$\"; then ruff check --fix \"$CLAUDE_FILE_PATH\" && ruff format \"$CLAUDE_FILE_PATH\"; fi'"
},
{
"matcher": "Bash",
"command": "sh -c 'if echo \"$CLAUDE_BASH_COMMAND\" | grep -q \"git commit\"; then echo \"[Hook] Commit detected. Running post-commit checks...\"; fi'"
}
]
}
}
Python 파일을 수정하면 자동으로 Ruff가 돌아간다. ruff를 안 쓰고 있다면 한번 써보길 권한다. 기존 flake8 + black 조합보다 체감상 훨씬 빠르다.
훅 커맨드가 0이 아닌 exit code를 반환하면 해당 도구 실행이 차단된다. 린트 에러가 있을 때 의도적으로 차단하려면 이걸 활용하면 되지만, 실수로 차단되면 당황스럽다. 처음에 이거 몰라서 한참 헤맸다.
단일 스킬로 처리하기 어려운 복잡한 태스크는 에이전트를 쓴다. Claude Code의 Agent 도구는 독립 서브프로세스를 띄워서 병렬로 작업을 처리한다.
에이전트 프로필은 .claude/agents/ 디렉토리에 마크다운으로 정의한다.
# .claude/agents/log-analyzer.md
서버 로그를 분석하는 에이전트다.
## 역할
- 에러 로그 패턴 분류
- 빈도 상위 10개 에러 추출
- 시간대별 에러 분포 분석
## 사용 도구
- Bash: 로그 파일 읽기, grep/awk 처리
- Grep: 패턴 검색
- Read: 설정 파일 확인
## 출력 형식
에러 유형 | 발생 횟수 | 최근 발생 시각 | 심각도
형식의 마크다운 테이블로 출력한다.
에이전트가 스킬과 다른 점은 독립 컨텍스트에서 실행된다는 거다. 메인 대화의 컨텍스트를 오염시키지 않으면서 무거운 작업을 돌릴 수 있다. 여러 에이전트를 동시에 띄워서 병렬 처리도 가능하다.
# 메인 대화에서 에이전트를 병렬로 호출하는 예시
1. log-analyzer 에이전트: 최근 24시간 에러 로그 분석
2. perf-checker 에이전트: API 응답시간 추세 분석
3. dep-auditor 에이전트: 의존성 보안 취약점 스캔
세 에이전트가 동시에 돌고, 결과를 모아서 일일 리포트를 생성한다.
다만 에이전트를 너무 잘게 쪼개면 오히려 오버헤드가 생긴다. 토큰도 각각 쓰니까. 나는 최소 5분 이상 걸리는 작업만 에이전트로 분리하고, 간단한 건 스킬로 처리한다.
CLAUDE.md로 프로젝트 컨텍스트 주입하기
Claude Code 자동화 시스템 구축에서 놓치기 쉬운 게 CLAUDE.md다. 프로젝트 루트에 이 파일을 두면 Claude Code가 매 세션 시작 시 자동으로 읽는다. 프로젝트의 컨벤션, 아키텍처, 금지 사항 같은 걸 여기에 적어둔다.
# CLAUDE.md
## 프로젝트 개요
Python 3.12 + FastAPI 기반 REST API 서버.
PostgreSQL 16, Redis 7.2 사용.
## 코드 컨벤션
- 타입 힌트 필수. Any 사용 금지.
- 모든 엔드포인트에 Pydantic v2 모델 사용.
- 에러 응답은 RFC 7807 (Problem Details) 형식.
- 테스트는 pytest + httpx.AsyncClient.
## 디렉토리 구조
- src/api/ : 라우터
- src/core/ : 비즈니스 로직
- src/models/ : SQLAlchemy 모델
- src/schemas/ : Pydantic 스키마
## 금지 사항
- print() 디버깅 금지. logging 모듈 사용.
- SELECT * 금지. 컬럼 명시.
- .env 파일 커밋 금지.
이게 있고 없고의 차이가 크다. 없으면 Claude Code가 매번 프로젝트 구조를 파악하느라 시간을 쓰고, 컨벤션도 들쭉날쭉해진다. 솔직히 이거 하나만 잘 써놔도 코드 품질이 확 올라간다.
CLAUDE.md 계층 구조
CLAUDE.md는 여러 위치에 둘 수 있다:
~/CLAUDE.md— 전역 설정. 모든 프로젝트에 적용./CLAUDE.md— 프로젝트 루트. 해당 프로젝트에만 적용./src/CLAUDE.md— 하위 디렉토리. 해당 디렉토리 작업 시 추가 로드
계층이 깊어질수록 구체적인 규칙을 넣는다. 전역에는 "한국어로 커밋 메시지 작성" 같은 공통 규칙, 프로젝트에는 기술 스택과 컨벤션, 하위 디렉토리에는 해당 모듈 특화 규칙을 넣는 식이다.

배치 처리: 대량 작업 자동화
파일 100개를 일괄 리팩토링하거나, PR 50개의 코드 리뷰를 돌려야 할 때. 이때 Claude의 Batch API가 필요하다.
Batch API 기본 구조
import anthropic
import json
client = anthropic.Anthropic()
# 배치 요청 생성
requests = []
for i, file_path in enumerate(target_files):
with open(file_path, "r") as f:
code = f.read()
requests.append({
"custom_id": f"review-{i}",
"params": {
"model": "claude-sonnet-4-20250514",
"max_tokens": 4096,
"messages": [
{
"role": "user",
"content": f"다음 코드를 리뷰해라. 보안, 성능, 에러 핸들링 관점에서.\n\n```python\n{code}\n```"
}
]
}
})
# JSONL 파일로 저장
with open("batch_input.jsonl", "w") as f:
for req in requests:
f.write(json.dumps(req) + "\n")
배치 요청을 JSONL 파일로 만들고, API에 제출한다:
# 배치 제출
batch = client.messages.batches.create(
requests=requests
)
print(f"Batch ID: {batch.id}")
print(f"Status: {batch.processing_status}")
결과는 비동기로 돌아온다. 완료까지 최대 24시간인데 보통 수십 분이면 끝난다. 비용도 일반 API 호출 대비 50% 할인이 적용된다. 바로 결과가 필요 없는 대량 작업이면 무조건 배치가 낫다.
배치 결과 수집 및 처리
import time
# 폴링으로 완료 대기
while True:
status = client.messages.batches.retrieve(batch.id)
if status.processing_status == "ended":
break
print(f"Processing... {status.request_counts.succeeded}/{status.request_counts.processing}")
time.sleep(30)
# 결과 수집
results = []
for result in client.messages.batches.results(batch.id):
if result.result.type == "succeeded":
review = result.result.message.content[0].text
results.append({
"id": result.custom_id,
"review": review
})
# 결과를 파일로 저장
with open("review_results.json", "w") as f:
json.dump(results, f, ensure_ascii=False, indent=2)
`custom_id`를 의미 있는 값으로 설정해라. 나중에 결과를 매칭할 때 `review-0`, `review-1`보다 `review-src/api/users.py` 식으로 파일 경로를 넣는 게 훨씬 편하다.
MCP(Model Context Protocol)는 Claude Code에 외부 도구를 붙이는 표준 프로토콜이다. DB 조회, 외부 API 호출, 파일 시스템 접근 같은 걸 Claude Code가 직접 할 수 있게 해준다.
MCP 서버 기본 구현
# mcp_server.py
from mcp.server import Server
from mcp.types import Tool, TextContent
import asyncio
import asyncpg
app = Server("db-query-server")
# DB 커넥션 풀
pool = None
@app.list_tools()
async def list_tools():
return [
Tool(
name="query_db",
description="PostgreSQL 데이터베이스에 읽기 전용 쿼리를 실행한다",
inputSchema={
"type": "object",
"properties": {
"sql": {
"type": "string",
"description": "실행할 SELECT 쿼리"
}
},
"required": ["sql"]
}
)
]
@app.call_tool()
async def call_tool(name: str, arguments: dict):
if name == "query_db":
sql = arguments["sql"]
# SELECT만 허용
if not sql.strip().upper().startswith("SELECT"):
return [TextContent(
type="text",
text="Error: SELECT 쿼리만 허용됩니다."
)]
global pool
if pool is None:
pool = await asyncpg.create_pool(
"postgresql://localhost:5432/mydb"
)
rows = await pool.fetch(sql)
result = [dict(row) for row in rows]
return [TextContent(
type="text",
text=str(result)
)]
if __name__ == "__main__":
asyncio.run(app.run())
이 서버를 Claude Code에 연결하려면 settings.json에 추가한다:
{
"mcpServers": {
"db-query": {
"command": "python",
"args": ["mcp_server.py"],
"cwd": "/path/to/project"
}
}
}
이러면 Claude Code에서 자연어로 "최근 가입한 유저 10명 보여줘"라고 하면 알아서 query_db 도구를 호출해서 SQL을 생성하고 결과를 보여준다.

보안 주의사항
MCP 서버에서 DB에 직접 연결할 때 절대로 DELETE, UPDATE, DROP을 허용하면 안 된다. 위 코드처럼 SELECT만 화이트리스트로 열어두는 게 기본이다. 아니면 읽기 전용 DB 유저를 따로 만들어서 연결하는 게 더 안전하다.
Claude Code 자동화 시스템 구축 시 비교: 접근 방식별 트레이드오프
자동화를 만드는 방법이 여러 가지다. 어떤 걸 써야 할지 판단 기준을 정리했다.
단일 작업 vs 파이프라인 vs 풀 자동화
| 기준 | 커스텀 스킬 단독 | 스킬 + 훅 파이프라인 | 에이전트 + MCP + 배치 |
|---|---|---|---|
| 구축 난이도 | 낮음 (마크다운 1개) | 중간 (settings.json 편집) | 높음 (코드 작성 필요) |
| 유지보수 | 쉬움 | 보통 | 복잡 |
| 처리 가능 범위 | 단일 대화 내 작업 | 파일 수정 전후 자동화 | 외부 시스템 연동, 대량 처리 |
| 적합한 상황 | 코드 리뷰, 문서 생성 | CI 전 검증, 포맷팅 | 로그 분석, 배치 리팩토링, DB 조회 |
| 토큰 비용 | 낮음 | 낮음 | 높음 (에이전트별 독립 세션) |
내 경험상, 대부분의 팀은 스킬 + 훅 파이프라인이면 충분하다. 에이전트와 MCP까지 동원해야 하는 상황은 생각보다 많지 않다. 근데 한번 맛보면 돌아가기 어렵긴 하다.
비용 최적화 포인트
배치 API는 일반 호출 대비 50% 저렴하다. 그런데 모든 걸 배치로 돌리면 결과를 기다리는 시간이 문제다. 나는 이렇게 나눈다:
- 즉시 응답 필요: 일반 API (스킬, 에이전트)
- 1시간 이내 결과 OK: 배치 API
- 정기 실행: 배치 + cron
코드 리뷰처럼 PR 올릴 때 바로 결과가 필요한 건 일반 API, 주간 코드 품질 리포트 같은 건 배치로 돌리는 식이다.
실전 파이프라인 예시: PR 자동 리뷰 시스템
지금까지 다룬 요소들을 조합해서 실전 파이프라인 하나를 만들어보자. PR이 올라오면 자동으로 코드 리뷰를 돌리는 시스템이다.
스킬 정의
# .claude/commands/pr-review.md
$ARGUMENTS PR을 리뷰한다.
1. 변경된 파일 목록을 가져온다 (gh pr diff)
2. 파일별로 아래 기준을 점검한다:
- 보안: 하드코딩된 시크릿, SQL 인젝션, XSS
- 성능: N+1 쿼리, 불필요한 동기 호출
- 테스트: 새 기능에 테스트가 있는지
- 타입: 타입 힌트 누락
3. 결과를 심각도별로 정리한다
4. gh pr comment로 리뷰 코멘트를 남긴다
훅으로 포맷팅 강제
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit",
"command": "sh -c 'ext=\"${CLAUDE_FILE_PATH##*.}\"; case $ext in py) ruff format \"$CLAUDE_FILE_PATH\";; ts|tsx) npx prettier --write \"$CLAUDE_FILE_PATH\";; esac'"
}
]
}
}
GitHub Actions와 연동
# .github/workflows/claude-review.yml
name: Claude PR Review
on:
pull_request:
types: [opened, synchronize]
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Claude Code Review
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
npm install -g @anthropic-ai/claude-code
claude -p "/pr-review ${{ github.event.pull_request.number }}" --output-format json > review.json
claude -p 플래그로 비대화형 모드에서 실행한다. CI/CD에서 돌리려면 이 플래그가 필수다. --output-format json을 붙이면 파싱하기 좋은 JSON으로 결과가 나온다.
Claude API 호출 비용 + GitHub Actions 러너 비용이 동시에 발생한다. PR이 많은 프로젝트에서는 draft PR에서는 건너뛰는 조건을 넣는 게 좋다. `if: github.event.pull_request.draft == false` 한 줄이면 된다.
트러블슈팅과 운영 팁
Claude Code 자동화 시스템 구축을 하다 보면 자잘한 문제들이 생긴다. 내가 겪은 것들을 정리해둔다.
흔한 에러와 해결
훅이 실행 안 될 때: settings.json 경로를 확인해라. 프로젝트 루트의 .claude/settings.json이 아니라 ~/.claude/settings.json에 넣어야 하는 경우가 있다. 스코프가 다르다.
MCP 서버 연결 실패: command에 절대 경로를 쓰는 게 안전하다. "command": "python"이 아니라 "command": "/usr/bin/python3"처럼. Claude Code가 실행되는 환경의 PATH와 내 터미널 PATH가 다를 수 있다.
에이전트가 컨텍스트를 잃을 때: 에이전트에 넘기는 프롬프트에 충분한 맥락을 포함해야 한다. "이전 대화를 참고해서"는 안 통한다. 에이전트는 독립 프로세스라 메인 대화를 모른다. 처음에 이것 때문에 시간 좀 날렸다.
`settings.json`이나 `CLAUDE.md`에 API 키를 절대 넣지 마라. 환경 변수로 관리하고, `.gitignore`에 `.env`를 반드시 추가해야 한다. GitHub에 키가 올라가면 몇 분 안에 악용된다.
Claude Code는 --verbose 플래그로 내부 동작을 볼 수 있다. 훅이 어떤 순서로 실행되는지, MCP 서버와 통신이 되는지 확인할 때 쓴다.
claude --verbose -p "/review"
로그에서 [Hook], [MCP], [Agent] 태그를 보면 각 컴포넌트의 동작을 추적할 수 있다.
이 자동화 구조가 실무에 남긴 것
Claude Code 자동화 시스템 구축을 하고 나서 바뀐 건 단순히 시간 절약만이 아니다. 반복 작업을 시스템에 맡기니까 정작 중요한 설계와 아키텍처 결정에 집중할 여유가 생겼다. 개인적으로 가장 체감이 큰 건 코드 리뷰 자동화다. 기계적인 체크(린트, 타입, 보안 패턴)는 Claude가 하고, 나는 비즈니스 로직과 설계 리뷰에만 집중한다.
핵심만 정리하면 이렇다. 스킬과 훅만으로도 일상 업무의 상당 부분을 자동화할 수 있고, MCP와 배치 API는 외부 연동과 대량 처리가 필요할 때 붙이면 된다. 처음부터 풀스택 자동화를 목표로 잡지 말고, 가장 반복적인 작업 하나를 스킬로 만드는 것부터 시작하는 게 맞다.
다음 단계로 갈 거라면 Anthropic의 Agent SDK를 한번 살펴볼 만하다. 에이전트 간 통신이나 상태 관리를 좀 더 체계적으로 할 수 있다. 그리고 MCP 서버를 직접 만들기 귀찮으면 MCP 공식 서버 목록에서 이미 만들어진 걸 가져다 쓰는 것도 방법이다. Postgres, GitHub, Slack 등 주요 서비스용 서버가 이미 있다.
관련 글
- Claude API 오케스트레이션 패턴 5가지: Python 워크플로우 자동화 실전 구현 – Claude API로 워크플로우를 자동화할 때 어떤 오케스트레이션 패턴을 써야 할까? 프롬프트 체이닝, 라우팅, 병렬화, 오케스트레이터-워…
- Claude 시스템 프롬프트 설계 패턴 7가지: 역할 지정부터 출력 포맷 제어까지 – Claude API를 쓸 때 시스템 프롬프트 하나가 응답 품질을 완전히 바꾼다. 실무에서 반복 검증한 7가지 설계 패턴을 코드 예제와 함께…
- Claude Projects 활용법 팀 지식베이스 구축 실전 가이드: 프롬프트 재사용과 컨텍스트 관리 – Claude Projects로 팀 지식베이스를 구축하고 3개월간 운영한 경험을 정리했다. 커스텀 인스트럭션 설계, 파일 업로드 전략, 토큰…