본문 바로가기

TIL

Golang Gin-gonic에서의 request 파싱 Validation에 대해서

728x90

회사에서 Gin을 쓰다가 struct 단에서의 Validation을 하려는데 gin context에서 binding을 할 때 쓰는 거에 따라서 결과가 달라서 정리를 해본다.

 

보통 body로 들어오는 요청을 처리하는 struct는 아래와 같이 구성한다.

type Bind struct {
    Name string `json:"name"`
}

여기서 만약 해당 struct로 body 값을 파싱하려면 아래와 같이 할 수 있다.

r.POST("/", func(c *gin.Context) {
	req := &Bind{}
	err := c.Bind(req)
	if err != nil {
		c.JSON(http.StatusBadRequest, err.Error())
		return
	}
	c.Status(http.StatusOK)
})

 

이때 현재 코드대로 하면 name 값이 안들어와도 에러 처리가 되지 않는다.

name 값이 optional 하다면 그대로 하면 되겠지만 필수라면 어떻게 처리가 가능할까?

간단하게 struct에서 binding:"required"를 추가하면 된다.

type Bind struct {
    Name string `json:"name" binding:"required"`
}

이렇게 Bind를 사용해서 binding:"required"와 같이 처리한다면 name 값이 안들어올시에 400 에러가 바로 처리된다.

만약 바로 처리되는게 싫고 따로 커스터마이징 하고싶다면 Bind 대신 ShouldBind 를 사용하면 된다.

r.POST("/", func(c *gin.Context) {
	req := &Bind{}
	err := c.ShouldBind(req)
	if err != nil {
		c.JSON(http.StatusBadRequest, err.Error())
		return
	}
	c.Status(http.StatusOK)
})

이러면 이제 err 처리 부분이 없다면 name 값이 안들어와도 통과되어 200이 나게 된다.

정리하자면

 

ShouldBind + binding:"required"
err만 return하고 따로 response까지 날려주진 않음. -> error 처리하는 부분이 없다면 아래 flow 그대로 실행

 

Bind + binding:"required"
err가 바로 남 -> 따로 err 를 받지 않고도 400 에러가 바로 남. -> 에러 처리하는 부분이 없어도 400 status code를 반환한다.

 

ShouldBind 만 있으면

에러가 잡히지 않음

 

Bind 만 있으면

에러가 잡히지 않음

 

상황에 맞게 쓰면 될거같다.

 

 

추가로 param와 query도 파싱할 경우가 생기는데 아래처럼 하면 된다.

 

Param

type Bind struct {
    Name string `uri:"name" binding:"required"`
}
r.POST("/:name", func(c *gin.Context) {
	req := &Bind{}
	err := c.BindUri(req)
	if err != nil {
		c.JSON(http.StatusBadRequest, err.Error())
		return
	}
	c.Status(http.StatusOK)
})

 

Query

type Bind struct {
    Name string `form:"name" binding:"required"`
}
r.GET("/", func(c *gin.Context) {
	req := &Bind{}
	err := c.BindQuery(req)
	if err != nil {
		c.JSON(http.StatusBadRequest, err.Error())
		return
	}
	c.Status(http.StatusOK)
})

 

이때 Param의 경우는 애초에 path에 있는 값이라서 값이 비어있는 경우는 다른 path로 인식하기에 사실상 binding의 필요성은 잘 모르겠고, Query의 경우는 key는 있어도 값을 주지 않으면 binding:"required"에서 걸리게 된다.

 

관련 코드

github.com/KimGenius/gin-gonic-validation-test

 

끝.

반응형