LLM이 포스터를 생성하고, 텍스트만 정확히 수정하고, PNG로 내보내는 오픈 텍스트 포맷
AI로 포스터를 만들 때 기존 방식은 한계가 있습니다.
| 방법 | 문제점 |
|---|---|
| AI 이미지 생성 | 글자 하나 바꾸면 전체 재생성, 디자인이 달라짐 |
| HTML/CSS 생성 | AI가 레이아웃 계산 실수, 픽셀 단위 오류 잦음 |
| PosterScript | .poster 파일이 상태로 존재 → content만 수정, 디자인 100% 유지 |
PosterScript는 선언형 텍스트 포맷입니다. AI가 생성하기 쉽고, 사람이 읽기 쉽고, 렌더러가 결정론적으로 그립니다.
사용자: "콘서트 포스터 만들어줘"
→ LLM이 .poster 파일 생성
사용자: "날짜를 9월로 바꿔줘"
→ LLM이 해당 @text의 content 한 줄만 수정
→ 렌더러가 그 텍스트만 업데이트
→ 레이아웃, 색상, 폰트 등 나머지 디자인 그대로 유지
사용자: "PNG로 저장해줘"
→ exportPNG() → 2배 해상도로 다운로드
@canvas
size: 800x1100
@bg
color: #070010
@image
id: hero
src: https://images.unsplash.com/photo-1493225457124?w=800
x: 0 y: 0 w: 100% h: 60%
fit: cover
opacity: 0.75
@shape
id: gradient-fade
x: 0 y: 45% w: 100% h: 55%
fill: linear-gradient(to bottom, transparent, #070010 60%)
@text
id: title
@editable
content: NOVA ECLIPSE
x: 40 y: 660
font: Bebas Neue
size: 80
color: #ffffff
tracking: 2
@text
id: date
@editable
content: 2025년 9월 20일
x: 40 y: 770
font: Noto Sans KR
size: 16
color: rgba(255,255,255,0.6)
@editable 플래그가 붙은 블록의 content만 수정하면 디자인이 유지됩니다.
posterscript/
├── packages/
│ ├── parser/ # @posterscript/parser — .poster → AST (zero deps)
│ ├── renderer/ # @posterscript/renderer — AST → DOM + PNG 내보내기
│ ├── cli/ # posterscript CLI — 생성, 검증, 렌더, 내보내기
│ └── share-server/ # @posterscript/share-server — 공유 링크 API
├── playground/ # 웹 에디터 + 실시간 미리보기
├── examples/ # 예시 .poster 파일
│ ├── concert.poster
│ ├── product.poster
│ └── minimal.poster
├── docs/
│ ├── SPEC.md # 언어 스펙 (source of truth)
│ ├── LLM_SYSTEM_PROMPT.md # AI 앱 연동용 시스템 프롬프트
│ └── START_PROMPT.md # Claude Code 개발 시작 프롬프트
└── spec/
└── POSTERSCRIPT.md # 영문 스펙
- Node.js 20+
- pnpm 9+
git clone https://github.com/your-org/posterscript.git
cd posterscript
pnpm install
# 터미널 1: 공유 서버 (포트 4000)
pnpm --filter @posterscript/share-server dev
# 터미널 2: 플레이그라운드 (포트 5173)
pnpm devhttp://localhost:5173 에서 에디터 + 실시간 미리보기를 사용할 수 있습니다.
# ANTHROPIC_API_KEY 환경변수 필요
export ANTHROPIC_API_KEY=sk-ant-...
npx posterscript generate "미니멀 재즈 콘서트 포스터"Generating poster...
✓ poster.poster 생성됨
▶ playground에서 확인:
http://localhost:5173/playground?p=aB3xK9
(링크는 24시간 후 만료됩니다)
--out jazz.poster 로 출력 파일명을 지정하거나, --no-open 으로 브라우저 자동 열기를 끌 수 있습니다.
전체 스펙은 docs/SPEC.md를 참조하세요.
| 블록 | 설명 | 필수 속성 |
|---|---|---|
@canvas |
캔버스 크기 (파일 맨 앞, 필수) | size (WxH) |
@bg |
배경색 또는 배경 이미지 | — |
@image |
이미지 요소 | id, src, x, y, w, h |
@text |
텍스트 요소 | id, content, x, y |
@shape |
도형 (사각형, 선, 오버레이 등) | id, x, y, w, h |
- 숫자만 쓰면 px:
x: 40→ 40px %를 붙이면 캔버스 기준:w: 100%→ 캔버스 전체 너비x,w→ 캔버스 너비 기준 /y,h→ 캔버스 높이 기준
@text 전체 속성 목록
| 속성 | 타입 | 기본값 | 설명 |
|---|---|---|---|
id |
string | (필수) | 고유 식별자 |
content |
string | (필수) | 텍스트 내용 (\n으로 줄바꿈) |
x, y |
px | % | (필수) | 위치 |
w, h |
px | % | auto | 크기 |
font |
string | sans-serif | Google Fonts 이름 |
size |
number | 16 | 폰트 크기 (px) |
weight |
100–900 | 400 | 굵기 |
color |
hex | rgb() | rgba() | #000000 | 글자색 |
align |
left | center | right | left | 가로 정렬 |
valign |
top | middle | bottom | top | 세로 정렬 |
line-height |
number | 1.35 | 행간 배수 |
tracking |
number | 0 | 자간 (px) |
uppercase |
true | false | false | 대문자 변환 |
opacity |
0–1 | 1 | 투명도 |
rotation |
number | 0 | 회전 (도) |
bg |
hex | rgb() | — | 텍스트 배경색 (버튼 스타일) |
radius |
number | 0 | 배경 모서리 둥글기 |
블록이 선언된 순서대로 그립니다. 나중에 선언된 블록이 위에 그려집니다.
@text
id: artist-name
@editable ← 이 플래그가 있으면
content: NOVA ECLIPSE ← LLM이 이 값만 수정 가능
x: 40 y: 660 ← 나머지 속성은 절대 건드리지 않음
size: 80
color: #ffffff
Playground는 코드 에디터와 캔버스가 양방향 동기화됩니다.
[코드 에디터] ←→ [비주얼 캔버스]
↕ ↕
코드 수정 → 캔버스 즉시 반영
캔버스 조작 → 코드 자동 업데이트
| 기능 | 동작 |
|---|---|
| 선택 | 요소 클릭. Shift+Click으로 다중 선택 |
| 이동 | 선택 후 드래그. 다중 선택 시 그룹 이동 |
| 리사이즈 | 8개 핸들 드래그. Shift로 비율 유지 (최소 20x20px) |
| 회전 | 상단 원형 핸들 드래그. Shift로 15도 단위 스냅 |
| 텍스트 편집 | @editable 텍스트 더블클릭 → 직접 편집 |
| 스냅 | 다른 요소 가장자리, 캔버스 중앙에 자동 정렬 |
| 그리드 | 16px 격자 표시 + 그리드 스냅 (토글) |
| 단축키 | 기능 |
|---|---|
Arrow |
선택 요소 1px 이동 |
Shift + Arrow |
10px 이동 |
Delete / Backspace |
선택 요소 삭제 |
Ctrl+D |
선택 요소 복제 |
Ctrl+A |
전체 선택 |
Ctrl+Z |
실행 취소 |
Ctrl+Shift+Z / Ctrl+Y |
다시 실행 |
[ / ] |
레이어 순서 변경 (앞으로/뒤로) |
Ctrl+Enter |
즉시 렌더링 |
- Properties: 선택 요소의 X, Y, W, H, Rotation, Opacity 직접 입력
- Layers: 모든 블록을 z-order 순으로 표시, 클릭으로 선택
- Status Bar: 캔버스 크기, 블록 수, 경고 표시
- PNG 저장: html2canvas로 2배 해상도 PNG 다운로드
- 링크 공유: share-server에 업로드 →
?p=IDURL 클립보드 복사 (24시간 유효)
docs/LLM_SYSTEM_PROMPT.md의 내용을 시스템 프롬프트에 넣으면
Claude, GPT 등 어떤 LLM이든 PosterScript 포맷으로 포스터를 생성/수정합니다.
- 모든 사용자 텍스트에
@editable플래그 추가 - Unsplash 실제 이미지 URL 사용
- 레이어 순서:
@bg→@image→@shape오버레이 →@text - 캔버스 크기: 세로 420x600, 가로 600x420
@editable블록의content값만 변경x,y,size,color,font등 다른 속성은 절대 변경하지 않음@editable이 아닌 블록은 건드리지 않음- 수정된 전체
.poster파일을 반환
posterscript <command> [options]| 명령어 | 설명 | 상태 |
|---|---|---|
generate <prompt> |
Claude API로 포스터 생성 | 구현됨 |
validate <file> |
.poster 파일 검증 | 미구현 |
render <file> |
브라우저 실시간 미리보기 | 미구현 |
export <file> |
PNG/PDF 내보내기 | 미구현 |
--out <file> 출력 파일명 (기본: poster.poster)
--no-open 브라우저 자동 열기 비활성화
생성된 포스터는 자동으로 share-server에 업로드되고, playground URL이 출력됩니다.
.poster 파일을 공유할 수 있는 간단한 REST API 서버입니다.
| 엔드포인트 | 설명 |
|---|---|
POST /share |
{ content: string } → { id, url } (6자 ID, 24시간 TTL) |
GET /share/:id |
{ content: string } 또는 404 |
- Hono + Node.js
- 메모리 저장 (서버 재시작 시 초기화)
- CORS 전체 허용
pnpm --filter @posterscript/share-server build
cd packages/share-server
railway upRailway 대시보드에서 환경변수 설정:
PORT=4000
PLAYGROUND_URL=https://your-playground.vercel.app
pnpm --filter @posterscript/share-server build
docker build -f packages/share-server/Dockerfile -t posterscript-share .
docker run -p 4000:4000 \
-e PLAYGROUND_URL=https://your-playground.vercel.app \
posterscript-share빌드 후 playground/dist/ 를 정적 호스팅합니다.
VITE_SHARE_SERVER_URL=https://your-server.railway.app pnpm build| 변수 | 사용처 | 기본값 | 설명 |
|---|---|---|---|
PORT |
share-server | 4000 |
서버 포트 |
PLAYGROUND_URL |
share-server | http://localhost:5173 |
공유 링크에 포함될 playground URL |
VITE_SHARE_SERVER_URL |
playground | http://localhost:4000 |
playground → share-server 호출 URL |
SHARE_SERVER_URL |
CLI | http://localhost:4000 |
CLI → share-server 호출 URL |
ANTHROPIC_API_KEY |
CLI | — | Claude API 키 |
.env.example 파일을 .env로 복사해서 사용하세요.
| 영역 | 기술 |
|---|---|
| 패키지 매니저 | pnpm workspaces |
| 언어 | TypeScript (strict) |
| 파서 | Zero-dependency, never throws |
| 렌더러 | Vanilla JS, position: absolute 기반 |
| 폰트 | Google Fonts 동적 로드 |
| PNG 내보내기 | html2canvas |
| 플레이그라운드 | Vite + Vanilla JS |
| CLI | Commander + Anthropic SDK |
| 공유 서버 | Hono + nanoid |
| 빌드 | tsup |
| 테스트 | Vitest |
pnpm install # 의존성 설치
pnpm dev # playground 개발 서버
pnpm build # 전체 빌드
pnpm test # 전체 테스트
pnpm test:parser # parser만 테스트MIT