designpaca/packages/skill/references/images.md
Yun Chan b92853bf2b
All checks were successful
ci / build (push) Successful in 23s
release / release (push) Successful in 36s
feat(skill): 색·모바일 내비를 인터뷰에 넣고 이미지 조달을 단계로 승격한다
실제로 한 페이지를 만들어 보고 드러난 것들이다.

0단계 인터뷰에 두 축을 더한다.

- 브랜드 색: 꽃집 작업에서 색을 묻지 않고 레퍼런스 실측 평균으로 정했다.
  결과는 좋았지만 브랜드 색이 있었다면 그걸 무시한 작업이 된다.
  "없다"는 답도 답이고, 그때는 피해야 할 색을 묻는다.
- 좁은 화면 내비: 항목 수는 0단계에 이미 정해져 있는데 구현에서 발견했다.
  2~4개는 쌓고, 5~6개는 가로 스크롤, 7개 이상만 여는 메뉴다.
  넷인데 햄버거를 쓰면 탭 한 번을 공짜로 뺏는 것이다.

4-0 이미지 조달 단계를 새로 만든다(references/images.md).

  자리를 만들기 전에 무엇을 실을지 정한다. codex 설치와 auth_mode 를 확인해
  생성 경로를 쓰고, 생성물이라는 사실을 design.md 에 남긴다.

  래퍼 실패 대응을 기록했다 — codex-cli 0.147.0 은 base64 를 돌려주지 않고
  ~/.codex/generated_images/<session>/exec-<id>.png 로 저장한다. 공식 래퍼는
  "image_gen 이 호출되지 않았다"며 실패하지만 파일은 멀쩡히 있다.
  실측에서 이 메시지를 보고 두 번 다시 만들었고 두 번 다 이미 있었다.

  싣기 전 최적화도 넣었다(실측 10.1MB → 603KB).

구현에서 넘어진 것 셋.

- images.md: <img width height> 를 적으면 그 height 가 계산된 높이가 되어
  aspect-ratio 가 조용히 무시된다. computed 는 "3 / 4" 로 멀쩡히 보이고
  실제 높이는 원본 1448px 이었다. height:auto 한 줄로 10.9 화면이 7 화면이 됐다.
- antipatterns.md: "컨트롤이 2줄로 접히나" 를 개별 높이로 재서 거짓 통과했다.
  링크는 한 줄짜리였고 줄바꿈된 것은 컨테이너였다(top 46/77).
  행 수는 높이가 아니라 top 값의 종류로 센다.
- typography.md: 세로쓰기에 가로쓰기 자간(0.14em)을 물리면 글자 사이 세로
  간격이 되어 낱글자가 흩어진다. 한글은 자소가 모여 한 글자라 특히 심하다.
- layout.md: 그리드 구조를 바꾸면 미디어쿼리도 같이 다시 써야 한다.
  넓은 화면은 멀쩡했고 390px 에서 헤드라인이 6줄이 됐다.
2026-08-21 04:13:03 +09:00

6.2 KiB

images.md — 사진을 어디서 구하고 어떻게 싣나

이미지는 대부분의 디자인에서 가장 무거운 자산이고 가장 큰 인상이다. 레이아웃이 좋아도 사진이 약하면 페이지가 약하다. 반대도 마찬가지다.

4단계(구현)에서 레이아웃을 잡기 전에 무엇을 실을지 정해라. 자리를 먼저 만들고 나중에 채우면 비율이 안 맞아 다시 짠다.


1. 조달 경로 — 위에서부터 확인한다

순위 경로 언제
1 사용자가 준 사진 있으면 무조건 이것. 실제 작업물을 이길 생성물은 없다
2 생성(codex image_gen) 콘셉트 확인용, 톤이 정확히 지정된 추상·분위기 컷
3 스톡 라이선스가 명확한 곳만. 출처를 design.md 에 적는다
4 없이 간다 타이포·색·여백만으로 만든다. 약한 사진보다 낫다

0단계에서 물어라: "쓸 수 있는 사진이 있나요?" 없다고 하면 2번으로 가되, 생성물이라는 사실을 design.md 에 적는다. 나중에 실제 사진으로 바꿀 때 레이아웃을 다시 짜지 않도록 비율을 미리 고정해 둔다.


2. codex 가 있으면 생성한다

설치 여부를 먼저 확인한다. 없으면 조용히 3번으로 내려간다.

codex --version                                   # 있나
node -p "JSON.parse(require('fs').readFileSync(require('os').homedir()+'/.codex/auth.json','utf8')).auth_mode"
# → "chatgpt" 여야 구독 경로다. "api_key" 면 사용자 과금이라 먼저 물어라.

래퍼가 실패해도 이미지는 만들어져 있다 — 반드시 확인해라

~/.codex/imagegen-headless/codex_imagegen.sh 는 세션 rollout 에서 image_generation_callbase64 를 찾는다. codex-cli 0.147.0 은 base64 를 돌려주지 않는다. exec 도구를 거쳐 파일로 저장하고, 래퍼는 "image_gen 이 호출되지 않았다" 며 실패한다.

실측에서 이 메시지를 보고 두 번 다시 만들었는데, 두 번 다 파일은 멀쩡히 있었다.

~/.codex/generated_images/<session-id>/exec-<call-id>.png

rollout jsonl 의 custom_tool_call_output 에 경로가 그대로 적혀 있다.

Generated images are saved to <디렉터리> as <디렉터리>\exec-<id>.png by default.

한 줄에 경로가 둘이므로 마지막 것을 쓴다. 공백을 허용하는 정규식은 앞 디렉터리부터 " as " 까지 통째로 삼킨다.

// 세션 파일에서 실제 저장 경로를 읽는다
const all = line.match(/[A-Za-z]:\\[^\s"]*generated_images[^\s"]*\.png/g);
if (all) hit = all[all.length - 1];

호출은 이렇게 한다. $imagegen 이 프롬프트 맨 앞에 와야 내장 도구를 쓴다 — 뒤에 붙이면 codex 가 스크립트를 짜려고 헤맨다.

printf '%s' "\$imagegen $PROMPT" \
  | codex exec --skip-git-repo-check --dangerously-bypass-approvals-and-sandbox -

실패로 판정하기 전에 ~/.codex/generated_images/ 를 봐라. "실패했다" 고 보고했는데 파일이 있으면 그건 도구가 아니라 판정이 틀린 것이다.

프롬프트 — 톤을 공통 문자열로 고정한다

여러 장을 만들 때 각 프롬프트에 톤을 다시 쓰면 장마다 색이 달라진다. 공통 접두사 하나를 만들고 장면만 바꿔라.

[공통] Editorial magazine photograph. Warm off-white setting (#F8F6F0),
       soft natural window light, low saturation, muted restrained palette.
       Photographic realism, shallow depth of field, fine film grain.
       No text, no logo, no watermark.
[개별] Overhead flat-lay on a worn wooden workbench: cut stems, florist shears, twine.
  • 3단계에서 정한 배경색을 프롬프트에 그대로 넣어라. 사진이 페이지 배경과 이어진다
  • 크기는 양변 16의 배수: 1152x1536(3:4) · 1536x1152(4:3) · 2048x1152(16:9)
  • 사람 얼굴은 피하는 쪽이 안전하다. 손·뒷모습·부분은 잘 나오고 얼굴은 어색해지기 쉽다
  • No text 를 넣어라. 넣지 않으면 간판·라벨에 뭉개진 글자가 생긴다

생성물은 반드시 눈으로 본다

Read 로 열어 확인한 뒤에만 쓴다. 특히 공간 사진(작업실·매장)이 어색해지기 쉽다. 주제가 안 맞으면 프롬프트를 한 번에 한 가지만 바꿔 다시 만든다.


3. 싣기 전에 반드시 줄인다

생성물은 1~3MB PNG 로 나온다. 그대로 실으면 페이지가 10MB 가 된다.

const w = Math.min(meta.width, meta.width > meta.height ? 1600 : 1100);
await sharp(src).resize({ width: w }).webp({ quality: 82 }).toFile(out);

실측: 10.1MB → 603KB (94% 감소). 화면에서 차이가 보이지 않는다.

쓰임 최대 폭
전체폭 배경·히어로 1600px
본문 폭 이미지 1100px
카드·썸네일 640px

4. <img>width/height 를 적었다면 height: auto 를 반드시 줘라

CLS 를 막으려고 속성을 적는 것은 맞다. 그런데 CSS 에서 높이를 정하지 않으면 속성 height 가 그대로 계산된 높이가 되어 aspect-ratio 가 무시된다.

img { max-width: 100%; height: auto; }   /* 이 한 줄이 없으면 */

실측 사고: .two-photo img { aspect-ratio: 3/4 } 를 줬는데 computed 값은 "3 / 4" 로 멀쩡히 보이고 실제 높이는 원본 1448px 이었다. aspect-ratio 는 폭·높이 중 하나가 auto 일 때만 높이를 정한다.

증상이 조용하다 — 오류도 경고도 없고 페이지만 길어진다. 이 한 줄을 넣자 전체 높이가 10.9 화면에서 7 화면이 됐다.

진단: 이미지 높이를 실제로 재라. 원본 픽셀 높이(예: 1448)가 그대로 나오면 이것이다.

[...document.querySelectorAll('img')]
  .filter(i => i.getBoundingClientRect().height > 1000)

5. alt 는 장식이 아니면 반드시 쓴다

  • 내용을 나르는 이미지 → 무엇이 보이는지 적는다. "이미지", "사진" 은 alt 가 아니다
  • 순수 장식(배경 텍스처·그레인) → alt="" + aria-hidden="true"
  • 캡션이 이미 설명하고 있으면 alt 는 짧게. 같은 문장을 두 번 읽히지 않는다