개발일지WhoAmI — 공부 기록을 발행 가능한 형태로 좁힌 파이프라인 →
공개 범위를 사람이 아니라 명령이 확인하게 했다
초기 /resume 한 경로의 빌드 결과물 검사에서 현재의 /resume·/share/shell 상시 비노출 검사와 전역 색인 차단 검사로 확장한 과정을 정리한다. 명령이 확인하는 범위와 검색 제외·접근 제어의 차이도 함께 구분한다.
목차 4
2026-08-09 정정 — 초기
/resume검사와 이후 추가된 전역 색인 차단 검사를 시점별로 구분했다. 현재 검사 범위는/resume·/share/shell의 공통 검사와 색인 차단 모드의 추가 검사이며, 검색 제외 지시는 접근 제어나 실제 색인 결과를 보장하지 않는다.
검사기를 처음 추가한 2026-07-28에는 상시 비노출 대상이 /resume 하나였다. 여기서 비노출은 사이트가 만드는 발견 경로에서 제외한다는 뜻이다. 주소를 아는 사람의 요청까지 막는 비공개나 인증을 뜻하지 않는다.
이 구분이 필요한 이유는 화면만 보고는 설정의 불일치를 알기 어렵기 때문이다. 페이지는 정상적으로 열리면서도 사이트맵이나 다른 페이지의 링크에 주소가 남을 수 있다. 반대로 빌드 결과물에 noindex가 있어도 검색 사업자가 아직 다시 수집하지 않았거나 그 지시를 처리하지 않았다면 실제 검색 결과는 바로 바뀌지 않을 수 있다.
처음에는 한 경로와 공통 검사 5개였다
초기 구현은 소스가 아니라 빌드 결과물인 dist를 열었다. 소스의 조건이 맞아도 빌드 설정이 덮거나 같은 내용이 다른 경로로 생성될 수 있기 때문이다. 당시 /resume 한 경로를 대상으로 확인한 항목은 다음 다섯 가지였다.
- 비노출 페이지 HTML에
noindex메타가 있는가 - 사이트맵에서 해당 경로가 빠졌는가
- 공개 페이지가 해당 경로로 링크하지 않는가
- 공개 페이지 본문에 경력 데이터의 조직명이 남지 않았는가
- 공개 페이지에 이메일 평문이나
mailto:링크가 남지 않았는가
하나라도 어긋나면 종료 코드 1로 멈췄다. 조직명은 검사기에 다시 적지 않고 경력 데이터 파일에서 읽었다. 검사 목록과 실제 데이터가 따로 바뀌는 문제를 줄이기 위한 선택이었다.
현재는 상시 비노출 5개와 전역 색인 차단 3개를 나눈다
2026-08-03에는 사이트 전체 색인 차단 검사가 추가됐고, 2026-08-06에는 share 경로군이 상시 비노출 대상에 들어갔다. 현재 scripts/check-exposure.mjs의 경로군은 resume과 share다. 빌드 결과물에서는 /resume과 /share/shell이 대상이며, 색인 허용·차단 모드와 관계없이 위의 공통 검사 5개를 적용한다. /share/shell은 공유 문서를 표시하는 정적 셸이다. KV에 저장되는 개별 공유 문서와 만료 여부는 dist에 없으므로 이 검사 범위에 들어가지 않는다.
전역 색인 차단은 별도 층이다. scripts/check-exposure.mjs는 SITE_PUBLIC이 정확히 1이 아닐 때 다음 세 가지를 추가로 확인하고, 기본 npm run release는 이 값을 0으로 고정한다. 따라서 npm run check:exposure를 직접 실행해 값이 비어 있어도 색인 차단 모드로 판정하며, 정확히 1일 때만 전역 세 검사를 건너뛴다.
robots.txt에Disallow: /가 있고Sitemap:줄이 없는가- 모든 HTML에
noindex메타가 있는가 dist/_headers의 전 경로 규칙에X-Robots-Tag: noindex가 있는가
Cloudflare는 정적 자산 디렉터리의 _headers 규칙을 정적 자산 응답에 적용한다고 설명한다. 이 검사기는 Cloudflare의 _headers 형식에 맞는 빌드 파일이 생겼는지를 볼 뿐, 배포된 응답 헤더를 HTTP로 다시 측정하지는 않는다.
npm run release:public은 반대로 SITE_PUBLIC=1을 강제로 넣어 전역 세 검사를 건너뛴다. 이때도 /resume과 /share/shell에 대한 공통 다섯 검사는 남는다. 두 명령 모두 부모 셸에 있던 SITE_PUBLIC 값을 자식 프로세스에서 덮기 때문에, 현재 모드는 셸의 잔류 값이 아니라 명령 이름으로 정한다.
모드를 기억하는 대신 명령 이름으로 골랐다
점검은 배포 전에 자동으로 실행되도록 release 경로에 넣었다. 현재 npm run release는 검증, 빌드, 공개 범위 검사를 순서대로 실행하고 CI도 같은 명령을 사용한다.
초기에는 사람이 셸에서 환경변수를 직접 넣어야 했다. PowerShell 환경변수는 창이 살아 있는 동안 남기 때문에 다음 실행에 의도치 않게 이어질 수 있고, 새 창에서는 빠질 수 있다. 지금은 기본 명령이 색인 차단, :public이 붙은 명령이 색인 허용을 선택한다.
다만 여기서 차단은 검색엔진에 보내는 지시의 범위다. Google은 noindex를 처리하려면 크롤러가 페이지를 읽을 수 있어야 하며, robots.txt가 요청을 막으면 noindex를 보지 못해 외부 링크만으로 URL이 검색 결과에 남을 수도 있다고 설명한다. 다른 검색엔진이 같은 규칙을 똑같이 처리한다고도 보장할 수 없다. 따라서 이 명령의 통과는 Google이 설명하는 noindex 조건을 만족한 실제 결과가 아니라, 이 사이트가 의도한 지시 파일을 만들었다는 뜻이다.
검색 제외는 접근 제어도 아니다. 주소를 아는 사람이나 링크를 받은 사람은 두 모드 모두 페이지를 열 수 있다. 인증이 필요하다면 요청을 정책과 대조하는 Cloudflare Access 같은 인증 계층을 별도로 두어야 한다.
검사기가 보지 못하는 것
이 점검은 조직명 문자열, mailto: 링크, 사이트맵 경로처럼 규칙으로 표현한 것만 찾는다.
현재 검사기는 버킷 이름을 찾지 않으며 이미지 안의 문자열도 읽지 않는다. 콘솔 캡처의 계정 ID와 사용자명은 사람이 확인하고, 명령 출력에 넣을 치환값은 미리 정해 두는 이유다.
사이트의 색인 지시는 소스 저장소에 적용되지 않는다. 저장소를 공개하면 경력 데이터 파일은 사이트의 noindex와 관계없이 직접 읽을 수 있으므로, 공개 전에는 그 데이터를 저장소 밖으로 옮겨야 한다.
2026-08-09 보완 내용은 코드와 Git 이력을 대조한 것이다. 배포 응답과 실제 색인 상태는 재확인하지 않았다.
함께 보면 좋은 글
이 기록과 태그가 겹치는 아티클입니다.