5분 AI.
TRENDSHIFT #1 딥다이브 · 2026-08-25 분석

awesome-gpt-image-2 딥다이브
— 프롬프트 모음집이 “제품”이 되기까지

겉보기엔 이미지 생성 프롬프트를 모아둔 awesome 목록입니다. 그런데 열어 보면 마크다운을 데이터베이스처럼 쓰는 빌드 파이프라인, 크레딧 차감을 안전하게 처리하는 결제 백엔드, 그리고 같은 데이터로 만든 에이전트 스킬이 한 저장소에 같이 들어 있습니다. 문서 저장소와 상용 서비스 코드가 한 몸인 드문 사례입니다. (저장소: freestylefly/awesome-gpt-image-2 · ⭐15,402 · 🍴1,632 · JavaScript · MIT · 2026-04-25 생성 · 2026-08-25 기준)
목차
  1. 프로젝트 한줄 요약
  2. 왜 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트 (기술별)
  7. 하드웨어 / 시스템 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한줄 요약

이 저장소가 정확히 무엇인가

awesome-gpt-image-2는 OpenAI의 이미지 모델 GPT-Image-2로 좋은 그림을 뽑아낸 사례 532개를 모아 놓고, 그 사례들에서 반복되는 뼈대를 22개의 재사용 템플릿으로 정리한 저장소입니다.

여기까지는 흔한 awesome 목록입니다. 이 저장소가 다른 지점은 그다음입니다 — 마크다운으로 적어 둔 사례들이 빌드할 때마다 cases.json이라는 데이터 파일로 변환되고, 그 한 벌의 데이터가 웹사이트와 AI 에이전트용 스킬 양쪽에 동시에 공급됩니다.

TERM
awesome 목록
특정 주제의 좋은 자료를 모아 놓은 깃허브 저장소를 가리키는 관행적 이름. 대개 README.md 하나에 링크만 나열합니다.
TERM
Prompt as Code (프롬프트를 코드처럼)
이 저장소가 내세우는 표어. 프롬프트를 “그때그때 쓰는 문장”이 아니라 버전이 붙고, 검증되고, 조립되는 자산으로 다루자는 뜻입니다. 그래서 프롬프트가 JSON 형태로도 제공되고, 빌드 검사를 통과해야 배포됩니다.
한 문장 비유

레시피 블로그가 아니라, 같은 레시피로 식당과 밀키트를 동시에 굴리는 주방

보통의 프롬프트 모음집은 레시피를 적어둔 블로그입니다. 읽고 따라 하면 끝입니다.

이 저장소는 레시피(마크다운)를 한 곳에만 적어 두고, 그걸 기계가 읽어서 손님용 메뉴판(웹사이트)집에서 쓰는 밀키트(AI 에이전트 스킬)를 자동으로 찍어 냅니다. 레시피를 고치면 둘 다 같이 바뀝니다.

그리고 하나 더 — 그 웹사이트는 취미 페이지가 아니라 로그인·크레딧·결제가 붙은 실제 상용 서비스이고, 그 서버 코드가 MIT 라이선스로 같은 저장소에 공개돼 있습니다. 공부 대상으로서 이 저장소의 진짜 값어치는 프롬프트가 아니라 여기에 있습니다.

2왜 주목받는가

타이밍, 그리고 “목록” 이상의 것

① 모델 출시 직후의 공백을 메웠다

새 이미지 모델이 나오면 항상 같은 문제가 생깁니다. 모델은 좋아졌는데 무슨 말을 어떻게 적어야 그 성능이 나오는지 아무도 모릅니다. 이 저장소는 커뮤니티에 흩어진 성공 사례를 모아 그 공백을 메웠고, 2026년 4월 25일 생성 이후 4개월 만에 별 1.5만 개를 받았습니다.

② 사례를 모으는 데서 멈추지 않고 ‘구조’를 뽑아냈다

사례 532개를 그냥 나열하면 쓸모가 떨어집니다. 이 저장소는 사례들에서 반복되는 뼈대를 12개 카테고리 × 22개 템플릿으로 압축했습니다. 각 템플릿에는 언제 쓰는지(useWhen), 지켜야 할 것(guidance), 흔히 망하는 지점(pitfalls)이 영어·중국어 양쪽으로 붙어 있습니다.

특히 “망하는 지점”을 명시한 게 실무적입니다. 예를 들어 UI 스크린샷 템플릿의 주의사항은 이렇습니다 — 플랫폼 이름을 뭉뚱그리지 말 것, 화면에 들어갈 글자의 가독성과 플랫폼 고유 요소를 조건으로 못 박을 것.

③ 같은 데이터로 에이전트 스킬까지 만들어 3중 배포

이 저장소의 스킬 gpt-image-2-style-library는 세 가지 경로로 설치됩니다. 하나의 소스에서 세 채널로 나가는 구조 자체가 배울 만합니다.

경로명령대상
skills CLInpx skills add freestylefly/awesome-gpt-image-2Claude Code · Codex · Cursor 등
Claude 플러그인/plugin marketplace add freestylefly/awesome-gpt-image-2Claude Code 내부
npm 패키지npm i -g gpt-image-2-style-librarynpm · GitHub Packages

④ 상용 서비스의 “돈 받는 코드”가 통째로 열려 있다

이게 공부 자료로서 가장 희소한 부분입니다. 결제·크레딧·환불처럼 실수하면 바로 돈 문제가 되는 코드는 보통 비공개입니다. 그런데 여기엔 Stripe 결제, 알리페이 결제, 크레딧 차감/환불, 관리자 대시보드, 유료 커뮤니티 QR 발급까지 실제로 돈이 오가는 흐름 전체가 마이그레이션 SQL과 함께 공개돼 있습니다.

⑤ 그런데 — 솔직하게 짚어야 할 것

균형 잡기
별 1.5만 개가 코드 품질의 증거는 아니다

내용의 출처가 재구성입니다. README의 면책 문구에 명시돼 있듯, 사례 대부분은 YouMind·OpenNana 등 커뮤니티에 공개된 프롬프트를 수집·재정리한 것입니다. 저장소는 원저작자 링크를 남기려 노력한다고 밝히고 있지만, 상업적 사용은 보장하지 않는다고 못 박고 있습니다. 회사 업무에 그대로 쓰기 전에 원 출처를 확인해야 합니다.

상업적 요소가 섞여 있습니다. README 상단에 후원사 4곳의 제휴 링크(?aff=)가 있고, 토론 그룹은 9.9위안 유료 전환됐습니다. 정보의 중립성을 기대할 자료는 아닙니다.

저장소가 무겁습니다. 예제 이미지 542장이 그대로 들어 있어 클론 용량이 약 311MB(그중 이미지 155MB)입니다. 코드만 보려는 사람에게는 과한 비용입니다.

경쟁 자료와 비교하면

유형대표 예이 저장소와의 차이
일반 프롬프트 목록대다수 awesome-prompts마크다운만 있고 소비할 방법은 “복사”뿐. 여기는 JSON·스킬·API로 나감
모델 공식 문서OpenAI 이미지 가이드문법은 알려주지만 “이렇게 쓰면 이런 그림이 나온다”는 대량 사례가 없음
상용 프롬프트 SaaSYouMind 등결과물은 비슷하나 구현이 닫혀 있음. 여기는 서버 코드까지 MIT

3기술 스택 전체 지도

이 저장소를 굴리는 부품 목록

프론트엔드

부품버전역할과 눈여겨볼 점
React19.2화면 전체. 다만 라우터 라이브러리를 안 씁니다 — 페이지 전환은 해시와 Vercel rewrite로 처리
Vite7.2번들러. publicDirdata/로 지정해 생성된 JSON과 이미지를 그대로 정적 자원으로 내보냄
lucide-react0.561아이콘. UI 라이브러리는 이것뿐이고 CSS는 전부 직접 작성(styles.css 3,408줄)
파일 구성main.jsx 한 파일에 3,764줄. 컴포넌트 분리를 거의 하지 않은 단일 파일 스타일
쉽게 말하면

요즘 유행하는 프레임워크(Next.js 등)를 쓰지 않고 필요한 것만 골라 직접 조립한 구성입니다. 라우터도 없고, CSS 프레임워크도 없습니다.

장점은 의존성이 적고 동작이 훤히 보인다는 것, 단점은 main.jsx 3,764줄처럼 한 파일이 비대해진다는 것입니다. 좋은 예와 나쁜 예를 한 저장소에서 같이 볼 수 있는 셈입니다.

백엔드 (서버리스 함수)

부품역할
Vercel Functionsapi/ 폴더의 파일 하나 = 엔드포인트 하나. 총 34개 함수
Node.js ESM프레임워크 없이 export default async function handler(req, res) 형태만 사용
api/_lib/밑줄로 시작해 엔드포인트로 노출되지 않는 공용 모듈 폴더. Vercel의 관행
node:test테스트 러너. Jest·Vitest 없이 Node 내장 기능만 사용 (node --test api/_lib/*.test.js)

데이터베이스 · 인증

부품역할과 눈여겨볼 점
Supabase Postgres사용자·크레딧·주문·즐겨찾기. 마이그레이션 SQL 12개가 시간순으로 쌓여 있어 기능이 자라온 순서가 보임
RLS (행 수준 보안)모든 테이블에 켜져 있음. “자기 것만 읽는다”가 DB 차원에서 강제됨
SECURITY DEFINER 함수크레딧 증감은 전부 함수 안에서만. 일반 사용자에게는 실행 권한 자체를 회수(revoke)
Supabase Auth구글 OAuth. 이메일 로그인은 끄도록 안내
Watcha OAuth별도 OAuth 연동이 하나 더 있음 (api/auth/watcha/)

결제 · 외부 연동

부품역할
Stripe 22.x해외 결제. 구독(멤버십)과 단건(크레딧 팩) 양쪽
alipay-sdk 4.x중국 내 결제. RSA2 서명, 콜백 검증, 환불까지 구현
이미지 생성 APIOpenAI 직결이 아니라 CIYUAN_BASE_URL이라는 중계 서비스 경유. model: 'gpt-image-2'
GA4 Data API관리자 대시보드의 방문 지표. OAuth 리프레시 토큰 방식

인프라 · CI

4아키텍처 심화 분석

이 저장소에서 훔칠 만한 설계 네 가지

전체 그림

┌──────────────────────────────────────┐ │ docs/gallery-part-1.md (6,776줄) │ ← 사람이 쓰는 곳 진실의 원천 ───▶ │ docs/gallery-part-2.md (12,067줄) │ (유일한 원본) │ docs/templates.md (1,080줄) │ └───────────────┬──────────────────────┘ │ npm run predev / prebuild │ (사람이 잊어도 자동 실행) ┌───────────────▼──────────────────────┐ │ scripts/generate-site-data.mjs │ 마크다운을 정규식으로 │ scripts/generate-style-skill.mjs │ 파싱 + 검증 게이트 └───────┬──────────────────┬───────────┘ │ │ ┌─────────────▼──────┐ ┌───────▼───────────────────┐ │ data/cases.json │ │ references/style-library │ │ 529 케이스 · 1.3MB │ │ .md (659줄) │ └─────────┬──────────┘ └───────┬───────────────────┘ │ │ ┌──────────────▼────────┐ ┌─────────▼──────────────────┐ │ 웹사이트 (React 19) │ │ 에이전트 스킬 (SKILL.md) │ │ 갤러리·필터·즐겨찾기 │ │ Claude Code · Codex · npm │ └──────────┬────────────┘ └────────────────────────────┘ │ 로그인 후 “이 프롬프트로 만들어보기” ┌──────────▼─────────────────────────────────────────────┐ │ Vercel Functions (api/) 34개 │ │ ├ generate-image.js ─▶ 크레딧 예약 ─▶ 이미지 API │ │ ├ billing/ (Stripe · Alipay) │ │ ├ community/ (유료 그룹 QR) │ │ └ admin/ (지표 · 환불 · 크레딧 조정) │ └──────────┬─────────────────────────────────────────────┘ │ ┌──────────▼──────────────────────────────────────────────┐ │ Supabase Postgres — RLS + SECURITY DEFINER RPC │ │ profiles · credit_transactions · generation_reservations│ │ community_orders · user_memberships · favorites │ └─────────────────────────────────────────────────────────┘

설계 ① 마크다운을 데이터베이스로 쓴다

사례 데이터는 DB에도, JSON 원본에도 없습니다. 사람이 읽기 좋은 마크다운 문서에만 있고, 빌드할 때 정규식으로 파싱해 JSON을 만들어 냅니다.

// scripts/generate-site-data.mjs — 마크다운에서 사례를 뜯어내는 부분
// 1) 케이스 경계는 HTML 앵커로 자른다
const chunks = text.split(/<a name="case-(\d+)"><\/a>/g);

// 2) 프롬프트는 "**提示词:**" 다음의 코드펜스 안
const match = normalized.match(/\*\*提示词:\*\*[\s\S]*?```(?:text)?\n([\s\S]*?)```/);

// 3) 카테고리가 비면 제목·본문 키워드로 추론 (규칙 12개)
['UI & Interfaces', ['ui','app','interface','dashboard','截图']],
['Charts & Infographics', ['infographic','diagram','图谱','信息图']],
// ... 매칭이 하나도 없으면 'Other Use Cases'로 떨어뜨림
쉽게 말하면

엑셀 대신 워드 문서를 대장으로 삼고, 필요할 때 프로그램이 워드를 읽어 엑셀을 만들어 내는 방식입니다.

기여자는 깃허브에서 마크다운만 고치면 되니 진입 장벽이 낮고, 소비 쪽(웹사이트·스킬)은 깔끔한 JSON을 받습니다. 대신 문서 서식이 흐트러지면 파싱이 조용히 어긋납니다 — 아래 ②가 그 대비책입니다.

설계 ② 빌드를 실패시키는 검증 게이트

마크다운 파싱은 깨지기 쉽습니다. 그래서 스킬 생성 스크립트에는 조건을 어기면 빌드를 멈추는 검사들이 박혀 있습니다.

// scripts/generate-style-skill.mjs
function assertUnique(items, field, label) {   // ① id 중복 금지
  if (seen.has(value)) throw new Error(`${label} has duplicate ${field}`);
}

// ② 템플릿이 가리키는 앵커가 templates.md에 실제로 있는지
const templateAnchors = new Set([...templateText.matchAll(/<a name="([^"]+)"><\/a>/g)]);

// ③ 커버 이미지 파일이 디스크에 실재하는지
function localImagePath(src) { return join(root, 'data', ...); }

// ④ 금지된 문체("不是…而是" 대비 구문)가 섞이면 실패
function assertNoPattern(text, label) { ... }
배울 점
깨진 링크는 “나중에 발견”이 아니라 “지금 빌드 실패”로

문서 저장소에서 가장 흔한 부패는 죽은 앵커와 사라진 이미지입니다. 이 저장소는 그 두 가지를 빌드 시점에 검사해 아예 배포되지 못하게 막습니다. 문서를 데이터로 쓰기로 했다면 반드시 따라붙어야 하는 짝입니다.

④번이 특히 흥미로운데, 문체 규칙까지 자동 검사합니다. 사람이 리뷰에서 매번 지적하던 걸 스크립트로 옮긴 것입니다.

설계 ③ 크레딧을 안전하게 깎는 ‘예약 → 확정 → 해제’ 3단계

이 저장소에서 가장 값진 코드입니다. 문제 상황은 이렇습니다 — 돈(크레딧)은 먼저 깎아야 하는데, 이미지 생성은 실패할 수 있습니다. 먼저 깎으면 실패 시 손해고, 나중에 깎으면 무한 생성이 가능해집니다.

사용자 "이 프롬프트로 만들어줘" │ ▼ ① reserve_generation_usage() ← DB 함수 안에서 원자적으로 │ ├ profiles 행을 FOR UPDATE 로 잠금 │ ├ 무료 1회가 남았나? ─ 예 ─▶ free_generations_used +1 │ ├ 크레딧이 있나? ─ 예 ─▶ credit_balance −1 + 거래내역 기록 │ └ 둘 다 없음 ─────▶ raise 'CREDITS_REQUIRED' → HTTP 402 │ ▼ reservation_id 발급 (status='pending') ② 외부 이미지 API 호출 (여기서 실패할 수 있음) │ ├── 성공 ─▶ complete_generation_reservation() status='succeeded' │ └── 실패 ─▶ release_generation_reservation() ├ 무료였으면 free_generations_used −1 (되돌림) ├ 크레딧이었으면 credit_balance +1 │ + credit_transactions 에 type='refund' 기록 └ status='failed', error_code 저장

핵심은 차감과 환불을 애플리케이션 코드가 아니라 데이터베이스 함수 안에서 처리한다는 점입니다. 서버가 중간에 죽어도 크레딧이 반쪽만 깎이는 상태가 생기지 않습니다.

-- supabase/migrations/202605090001_user_credits.sql
create or replace function public.reserve_generation_usage(...)
language plpgsql
security definer              -- 함수 소유자 권한으로 실행
set search_path = public      -- 검색 경로 고정 = 함수 가로채기 방지
as $$
begin
  select * into v_profile from public.profiles
   where id = p_user_id for update;   -- ★ 행 잠금: 동시 요청 직렬화
  ...
TERM
FOR UPDATE (행 잠금)
읽으면서 그 행에 자물쇠를 겁니다. 같은 사용자가 버튼을 두 번 빠르게 눌러도 두 번째 요청은 첫 번째가 끝날 때까지 기다립니다. 이게 없으면 잔액 1개로 두 번 생성되는 이중 지출이 발생합니다.
TERM
사가(saga) 패턴
여러 시스템에 걸친 작업을 한 트랜잭션으로 묶을 수 없을 때 쓰는 방법. 각 단계마다 “되돌리는 방법”을 미리 준비해 두고, 실패하면 역순으로 되돌립니다. 여기서 release_...가 그 보상 동작입니다.

설계 ④ 권한을 “주지 않는” 방식의 보안

-- 같은 파일 끝부분. 순서가 중요하다: 먼저 회수, 그다음 딱 하나만 허용
revoke execute on function public.reserve_generation_usage(...)
  from public, anon, authenticated;     -- 로그인한 사용자조차 못 부름

grant execute on function public.reserve_generation_usage(...)
  to service_role;                       -- 서버만 부를 수 있음

브라우저가 들고 있는 열쇠(anon key)로는 크레딧 함수를 호출할 방법이 아예 없습니다. 서버 전용 열쇠(SUPABASE_SERVICE_ROLE_KEY)는 Vercel 환경변수에만 두고 브라우저 코드에 절대 넣지 않습니다.

쉽게 말하면

“금고를 잠갔다”가 아니라 “금고 열쇠를 애초에 나눠주지 않았다”에 가깝습니다. 클라이언트 코드에 검사 로직을 잔뜩 넣는 것보다 훨씬 튼튼합니다 — 클라이언트 코드는 사용자가 마음대로 고칠 수 있으니까요.

설계 ⑤ 로컬 개발용 Vercel 흉내내기

Vercel Functions는 클라우드에서만 도는 게 원칙이라 로컬 개발이 번거롭습니다. 이 저장소는 Vite 플러그인 100줄로 그걸 흉내 냅니다.

// scripts/vite-local-api.mjs
export function localVercelApi() {
  return {
    name: 'local-vercel-community-api',
    apply: 'serve',                  // 개발 서버에서만 동작
    configureServer(server) {
      server.middlewares.use(async (req, res, next) => {
        // Vercel이 넣어주는 것들을 손으로 채워 넣는다
        req.query = Object.fromEntries(requestUrl.searchParams.entries());
        attachVercelResponseHelpers(res);   // res.status().json() 흉내
        const module = await routeLoader();
        await module.default(req, res);      // 실제 핸들러를 그대로 실행
      });
    }
  };
}

포인트는 핸들러 코드를 하나도 고치지 않는다는 것입니다. 부족한 건 Vercel이 얹어주는 req.queryres.status().json()뿐이라, 그 둘만 채워 주면 같은 파일이 로컬에서도 돕니다.

5디렉토리 구조 해부

어디에 무엇이 있고, 어디부터 읽어야 하나
awesome-gpt-image-2/ 총 655개 파일 · 311MB (이미지 155MB) │ ├─ docs/ ← ★ 진실의 원천 (사람이 쓰는 곳) │ ├─ gallery-part-1.md 6,776줄 · 케이스 1~165 │ ├─ gallery-part-2.md 12,067줄 · 케이스 166~532 │ ├─ gallery.md 808줄 · 카테고리별 색인 │ ├─ templates.md 1,080줄 · 22개 산업용 템플릿 + 함정 안내 │ ├─ alipay-web-payment.md 알리페이 연동 절차서 │ └─ paid-community.md 유료 커뮤니티 운영 런북 │ ├─ data/ ← 생성물 + 정적 자원 (Vite publicDir) │ ├─ cases.json 1.3MB · 529건 (빌드 산출물, 직접 편집 금지) │ ├─ style-library.json 41KB · 카테고리13·스타일19·씬10·템플릿22 │ └─ images/ 155MB · 예제 이미지 542장 │ ├─ scripts/ ← 빌드 파이프라인 │ ├─ generate-site-data.mjs 189줄 · 마크다운 → cases.json │ ├─ generate-style-skill.mjs 169줄 · JSON → 스킬 레퍼런스 + 검증 게이트 │ ├─ vite-local-api.mjs 100줄 · 로컬에서 Vercel 함수 흉내 │ └─ alipay-webpay-sandbox-server.mjs 234줄 · 결제 샌드박스 │ ├─ api/ ← Vercel Functions 34개 │ ├─ _lib/ 공용 모듈 (밑줄 = 엔드포인트 아님) │ │ ├─ supabase.js 182줄 · 인증 컨텍스트 · 프로필 upsert │ │ ├─ billing.js 379줄 · Stripe 카탈로그·주문·크레딧 지급 │ │ ├─ alipay.js 246줄 · RSA2 서명·콜백 검증·환불 │ │ ├─ community.js 317줄 · 유료 그룹 주문 상태기계·레이트리밋 │ │ └─ *.test.js 395줄 · node:test 단위 테스트 │ ├─ generate-image.js 245줄 · ★ 예약→생성→확정/해제 (가장 볼 만함) │ ├─ billing/ Stripe 9개 + alipay/ 6개 │ ├─ community/ 유료 그룹 QR 5개 │ ├─ admin/ 지표·환불·크레딧 조정 8개 │ └─ auth/watcha/ OAuth 시작·콜백 │ ├─ supabase/migrations/ ← SQL 12개, 파일명이 곧 연대기 │ ├─ 202605090001_user_credits.sql 크레딧·예약 3함수 │ ├─ 20260509090000_membership_billing.sql 멤버십·크레딧팩·Stripe │ ├─ 20260721090000_alipay_webpay.sql 알리페이 │ └─ 20260722090000_paid_community.sql 유료 커뮤니티·QR(bytea) │ ├─ agents/skills/gpt-image-2-style-library/ ← 에이전트 스킬 (npm 배포) │ ├─ SKILL.md 에이전트가 읽는 지침 │ ├─ references/style-library.md 659줄 (생성물) │ ├─ agents/openai.yaml Codex용 메타데이터 │ └─ bin/install.mjs CLI 설치기 │ ├─ src/ ← 프론트엔드 │ ├─ main.jsx 3,764줄 (단일 파일) │ ├─ community.jsx 681줄 │ └─ styles.css 3,408줄 │ ├─ .claude-plugin/marketplace.json Claude Code 플러그인 등록 └─ .github/workflows/publish-style-skill.yml 태그 푸시 → npm 배포
읽는 순서 추천
30분만 쓸 거라면 이 네 파일

1. scripts/generate-site-data.mjs (189줄) — 마크다운을 데이터로 바꾸는 전 과정이 한 파일에 다 있습니다.
2. supabase/migrations/202605090001_user_credits.sql — 크레딧 3함수. 이 저장소의 정수.
3. api/generate-image.js (245줄) — 위 SQL을 애플리케이션이 어떻게 부르는지.
4. scripts/vite-local-api.mjs (100줄) — 로컬 개발 문제를 작게 푸는 방법.

주의
전체 클론은 311MB — 코드만 볼 거면 걸러 받으세요

예제 이미지 542장이 저장소에 그대로 커밋돼 있습니다. 코드 공부가 목적이면 아래처럼 이미지 없이 받는 편이 낫습니다.

git clone --depth 1 --filter=blob:none --sparse ...git sparse-checkout set api scripts supabase agents src

6학습 포인트

이 저장소에서 실제로 배워 갈 수 있는 것

① 결제·크레딧 시스템 설계 난이도 높음 · 가치 최상

배울 것: 예약-확정-해제 3단계, FOR UPDATE 행 잠금, 보상 트랜잭션, 거래 원장(credit_transactions) 분리.

왜 귀한가: 이런 코드는 대개 회사 안에만 있습니다. 잔액 하나로 두 번 결제되는 사고, 실패했는데 돈만 빠지는 사고는 전부 이 설계를 대충 해서 생깁니다.

실습 아이디어: reserve_generation_usage를 직접 psql에 붙여넣고, 서로 다른 두 세션에서 동시에 호출해 보세요. FOR UPDATE를 지웠을 때와 남겼을 때 잔액이 어떻게 달라지는지가 바로 눈에 보입니다.

② 문서를 데이터로 쓰는 빌드 파이프라인 난이도 중간 · 응용범위 넓음

배울 것: 마크다운 정규식 파싱, 키워드 기반 분류 추론, 그리고 깨지면 빌드를 세우는 검증.

어디에 쓰나: 사내 위키를 검색 API로, 블로그 글을 뉴스레터 데이터로, 회의록을 대시보드로 — 원본이 문서이고 소비처가 여럿일 때 같은 패턴이 그대로 먹힙니다.

실습 아이디어: 자기 블로그의 마크다운 글을 파싱해 posts.json을 만드는 스크립트를 써 보세요. 그다음 assertUnique처럼 슬러그 중복이면 빌드 실패를 추가해 보면 게이트의 감각이 옵니다.

③ 하나의 소스를 여러 채널로 배포하기 난이도 중간

배울 것: data/style-library.json 하나에서 웹 UI·스킬 레퍼런스·npm 패키지가 파생되는 구조. GitHub Actions에서 태그로 배포를 거는 방법.

핵심 통찰: 스킬을 “따로 관리하는 문서”로 두면 반드시 사이트와 어긋납니다. 생성물로 만들어 두면 어긋날 수가 없습니다 — 이 저장소가 references/style-library.md를 손으로 쓰지 않는 이유입니다.

④ 에이전트 스킬 작성법 난이도 낮음

SKILL.md가 짧고 좋은 예입니다. 배울 지점 세 가지 —

⑤ 프레임워크 없이 서버리스 API 짜기 난이도 낮음~중간

Express도 NestJS도 없습니다. export default async function handler(req, res)_lib/ 공용 모듈만으로 34개 엔드포인트가 굴러갑니다. 프레임워크가 실제로 무엇을 대신해 주고 있었는지(라우팅·바디 파싱·에러 처리) 손으로 확인해 볼 수 있는 크기입니다.

⑥ 프롬프트 엔지니어링 그 자체 난이도 낮음

템플릿 문서가 알려주는 핵심은 “예쁜 형용사”가 아니라 고정해야 할 축입니다.

고정하는 이유
주제 · 과업무엇을 그릴지가 흔들리면 나머지가 다 흔들림
구도 · 레이아웃“2열 3행 그리드”처럼 못 박아야 반복 생성이 일관됨
스타일 · 재질모델이 임의로 고르는 폭을 좁힘
글자 요구사항화면에 들어갈 문구를 명시하지 않으면 깨진 글자가 나옴
비율 · 출력형식재작업의 가장 흔한 원인
금지 조건“하지 말 것”을 적어야 반복되는 실패가 줄어듦

7하드웨어 / 시스템 요구사항

직접 돌려 보려면 무엇이 필요한가
구분요구사항
Node.js22 이상 (CI가 22를 씀). Vite 7 · React 19가 최신 Node를 전제
디스크클론 311MB + node_modules 약 200MB. 이미지 제외 시 크게 줄어듦
GPU불필요. 이미지 생성은 전부 외부 API 호출 — 로컬 추론 없음
메모리일반 노트북이면 충분. cases.json 1.3MB를 브라우저가 통째로 읽는 정도

단계별로 무엇까지 되나

하고 싶은 것필요한 것비용
사례·템플릿 읽기없음 (깃허브에서 바로)무료
에이전트 스킬 쓰기Claude Code 또는 Codex무료 (에이전트 요금 별도)
사이트 로컬 실행npm i && npm run dev무료 (로그인·생성은 비활성)
로그인·크레딧까지Supabase 프로젝트 + 마이그레이션 12개 적용Supabase 무료 티어 가능
이미지 생성까지CIYUAN_API_KEY (중계 API 유료 키)유료
결제까지Stripe 키 + 알리페이 상점 계정Stripe 테스트는 무료, 알리페이는 중국 사업자 필요
환경변수 다룰 때
브라우저로 새면 안 되는 값들

SUPABASE_SERVICE_ROLE_KEY · STRIPE_SECRET_KEY · ALIPAY_PRIVATE_KEY · CIYUAN_API_KEY서버 전용입니다. Vite에서는 VITE_ 접두사가 붙은 변수만 브라우저 번들에 들어가는데, 이 규칙을 착각해 비밀 키에 VITE_를 붙이면 그 순간 전 세계에 공개됩니다.

.env.example을 보면 VITE_SUPABASE_ANON_KEY(공개용)와 SUPABASE_SERVICE_ROLE_KEY(비공개)가 이름부터 구분돼 있습니다. 이 명명 규칙 자체가 안전장치입니다.

8직접 해볼 수 있는 실습 과제

읽기만 하면 남지 않습니다 — 손으로 해볼 것 다섯
과제 1 · 난이도 ★☆☆☆☆ · 20분

스킬을 설치해서 프롬프트를 “뽑아” 보기

Claude Code나 Codex에 스킬을 깔고, 같은 요구를 스킬 있을 때와 없을 때 각각 시켜 결과를 비교합니다.

npx skills add freestylefly/awesome-gpt-image-2 \
  --skill gpt-image-2-style-library --agent claude-code --global --yes --copy

요청 예시: “gpt-image-2-style-library로 RAG 구조를 설명하는 인포그래픽 프롬프트를 만들어줘”

확인할 것: 스킬이 있을 때 출력에 템플릿 이름·예시 케이스 번호·비율·금지 조건이 붙어 나오는지. 그 차이가 곧 “레퍼런스를 읽는다”의 효과입니다.

과제 2 · 난이도 ★★☆☆☆ · 1~2시간

내 마크다운으로 cases.json 만들기

generate-site-data.mjs를 흉내 내, 자기 글(블로그·노트·회의록)을 파싱해 JSON을 뽑는 스크립트를 씁니다.

  1. 문서를 자를 경계 표시를 정한다 (원본은 <a name="case-N">를 씀)
  2. 필드 3~4개를 정규식으로 뽑는다 (제목·본문·출처·태그)
  3. 키워드 규칙으로 카테고리를 추론하고, 아무것도 안 맞으면 ‘기타’로
  4. package.jsonprebuild 훅으로 걸어 잊어도 자동 실행되게 한다

배우는 것: 원본을 하나로 두는 습관. 이게 몸에 붙으면 “문서와 데이터가 어긋나는” 문제 자체가 사라집니다.

과제 3 · 난이도 ★★★☆☆ · 반나절

크레딧 3함수를 로컬 Postgres에 올려 동시성 깨뜨려 보기

이 저장소에서 가장 남는 게 많은 실습입니다.

  1. 도커로 Postgres를 띄우고 202605090001_user_credits.sql을 적용
  2. 크레딧 1개인 사용자를 하나 만든다
  3. 터미널 두 개에서 reserve_generation_usage동시에 호출 → 하나는 성공, 하나는 CREDITS_REQUIRED가 나오는지 확인
  4. 이제 FOR UPDATE를 빼고 다시 → 둘 다 성공해서 잔액이 −1이 되는지 확인
  5. 마지막으로 release_...를 불러 크레딧이 되돌아오고 credit_transactionsrefund가 남는지 확인

배우는 것: 이중 지출을 “글로 아는 것”과 “직접 만들어 본 것”의 차이. 4번이 실제로 재현되는 순간이 이 실습의 전부입니다.

과제 4 · 난이도 ★★★☆☆ · 반나절

빌드 게이트를 내 프로젝트에 이식하기

generate-style-skill.mjs의 검증 4종을 골라 자기 문서 저장소에 붙입니다.

배우는 것: 리뷰에서 매번 지적하던 것을 스크립트로 옮기는 감각. 사람의 주의력에 기대는 규칙은 반드시 언젠가 뚫립니다.

과제 5 · 난이도 ★★★★☆ · 1~2일

같은 구조로 “내 도메인” 라이브러리 만들기

주제를 바꿔 전체 파이프라인을 재현합니다 — 예: 사내 SQL 쿼리 모음, 디자인 시스템 컴포넌트 사례, 고객 응대 문구집.

배우는 것: “문서 저장소”를 “제품”으로 바꾸는 최소 구성. 결제를 뺀 나머지는 대부분 하루 안에 재현됩니다.

9관련 기술 심화 학습 로드맵

4주 코스 — 이 저장소를 축으로

1주차 · 파이프라인과 데이터 생성

읽기generate-site-data.mjs · generate-style-skill.mjs · package.json의 pre 훅
개념단일 진실원(SSOT) · 빌드타임 생성 · 멱등한 스크립트 · 검증 게이트
실습과제 2 (내 마크다운 → JSON)
확장정규식으로 문서 파싱할 때의 함정 — 코드펜스 중첩, 개행 차이(\r\n), 유니코드 문장부호

2주차 · Postgres와 트랜잭션

읽기마이그레이션 12개를 날짜순으로. 기능이 자라난 순서가 그대로 보입니다
개념RLS · SECURITY DEFINER · search_path 고정 · FOR UPDATE · 격리 수준
실습과제 3 (동시성 깨뜨리기)
확장credit_balance 열 하나로 끝내지 않고 credit_transactions 원장을 따로 두는가 — 회계의 복식부기와 같은 이유

3주차 · 서버리스와 결제

읽기api/generate-image.js_lib/billing.jsbilling/webhook.js_lib/alipay.js
개념웹훅 서명 검증 · 멱등키 · 콜백 재전송 대비 · 주문 상태기계 · 레이트 리밋
실습Stripe 테스트 모드로 결제 한 건을 끝까지 흘려보기 (stripe listen으로 웹훅 수신)
확장알리페이 notify 처리에서 같은 알림이 여러 번 와도 안전한가를 코드로 확인 (community_alipay_notify_events 테이블이 왜 있는지)

4주차 · 에이전트 스킬과 배포

읽기SKILL.md · marketplace.json · publish-style-skill.yml · bin/install.mjs
개념점진적 공개(핵심만 먼저, 상세는 필요할 때) · 스킬 트리거 문구 설계 · 태그 기반 릴리스
실습과제 5 (내 도메인 라이브러리)
확장스킬 설명(description)을 바꿔 가며 언제 자동으로 불려 나오는지 실험 — 트리거 문구가 스킬 품질의 절반입니다

10핵심 키워드 사전

이 문서에 나온 용어 정리

프롬프트 · 에이전트

GPT-Image-2OpenAI의 이미지 생성 모델. 이 저장소는 API로 model: 'gpt-image-2'를 호출
Prompt as Code프롬프트를 버전·검증·조립이 가능한 자산으로 다루자는 접근
템플릿 (template)여러 사례에서 공통으로 뽑아낸 프롬프트 뼈대. 이 저장소엔 22개
스타일 태그 / 씬 태그사례를 검색·분류하는 두 축. 각각 19개 · 10개
함정 (pitfalls)템플릿마다 붙는 “이렇게 하면 망한다” 목록
에이전트 스킬SKILL.md + 참고문서 묶음. AI 에이전트가 필요할 때 읽어들이는 지침
점진적 공개핵심만 먼저 싣고 상세는 필요할 때 읽게 하는 토큰 절약 설계

빌드 · 파이프라인

단일 진실원 (SSOT)같은 사실을 한 곳에만 적어 두는 원칙. 여기서는 docs/*.md
생성물 (generated)스크립트가 만들어 내는 파일. cases.json · style-library.md직접 고치면 다음 빌드에 덮어써짐
빌드 게이트조건을 어기면 빌드를 실패시키는 검사
prebuildnpm이 build 직전에 자동 실행하는 스크립트. 사람이 잊어도 돌아감
멱등 (idempotent)몇 번을 돌려도 결과가 같은 성질

데이터베이스 · 백엔드

RLS (행 수준 보안)“누가 어떤 행을 볼 수 있는가”를 DB가 강제하는 기능
SECURITY DEFINER함수를 호출자가 아니라 함수 소유자 권한으로 실행. 강력한 만큼 search_path 고정이 필수
FOR UPDATE읽으면서 그 행을 잠가 동시 요청을 줄 세우는 구문
사가 (saga)여러 시스템에 걸친 작업을 단계별 보상 동작으로 되돌리는 패턴
이중 지출잔액 하나로 두 번 쓰이는 사고. 동시성 제어가 없을 때 발생
service_roleSupabase의 서버 전용 열쇠. RLS를 통과하므로 브라우저에 절대 두면 안 됨
anon key브라우저에 넣어도 되는 공개 열쇠. RLS가 지켜 주는 범위 안에서만 동작
서버리스 함수서버를 직접 띄우지 않고 요청이 올 때만 실행되는 함수. 여기선 Vercel Functions
웹훅 (webhook)결제사가 “결제됐다”고 우리 서버에 거는 콜백. 서명 검증과 재전송 대비가 핵심
byteaPostgres의 이진 데이터 타입. 여기선 유료 그룹 QR 이미지를 DB에 직접 보관

프론트엔드 · 배포

Vite publicDir가공 없이 그대로 배포할 정적 자원 폴더. 여기선 data/
VITE_ 접두사이 접두사가 붙은 환경변수만 브라우저 번들에 포함됨 — 비밀 키에 붙이면 유출
rewrite / cleanUrlsVercel이 URL을 내부적으로 다른 파일에 연결해 주는 설정
ESM / .mjsimport/export를 쓰는 최신 JS 모듈 방식과 그 확장자

11참고 링크

원본과 그 주변

저장소

배경 지식

현재 상태 (2026-08-25 확인)

스타 / 포크⭐15,402 · 🍴1,632 · 열린 이슈 12
생성일2026-04-25 (약 4개월)
최근 커밋2165987 “fix: restore dialog scroll position instantly” (2026-08-24)
규모파일 655개 · 311MB (이미지 155MB) · 코드 약 1.06만 줄
사례 / 템플릿README 표기 532건 · 빌드 산출물 cases.json 기준 529건 / 템플릿 22개
언어JavaScript (ESM) · 문서는 중국어 중심, README는 영/중/일 3개국어
라이선스MIT — 단, 사례 콘텐츠의 상업적 사용은 보장하지 않는다고 명시
스킬 패키지gpt-image-2-style-library v1.0.4 (npm · GitHub Packages)
쓰기 전에 알아둘 것
한계 네 가지

① 콘텐츠 출처가 재구성입니다. 사례는 YouMind·OpenNana 등 커뮤니티 공개 프롬프트를 수집·재정리한 것이고, 저장소도 상업적 사용을 보장하지 않는다고 밝힙니다. 업무 투입 전 원 출처 확인이 필요합니다.

② 중국어 중심입니다. README는 3개국어지만 templates.md와 갤러리 본문은 대부분 중국어입니다. 프롬프트 자체는 영어·중국어가 섞여 있습니다.

③ 코드는 “운영 중인 서비스”의 코드입니다. 교재로 쓰기 좋게 정리돼 있지 않습니다. main.jsx 3,764줄이 대표적이고, 테스트도 _lib 일부(395줄)에만 있습니다. 좋은 부분(SQL·파이프라인)과 그렇지 않은 부분이 섞여 있다는 걸 알고 보세요.

④ 상업적 이해관계가 있습니다. README 상단 후원사 4곳이 전부 제휴 링크이고, 이미지 생성은 특정 중계 API(ciyuan.today)를 전제로 합니다. 도구 선택의 중립적 기준으로 삼기엔 무리가 있습니다.