# HTTP 프로토콜 & Gin 웹 프레임워크 학습 이 문서는 `grpccanary` 프로젝트의 **2단계: HTTP 서버 예제**에 대한 이론적 배경과 코드 구조를 설명합니다. HTTP(Hypertext Transfer Protocol)는 클라이언트와 웹 서버가 웹에서 리소스를 교환하기 위해 정의한 규약입니다. Go 언어에서는 전통적인 `net/http` 표준 라이브러리 외에도, 성능이 우수하고 사용하기 쉬운 서드파티 웹 프레임워크인 **Gin-gonic**을 주로 사용하여 RESTful API를 신속하게 설계합니다. --- ## 1. REST API와 HTTP 통신 REST(Representational State Transfer)는 웹 상의 리소스를 HTTP 메서드(`GET`, `POST`, `PUT`, `DELETE` 등)와 URI 경로를 활용해 상태를 제어하는 아키텍처 스타일입니다. * **JSON 데이터 연계**: 대다수의 HTTP REST API는 클라이언트와 데이터를 송수신할 때 데이터 교환 바디(Body)에 텍스트 기반의 **JSON 포맷**을 담아 통신합니다. * **유연성과 한계**: JSON을 사용한 HTTP 통신은 어떤 기기에서나 쉽게 파싱이 가능해 클라이언트-서버 통신에 널리 쓰이지만, 엄격한 스키마 정의가 없어 타입 런타임 오류가 발생하기 쉽고 바이너리 통신에 비해 무겁다는 특징이 있습니다. --- ## 2. Gin 웹 프레임워크 Go 진영에서 대표적으로 사랑받는 웹 프레임워크 중 하나로, 빠른 속도와 미들웨어 체인 구성, 편리한 라우팅 그룹 관리 기능을 지원합니다. ### `gin.Default()` vs `gin.New()` * **`gin.New()`**: 미들웨어가 탑재되지 않은 완전히 빈 라우터 엔진을 인스턴스화합니다. 성능에 민감하고 로깅이나 복구 미들웨어를 직접 커스텀할 때 활용합니다. * **`gin.Default()`**: 기본적인 로깅 미들웨어(`gin.Logger()`)와 오류 복구 미들웨어(`gin.Recovery()`)가 사전 탑재된 상태로 기동되어 보통의 개발 시에 편리하게 사용됩니다. --- ## 3. 실습 코드 분석 (`examples/httpentity/server.go`) 저장소의 [server.go](file:///home/godopu16/PuKi/lab/canary_projects/grpccanary/examples/httpentity/server.go) 파일에는 Gin 라우터를 구성하고 API 서버와 정적 웹 서빙을 혼합하여 라우팅을 우회 처리하는 설계 패턴이 주석 상태로 존재합니다. ### 3.1 라우터 엔진 분리 및 통합 핸들링 ```go apiEngine := gin.New() apiGroup := apiEngine.Group("/api") { apiGroup.GET("/randomNumber", GET_RandomNumber) apiGroup.GET("/randomPassword", GET_RandomPassword) apiGroup.GET("/randomDate", GET_RandomDate) } staticEngine := gin.New() staticEngine.Static("/", "./web") ``` * **API 그룹 분리**: `/api`로 들어오는 모든 요청을 `apiEngine`이 받아서 각각 `/randomNumber`, `/randomPassword` 등의 실제 비즈니스 로직 핸들러로 전달하게 설계되어 있습니다. * **정적 서빙**: 그 외의 요청에 대해서는 `./web` 경로의 정적 파일(HTML, CSS, JS)을 제공하기 위한 `staticEngine`을 별개 구성합니다. * **단일 엔트리 우회**: 메인 엔진(`r`)은 전방위 라우팅 `/*any`를 구성하여, 경로 패턴에 `/api`가 들어있으면 API 엔진에 역할을 위임하고, 그렇지 않으면 정적 파일 서버로 포워딩합니다. ### 3.2 JSON 디코딩 및 API 핸들러 ```go func GET_RandomNumber(c *gin.Context) { dec := json.NewDecoder(c.Request.Body) obj := map[string]interface{}{} dec.Decode(&obj) response := map[string]interface{}{ "value": 10, } c.JSON(http.StatusOK, response) } ``` * `c.Request.Body`를 `json.NewDecoder`로 받아서 맵에 디코딩하여 요청 매개변수(시드 등)를 취득합니다. * 비즈니스 연산 후 `c.JSON()` 함수를 통해 원하는 응답 구조를 손쉽게 클라이언트에 JSON 문자열 형태로 내보내 줍니다.