뽀미의 개발노트

Go로 clean architecture 구현시 Middleware (logger, recovery)역할 본문

Go lang

Go로 clean architecture 구현시 Middleware (logger, recovery)역할

산타는 뽀미 2025. 1. 1. 22:31

Middleware는 코드 전체에서 작동하는 공통함수를 따로 빼놓은 부분이라고 생각하면 된다. 웹 백엔드 구현시 Middleware 디렉토리에 CORS, Authentication 을 많이 넣지만, 그건 다른 좋은 예시도 많으므로 이번 포스팅에서는 logger와 recovery만 다루도록 함.

 


 

프로젝트에서 gin으로 웹서버를 구현하고 있다. 기존에 middleware를 사용하지 않았을 때는 gin.Default()로 Gin Router를 생성했었고, gin에 디폴트로 내장된 logger와 recover 기능을 이미 사용 중이었다. 이번에 middleware에 따로 logger와 recovery를 구현하여 나만의 미들웨어를 사용하기로 결정함.

package main

import (
	"github.com/gin-gonic/gin"
)

func main() {

	// Gin Router 생성
	router := gin.New()

	// 미들웨어 등록
	router.Use(middleware.Logger())
	router.Use(middleware.Recovery())
    
    // 아래에 main 함수 구현..
}

나의 커스텀 미들웨어를 사용하려면 gin.Default()가 아닌 gin.New()를 사용해야 한다.

middleware > logger.go에 로깅하고 싶은 내용을 추가한다. 요청 시작 시간, 요청 처리, 요청 종료 시간, 처리 시간, 요청 메서드, 상태코드, 클라이언트IP 등등을 출력하도록 한다. 그리고 서버를 실행시키고 GET 등의 요청을 해보면??

logger에 순수 내용만 구성했을 때

위와 같이 별 감흥 없는 시시한 로그가 출력되고 만다... gin.Default()로 내장 logger 사용했을때는 굉장히 색깔도 예쁘게 나오고 했는데 말이지?? 그래서 gin-gonic/gin의 logger 코드 (https://github.com/gin-gonic/gin/blob/master/logger.go)를 참고하여 내것도 필요한 것만 반영하면서 예쁘게 보이게 바꿨다.

logger에 색상 추가했을 때

어떤 HTTP 메서드를 요청했는지, 어떤 상태코드인지 보기 편해졌다!!

 


 

이제는 recovery.go를 구현할 차례!! 

recovery에 순수 코드만 구성했을 때

Recovery 미들웨어가 실행되면 defer recover()를 등록해두었다가 어느 계층에서 패닉이 발생하면 콜스택을 거슬러 올라가다가 등록해둔 defer recover() 함수에서 panic을 캐치한다. 500에러를 클라이언트에 반환하고 서버가 죽지 않고 계속 실행되도록 해준다.

단, recovery는 예외 처리의 마지막 수단이며 가능한 한 적절한 에러 처리를 통해 패닉이 발생하지 않도록 하는 것이 중요하다고 한다. 예상 가능한 에러는 error를 리턴하여 명시적으로 처리하는 것이 바람직하다.

근데 어쨌든 순수 로직만 구현하면 터미널에 저렇게 로깅되는 것이 불만이었다. 전부 다 흰 글씨로 되어있어서 어디에서 패닉이 일어났다는 건지 알고 싶으면 인상 쓰고 한참을 찾아봐야하는,,, 그래서 이것도 색상을 추가하고 전체 콜스택과 프로젝트 내부 콜스택을 따로 출력해서 '내 코드에서 어디가 문제인건지' 알 수 있도록 했다.

recovery에 색상 + 스택 트레이스 구분 구현했을 때

그랬더니 이런 식으로 내 코드 내에 panic 이 일어난 곳을 정확히 찝어준다. 내가 일부러 이거 테스트 하려고 handler.go에 panic을 발생시켰는데(nil 슬라이스에 접근하도록 함)그 파일이랑 함수랑 줄까지 자세하게 가르쳐 준당!!! 와아아ㅏ~!!! 코드는 gin에서 공개한 recovery 코드 (https://github.com/gin-gonic/gin/blob/master/recovery.go)를 참고하여 원하는 대로 커스텀하면 된다.

암튼 이런 식으로 middleware를 구현하였고, gin에 내장된게 아니라 내가 마음대로 커스텀한 logger와 recovery를 쓸 수 있게 되었다. 추후 로그인/회원가입 기능 구현하는 프로젝트에서는 auth도 구현하고, 웹 작업 할때는 CORS도 구현할 예정이다.