gin 에서 에러 핸들링을 처리 할 때, 보통 middleware 를 하나 만들어 처리를 한다.
검색을 했을 때, 괜찮은 방법들이 없어서 생각하며 만들었는데
지금 다시 찾아보니까 이 방법 괜찮은것 같다.
(적용을 한번 해보고 더 나은 방식으로 할 필요가 있겠다)
https://www.mo4tech.com/use-middleware-for-global-error-handling-in-gin.html
Posted on Sept. 12, 2022, 8:14 p.m. by Aaryahi Keer
본인이 만든 방식은 middleware 쪽에서 처리한 부분은 아니고
error.go 라는 파일을 하나 만들어 import 하는 방식으로 처리했다.
간단하게 예를 들어보면
먼저 error code 를 상수로 정의했다.
많은 에러들이 있지만, 각각의 database table 에 맞는 에러코드 및
프로젝트에 맞는 에러코드를 추가해주면 된다.
const (
INVALID_PARAMS = 100000
ERROR_SERVER = 100001
AUTHORIZATION_HEADER_NOT_FOUND = 110000
EXPIRED_TOKEN = 110001
INVALID_TOKEN = 110002
NOT_FOUND_PAGE = 120000
)
숫자는 프로젝트를 하는 사람들과의 약속으로 정하면 된다.
그 다음 각 상수의 에러내용을 좀 더 구체적으로 작성했다.
var msg = map[int]map[string]int{
INVALID_PARAMS: {"Invalid params": http.StatusBadRequest},
ERROR_SERVER: {"Server error": http.StatusInternalServerError},
AUTHORIZATION_HEADER_NOT_FOUND: {"Authorization header not found": http.StatusBadRequest},
EXPIRED_TOKEN: {"Expired token": http.StatusUnauthorized},
INVALID_TOKEN: {"Invalid token": http.StatusUnauthorized},
NOT_FOUND_PAGE: {"Page not found": http.StatusNotFound},
}
그 다음 msg 를 가져오는 코드를 작성한다.
func getErrorMsg(code int) (string, int) {
msg, ok := msg[code]
if ok {
for message, httpStatus := range msg {
return message, httpStatus
}
}
return "", 0 // ok 가 false 일 때, 임시적으로 return "", 0 을 해놓았는데 이것도 정하면 된다. 에러코드가 정의 되어있지 않은 경우이다.
}
에러코드를 check 하는 코드를 작성한다.
func CheckErrorCode(c *gin.Context, err error, code int) bool {
if err != nil {
message, httpStatus := getErrorMsg(code) // message 와 http 상태코드 가져온다.
c.JSON(httpStatus, gin.H{
"code": code,
"message": message,
})
c.Abort() // Abort 처리 까지 해준다.
return true
}
return false
}
직접 사용 할때는
예를 들어 Gin 에서 ShouldBindJSON 사용하여 body 값을 받을 때
// func (*gin.Context).ShouldBindJSON(obj any) error
err := c.ShouldBindJSON(&body)
if CheckErrorCode(c, err, 100000) {
return
}
이런식으로 처리 할 수 있다.
에러를 반환하지 않는 예를 들어 string 빈 값을 체크 하거나 할 때는
errors 를 import 하여 강제로 에러 메시지를 넣어주면 된다.
import (
"errors"
)
// func (*gin.Context).Query(key string) (value string)
name := c.Query("name")
if name == "" {
if CheckErrorCode(c, errors.New("err"), 100000) {
return
}
}
방법은 많고 본인이 편한 방법을 사용하면 된다.
위 링크의 방식도 괜찮아서 저 방법으로도 구현을 해봐야겠다.