[Go] Go Web Programming Basic 05 - 파라미터 처리

파라미터 처리

이번에는 파라미터 처리에 대해서 알아보자.

Path Variable 사용하기.

지금까지 라우팅을 통해서 엔드포인트에 대한 핸들러 등록을 수행했다.

이제부터는 리퀘스트를 분석하는 방법을 알아보자.

Path Variable

/api/users/{id} 와 같이 {id} 에 대한 값을 PathVariable 이라고 한다.

이 id 에 해당하는 값은 URL encoding 된 어떠한 값이든 가능하다.

api_users.go 파일에서 UserById 함수를 다음과 같이 수정하자.

func UserByID(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	userID := vars["id"]

	fmt.Fprintf(w, "UserByID :%v", userID)
}

mux.Vars 를 이용하여 Request의 내용을 추출한다.

소스 내용을 보면 func Vars(r *http.Request) map[string]string 으로 결과값을 map 을 반환한다.

위와 같이 vars[“id”] 처럼 path variable 을 조회할 수 있다.

테스트해보기.

이제 프로그램을 실행하고, 다음과 같이 테스트해보자.

go run main.go route_module.go api_subjects.go api_users.go
Server start on port:  8080
✗ curl localhost:8080/api/users/kido
UserByID :kido

정상적으로 PathVariable 가 전달 되었음을 알 수 있다.

여러개 PathVariable

이제는 조금더 나아가 Multiple Path Variable 을 만들어 보자.

핸들러를 다음과 같이 등록하자.

api_user.go 파일의 핸들러 부분을 다음과 같이 등록한다.

handler 등록

		{path: "/users/{id}/summary/{key}", fun: GetUserSummaryByKey, methods: []string{"GET"}},

handler 함수 작성

func GetUserSummaryByKey(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	userID := vars["id"]
	summaryKey := vars["key"]

	fmt.Fprintf(w, "UserByID :%v, key: %v", userID, summaryKey)
}

살펴본바와 같이 PathVariable 을 통해서 값을 가져올 수 있다.

결과 보기

 curl http://localhost:8080/api/users/kido/summary/height
UserByID :kido, key: height

 curl http://localhost:8080/api/users/kido/summary/region
UserByID :kido, key: region

Regular Expression 적용하기.

PathVariable 를 특정 조건에 부합하는 값만을 받기위해 Regular Express 을 이용할 수 있다.

사용자 아이디가 숫자로만 이루어 진 값이라고 해보자. 그럼 다음과 같은 URI 를 작성할 수 있다.

  • /api/users/{id:[0-9]+}

위와 같이 적용하면 users/ 다음에 오는 값은 오직 숫자로만 구성된 값이 올 수 있다는 의미이다.

그럼 api_users.go 를 다음과 같이 수정해보자.

... 생략 
func usersHandlers() []handler {
	return []handler{
		{path: "/users/{id}/summary/{key}", fun: GetUserSummaryByKey, methods: []string{"GET"}},

		// 이 부분에서 regular expression 을 적용했다. 
		{path: "/users/{id:[0-9]+}", fun: UserByID, methods: []string{"GET"}},
		{path: "/users/{id}", fun: DeleteUserByID, methods: []string{"DELETE"}},
		{path: "/users", fun: CreateUser, methods: []string{"POST"}},
		{path: "/users", fun: AllUsers, methods: []string{"GET"}},
		{path: "/users", fun: UpdateUser, methods: []string{"PUT"}},
	}
}
... 생략 
  • path: “/users/{id:[0-9]+}”: 이 의미는 /users/숫자 인 경로가 들어오면 UserByID 핸들러로 라우팅 하라는 의미이다.

만약 /users/hello123 등과 같은 값이 들어온다면 아마도 /users 이고 GET 인 AllUsers 핸들러로 라우팅 될 것이다.

위와 같이 작성하고 테스트를 해보자.

테스트하기.

 curl http://localhost:8080/api/users/123
UserByID :123

정상적으로 숫자가 들어왔고, 원하는 값이 반환 되었다.

 curl http://localhost:8080/api/users/hello111
AllUsers

숫자에 매치되는 라우팅은 건너 뛰고, AllUsers 핸들러를 호출한 것을 확인할 수 있다.

Wrap Up

PathVariable 을 이용하면 의미있는 REST Api 를 작성할 수 있다. REST Endpoint 작성 가이드에 따라, 활용하면 좋을듯 하다.

QueryString

이번에는 쿼리 스트링을 알아보자.

REST API 엔드포인트를 작성할때 일반적으로 Resource 의 Location 을 이용하여 요청을 보낸다.

Resource Location 은 명사로 작성이 되며, 오퍼레이션은 기본적으로 Method 를 이용하여 작성한다.

이렇게 작성하다보면 다양한 조건에 대한 조건식을 전송하거나, 동사형 파라미터가 필요할 경우 REST api 엔드포인트를 작성하기 매우 어렵다.

이럴경우 Query String 을 사용하면 쉽게 이런 문제를 해결할 수 있다.

예시

/api/users?page=1&rows=10&startName=ki

위와 같은경우 쿼리 스트링은 ?page=1&rows=10&startName=ki 이다.

쿼리 스트링을 추출하여 사용자 검색시 페이지는 1번 페이지, 페이지당 row 개수는 10, 검색 조건은 이름이 ki 로 시작하는 결과를 추출하라는 의미이다.

쿼리 스트링 추출하기.

이제 코드로 쿼리 스트링을 추출해보자.

api_users.go 파일을 다음과 같이 수정하자.

... 생략 
func AllUsers(w http.ResponseWriter, r *http.Request) {

	values := r.URL.Query()

	page := values["page"]
	rows := values["rows"]
	startName := values["startName"]

	fmt.Fprintf(w, "AllUsers: %v %v %v", page, rows, startName)
}
... 생략
  • r.URL.Query(): 이를 이용하면 쿼리 스트링을 map 으로 반환한다.

결과 확인하기.

 curl http://localhost:8080/api/users?page=1&rows=10&startName=ki
AllUsers: [1] [10] [ki]

위와 같이 원하는 결과가 반환 되었다. 이제 쿼리 스트링을 이용하여 복잡한 조건의 REST API 를 작성할 수 있게 되었다.

Wrap Up

지금까지 매우 간단한 작업이지만, REST Api 를 위해서 필수적인 QueryString 처리를 알아 보았다.

Request 의 URL 구조체는 클라이언트로 특정 엔드포인트에 접근하기 위한 URI 작성과 요청 엔드포인트에 대한 다양한 방법을 제공하고 있다.

URL.Query 에서 참조하자.

관련 Git 에서 소스코드를 확인 가능