로그가 왜 중요해? 그러면 어떻게 로깅 할거야?

2023. 7. 30. 23:57프로젝트

728x90
반응형

현재 음악 추천 서비스 개발을 진행 중이다.

2차 데모데이가 끝나고 3차 데모데이를 시작하는 주간에 백엔드에서는 로깅 롤링 전략을 정했다.

 

로깅이라는 것은 기록을 남기는 작업을 의미한다. 애플리케이션 개발을 할 때 로깅을 남긴다는 것은 사용자의 요청과 응답이나 예외에 대해서 로깅을 남긴다고 생각하면 된다.

 

디깅룸 팀에서는 2차 데모데이까지는 예외에 대한 로깅을 남기는 것을 목표로 잡았다. 그리고 지난주에 로깅에 대해서 조금 더 구체적인 전략을 짜기로 결정했다.

 


로깅의 중요성

 

사실 솔직히 말하면 나는 예상치 못한 예외에 대한 로깅을 남기는 것만 중요하게 생각했다. 예상치 못한 동작이 진행되는 것들에 대해 로그를 남겨두면 추후에 개발자들이 보고 예상치 못한 예외를 처리할 수 있다는 점에서 로그가 의미 있다고 생각했다. 로깅을 다분히 개발자적인 입장에서 바라보았기 때문이다.

 

로그가 필요한 시점은 그 뿐만이 아니라는 사실을 지난 한 코치님의 강의를 통해 알게 되었다. 실제 현업에서는 사용자의 문의 전화를 많이 받는다고 한다. 단순히 서비스 문의 전화도 있겠지만 본인이 주문하지 않았는데 주문이 되어있다거나, 주문을 했는데 주문을 하지 않았다고 되어있거나 하는 등의 항의 전화도 많다고 한다. 이때 사용자의 요청과 응답에 대한 기록을 온전히 가지고 있어야지 이러한 문의 내용에도 대응할 수 있다. 

 

결국 로깅이라는 것은 그저 관성에 의해 남기는 것이 아닌 개발자와 사용자 모두에게 의미 있는 방향으로 남기는 것이 중요하다는 것을 알 수 있다.

 

이러한 측면에서 우리도 로깅을 개발자에게 유용한 로깅과 사용자에게 유용한 로깅, 두 가지 측면으로 분류를 했고, 이에 기반한 전략을 수립했다.

 


개발자를 위한 로깅

우선 개발자를 위한 로깅으로는 예상치 못한 예외에 대해서만 로그를 남기기로 했다. 예상치 못한 에러는 서비스 운영에 문제를 일으킬 수 있기 때문에 이는 따로 처리해주기로 결정을 했다. 이에 따라 예상치 못한 에러를 위한 로그 파일을 따로 생성했고, 해당 에러가 발생하면 콘솔과 파일에 저장한다. 

log.error()로 예상치 못한 예외에 대해서 로그를 남기고 있다.

 

물론 예상가능한 예외는 로그를 남기지 않기로 결정했다. 해당 예외가 발생하더라도 서비스 운영에 파급효과가 크지 않다고 판단했기 때문이다. 뒤에서도 나오겠지만 이러한 류의 로그는 '모든 요청과 응답에 대한 로깅'을 할 때 로그를 남기기로 했다. 

핸들러가 없는 url로 들어올 경우는 예상 가능한 예외이기에 이는 로그를 따로 처리하지 않았다.

 

결국 개발자가 예상하지 못한 예외는 우리가 로깅파일이나 콘솔을 주기적으로 확인하면서 예상하지 못한 예외가 발생했을 때 이를 대응할 수 있도록 처리했다. 

 

하지만 지금은 개발자가 직접 로깅파일을 들여다봐야지 문제가 발생했는지를 파악할 수 있다는 단점이 있다. 이러한 예외 로깅에 대한 수동성은 예상치 못한 예외의 즉각적인 대응을 못하도록 하는 요인일 될 수 있다. 이러한 부분은 앞으로 3차 데모데이 기간과 4차 데모데이 기간에 개선해야한다. 


사용자를 위한 로깅

위에서도 잠깐 언급했지만 사용자를 위한 로깅은 사용자의 요청과 응답에 대한 로깅이라고 생각한다. 사용자가 했던 행동을 기록해둔다면 나중에 컴플레인이 들어오거나 어떤 문의가 들어왔을 때 이를 적극적으로 대응할 수 있다. 그래서 사용자의 응답과 요청에 대해서 로깅을 남기자는 의견은 모두 동의했다. 하지만 어느 정도의 범위까지 우리가 알아야하는가에 대해서는 의견이 갈렸었다.

 


어디까지 저장할 것인가?

 

처음에는 요청 url, 요청 시간, 요청 payload, 요청 header, 응답 payload, 응답 header, 요청을 받고 응답을 하기까지의 걸린 시간을 모두 로그에 저장하자고 합의를 봤다. 하지만 중간에 요청과 응답에 대한 payload나 header를 저장해도 괜찮은 가에 대한 의구심이 일었다. 

 

이를테면 회원가입이나 로그인 부분에서 문제가 발생할 수 있다. 회원가입이나 로그인을 할 때 사용자의 민감한 정보나 비밀번호가 함께 전달될 수 있다. 하지만 서버의 입장에서는 이러한 민감한 정보를 바로 저장하면 안된다. 저장을 하더라도 암호화를 하거나 다른 방식으로 저장을 해야한다. 따라서 요청과 응답에 대한 로깅을 할 때 이러한 부분을 고려하게되니 복잡도가 늘어나게 되었다.

 

물론 이러한 부분을 모두 고려해서 로그를 남긴다면 좋지만 현실적으로 어려운 부분이 있다. 한정된 시간과 자원 속에서 개발을 해야하는 우리는 항상 우선순위를 따져야한다. 뭐 지금이야 배운다라는 측면도 있기 때문에 어느 정도 용인되는 부분이 있기야 하지만 그래도 어느정도 우선순위를 따져가면서 개발하는 것이 중요하다고 생각한다. 지금은 핵심 기능에 대한 개발이 완료되지 않은 상황이기에 로깅은 핵심 기능 개발에 비해 다소 후순위로 밀릴 수 밖에 없다.

 

두번째로는  payload나 header 정보를 저장하기 위해 들이는 노력과 이를 개발했을 때 얻게 되는 이익을 고려해봐야한다. 요청과 응답에 대해서 올바르게 처리했는지에 대한 정보는 요청을 보냈다는 사실과 응답에 대한 status 코드를 통해 알 수 있다. payload나 header는 조금 더 사용자와의 CS를 잘 하기 위한 용도로서 사용될 뿐이다. 결국 노력에 비해 얻을 수 있는 이점이 적다. 물론 이점이 분명 존재하기 때문에 언젠가는 이를 반영해야하겠지만 앞서 언급했던 우선순위를 고려한다면 이는 후순위로 밀릴 수 밖에 없다.

 

사실 아직 사용자가 없는 상황에서, 더군다나 핵심 기능에 대한 개발도 완료가 안된 상황에서 이러한 부분에 시간을 많이 쏟는 것은 우리가 지금 취해야할 행동은 아니라고 생각했다. 

 

이러한 논의 끝에 payload와 header 정보는 로그에 저장하는 내용에서 제외하기로 결정했다.


사용자를 위한 로깅은 info로 설정하기로 결정했다. 이는 필터로 구현했다. aop나 interceptor 등 다양한 의견들이 나왔지만 모든 요청에 대해 처리를 해준다는 특징 때문에 바깥쪽에서 이를 처리하기로 결정했다. 물론 더 바깥쪽이라면 웹서버 단이나 리버스 프록시에서 처리해줄수도 있다. 하지만 현재 예외 처리에 대한 로깅을 어플리케이션 단에서 하고 있고, 마찬가지로 우선순위에서 밀려 이 또한 일단은 애플리케이션에서 관리해주기로 결정했다. 

 

현재 로깅을 애플리케이션에서 모두 처리해줄 수 있다는 이점 때문에 서비스 규모가 커져서 문제가 발생하지 않는다면 계속 필터를 사용해서 로깅을 관리하지 않을까 싶다.

 

 

사용자를 위한 로깅은 위에서 볼 수 있듯이 log.info로 관리를 해주고 있다. info로 관리해서 error와는 다르게 콘솔에는 찍지 않고, 파일에만 저장하는 식으로 처리해주었다. 콘솔에 로그가 계속 찍히면 로그를 남기는 의의가 없어지지 않겠는가. 

 


결국 위에서 본 것처럼 다음과 같은 파일들이 저장된다.

 

 

 

로그 롤링 전략은 없어?

 

물론 우리도 롤링 전략을 사용해서 날마다 새로운 로그를 찍거나 일정 기간이 지나거나 파일 용량이 차게 되면 로그 파일을 비워주는 등의 내용을 구현했다. 하지만 이러한 롤링 전략은 rule of thumbs에 기반해야한다고 생각한다. 다시 말해 사용자가 생기고 사용자 요청 주기를 분석해서 롤링 전략을 짜는 것이 중요하다고 생각한다.

 

대강 사용자의 유입을 예상해서 전략을 짜는 것도 중요하지만 사용자가 없는 이 시점에 롤링 전략을 어떻게 해야한다~라고 정하는 것은 탁상공론에 불과하다고 생각한다. 사용자가 생기고, 일정한 유입이 생기면 그때 롤링 전략을 수립하는 것이 더 유의미하다고 생각해 이는 블로깅에서 제외했다.

 

어쨌든 지금 시점에서 롤링 전략보다 더 중요한 것은 우리가 어떤 내용을 로그로 남기기로 했는지, 왜 그 내용을 로그로 남기기로 했는지인 것 같다. 

728x90
반응형