일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
- 러스트 기초
- ethers v6
- vue기초
- 스마트컨트렉트 함수이름 중복 호출
- 머신러닝기초
- redux toolkit 설명
- 오블완
- Vue.js
- 티스토리챌린지
- cloud hsm
- cloud hsm 사용하기
- erc4337
- Vue
- 체인의정석
- 러스트 기초 학습
- 스마트 컨트렉트 함수이름 중복
- ambiguous function description
- git rebase
- 러스트기초
- 스마트컨트렉트 예약어 함수이름 중복
- redux 기초
- rust 기초
- ethers typescript
- SBT표준
- 계정추상화
- erc4337 contract
- cloud hsm 서명
- 컨트렉트 동일한 함수이름 호출
- ethers type
- ethers websocket
- Today
- Total
체인의정석
Go Gin으로 API 만들기: POST/GET 기본 구조 + Swagger 작성법 본문
1. POST 요청 (생성)
기본 흐름
- 클라이언트가 JSON 데이터 보냄
- 서버가 JSON 파싱해서 구조체에 매핑
- 데이터를 저장하거나 처리
- 성공하면 200 OK, 실패하면 에러 응답
// CreateExample
// @Summary Example 데이터 생성
// @Description 새로운 Example 데이터를 생성합니다.
// @Tags example
// @Accept json
// @Produce json
// @Param body body CreateExampleRequest true "Example 생성 요청 데이터"
// @Success 200 {object} RespHeader
// @Failure 400 {object} RespHeader
// @Failure 500 {object} RespHeader
// @Router /v1/examples [post]
func (h *Handler) CreateExample(c *gin.Context) {
var req CreateExampleRequest
if err := c.ShouldBindJSON(&req); err != nil {
RespError(c, http.StatusBadRequest, "Invalid request body")
return
}
// 비즈니스 로직 처리 (예시)
if err := insertExampleToDB(req); err != nil {
RespError(c, http.StatusInternalServerError, err.Error())
return
}
RespOK(c, NewRespHeader(Success))
}
2. GET 요청 (조회)
기본 흐름
- 클라이언트가 조회 요청
- 필요한 경우 Query 파라미터 받음
- 서버가 데이터 조회 후 응답
- 성공하면 200 OK 리스트 반환
// GetAllExamples
// @Summary Example 리스트 조회
// @Description Example 데이터를 상태값에 따라 조회합니다.
// @Tags example
// @Accept json
// @Produce json
// @Param status query string false "Example 상태 (예: active, inactive)"
// @Success 200 {object} GetExamplesResponse
// @Failure 500 {object} RespHeader
// @Router /v1/examples [get]
func (h *Handler) GetAllExamples(c *gin.Context) {
status := c.Query("status")
if status == "" {
status = "active" // 기본값
}
// 비즈니스 로직 처리 (예시)
examples, err := getExamplesFromDB(status)
if err != nil {
RespError(c, http.StatusInternalServerError, err.Error())
return
}
resp := GetExamplesResponse{
RespHeader: NewRespHeader(Success),
Examples: examples,
}
RespOK(c, resp)
}
📌 Swagger 주석 작성시 주의할 점
@Summary | 한 줄 요약 (짧고 직관적으로) |
@Description | 상세 설명 (필요하면 한두 줄) |
@Tags | Swagger 카테고리 메뉴 분류 |
@Accept / @Produce | json이면 그냥 둘 다 "json" |
@Param | body 또는 query 명시 정확히 (특히 GET 쿼리) |
@Success / @Failure | 응답 타입, HTTP 코드 반드시 맞게 |
@Router | API 엔드포인트 + HTTP 메서드 지정 |
*응답값과 요청 body값은 미리 객체 형태로 만들어서 관리
아래와 같이 정의하면 되며 binding, required와 같은 요구조건등을 통해서 필수 값을 따로 지정할 수도 있다.
type ExampleRequest struct {
NickName string `json:"nick_name" binding:"required"`
WalletAddress string `json:"wallet_address" binding:"required"`
Team string `json:"team"`
}
DB와 상호 작용하는 부분은 따로 빼서 관리를 하였는데
먼저 DB에 대한 entitiy 부분을 따로 정의해서 빼 준 후에
type UserInfo struct {
Id primitive.ObjectID `json:"id" bson:"_id, omitempty"`
NickName string `json:"nick_name" bson:"nick_name"`
ExampleAddress string `json:"example_address" bson:"example_address"`
Team string `json:"team" bson:"team"`
}
다음과 같이 mongo db 모듈을 써서 crud를 진행하였다.
func (a *AccountDB) FindUser(wallet string, out *entity.UserInfo) error {
filter := bson.M{"example_address": wallet}
err := a.userInfo.FindOne(context.TODO(), filter).Decode(out)
if err == mongo.ErrNoDocuments {
return errors.New("user not found")
}
return err
}
https://www.mongodb.com/docs/manual/reference/method/db.collection.findOne/
db.collection.findOne() - Database Manual v8.0 - MongoDB Docs
If the query plan changes to use a different index, the method may return a different document. If your use case requires that a particular record is chosen consistently, you must use the options document to specify a sort. For details on using findOne() w
www.mongodb.com
공식문서에 따라서 db에 맞는 문법을 넣어서 리턴해 주었다.
전체 조회 등의 경우 다음처럼 옵션을 주는 방법도 있다. projection 그리고 cursor등을 사용하면 mongodb에서 select all 처럼 사용이 가능하다.
func (a *AccountDB) FindUserByWalletAll() ([]string, error) {
ctx := context.TODO()
// projection으로 wallet_address만 가져오기
opts := options.Find().SetProjection(bson.M{"example_address": 1})
cursor, err := a.userInfo.Find(ctx, bson.M{}, opts)
if err != nil {
return nil, err
}
defer cursor.Close(ctx)
var addresses []string
for cursor.Next(ctx) {
var result struct {
ExampleAddress string `bson:"example_address"`
}
if err := cursor.Decode(&result); err != nil {
return nil, err
}
addresses = append(addresses, result.ExampleAddress)
}
return addresses, nil
}
에러나 응답 리턴의 경우 따로 에러를 만들었으며 API 응답에 대한 부분만 Utils로 따로 빼서 해당 에러 메세지를 담아서 최종적으로 전달하였다.
// RespOK - 성공 응답 헬퍼
func RespOK(c *gin.Context, body interface{}) {
c.JSON(http.StatusOK, body)
}
// RespError - 실패 응답 헬퍼
func RespError(c *gin.Context, status int, msg string) {
c.JSON(status, protocol.NewRespHeader(protocol.Failed, msg))
c.Abort()
}
이렇게 응답의 경우 공통으로 묶은 후에 자체적으로 규칙을 정해서 통일된 형태로 내려주면 된다.
'개발 > backend(go)' 카테고리의 다른 글
API에서 블록체인 지갑 주소 받아올 때 해야할 필수 처리 (대소문자 처리 & 공백 제거) (2) | 2025.06.18 |
---|---|
go 응답 값 타입 any처럼 유연하게 지정하기 interface 사용법 (0) | 2025.06.11 |
Go) JWT 발급 및 인증 로직 (백엔드) (0) | 2025.04.10 |
Go 언어로 메타 마스크 로그인 로직, Signature 검증 (백엔드) (0) | 2025.04.09 |
MongoDB+Go 에서의 Cursor를 활용한 다중 데이터 조회 (select all) (0) | 2025.04.08 |