딜리버리 프로덕트 개발팀의 개발문화 - 로그 & 알람편

딜리버리 프로덕트 개발팀에서 안정적인 서비스 제공을 위한 고군분투기

인사!


안녕하세요
컬리 새벽배송의 핵심!! 딜리버리 프로덕트에서 열쒸미 프로덕트를 만들고 있는 김태훈입니다.
새벽배송, 컬리나우, 택배 등 라스트마일의 모든 것을 경험하고 싶은 분은 언제든 환영입니다!

[컬리] 커머스/풀필먼트 백엔드 개발자 (Backend Developer)


앞서 말씀드린 대로, 저희 팀은 고객에게 다양한 스타일의 라스트마일 서비스를 제공하기 위해 많은 시스템을 만들어가고 있습니다. 하지만 여러 시스템들이 추가되는 과정에서 프로덕트의 복잡도는 증가하고, 서비스의 안정성은 낮아지게 되는데요, 이렇게 높아진 복잡도를 낮추고 서비스의 안정성을 높이기 위해 딜리버리의 모든 개발자들은 오늘도 밤을 새우며 여러가지 해결 방안을 고민하고 시도하여 문제를 해결하고 있습니다. 정말 재미있겠네요! ㅎㅎ
이런 문화를 가지기까지 여러 시도가 있었는데요, 오늘은 코드레벨의 문제 상황을 잘! 그리고 빠르게! 인지하기 위해 딜리버리 프로덕트 개발팀에서 실천 중인 방안을 소개하고자 합니다.

문제 상황을 어떻게 빠르게 확인할 수 있나요?


운영 중인 시스템의 내부상황을 우리가 어떤 방식으로 이해할 수 있을까요? 가령 ‘어디로부터 어떤 형태의 데이터가 특정 단계를 거쳐 가는 중 한 곳에서 문제가 생겼고 그로인해 정상적인 응답을 주지 못했다’ 이런 상황을 말이죠. 여러 가지 방안이 있겠지만, 가장 보편화된 방법은 아마도 로그를 남기는 것이라고 생각합니다. 이러한 로그는 남기는 방법에 따라 우리에게 데이터의 흐름, 상태, 문제의 원인등 다양한 정보를 제공해줄 수 있고 우리는 로그를 보며 문제를 추적하고 원인을 확인하여 문제를 해결하게 됩니다.
안정적인 서비스를 제공하기 위해서는 운영 중 발생 가능한 문제 상황을 사전에 방지하거나, 문제가 생겼을 경우 빠르게 인지하고 복구해야 하는데요, 로그를 활용하면 시스템의 문제 상황을 사전에 방지하거나 빠르게 인지할 수 있겠네요!

자 이제 구체적인 계획을 세워 봅시다


우리는 이미 많은 로그를 남기고 있습니다. 경고(WARN), 에러(ERROR), 혹은 정보 제공(INFO)을 위한 로그들 말이죠. (INFO, WARN, ERROR 등을 로그 레벨이라고 합니다.) 하지만 로그 레벨에 대한 명확한 규칙이 없다 보니 무분별한 에러 로그, 즉 가짜 에러들이 존재하게 됩니다.
이러한 가짜 에러들에 알람이 반응하면 이는 우리를 피곤하게 하고 점차 무뎌지게 만듭니다.

집에서 생일초를 켤 때마다 화재경보가 울린다면 어떨까요? 진짜 불이 난 상황에서도 화재경보를 들으며 ‘또 생일초를 켰군!’ 이라고 생각하게 될 겁니다.
마찬가지로 불필요한 에러 알람이 계속 발생하면 우리는 점차 경계심을 잃고 무뎌지게 됩니다. ‘또 생일초를 켰겠지’ 라고 생각하게 되죠. 오늘도 별거 없겠지 하는 순간 장애는 찾아옵니다.
앞으로 소개할 내용은 생일초를 켤 때와 생일초 때문에 벽이 불타고 있는 것을 구분할 수 있는 임계점을 찾기 위한 노력에 대한 이야기 입니다.


이제, 진짜 문제일 때만 에러로 기록합시다!
먼저, 어떤 에러 로그가 있으며 얼마나 많은 에러 로그가 있는지 확인하기 위해 로깅 시스템을 열어 에러 로그만 살펴보았습니다.

차르봄바
출처:wikipedia

10일치 아님. 10분치임
© 2024.Kurly.All right reserved

🐶나 🐮나 다 에러네요. 우리가 얼마나 생각없이 에러 로그를 남겼는지 실감했죠.
정제 작업이 필요했습니다.
먼저 로그 레벨의 기준을 정해야 했는데요, 팀 내에서 회의를 거쳐 아래와 같이 정의했습니다.

  • 에러(ERROR) : 즉각 대응해야 하는 것
  • 경고(WARN) : 당장 문제는 없지만 빈도가 많을 경우 문제가 있을 수 있는 것

먼저, 발생 시 바로바로 대응을 해야하는 것들은 에러 로그를 남기고 알람이 즉각 반응하도록 하였습니다.(에러 로그가 발생할 때마다 알람이 울리도록 구성) 여기엔 저희가 의도하지 않은 어플리케이션의 예외들도 포함되어 있습니다.
두 번째로, 한두 번 발생했을 때는 큰 문제가 없지만 빈도가 많을 경우 문제가 있을 수 있는 경우도 있습니다. 이런 상황에서는 경고 로그를 남기고 특정 기간 내에 임계치를 넘어서면 알람이 오도록 설정했습니다.
보통 이런 예외들은 도메인(혹은 api나 메서드가 될 수도 있습니다) 의 특성을 많이 타기 때문에 각 상황에 맞게 모니터링 주기를 설정해야 합니다.
가령 같은 외부 호출이라도 응답 시스템의 상태,호출 빈도 등에 따라 1분 간격으로 확인하거나 10분 간격으로 확인해야 할 수 있습니다. 금방 복구되는 시스템도 있고 그렇지 않은 시스템도 있고요. 이건 모니터링을 하면서 조정해가야 합니다. 먼저 공통 범위 알람으로 설정을 하고 사용성이 다르게 발생하는 것들은 별도의 알람으로 설정합니다.

공통 범위 알람은 일반적으로 사용할 경고 알람 입니다. 저희는 5분내에 100회 정도로 규정하고 있습니다. 패턴을 알지 못하는 경고 레벨은 이쪽에 등록해 둔 후에 조절이 필요하면 기준을 정해 별도의 알람으로 분리됩니다.


예시를 보며 상세히 알아봅시다





가짜 에러
© 2024.Kurly.All right reserved

이런 에러는 사실 에러가 아닙니다. 의도된 예외이고 개발자가 대응할게 없습니다. 대신 사용자에게 잘못되었음을 알리고 조건을 변경하여 재시도를 유도 해야하죠. 하지만 이런 녀석들도 짧은 시간에 굉장히 많이 반복된다면 문제상황을 의심해 볼 수 있습니다. 그러므로 에러 로그를 경고 로그로 변경하고 공통 범위 알람을 걸어둡니다. 이 후 빈도는 조정을 하면 되니까요.



진짜가 나타나따
© 2024.Kurly.All right reserved

요번엔 실제 문제가 있는 에러 입니다. 빠르게 대응하고 필요에 따라 핫픽스, 혹은 티켓을 만들어 대응하고 잠시 알람에서 제외 시킬 수 있습니다.



아프지마 서버야
© 2024.Kurly.All right reserved

외부시스템과 연동하는 구간은 간간히 타임아웃을 발생시킵니다. 하지만 대부분 재처리가 되어 한번의 발생에서는 대응할 필요가 없고 여러번 지속적으로 발생한다면 그에 맞는 대응이 필요하겠죠. 이런 녀석은 경고 로그로 변경하고 기간과 임계치를 설정하여 알람을 받도록 합니다.(당연히 수정된 코드가 릴리즈 될때 까지는 알람을 예외처리 해야합니다) 서킷브레이커가 있다면 서킷이 열렸을때 알람을 받을 수 도 있습니다.



깜짝이야
© 2024.Kurly.All right reserved

어떤 로그는 어플리케이션에서 제어할 수 없는 것들도 존재 합니다.(카프카라던가 레디스,디비 등등) 이런것들은 로그 레벨을 조정하기 어렵기 때문에 패턴을 살펴 적절한 알람을 걸거나 알람대상에서 제외 시켜줘야 합니다. 저희는 MSK를 사용중인데요 요게 정기적으로 업데이트가 있고 이럴때마다 대량의 경고 로그가 올라오게 됩니다. 공통으로 사용하는 경고 레벨 범주에 들어 새벽에 놀란 마음을 쓸어내린곤 했죠. 요런 친구들은 예외처리를 해둡니다.

이렇게 완성된 로그



깔-끔
© 2024.Kurly.All right reserved

최근 3일간 10개가량의 시스템 에러 로그는 4건 경고 로그는 355건이었고 사용자보다 먼저 혹은 준 실시간으로 문제상황을 인지 할 수 있었습니다. (해결해야할 이슈들은 다음 릴리즈에 처리될 예정입니다.)

이제 저희팀은 정말 에러일때만 알람을 받을 수 있게 되었습니다!

그럼에도 이후 서비스를 개선&추가하며 여러 가짜 에러 로그들이 생길 것입니다. 그럴수 밖에 없죠. 그래서 로그도 코드처럼 꾸준히 관리가 되어져야 합니다. 신규 에러가 발생시 즉각 확인하고 팀의 정해진 기준에 맞춰 티켓을 생성하고 잠시 알람에서 제외 혹은 핫픽스를 하는 그런 문화가 만들어져야 합니다.

팀웍 굿
© 2024.Kurly.All right reserved

혼자서도 잘해요
© 2024.Kurly.All right reserved

처음부터 완벽하게 하려고 하지 마세요. 불가능합니다. 같은 도메인이더라도 사용자,트래픽,운영시간 등등 거의 모든 요소에 의해 패턴이 다르기 때문입니다.

  • 자주 울리는데 확인해보니 별일없다 ➡ 빈도를 느슨하게
  • 장애가 발생했는데 울리지 않았다 ➡ 더 타이트하게

운영하며 각자 도메인에 적절한 수준을 찾아야합니다.
사실 굉장히 귀찮은 작업이긴 합니다.
하.지.만. 해볼만한 가치가 충분하다고 생각합니다.

이거 완젼 럭키비키쟈나~


이 작업을 개발환경에서부터 습관을 들인다면 디버깅능력 향상은 물론 운영에서 발생할 문제를 사전에 예방 하는 효과도 누릴 수 있습니다. 또 이렇게 운영하면 (훈련하면) 코드에서 예외처리를 할때 한번 더 생각하게 됩니다. 이 예외가 생겼을때 어떻게 해결해야하는지? 바로해결 가능한지? 정말 예외인지? 로그를 남겨야 하는지? 등등 …
개발자는 점점 더 로그를 확인하기 쉽게 만들고 꼭 남겨야 할 부분과 그렇지 않은 부분을 판단 할 수 있게 됩니다.

이상 안정적인 서비스 제공과 더불어 개발자의 능력도 향상 시킬수 있는 딜리버리 프로덕트 개발팀의 practice 였습니다~

긴글 읽어주셔서 감사합니다 !