- 분야: DevOps
- 기술 스택: TypeScript · robots.txt · X-Robots-Tag
- 관련 기술: 학습 경로 · 인증 리다이렉트 · 검색엔진 크롤링
문제와 원인
학습 경로는 robots.txt에서 크롤링을 막으면서 페이지 metadata에 noindex를 설정했다. 크롤러가 페이지를 읽기 전에 차단돼 색인 제외 신호에 접근할 수 없었다. 비로그인 학습·관리 경로는 인증으로 리다이렉트했고, 해당 응답에는 X-Robots-Tag가 없어 첫 응답에도 제외 신호를 전달할 필요가 있었다.
수정 전 코드
robots()
disallow: [
"/learn/",
"/admin",
"/api/",
],
proxy.ts — proxy()
return applySecurityHeaders(
NextResponse.next({ request: { headers: requestHeaders } }),
host === CANONICAL_HOST && protocol === "https",
request.headers.get("accept")?.includes("text/html") ?? false,
policy,
);
수정 후 코드
robots에서 /learn/을 제거하고 관리자·API 차단을 유지했다.
robots()
disallow: [
"/admin",
"/api/",
],
proxy.ts — proxy()
proxy가 보안 헤더를 적용한 뒤 즉시 반환하던 응답을 변수로 받아, 학습·관리 경로에 X-Robots-Tag를 추가했다.
const response = applySecurityHeaders(
NextResponse.next({ request: { headers: requestHeaders } }),
host === CANONICAL_HOST && protocol === "https",
request.headers.get("accept")?.includes("text/html") ?? false,
policy,
);
if (/^\/(?:learn|admin)(?:\/|$)/u.test(request.nextUrl.pathname)) {
response.headers.set("X-Robots-Tag", "noindex, nofollow");
}
return response;
현재 소스는 isIndexableLearningPath로 공개 이론과 개인 풀이·기록 경로를 나누고, 공개 이론에는 일괄 noindex 적용을 제외한다.
검증 결과
Node.js의 로컬 서버에서 수정 전후 원본 proxy·robots 모듈과 실제 NextRequest·NextResponse를 실행했다. canonical HTTPS·HTML GET, 경로 6개·합성 User-Agent 2종(Googlebot·일반 브라우저)을 조합해 수정본별 12개, 총 24개 요청을 각 1회 적용하고 robots 원문 2개를 비교했다. 결과는 인증 handler 앞의 middleware 통과 응답이다.
| 경로 | 수정 전 robots / proxy 헤더 | 수정 후 robots / proxy 헤더 |
|---|---|---|
/learn/sql/sqld/practice | 차단 / 없음 | 허용 / noindex, nofollow |
/learn/sql/sqlp/mock-exams | 차단 / 없음 | 허용 / noindex, nofollow |
/learn/sql/sqld/records | 차단 / 없음 | 허용 / noindex, nofollow |
/admin | 차단 / 없음 | 차단 / noindex, nofollow |
/api/study | 차단 / 없음 | 차단 / 없음 |
/api/auth/google/callback | 차단 / 없음 | 차단 / 없음 |
| 표본 집계 | 수정 전 | 수정 후 |
|---|---|---|
| 학습 경로의 크롤링 허용·noindex 동시 충족 | 0/3경로 | 3/3경로 |
| 학습·관리 경로의 proxy noindex 헤더 | 0/4경로 | 4/4경로 |
| robots 차단 경로 | 6/6경로 | 3/6경로 |
| API·callback의 proxy noindex 헤더 | 0/2경로 | 0/2경로 |
| 두 User-Agent의 판정 | 동일 | 동일 |
Swagger UI의 로컬 응답 화면(1,280×720 CSS px·DPR 2)은 전후 robots와 수정 후 학습 proxy를 각각 1회 요청한 결과다. robots 응답은 HTTP 200이며, 학습 proxy는 middleware HTTP 200과 X-Robots-Tag: noindex,nofollow를 표시했다.
학습 경로를 통과한 proxy 응답에는 X-Robots-Tag: noindex,nofollow가 포함됐다.