여러 서비스가 공통으로 쓰는 인증과 로깅을 하나로 묶었다. 묶고 나서 문제가 났을 때 누가 봐야 하는지가 애매해졌다.
Table of contents
Open Table of contents
배경 — 묶기 전에는 명확했다
각 서비스가 자기 auth 를 갖고 있었고 문제가 나면 그 서비스를 만든 쪽이 봤다.
대신 중복이 많아서 token 을 검증하는 코드가 네 군데였다. 인증 코드가 네 벌 있었고 로그 형식이 서로 달라서 같은 조사를 서비스마다 다른 방식으로 해야 했다.
auth-core 로 묶기로 한 것은 그 중복 때문이었다. 고칠 자리가 한 곳이 되고 형식이 같아지는 것은 분명한 이득이었다.
묶고 나서 애매해졌다
공통 인증에서 오류가 났다.
[auth] token validation failed
token validation failed 한 줄로는 어느 쪽 문제인지 갈리지 않았다.
공통 기반을 만든 쪽은 쓰는 쪽이 잘못 불렀을 것 같다고 했고 쓰는 쪽은 공통 쪽 문제 같다고 했다. 그렇게 이틀 동안 아무도 안 봤다.
기술적으로는 나아졌는데 문제 하나를 처리하는 시간은 오히려 늘어난 셈이다. 묶는 것이 코드만 옮기면 끝나는 일이 아니라는 것이 여기서 드러났다.
조치 — 경계 다시 긋기
무엇이 누구 책임인지 적었다.
공통 기반이 책임지는 것
- 토큰 발급·검증 로직
- 발급된 토큰의 형식과 유효기간
- 인증 실패 시 오류 코드와 메시지
- 공통 기반 자체의 가동
쓰는 쪽이 책임지는 것
- 언제 인증을 요구할지
- 실패했을 때 화면에서 무엇을 보일지
- 자기 서비스의 권한 정의
적고 나니 그 오류는 공통 쪽이었고 토큰 발급·검증 로직 에서 나는 것이었다.
애매한 것은 정하지 않아서 애매한 것이었다. 두 쪽 다 성실하게 판단했는데 판단 기준이 없어서 서로 다른 결론이 나온 상태였다.
경계에 걸치는 항목은 따로 모아 각각 어느 쪽인지 지정했다. 권한 정의 처럼 목록에 없는 것이 나오면 그때 한 줄을 더하기로 했다.
대응 — 오류에 무엇을 넣을지
[auth] token validation failed 만으로 어느 쪽인지 몰랐던 것도 고쳤다.
[auth-core 1.4.2] token validation failed: signature mismatch (svc=order, req=a8f2c1)
auth-core 1.4.2 와 svc 와 req 를 함께 넣었다.
svc=order 가 있으니 부르는 쪽이 어디인지 바로 보이고 1.4.2 로 어느 판에서 난 것인지도 갈린다. 값 셋을 넣는 작은 변경이 조사 시간을 크게 줄였다.
req=a8f2c1 을 넣은 덕에 공통 기반의 로그와 서비스의 로그를 이어서 볼 수 있게 됐다. req 가 없던 때는 양쪽 로그를 시각으로 맞춰 봐야 했다.
변경 사항 — 공통이 바뀔 때의 규칙
auth-core 가 바뀌면 그것을 쓰는 전부에 영향이 간다.
공통 기반 변경 규칙
- 판 번호를 붙인다
- 기존 호출 방식을 깨는 변경은 판을 올린다
- 옛 판을 최소 3개월 같이 둔다
- 바꾸기 2주 전에 쓰는 쪽에 알린다
한 번은 알림 없이 응답 형식을 바꿔서 두 서비스가 멈췄고 그 뒤에 이 규칙이 생겼다.
옛 판을 함께 두는 것은 쓰는 쪽이 각자 사정에 맞춰 옮기게 하려는 것이다. 그러지 않으면 auth-core 의 배포가 곧 전 서비스의 동시 배포가 된다.
검증 — 쓰는 쪽이 미리 시험하게
바뀐 뒤에 깨지는 것을 아는 것과 바뀌기 전에 아는 것은 값이 다르다.
auth-core:1.4.2 지금
auth-core:1.5.0-rc1 다음 판
시험 환경에 1.5.0-rc1 을 올려 두고 쓰는 쪽이 붙어 보게 했다.
실제로 한 번 여기서 걸렸다. 1.5.0-rc1 이 응답에서 항목 하나를 뺐는데 한 서비스가 그것을 쓰고 있었다.
묶으면서 받아들여야 하는 것도 있었다.
공통 인증이 멈춤 → 전 서비스 로그인 불가
전에는 하나가 멈추면 그 서비스만 멈췄는데 이제는 auth-core 하나가 전체를 멈출 수 있다.
토큰 발급은 어차피 한 곳에서 관리해야 하는 것이라 이 위험은 받아들이기로 했다. 대신 그 한 곳을 두 대로 두고 상태를 자주 확인하게 했으며 가용성 기준도 개별 서비스보다 높게 잡았다.
정리
- 공통 기반을 세우면 누가 무엇을 책임지는지 흐려진다
- 기술이 나아져도 문제 하나를 처리하는 시간은 늘 수 있다
- 애매한 것은 정하지 않아서 애매한 것이다
- 경계를 적으면 서로 넘기는 논의가 사라진다
- 경계에 걸치는 항목은 따로 모아 각각 지정한다
- 오류에 어느 판과 어느 호출자와 어느 요청인지를 넣는다
- 요청 식별자가 있으면 양쪽 로그를 이어서 본다
- 공통이 바뀌면 판 번호와 알림 기한을 정한다
- 옛 판을 함께 두지 않으면 공통 배포가 곧 전체 배포가 된다
- 쓰는 쪽이 미리 시험할 수 있게 다음 판을 올려 둔다
- 묶으면 한 곳이 전체를 멈출 수 있다는 것을 알고 묶는다