일기 slecs

감사 잔여분, 인증서, 그리고 홍보 플레이북을 다 한 날에

목차

오늘 아침 처음 연 터미널은 404_pjt 였다. 사실 이건 어제부터 쌓인 숙제였다. 2차 보안 감사 결과를 받아보면 늘 이런 식이다. 1차에서 대부분을 처리하고, "이 정도면 됐겠지"라고 PR 올리고 나면 얼마 안 가 "반쪽짜리 수정 4건 남아있습니다"라는 코멘트가 돌아온다. 오늘 아침이 딱 그 꼴이었다.

반쪽수정 4곳 - 손이 많이 가는데 설명은 짧아지는 작업들

egovframework 계열 레거시 프로젝트는 건드릴 때마다 긴장을 좀 한다. slecs 네임스페이스 안에 popup, appdevice, utl, 그리고 클라우드 유틸 쪽까지 - 얼핏 보면 간단한 내부 클래스 수정인데, 이게 정부 프레임워크 위에 얹힌 코드라 건드리는 범위 이상의 영향을 예측해야 한다. 자칫 잘못 건드리면 공공 시스템 특유의 인터셉터 체인이 꼬이거나, 어딘가 숨어있는 필터가 오동작한다.

4곳이 남은 이유도 사실 이해는 간다. 1차 수정 당시에 "이건 외부 입력이 닿지 않는 내부 경로잖아"라고 판단한 부분들이었을 텐데, 감사팀 눈에는 잠재 경로로 보인 것이다. 맞는 말이다. "현재는 외부 입력이 닿지 않는다"는 구조적 보장이 아니고, 리팩터링 한 번이면 경로가 열릴 수 있으니. 그래서 방어적으로 차단하는 게 맞다.

커밋 메시지에 codex APPROVE 라고 붙였다. 이 프로젝트는 AI 코드 리뷰를 한 단계 거치는 흐름을 타고 있는데, 보안 수정 건들은 특히 "내가 의도한 대로 막혔는지" 이중 확인을 선호한다. 통과됐으니 최종 커밋. 사실 이 네 곳 수정 자체는 코드 분량이 많지 않다. 하지만 감사 사이클에서 "마저 처리했다"는 상태로 닫는 게 심리적으로도 중요하다. 남기면 계속 목에 걸린다.

오전 한 시간 반 정도 쓴 것 같다. 그걸로 404_pjt 는 오늘 탭을 닫았다.


인증서 기능, 생각보다 깊이 들어간 이야기

오전 중반쯤부터 완전히 다른 코드베이스로 갈아탔다. Next.js 기반 프로젝트인데, /s/[epoch]/certificate 경로에 붙는 Certificate of Ownership 기능을 오늘 마무리했다.

이게 어떤 기능인지 간단히 설명하면, 특정 에포크(초 단위 타임스탬프)를 소유했다는 인증서를 사용자가 다운로드하거나 출력할 수 있게 해주는 것이다. 개념 자체는 심플한데, 구현을 들어가면 생각지 못한 지점에서 자꾸 막힌다.

CertificateActions.tsx 파일이 핵심이었다. 다운로드와 프린트 액션을 분리하는 구조로 갔는데, 처음에는 하나의 컴포넌트에 때려박으려고 했다가 역할이 명확히 다르다고 판단해서 나눴다. 다운로드는 이미지/PDF 생성 흐름, 프린트는 브라우저 프린트 다이얼로그 흐름이라 상태 관리 방식이 달라지기 때문이다.

globals.css 를 건드린 건 프린트 미디어 쿼리 때문이다. @media print 블록에서 헤더, 네비게이션, 불필요한 UI 요소들을 숨기고 인증서 영역만 남기는 처리를 했다. 이게 처음엔 될 것 같았는데, 특정 브라우저에서 페이지 여백 계산이 달라져서 인증서가 잘리는 상황이 나왔다. 브라우저별 프린트 동작이 아직도 통일이 안 돼있다는 게 2026년이 됐어도 여전히 사실이다.

SecondPageClient.tsx 에서는 certificate 페이지로 넘어가는 진입점을 붙였다. 에포크 값을 URL로 가져가는 구조라 파라미터 전달은 깔끔한데, 기존 SecondPageClient 에서 certificate 섹션이 자연스럽게 보이게 레이아웃을 조금 손봤다. 이 파일은 이미 덩치가 있어서 건드릴 때마다 다른 부분에 의도치 않게 영향이 갈 수 있어 조심했다.

certificate/page.tsx 는 서버 컴포넌트로 두고, 실제 액션은 클라이언트 컴포넌트에 위임하는 패턴. Next.js App Router 에서 흔한 분리 방식인데, 이 프로젝트에서 일관되게 가져가고 있어서 여기서도 맞췄다.

tsconfig.tsbuildinfo 가 커밋에 섞인 건 항상 조금 찝찝하다. 빌드 캐시 파일이라 보통 .gitignore 에 넣는 편인데, 이 프로젝트 설정이 왜인지 추적하는 구조인 것 같다. 뭔가 이유가 있겠지 하고 넘겼지만, 나중에 한 번은 확인해봐야 할 지점이다.

인증서 기능 자체는 오늘 다 됐다. CLAUDE.md 에 feature 기록까지 남겼으니, 다음 사람이 이 코드 봤을 때 "이 경로가 왜 있지?" 하는 상황은 없을 것이다.


홍보 플레이북이라는 것을 처음 제대로 만든 날

오늘 커밋 목록에서 docs 프리픽스가 다섯 개나 붙어있다. 전부 홍보 관련이다. 평소라면 "오늘 홍보 좀 했네" 하고 넘길 수 있는데, 오늘은 결이 달랐다. 플레이북을 처음으로 문서로 정착시킨 날이기 때문이다.

docs/promo-playbook.md 를 새로 만들었다. 내용의 핵심은 세 가지였다. 헤드비온 계정을 이용한다는 것, 게임플레이 캡처가 반드시 수반돼야 한다는 것, 그리고 인디 톤을 유지한다는 것. 마지막 게 제일 중요하다. 자동화 도구를 돌리면 어김없이 톤이 매끈하게 다듬어진 "마케팅 글" 냄새가 난다. 그게 싫어서 "자동화 함정 지침"이라는 이름으로 따로 섹션을 뒀다. 자동화가 생성한 문구를 그냥 쓰면 안 되는 이유, 어떤 지점에서 반드시 사람 손을 타야 하는지.

오늘 실제로 게시한 채널이 Hashnode, Medium, X, Pinterest 네 곳이다. 커밋 순서를 보면 플레이북부터 만들고 게시를 시작한 게 아니라, 게시하면서 동시에 플레이북을 쓴 것 같다. 실제로 그랬다. 채널마다 게시하면서 "아 이건 다음번에 꼭 남겨야 하는 노하우인데"라는 게 나올 때마다 메모 형태로 쌓고, 다 올리고 나서 정리해서 플레이북으로 굳혔다.

docs/assets/mayday-gameplay-sunset.png 가 커밋에 들어간 것도 이 흐름의 일부다. MAYDAY 게임플레이 캡처를 직접 찍어서 올렸다는 뜻이다. 게임 홍보에서 텍스트나 로고 이미지보다 실제 플레이 장면이 훨씬 설득력 있다는 건 오래된 진리인데, "캡처 필수"라는 원칙을 플레이북에 명시한 건 오늘이 처음이다.

Pinterest 까지 올리면서 1차 홍보 사이클이 닫혔다. 뭔가 뿌듯하면서도 "이게 효과가 있을까?" 하는 의구심은 항상 남는다. 지표가 보이기 전까지는 모른다. 그냥 해놓고 기다리는 것 외에 지금 할 수 있는 게 없다.


자동으로 돌아간 것들

chore(psy) 커밋은 오늘도 나왔다. daily auto-generated tests (2026-07-12) - 정해진 날짜에 정해진 파이프라인이 돌아서 세 개의 콘텐츠를 만들어냈다. baseball-stadium-type, friend-ghosting-type, midnight-convenience-ghost. 커버 이미지까지 .webp 로 함께 들어왔다.

이걸 볼 때마다 감정이 복합적이다. 자동화가 잘 돌아간다는 뿌듯함이 있으면서, "내가 직접 기획한 게 아닌 콘텐츠가 내 이름으로 나간다"는 약간 낯선 느낌도 있다. friend-ghosting-type 같은 제목을 보면 제법 그럴듯하다 싶고, midnight-convenience-ghost 는 뭔가 감성적으로 잘 뽑혔다는 생각도 든다. 사람이 기획했으면 이 조합이 나왔을까?

이미지 파일이 public/covers/ 아래에 들어가고, 콘텐츠 JSON이 src/content/tests/ 에 들어가는 구조다. 파이프라인이 정해진 경로로 토해내는 것을 매일 커밋으로 확인만 하면 된다. 오늘은 특이사항 없이 깔끔하게 들어왔다.


오늘을 한 줄로 묶으면

커밋이 아홉 개인데 체감은 세 개의 서로 다른 날이 겹친 느낌이다. 보안 감사 마무리는 의무의 영역, 인증서 기능은 집중력이 제일 많이 들어간 구현의 영역, 홍보 플레이북은 "이걸 언제 한번 정리해야지" 하던 걸 오늘 마침내 한 영역.

프로젝트가 여러 개인 날은 컨텍스트 전환 비용이 만만치 않다. Java 레거시에서 Next.js로, 거기서 마케팅 문서로. 브레인이 매번 기어를 바꿔야 한다. 그 비용을 어떻게 줄일지는 아직도 답을 못 찾았다.

보안 수정 쪽은 확실히 닫혔다. 인증서 기능은 배포 후 실사용에서 어떤 엣지케이스가 나올지 좀 더 봐야 한다. 홍보는 이제 결과를 기다리는 단계다. 자동화 테스트는 잘 돌아가고 있다.

오늘 가장 오래 붙잡은 건 globals.css 의 프린트 스타일이었고, 가장 짧게 건드린 건 CLAUDE.md 문서 업데이트들이었다. 길이와 중요도가 꼭 비례하는 건 아니라는 걸 오늘도 확인했다.

댓글 0

첫 댓글 달아줘.