happygrammer

Go 웹 프로그래밍 - Go언어에서 쿠키 사용하기 본문

Go 웹 프로그래밍 - Go언어에서 쿠키 사용하기


쿠키는 클라이언트에 저장된 작은 정보입니다. 기본적으로 서버가 HTTP 응답 메시지를 통해 보내 온 메시지를 이용합니다. 클라이언트가 HTTP 요청을 서버에 보낼 때마다 쿠키도 함께 전송됩니다. 쿠키는 HTTP가 상태를 가지지 않는(stateless-ness) 문제를 극복하기 위한 용도로 설계되었습니다. 비록 이 방법이 유일한 것은 아니지만 인기 있는 방법 중 하나입니다. 특히 인터넷 광고 도메인은 의존도가 높습니다. 쿠키에는 많은 종류가 있습니다. 서드 파티 쿠키, 좀비 쿠키(zombie cookies), 슈퍼 쿠키(super cookies)와 같이 흥미로운 이름이 명명된 쿠키도 포함합니다. 그러나 일반적으로는 두 종류 의 쿠키만을 다룹니다. 하나는 세션 쿠키(session cookie)이며 다른 하나는 영속 쿠키(persistent cookies)입니다. 영속 쿠키는 다양한 변형 타입이 존재합니다.

쿠키 구조는 다음 예제에서 보는 바와 같습니다. 이 예제에서는 Go에서 쿠키를 표현하는 방법에 관한 내용을 포함하고 있습니다.

ttype Cookie struct {
  Name string
  Value string
  Path string
  Domain string
  Expires time.Time
  RawExpires string
  MaxAge int
  Secure bool
  HttpOnly bool
  Raw string
  Unparsed []string
}

만약 필드 설정이 만료되지 않았다면, 쿠키는 세션이거나 일시적으로 사용하는 쿠키입니다. 세션 쿠키는 브라우저가 닫히면 브라우저에서 제거됩니다. 달리 말하면 영속 쿠키는 영속성이 있어 제거되지 않습니다. 만료 시간 설정에는 두 가지 방법이 있습니다. Expires 필드를 이용하는 것과 MaxAge 필드를 이용하는 것입니다. Expires는 쿠키가 만료되는 시점을 의미하며, MaxAge는 브라우저에서 생성되고 나서 얼마만큼 지속할 것인지를 의미합니다. 이것은 Go를 위해 디자인되지 않았습니다. 브라우저에 따라 다양한 방식으로 구현됩니다. HTTP 1.1에서는 Expires는 더 이상 사용하지 않고 MaxAge를 사용합니다. 그러나 거의 대부분의 브라우저에서는 Expires를 여전히 지원하고 있습니다. MaxAge의 경우 마이크로소프트 익스플로러 6, 7, 8에서 지원되지 않습니다. 실용적인 해결책은 Expires와 MaxAge를 모두 이용해 모든 브라우저에서 지원되도록 하는것입니다.

브라우저로 쿠키 전송

쿠키는 쿠키를 사용하기 위한 문자열 메소드가 있으며, 이 메소드는 직렬화된 쿠키를 반환합니다. 반환된 결과는 Set-Cookie 응답 헤더에서 설정됩니다. 이에 관한 예제를 살펴보겠습니다.

브라우저로 쿠키 전송

package main
import (
    "net/http"
)
func setCookie(w http.ResponseWriter, r *http.Request) {
  c1 := http.Cookie{
  Name: "first_cookie",
  Value: "Go Web Programming",
    HttpOnly: true,
  }
  c2 := http.Cookie{
  Name: "second_cookie",
  Value: "Manning Publications Co",
  HttpOnly: true,
  }
  w.Header().Set("Set-Cookie", c1.String())
  w.Header().Add("Set-Cookie", c2.String())
}
func main() {
    server := http.Server{
        Addr: "127.0.0.1:8080",
    }  
    http.HandleFunc("/set_cookie", setCookie)
    server.ListenAndServe()
}

여러분은 Set 메소드를 이용해 첫 번째 쿠키를 추가할 수 있고, Add 메소드는 두 번째 쿠키를 추가할 수 있습니다. 이제 브라우저에서 http://127.0.0.1:8080/set_cookie로 접속해 보겠습니다. 그리고 브라우저에서 인스펙터(inspector) 창을 열어 보겠습니다. 보다시피 그림 4-3과 같이 쿠키 목록이 나타납니다. Go는 간단하게 쿠키 설정을 위한 단축키를 제공합니다. SetCookie 함수를 net/http 라이브러리를 호출해 사용한다면, 예제 4-13을 변형해 응답 헤더에 변화를 줄 수 있습니다.

예제 4-14. SetCookie를 이용해 브라우저로 쿠키 전송

func setCookie(w http.ResponseWriter, r *http.Request) {
  c1 := http.Cookie{
  Name: "first_cookie",
  Value: "Go Web Programming",
  HttpOnly: true,
  }
  c2 := http.Cookie{
  Name: "second_cookie",
  Value: "Manning Publications Co",
  HttpOnly: true,
  }
  http.SetCookie(w, &c1)
  http.SetCookie(w, &c2)
}

큰 차이는 없습니다. 주의해야 할 것은, 참조를 이용해 쿠키가 전달되어야 합니다.

4.4.3 브라우저로부터 쿠키 얻기

이제 쿠키 설정을 시작해 보겠습니다. 여러분은 클라이언트의 쿠키를 탐색을 원할 것입니다. 이와 관련된 예제는 다음과 같습니다.

예제 4-15. 헤더로부터 쿠키 얻기

package main
import (
"fmt"
"net/http"
)

func setCookie(w http.ResponseWriter, r *http.Request) {
  c1 := http.Cookie{
      Name: "first_cookie",
      Value: "Go Web Programming",
      HttpOnly: true,
  }
  c2 := http.Cookie{
      Name: "second_cookie",
      Value: "Manning Publications Co",
      HttpOnly: true,
  }
  
  http.SetCookie(w, &c1)
  http.SetCookie(w, &c2)
  
}

func getCookie(w http.ResponseWriter, r *http.Request) {
  h := r.Header["Cookie"]
  fmt.Fprintln(w, h)
}

func main() {
  server := http.Server{
  Addr: "127.0.0.1:8080",
  }
  http.HandleFunc("/set_cookie", setCookie)
  http.HandleFunc("/get_cookie", getCookie)
  server.ListenAndServe()
}


서버를 다시 컴파일하고 재실행해 보겠습니다. 그리고 나서 http://127.0.0.1:8080/get_cookie로 접속하겠습니다. 그러면 브라우저에서 다음과 같은 메시지를 확인할 수 있습니다.

[first_cookie=Go Web Programming; second_cookie=Manning Publications Co]

위 문자열 조각은 단일 문자열입니다. 만약 여러분이 이름-값 쌍에 대해 얻길 원한다면, 문자열을 분석(parse)해 주어야 합니다. 그러나 이어지는 예제에서도 확인할 수 있듯이 Go는 쿠키를 얻는 쉬운 방법을 제공해 주고 있습니다.

예제 4-16. Cookie와 Cookies 메소드 이용

package main
import (
"fmt"
"net/http"
)

func setCookie(w http.ResponseWriter, r *http.Request) {
  c1 := http.Cookie{
  Name: "first_cookie",
  Value: "Go Web Programming",
  HttpOnly: true,
  }
    c2 := http.Cookie{
  Name: "second_cookie",
  Value: "Manning Publications Co",
  HttpOnly: true,
  }
  http.SetCookie(w, &c1)
  http.SetCookie(w, &c2)
}

func getCookie(w http.ResponseWriter, r *http.Request) {
  c1, err := r.Cookie("first_cookie")
  if err != nil {
  fmt.Fprintln(w, "Cannot get the first cookie")
  }
  cs := r.Cookies()
  fmt.Fprintln(w, c1)
  fmt.Fprintln(w, cs)
}

func main() {
  server := http.Server{
  Addr: "127.0.0.1:8080",
  }
  
  http.HandleFunc("/set_cookie", setCookie)
  http.HandleFunc("/get_cookie", getCookie)
  server.ListenAndServe()
}


Go는 요청 시 쿠키 메소드를 제공해 줍니다. 이와 관련된 내용은 예제 4-16에서 굵은 글씨체로 표시했습니다. 이 메소드는 해당 이름으로 명명된 쿠키를 검색할 수 있게 해 줍니다. 만약 쿠키가 존재하지 않는다면 에러를 발생시킵니다. 이 메소드는 단일 값을 얻을 수 있고, 만약 여러분이 다중 쿠키를 얻길 원한다면 방법이 있습니다. 모든 쿠키를 Go 슬라이스(slice)로 검색하면 됩니다. 그러면 헤더를 통해 동일한 내용을 얻을 수 있습니다. 재컴파일 후, 서버를 재실행하고 http://127.0.0.1:8080/get_cookie로 지금 접속해 보겠습니다. 여러분이 브라우저에서 확인할 수 있는 내용은 다음과 같습니다.

first_cookie=Go Web Programming [first_cookie=Go Web Programming second_cookie=Manning Publications Co]

쿠키 설정 시 Expires나 MaxAge 필드를 설정하지 않았습니다. 그래서 세션 쿠키가 반환되었습니다. 이 점을 확인해 보기 위해 브라우저를 종료해 보겠습니다(탭을 끄지 않고 완전히 브라우저를 종료합니다). 그리고 나서 http://127.0.0.1:8080/get_cookie에 다시 접속해 보겠습니다. 그러면 쿠키가 사라졌다는 것을 확인할 수 있습니다.

Go 웹 프로그래밍 108 ~ 116p의 내용을 발췌 했습니다.

댓글쓰기 폼