← 가이드 목록으로 ← Back to guides

Go 웹 서버와 HTTP 핸들링 완벽 가이드 Go Web Server & HTTP Handling Complete Guide

Go의 동시성 패턴을 익혔다면, 이제 실제 웹 서버를 구축할 차례입니다. 표준 라이브러리 net/http만으로도 강력한 REST API를 만들 수 있습니다.

After learning Go's concurrency patterns, it's time to build real web servers. You can create powerful REST APIs using just the standard library net/http.

기본 HTTP 서버 Basic HTTP Server

package main

import (
  "fmt"
  "net/http"
)

func main() {
  // 핸들러 등록
  http.HandleFunc("/hello", helloHandler)
  http.HandleFunc("/api/users", usersHandler)

  // 서버 시작
  fmt.Println("Server starting on :8080")
  http.ListenAndServe(":8080", nil)
}

func helloHandler(w http.ResponseWriter, r *http.Request) {
  fmt.Fprintf(w, "Hello, World!")
}
package main

import (
  "fmt"
  "net/http"
)

func main() {
  // Register handlers
  http.HandleFunc("/hello", helloHandler)
  http.HandleFunc("/api/users", usersHandler)

  // Start server
  fmt.Println("Server starting on :8080")
  http.ListenAndServe(":8080", nil)
}

func helloHandler(w http.ResponseWriter, r *http.Request) {
  fmt.Fprintf(w, "Hello, World!")
}

JSON API 핸들러 JSON API Handler

type User struct {
  ID int `json:"id"`
  Name string `json:"name"`
  Email string `json:"email"`
}

func usersHandler(w http.ResponseWriter, r *http.Request) {
  switch r.Method {
  case http.MethodGet:
    users := []User{{1, "Kim", "[email protected]"}}
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(users)

  case http.MethodPost:
    var user User
    if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
      http.Error(w, err.Error(), http.StatusBadRequest)
      return
    }
    w.WriteHeader(http.StatusCreated)
    json.NewEncoder(w).Encode(user)

  default:
    http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
  }
}
type User struct {
  ID int `json:"id"`
  Name string `json:"name"`
  Email string `json:"email"`
}

func usersHandler(w http.ResponseWriter, r *http.Request) {
  switch r.Method {
  case http.MethodGet:
    users := []User{{1, "Kim", "[email protected]"}}
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(users)

  case http.MethodPost:
    var user User
    if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
      http.Error(w, err.Error(), http.StatusBadRequest)
      return
    }
    w.WriteHeader(http.StatusCreated)
    json.NewEncoder(w).Encode(user)

  default:
    http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
  }
}

미들웨어 패턴 Middleware Pattern

미들웨어는 핸들러를 감싸서 로깅, 인증, CORS 등 공통 기능을 처리합니다.

Middleware wraps handlers to handle common functionality like logging, authentication, and CORS.

// 로깅 미들웨어
func loggingMiddleware(next http.Handler) http.Handler {
  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    start := time.Now()
    next.ServeHTTP(w, r)
    log.Printf("%s %s %v", r.Method, r.URL.Path, time.Since(start))
  })
}

// CORS 미들웨어
func corsMiddleware(next http.Handler) http.Handler {
  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Access-Control-Allow-Origin", "*")
    w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE")
    next.ServeHTTP(w, r)
  })
}

// 미들웨어 체이닝
func main() {
  mux := http.NewServeMux()
  mux.HandleFunc("/api/users", usersHandler)

  handler := loggingMiddleware(corsMiddleware(mux))
  http.ListenAndServe(":8080", handler)
}
// Logging middleware
func loggingMiddleware(next http.Handler) http.Handler {
  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    start := time.Now()
    next.ServeHTTP(w, r)
    log.Printf("%s %s %v", r.Method, r.URL.Path, time.Since(start))
  })
}

// CORS middleware
func corsMiddleware(next http.Handler) http.Handler {
  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Access-Control-Allow-Origin", "*")
    w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE")
    next.ServeHTTP(w, r)
  })
}

// Middleware chaining
func main() {
  mux := http.NewServeMux()
  mux.HandleFunc("/api/users", usersHandler)

  handler := loggingMiddleware(corsMiddleware(mux))
  http.ListenAndServe(":8080", handler)
}

Graceful Shutdown Graceful Shutdown

func main() {
  srv := &http.Server{
    Addr: ":8080",
    Handler: mux,
  }

  // 시그널 채널
  quit := make(chan os.Signal, 1)
  signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)

  go func() {
    log.Println("Server starting...")
    srv.ListenAndServe()
  }()

  <-quit
  log.Println("Shutting down...")

  ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
  defer cancel()

  srv.Shutdown(ctx)
}
func main() {
  srv := &http.Server{
    Addr: ":8080",
    Handler: mux,
  }

  // Signal channel
  quit := make(chan os.Signal, 1)
  signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)

  go func() {
    log.Println("Server starting...")
    srv.ListenAndServe()
  }()

  <-quit
  log.Println("Shutting down...")

  ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
  defer cancel()

  srv.Shutdown(ctx)
}

💡 인기 Go 웹 프레임워크 💡 Popular Go Web Frameworks

  • Gin: 빠르고 간단한 라우팅
  • Gin: Fast and simple routing
  • Echo: 성능과 확장성
  • Echo: Performance and extensibility
  • Fiber: Express.js 스타일
  • Fiber: Express.js style