돌아가던 ASP.NET 서비스를 CodeIgniter 로 다시 짜서 돌게 하는 일을 맡았다. 코드 변환이 가장 오래 걸릴 것으로 보고 시작했다.
Table of contents
Open Table of contents
배경 — 코드보다 경계가 오래 걸렸다
옮기기 전에 이 서비스가 바깥과 무엇을 주고받는지를 적었다. 들어오는 것과 나가는 것과 옆에 있는 것으로 나누니 각각 여러 항목이 나왔다.
요청 경로와 ActiveMQ 구독 토픽과 스케줄이 들어오는 쪽이고 MySQL 과 외부 인터페이스와 파일 저장소와 발행이 나가는 쪽이었다. 설정과 자격증명과 로그가 옆에 있는 것이었는데 실제 작업량은 코드가 아니라 이 목록이 정했다.
조치 — 설정 읽는 방식과 경고 로그
옛 환경은 Web.config 의 appSettings 를 읽었고 새 환경은 .env 를 env() 로 읽는 것이 표준이었다. 옮기는 동안 양쪽이 함께 도므로 둘 다 지원하되 새 방식을 우선하게 했다.
옛 방식으로 읽으면 log_message('warning', ...) 을 남기게 한 것이 중요했다. 그 로그가 안 나오면 전부 옮겨졌다는 근거가 되기 때문이다.
막힌 지점 — 사람 작업이었던 자격증명
가장 오래 걸린 것이 자격증명 이관이었다. 옛 환경은 Web.config 에 있었고 새 환경은 서버의 환경 변수를 쓰는데 옮기려면 값을 아는 사람이 필요했다.
일부는 재발급하고 일부는 담당자에게 받았는데 재발급이 안 되는 것이 하나 있어서 그것만은 옛 값을 꼭 옮겨야 했다. 코드 작업이 아니라 사람 작업이므로 일정에도 그렇게 잡아야 했다.
해 본 것 — 로그 형식과 전환 기간
옛 서비스의 로그를 파싱하는 대시보드가 있어서 새 서비스가 다른 형식으로 찍으면 그것이 깨진다. 두 서비스가 함께 도는 동안에는 한 대시보드로 봐야 하므로 전환 기간에는 옛 형식으로 맞추는 쪽을 골랐다. 이유는 한 번에 둘을 바꾸면 문제가 났을 때 어느 쪽 때문인지 못 갈라서다.
대신 CodeIgniter 의 기본 로그 형식을 버리고 옛 형식을 흉내 내는 핸들러를 하나 더 유지하는 것을 감수했다. 전환이 끝난 뒤에 새 형식으로 바꾸고 대시보드를 고치기로 순서를 나눴다.
검증 — 동등성 확인과 되돌림
옮긴 것이 옛것과 같게 도는지는 병행 운영으로 확인했다. 새것을 돌리되 결과는 옛것을 쓰고 diff 만 기록하니 실제 트래픽으로 검증됐다.
나온 차이는 대부분 빈 값과 아주 큰 값과 특수 문자 같은 경계 조건이었다. JWT 검증도 그중 하나였는데 옛것은 exp 가 없는 토큰을 통과시켰고 새것은 거부했다. 옛 서비스를 끄지 않은 채 트래픽만 단계적으로 옮겼고 옛것을 지우는 것은 마지막에 며칠을 더 두고 했다.
정리
- 다른 런타임으로 옮길 때 코드보다 경계가 오래 걸린다
- 들어오는 것과 나가는 것과 옆에 있는 것을 목록으로 만든다
- 그 목록이 실제 작업량을 정한다
- 설정은 양쪽을 지원하되 옛 방식에 경고를 남긴다
- 그 경고가 안 나오는 것이 전환 완료의 근거다
- 자격증명 이관은 사람 작업이므로 일정에 그렇게 잡는다
- 로그 형식은 전환 기간에 옛 형식으로 맞추고 나중에 바꾼다
- 동등성은 병행 운영으로 실제 트래픽에서 확인한다