- Published on
문서 속 코드 스크린샷은 언제부터 거짓말이 되는가 — 이미지를 빌드 산출물로 만들기
- Authors

- Name
- Youngju Kim
- @fjvbn20031
- 반년 지난 문서의 스크린샷이 하는 일
- 스크린샷은 산출물인데 소스가 없습니다
- goshot이 하는 일
- 명령이 되는 순간 달라지는 것
- 터미널 출력도 같은 문제를 갖고 있습니다
- 비밀 가리기는 부가 기능이 아닙니다
- 스타일 설정을 저장소에 두기
- 이번 주에 붙일 수 있는 최소 구성
- 정리와 출처
반년 지난 문서의 스크린샷이 하는 일
가이드 문서 중간에 예쁜 코드 스크린샷이 하나 박혀 있습니다. 어두운 배경에 둥근 모서리, 왼쪽 위에 빨강 노랑 초록 점 세 개. 여섯 달 전에 누군가 자기 편집기에서 캡처해 붙인 것입니다.
그 사이에 함수 이름이 바뀌었습니다. 옵션 하나가 사라졌습니다. 문서의 본문은 갱신됐습니다. 이미지는 그대로입니다. 이제 그 페이지는 위쪽 문단에서 새 이름을 말하고 아래쪽 이미지에서 옛 이름을 보여 줍니다. 그리고 처음 온 사람은 대개 이미지를 믿습니다. 글보다 그림이 구체적으로 보이기 때문입니다.
문제는 이미지가 틀렸다는 것이 아닙니다. 틀렸다는 사실을 아무도 알 수 없다는 것입니다. 코드 블록이었다면 검색에 걸렸을 텐데 이미지는 걸리지 않습니다.
스크린샷은 산출물인데 소스가 없습니다
이 문제를 다르게 말하면 이렇습니다. 문서 저장소에 들어 있는 그 PNG 파일은 산출물입니다. 그런데 그것을 다시 만들 방법이 저장소에 없습니다. 어떤 편집기에서, 어떤 테마로, 어떤 폰트 크기로, 어느 부분을 잘라서 찍었는지가 기록되어 있지 않습니다.
우리는 이런 상황을 다른 영역에서는 곧바로 문제로 봅니다. 빌드 결과물을 소스 없이 저장소에 커밋하면 리뷰에서 지적이 나옵니다. 그런데 이미지는 이상하게 예외가 됩니다. 이미지는 문서의 장식이지 코드가 아니라고 생각하기 때문입니다.
기준을 하나로 맞추면 해야 할 일이 분명해집니다. 명령 한 줄로 다시 만들 수 없는 것은 저장소에 두지 않는다. 이미지도 예외가 아닙니다.
그 전에 한 단계 먼저 물어야 할 것이 있습니다. 이 코드가 굳이 이미지여야 하는가입니다. 문서 안의 코드는 대부분 코드 블록이 낫습니다. 복사할 수 있고, 검색에 걸리고, 화면 낭독기가 읽고, 화면 폭에 맞춰 접힙니다. 이미지가 정당한 경우는 좁습니다. 강조 색이나 편집기 표시처럼 텍스트로 옮길 수 없는 정보가 함께 있어야 할 때, 발표 슬라이드나 소셜 카드처럼 텍스트를 넣을 수 없는 매체에 실을 때, 그리고 터미널의 색과 정렬이 설명의 일부일 때 정도입니다. 이 셋에 해당하지 않는데 이미지를 쓰고 있었다면, 재생성 문제를 푸는 것보다 코드 블록으로 되돌리는 쪽이 먼저입니다.
goshot이 하는 일
goshot은 코드와 터미널 출력을 이미지로 만드는 Go 라이브러리이자 CLI입니다. README는 스스로를 Carbon이나 Silicon과 비슷한 도구라고 소개합니다. 차이는 웹 페이지가 아니라 명령줄에서 돈다는 점이고, 이 글의 논지에서는 그 차이가 전부입니다.
기능 목록에서 확인한 것만 적으면, 구문 강조는 chroma를 써서 수백 가지 테마를 지원하고, ANSI 색이 들어간 터미널 출력을 그대로 렌더링하며, 창 장식은 macOS와 Windows 11과 GNOME과 KDE Breeze 모양을 고를 수 있습니다. 배경은 단색과 일곱 가지 그라디언트와 이미지를 지원하고, 출력은 PNG와 JPEG와 BMP이며 클립보드와 표준 출력으로도 내보냅니다. 그리고 API 키와 토큰과 비밀번호를 자동으로 가리는 기능이 목록에 들어 있습니다.
기본 사용은 이렇습니다.
# 파일 하나를 이미지로
goshot main.go -o main.png
# 표준 입력을 받아 클립보드로
cat main.go | goshot -c
# 테마와 창 모양과 배경을 지정
goshot main.go -t catppuccin-mocha -C gnome -b '#1e1e2e'
# 특정 줄만 강조
goshot main.go --highlight-lines 10..14
설치는 Go가 있으면 go install github.com/watzon/goshot/cmd/goshot@latest이고, Arch의 AUR과 우분투 PPA 패키지도 안내되어 있습니다.
라이브러리로 쓸 때의 구조도 봐 둘 만합니다. README는 이것을 작은 파이프라인으로 설명합니다. 내용을 이미지로 그리고, 그것을 창 장식으로 감싸고, 배경 위에 올립니다. 세 단계가 각각 독립된 개념이라 하나만 바꾸기 쉽습니다. 문서 도구를 직접 만든다면 이 분리 자체가 참고할 만한 설계입니다. 테마를 바꾸는 일과 창 모양을 바꾸는 일과 여백을 바꾸는 일이 서로를 건드리지 않으면, 나중에 스타일을 일괄 변경할 때 고칠 자리가 한 곳으로 모입니다.
명령이 되는 순간 달라지는 것
goshot 자체가 특별한 도구라서가 아닙니다. 이미지 생성이 명령이 되면 세 가지가 따라옵니다.
첫째, 문서 갱신과 이미지 갱신이 같은 작업이 됩니다. 코드를 고치고 문서를 고칠 때 이미지 생성 명령을 한 번 더 돌리면 됩니다. 사람이 캡처 도구를 열고 창 크기를 맞추고 잘라내는 과정이 사라집니다.
둘째, 차이가 눈에 보입니다. 이미지가 소스에서 결정론적으로 만들어지면, 코드가 안 바뀌었을 때 이미지도 안 바뀝니다. 그래서 변경 사항에 이미지 파일이 올라왔다는 것 자체가 신호가 됩니다.
셋째, 일관성이 규칙이 됩니다. 테마와 폰트와 여백이 명령의 인자로 적히므로, 팀원마다 다른 편집기 테마로 찍은 스크린샷이 섞이는 일이 없어집니다.
터미널 출력도 같은 문제를 갖고 있습니다
문서에서 더 자주 낡는 것은 코드보다 터미널 출력입니다. 명령의 출력 형식은 도구 버전이 오르면 조용히 바뀌기 때문입니다. goshot은 명령을 실행하고 그 출력을 그대로 이미지로 만드는 하위 명령을 제공합니다.
# 명령을 실행하고 출력을 이미지로
goshot exec -A -p -- go test ./...
# 제목 표시줄 색을 내용에 맞춰 자연스럽게
goshot exec -A -p --title-bar-color auto -- ls -la
여기서 중요한 것은 이미지가 예쁘다는 점이 아니라, 그 출력이 문서를 만들 때 실제로 실행된 결과라는 점입니다. 손으로 옮겨 적은 출력은 옮기는 사람이 줄을 지우거나 다듬으면서 원본과 달라지고, 그 차이를 나중에 검증할 방법이 없습니다.
비밀 가리기는 부가 기능이 아닙니다
기능 목록 중 실무에서 가장 값이 나가는 것은 자동 가리기라고 생각합니다. 스크린샷을 통한 자격 증명 유출이 위험한 이유는 유출 자체보다 탐지가 어렵다는 데 있습니다. 저장소에 커밋된 텍스트 키는 비밀 스캐너가 잡아냅니다. 이미지 안에 들어간 키는 잡히지 않습니다. 사람이 눈으로 발견할 때까지 그대로 있습니다.
goshot은 API 키와 토큰과 비밀번호를 자동으로 가리는 기능을 내세우고, 가리는 방식도 고를 수 있게 되어 있습니다.
goshot config.go --redact --redact-style blur
다만 여기서 한 가지를 분명히 해야 합니다. 자동 가리기는 알려진 패턴에 반응하는 장치이고, 사내 시스템의 고유한 형식은 패턴에 없을 수 있습니다. 그래서 이 기능은 마지막 방어선이 아니라 첫 번째 그물로 두는 것이 맞습니다. 진짜 방어선은 문서를 만들 때 실제 자격 증명이 들어간 환경을 쓰지 않는 것입니다.
스타일 설정을 저장소에 두기
goshot은 자주 쓰는 플래그의 기본값을 설정 파일에 둘 수 있습니다. README에 따르면 ~/.config/goshot/config.yaml에 플래그 이름과 값을 평평한 형태로 적고, 명령줄에서 준 플래그가 항상 이깁니다.
theme: catppuccin-mocha
chrome: mac
background: '#1e1e2e'
corner-radius: 12
이 파일이 홈 디렉터리에 있으면 사람마다 다른 결과가 나옵니다. 그래서 문서를 만드는 저장소라면 이 값들을 홈이 아니라 프로젝트 안에 두고 스크립트에서 명시적으로 넘기는 편이 낫습니다. 그러면 스타일 변경이 코드 리뷰에 올라오고, 어느 날 갑자기 문서 전체의 배경색이 바뀌는 일이 생기지 않습니다.
이번 주에 붙일 수 있는 최소 구성
가장 작은 형태는 이렇습니다. 이미지의 소스가 될 코드 조각을 따로 파일로 두고, 그 파일에서 이미지를 만드는 규칙을 하나 적습니다.
# docs/snippets/*.go 에서 docs/images/*.png 를 만든다
SNIPPETS := $(wildcard docs/snippets/*.go)
IMAGES := $(patsubst docs/snippets/%.go,docs/images/%.png,$(SNIPPETS))
images: $(IMAGES)
docs/images/%.png: docs/snippets/%.go
goshot $< -o $@ -t catppuccin-mocha -C mac --redact
이렇게 두면 코드 조각이 실제 컴파일 대상이 되므로, 스니펫이 낡으면 빌드나 린트가 먼저 알려 줍니다. 이미지는 그 뒤에 따라옵니다. 이미지가 낡는 문제를 이미지로 푸는 대신 소스가 낡는 문제로 되돌린 것이 이 구성의 요점입니다.
여기서 솔직하게 적어 둘 것이 있습니다. 이 Makefile은 제가 goshot을 설치해 실제로 돌려 본 결과가 아닙니다. goshot의 명령과 플래그는 저장소 README에서 확인한 것이고, Makefile의 패턴 규칙 부분은 일반적인 make 문법입니다. 도입할 때는 작은 스니펫 하나로 먼저 돌려 보시기 바랍니다.
정리와 출처
핵심은 도구 이름이 아닙니다. 문서에 들어가는 이미지에도 다른 산출물과 같은 기준을 적용하자는 것입니다. 명령으로 다시 만들 수 있는가. 만들 수 없다면 그 이미지는 언젠가 아무도 모르게 틀린 것을 말하기 시작합니다.
- watzon/goshot 저장소 — 기능 목록, CLI 예시, 설정 파일 형식, 라이선스. 본문의 goshot 관련 서술은 모두 이 저장소의 README에서 확인했습니다.
- 저장소 메타데이터로 확인한 사항: 라이선스는 MIT, 주 언어는 Go, 저장소 생성은 2024년 11월입니다. 1인 개발자가 유지하는 프로젝트이며 대기업이 뒤를 받치는 도구가 아니라는 점을 감안해 도입 여부를 판단하시기 바랍니다.
- 본문의 CLI 예시는 README에 실린 것을 옮긴 것이고, Makefile 예시는 실행해 확인하지 않았습니다.