<--SyntaxHighlighter--> SyntaxHighlighter.all();
JSON / XML 응답

이 섹션에서는 요청 헤더에 따라 애플리케이션이 HTML, JSON 또는 XML 형식으로 응답 할 수 있도록 애플리케이션을 약간 리팩터링합니다.

1. 재사용 가능한 함수 만들기

Route Handler에서 지금까지는 Gin의 컨텍스트 중 HTML을 사용했습니다. 항상 HTML페이지를 보여줄 때는 괜찮지만, 요청에 따라 응답 형식을 변경하고 싶을 때에는 렌더링을 처리하는 단일 함수로 리팩토링해야합니다(?). 이렇게 함으로써 Route Handler는 유효성 검사(validation) 및 데이터 추출(data fetching)에 집중하도록 할 수 있습니다.

 

Route Handler는 응답 형식에 관계없이 동일한 유효성 검사, 데이터 추출 및 처리를 수행해야합니다. 이 부분이 완료되면 데이터를 사용하여 원하는 형식의 응답을 생성 할 수 있습니다. HTML 응답이 필요한 경우 데이터를 HTML 템플릿에 전달하고, JSON 응답이 필요한 경우이 데이터를 JSON으로 변환, XML에서도 마찬로 데이터를 보내줄 수 있습니다.

 

main.go 파일 내부에 모든 Route Handler가 사용할 render 함수를 만들겠습니다. 이 함수는 request의 Accept header를 참조하여 rendering을 처리할 것입니다.

 

Gin에서는 라우트 핸들러에 전달 된 Context 객체에 Request라는 필드가 포함됩니다. This field contains the header field which contains all the request headers. Get 메소드를 를 이용하여 Header로부터 Accept header를 다음과 같이 추출할 수 있습니다.

// c is the Gin Context 
c.Request.Header.Get("Accept")
  • application/json 으로 설정하면 함수가 JSON을 렌더링합니다.
  • application/xml 으로 설정하면 함수가 XML을 렌더링하고
  • 이것이 다른 것으로 설정되거나 비어 있으면 함수는 HTML을 렌더링합니다.

main.go에 render 함수를 아래와 같이 추가합니다.

package main

import (
	"net/http"

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

var router *gin.Engine

func main() {
	router := gin.Default()

	router.LoadHTMLGlob("templates/*")

	router.GET("/", showIndexPage)
	router.GET("/article/view/:article_id", getArticle)

	router.Run()

}

func render(c *gin.Context, data gin.H, templateName string) {

	switch c.Request.Header.Get("Accept") {
	case "application/json":
		// Respond with JSON
		c.JSON(http.StatusOK, data["payload"])
	case "application/xml":
		// Respond with XML
		c.XML(http.StatusOK, data["payload"])
	default:
		// Respond with HTML
		c.HTML(http.StatusOK, templateName, data)
	}

}

2. 유닛 테스트를 통한 Route Handler 요구사항 정의 =>생략...

3. Route Handler 업데이트

기존의 c.HTML방법을 render 함수로 바꿔주기만 하면 됩니다.

 

<기존>

func showIndexPage(c *gin.Context) {
  articles := getAllArticles()

  // Call the HTML method of the Context to render a template
  c.HTML(
    // Set the HTTP status to 200 (OK)
    http.StatusOK,
    // Use the index.html template
    "index.html",
    // Pass the data that the page uses
    gin.H{
      "title":   "Home Page",
      "payload": articles,
    },
  )

}

<변경>

func showIndexPage(c *gin.Context) {
  articles := getAllArticles()

  // Call the render function with the name of the template to render
  render(c, gin.H{
    "title":   "Home Page",
    "payload": articles}, "index.html")

}

 

JSON 형식으로 Article List 추출

JSON테스트를 위해새로 어플리케이션을 빌드한 후 아래를 실행합니다.

curl -X GET -H "Accept: application/json" http://localhost:8080/

다음과 같은 응답을 반환해야합니다.

[{"id":1,"title":"Article 1","content":"Article 1 body"},{"id":2,"title":"Article 2","content":"Article 2 body"}]

 

XML 형식으로 Article 추출

XML 테스트를 위해 아래의 명령어를 실행합니다.

curl -X GET -H "Accept: application/xml" http://localhost:8080/article/view/1

다음과 같은 응답을 반환해야합니다.

<article><ID>1</ID><Title>Article 1</Title><Content>Article 1 body</Content></article>

 

4. Application 테스트

 이제 우리가 작성한 테스트를 실행하고 결과를 확인해 보겠습니다. 프로젝트 폴더에서 다음 명령을 실행합니다.

go test -v

이 명령을 실행하면 아래와 유사한 결과가 나타납니다.

=== RUN   TestShowIndexPageUnauthenticated
[GIN] 2016/06/14 - 19:07:26 | 200 |     183.315µs |  |   GET     /
--- PASS: TestShowIndexPageUnauthenticated (0.00s)
=== RUN   TestArticleUnauthenticated
[GIN] 2016/06/14 - 19:07:26 | 200 |     143.789µs |  |   GET     /article/view/1
--- PASS: TestArticleUnauthenticated (0.00s)
=== RUN   TestArticleListJSON
[GIN] 2016/06/14 - 19:07:26 | 200 |      51.087µs |  |   GET     /
--- PASS: TestArticleListJSON (0.00s)
=== RUN   TestArticleXML
[GIN] 2016/06/14 - 19:07:26 | 200 |      38.656µs |  |   GET     /article/view/1
--- PASS: TestArticleXML (0.00s)
=== RUN   TestGetAllArticles
--- PASS: TestGetAllArticles (0.00s)
=== RUN   TestGetArticleByID
--- PASS: TestGetArticleByID (0.00s)
PASS
ok    github.com/demo-apps/go-gin-app 0.084s

이 출력에서 ​​볼 수 있듯이이 명령은 우리가 작성한 모든 테스트를 한번에 실행하며,이 경우 애플리케이션이 의도 한대로 작동하고 있음을 나타냅니다. 출력을 자세히 살펴보면 Go가 경로 핸들러를 테스트하는 과정에서 HTTP 요청을 수행했음을 알 수 있습니다.

 


이렇게 Gin Framework에 대한 강좌 따라하기를 수행해보았는데요, 마지막 JSON/XML 부분과 최종 테스트 부분은 아직 정확히 테스트는 못해보고 그냥 자료 번역 수준으로 올려놓습니다. 나중에라도 익숙해지면 해보려구요. 혹시라도 참고가 되시면 좋겠습니다.

 

그럼 이만~~~

+ Recent posts