유권자총연맹 — 검색 순위를 잃지 않고 홈페이지를 통째로 옮기는 일
빌더에 묶여 있던 기관 홈페이지를 워드프레스로 옮겼다. 게시물 283건과 이미지 625개, 그리고 이미 자리 잡은 검색 순위를 한 건도 잃지 않는 것이 조건이었다.
담당자가 글 하나 못 고치는 홈페이지
의뢰를 받고 처음 사이트를 열었을 때 가장 먼저 눈에 들어온 건 디자인이 아니라 구조였다. Cafe24 빌더로 만들어진 PC 전용 사이트였고, 게시판도 회원도 콘텐츠도 전부 빌더 안에 묶여 있었다.
담당자는 공지 하나를 고치려고 해도 직접 손댈 수 없었고, 모바일에서는 PC 화면이 그대로 축소돼 사실상 읽기 어려운 상태였다. 백업을 받는 것도, 다른 곳으로 옮기는 것도 마음대로 되지 않았다.
새로 만드는 것보다 어려운 조건
사이트를 새로 만드는 일 자체는 어렵지 않다. 어려운 건 조건이었다. 수년간 쌓인 게시물과 이미지, 그리고 이미 자리 잡은 검색 순위를 한 건도 잃지 않아야 했다.
기관 홈페이지에서 검색 유입은 자산이다. 예쁘게 다시 만들어놓고 검색에서 사라지면 그건 실패한 이전이다. 그래서 이 프로젝트의 1순위 기준은 처음부터 끝까지 "순위를 떨어뜨리지 않는다"였다.
먼저 전부 세어봤다
옮기기 전에 무엇을 옮겨야 하는지부터 정확히 알아야 했다. 빌더 사이트 전체를 크롤링해 URL 구조와 게시판 5종, 정적 페이지 17종을 목록화했다.
세어보니 게시물 283건, 페이지 30개, 원본 이미지 625개에 373MB였다. 이걸 전량 회수해 워드프레스로 옮겼다. 유료 테마나 페이지빌더는 쓰지 않고 테마를 직접 만들었다. 나중에 유지비가 드는 구조를 남기고 싶지 않았다.
작업은 운영 서버와 같은 구성(PHP 8.2 + MariaDB)을 Docker로 로컬에 띄워놓고 했다. 로컬에서 되면 배포도 된다는 확신이 있어야 마음 놓고 부순다.
옛 주소를 그대로 살릴 수 없었다
가장 큰 난제는 주소였다. 빌더의 게시글 주소가 board.php?com_board_id=..&com_board_idx=.. 형태의 쿼리스트링이라, 워드프레스 구조로는 같은 주소를 재현할 방법이 없었다.
그래서 옛 주소를 새 주소로 하나씩 연결하는 301 처리를 테마에 직접 구현했다. 게시글뿐 아니라 첨부파일 다운로드 링크까지 매핑했다. 어딘가에 걸려 있을 외부 링크와 검색 결과가 빈손으로 끝나지 않도록.
이미지는 옛 서버에만 있었다
본문 569건과 첨부 메타 908건이 옛 도메인의 절대경로를 물고 있었다. 겉으로는 멀쩡해 보여도, 옛 사이트를 내리는 순간 이미지가 전부 사라지는 상태였다.
이미지와 첨부파일을 전량 미러링하고, 출력 시점에 경로를 새 위치로 바꾸도록 처리했다. 그리고 옛 사이트가 없다고 가정한 상태에서 전 페이지를 다시 확인했다.
도메인을 바꾸는 순간 다 깨질 뻔했다
이 프로젝트에서 가장 아찔했던 대목이다. 경로를 바꿔주는 그 로직이 조건 없이 동작하도록 되어 있었다. 임시 도메인에서는 아무 문제가 없었지만, 사이트 주소가 실도메인으로 바뀌는 순간 테마의 CSS와 JS, 메뉴까지 전부 치환 대상이 되는 구조였다.
전환하고 나서 알았으면 사이트 전체가 깨진 채로 공개됐을 것이다. 다행히 전환 전에 "전환 후 상태"를 흉내 내는 테스트를 만들어 돌려봤고, 거기서 발견했다. 치환 범위를 옛 사이트 자산 경로로만 한정해 막았다.
겁이 나면 미리 흉내를 내본다. 이번에 다시 배웠다.
작업하다 취약점을 하나 주웠다
의뢰받은 일은 아니었지만 그냥 둘 수 없는 걸 발견했다. 주소에 파라미터 하나만 붙이면 로그인도 없이 회원 25명의 실명이 전부 조회됐다. 워드프레스의 기본 동작 때문이었다. 작성자 아카이브를 리다이렉트하고 REST API의 사용자 목록을 차단했다. 이메일과 생년월일이 노출되지는 않았다.
메일도 문제였다. 비밀번호 재설정 메일이 자꾸 스팸함으로 갔다. SPF 레코드는 정상이었는데도 그랬다. 실제 메일 헤더를 열어보니 봉투 발신자가 호스팅사 기본값이라, 정작 도메인의 SPF는 조회조차 되지 않고 있었다. 설정만 보고 있었으면 못 찾았을 문제다.
사람 손으로 확인하지 않았다
옮길 게 300건이 넘으면 눈으로 확인하는 방식은 반드시 뚫린다. 배포는 스크립트로 자동화해 업로드 전에 운영본을 백업하고 바이트 단위로 일치를 확인했다. 콘텐츠 반영은 토큰으로 보호된 일회성 스크립트가 실행 후 스스로 삭제되는 방식으로 처리해, 운영 DB를 직접 건드리지 않았다.
최종 점검은 실제 브라우저를 띄워서 했다. 24개 화면을 두 해상도에서 자동으로 렌더링해 깨진 이미지, 혼합 콘텐츠, 가로 넘침, 콘솔 오류를 전수 확인했고 전 항목 0건이었다. 전체 313개 문서를 다시 크롤해 오류 0건, 옛 도메인 잔존 0건도 함께 확인했다.
남기고 나오는 일
이전이 끝이 아니었다. 앞으로 이 사이트를 운영할 사람은 비개발자였다. 혼자 할 수 있어야 끝나는 프로젝트였다.
실제 관리자 화면 11장을 찍어 번호를 붙인 관리자 설명서 8쪽, SSL·DNS·색인·301·보안·속도 실측치를 담은 점검 기록서 5쪽, 그리고 언제든 다시 돌려볼 수 있는 자동 점검 스크립트를 함께 넘겼다.
결국
이 프로젝트의 8할은 새로 만드는 일이 아니라 잃지 않는 일이었다. 옮기는 기술보다, 무엇을 잃을 수 있는지 먼저 세어보는 쪽이 훨씬 중요했다.
새 사이트는 rokvf.or.kr에서 볼 수 있다.