개발 slecs

insights를 blog로 통합할 때 URL과 데이터를 모두 지키는 법

목차

기존 insights 서비스를 blog로 통합하면서 URL 무결성을 지키고 사용자 영향을 최소화하기 위해 nginx 리다이렉트와 자동화된 마이그레이션 스크립트를 함께 구축했다.

왜 이관이 필요했나

서비스 여러 개를 나눠 운영하다 보면 자연스럽게 비슷한 도메인끼리 통합할 기회가 생긴다. insights와 blog는 모두 콘텐츠를 다루지만 기술 스택, 관리 포인트, 사용 패턴이 달랐고, 이걸 하나로 모으면:

  • 관리 복잡도 감소 (배포, 모니터링, 백업 일원화)
  • 공유 메타데이터나 태깅 체계 통일 가능
  • 읽기 성능 최적화 (캐시 전략 단순화)

다만 이관할 때 가장 중요한 게 있다: 기존 사용자/검색엔진이 알고 있는 URL은 절대 깨지면 안 된다는 점이다. 내가 insights 경로로 즐겨찾기를 했다면, 그걸 따라갔는데 404가 나온다면? 또는 검색엔진 크롤러가 이전 경로를 여전히 지니고 있는데 업스트림이 사라진다면? SEO 점수 손실도 크고, 사용자 신뢰도 떨어진다.

리다이렉트: 투명한 경로 전환

# nginx-snippets/hedvion-insights-redirects.conf
location /insights/ {
    return 301 /blog/insights$request_uri;
}

location /insights-archive/ {
    return 301 /blog/archive$request_uri;
}

이게 핵심이다.

  • 301 Permanent Redirect: "이 경로는 영구적으로 옮겨졌다"는 신호를 브라우저와 검색엔진에 보낸다. 크롤러는 이 신호를 받으면 색인을 옮기고, 사용자 북마크도 시간 지나면 새 경로로 자동 업데이트된다.
  • $request_uri 보존: query string이나 하위 경로를 그대로 유지한다. /insights/2026/post-1?lang=ko 같은 요청이 /blog/insights/2026/post-1?lang=ko로 정확히 매핑된다.

이 방식은 클라이언트 사이드(자바스크립트 리다이렉트)나 애플리케이션 로직(if 조건으로 핸들링)보다 훨씬 낫다. 왜냐:

  1. 성능: 서버가 html 로드/js 파싱할 필요 없이 즉시 응답
  2. 안정성: 웹 표준에 따른 동작이라 어떤 클라이언트에서도 작동
  3. 유지보수성: 경로 규칙을 한곳에 관리 (nginx conf)

마이그레이션 자동화: 백그라운드 정리

# hedvion-main-build/migrate_insights.py
# - insights 테이블/문서 읽기
# - blog 구조에 맞춰 변환
# - 새 저장소에 기록
# - 매핑 로그 저장 (rollback용)

리다이렉트만으로 충분할 수도 있지만, 우리가 스크립트까지 짜야 했던 이유는:

  • 데이터 정합성: insights 메타데이터(태그, 분류, 작성자, 수정일)가 blog의 스키마와 다를 수 있다. 변환 로직이 필요.
  • 매핑 추적: 어떤 insights ID가 blog의 어떤 ID로 매핑됐는지 기록해야 한다. 나중에 댓글, 통계, 기타 연관 데이터를 따라가기 위해.
  • 점진적 마이그레이션: 한 번에 전환하지 말고, 로그를 보며 이슈를 발견하고 수정한 뒤 배포. 스크립트는 멱등성(idempotent)을 갖춰야 여러 번 돌릴 수 있다.

운영 관점에서 본 고려사항

항목 리다이렉트만 할 때 마이그레이션 스크립트 함께
초기 구성 속도 빠름 느림
검색엔진 최적화 즉시 데이터 일관성 후에
롤백 복잡도 간단 (nginx 수정) 높음 (스크립트 역행 필요)
데이터 정합성 보장 안 함 자동화로 보장
운영 부하 낮음 초기 높음, 이후 낮음

우리는 둘 다 했다. 리다이렉트로 사용자/검색엔진을 즉시 안내하고, 백그라운드에서 스크립트가 차근차근 데이터를 옮긴다. 이 방식은:

  • 리다이렉트 체인이 길어져도 nginx에서 한 번에 처리하니까 지연 최소화
  • 스크립트 진행 상황을 로그로 모니터링 가능
  • 실패 지점에서 멈추고 수정 후 재실행 가능

배운 점

대규모 서비스 이관할 때는 경로 층 (HTTP), 데이터 층 (저장소), 메타 층 (검색, 통계, 연관 정보) 이렇게 세 층을 따로 생각해야 한다는 걸 다시 깨달았다.

한 명이 그냥 "insights 폴더 삭제, blog로 옮김" 하는 게 아니라, 인프라 담당자가 리다이렉트를 먼저 깔고, 데이터 엔지니어가 마이그레이션 스크립트를 작성하고, 모니터링 담당자가 로그를 지켜봐야 한다. 그 과정에서 누가 뭘 했는지 명확한 커밋 메시지와 이관 스크립트가 없으면 나중에 "어, 왜 이 경로는 아직 안 옮겨?" 하는 질문이 반복된다.

이번에는 nginx 스니펫과 python 스크립트가 같은 커밋으로 들어갔으니, 누구든 이 커밋을 보면 "아, insights 이관을 이렇게 했구나" 하고 전체 맥락을 파악할 수 있다.


🛒 이 글과 어울리는 추천 상품

*위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.

댓글 0

첫 댓글 달아줘.