[go] Go 언어를 사용한 RESTful API의 확장 가능한 아키텍처 설계

Go 언어는 간단하면서도 강력한 기능을 제공하여 웹 애플리케이션의 개발과 운영에 적합한 선택지이다. RESTful API는 널리 사용되는 웹 서비스 아키텍처 중 하나로, 클라이언트와 서버 사이의 통신을 위한 규칙을 정의한다. 이번 블로그에서는 Go 언어를 사용하여 확장 가능하고 유지 보수하기 쉬운 RESTful API의 아키텍처를 설계하는 방법에 대해 알아보겠다.

1. 패키지 구조

요청을 처리하는 핸들러, 데이터 모델, 데이터베이스 연결 등 각 기능을 독립적인 패키지로 구성하는 것이 좋다. 이렇게 함으로써 각 기능을 담당하는 코드를 분리하여 모듈화하고, 의존성을 최소화할 수 있다. 예를 들어, handlers, models, database와 같은 디렉토리를 생성하여 각 기능에 대한 코드를 저장할 수 있다.

2. 라우팅 기능

라우팅은 요청을 적절한 핸들러로 전달하는 역할을 한다. Go 언어에서는 http 패키지를 사용하여 라우터를 구현할 수 있다. mux 라이브러리는 많은 기능과 유연성을 제공하여 RESTful API의 라우팅을 쉽게 설정할 수 있다.

package main

import (
	"net/http"

	"github.com/gorilla/mux"
)

func main() {
	// 라우터 생성
	router := mux.NewRouter()

	// 핸들러 등록
	router.HandleFunc("/api/users", getUsersHandler).Methods("GET")
	router.HandleFunc("/api/users/{id}", getUserHandler).Methods("GET")
	router.HandleFunc("/api/users", createUserHandler).Methods("POST")
	router.HandleFunc("/api/users/{id}", updateUserHandler).Methods("PUT")
	router.HandleFunc("/api/users/{id}", deleteUserHandler).Methods("DELETE")

	// 서버 시작
	http.ListenAndServe(":8080", router)
}

위 예제에서 /api/users와 같은 URL 패턴에 대해 적절한 핸들러 함수를 등록하고 있다. 이렇게 함으로써 각 요청에 대한 핸들러 함수를 구현하고, 해당 함수를 라우터에 등록하여 요청을 처리할 수 있다.

3. 데이터베이스 연결

Go 언어에서 데이터베이스와의 연결은 일반적으로 SQL 패키지와 해당 데이터베이스 드라이버를 사용하여 처리한다. 데이터 연결이 필요한 패키지에서 데이터베이스 연결을 설정하고, 필요한 쿼리를 작성하여 데이터를 가져올 수 있다. 이를테면, PostgreSQL과의 연결 설정은 다음과 같다.

package database

import (
	"database/sql"

	_ "github.com/lib/pq"
)

// 데이터베이스 연결 풀
var db *sql.DB

func init() {
	var err error

	// 데이터베이스 연결
	db, err = sql.Open("postgres", "postgresql://user:password@localhost/mydb?sslmode=disable")
	if err != nil {
		panic(err)
	}

	// 연결 풀 설정
	db.SetMaxOpenConns(10)
	db.SetMaxIdleConns(5)
}

// 데이터베이스 연결 반환
func GetDB() *sql.DB {
	return db
}

위 예제에서는 database/sql 패키지와 github.com/lib/pq 드라이버를 사용하여 PostgreSQL과의 연결을 설정하고 있다. sql.Open 함수를 사용하여 데이터베이스에 연결하고, db.SetMaxOpenConnsdb.SetMaxIdleConns 함수를 사용하여 연결 풀의 최대 크기를 설정한다. 필요한 곳에서 GetDB 함수를 호출하여 연결된 데이터베이스에 접근할 수 있다.

4. 핸들러 함수

각 요청에 대한 핸들러 함수를 구현해야 한다. 핸들러 함수는 요청을 처리하고, 필요한 경우 데이터베이스 연결을 생성하여 데이터를 조회 또는 조작한다. 예를 들어, GET /api/users 요청에 대한 핸들러 함수는 다음과 같이 작성할 수 있다.

package handlers

import (
	"encoding/json"
	"net/http"

	"github.com/yourusername/yourproject/models"
)

func getUsersHandler(w http.ResponseWriter, r *http.Request) {
	// 데이터베이스 연결
	db := database.GetDB()
	defer db.Close() // 연결 종료

	// 데이터 조회
	users, err := models.GetUsers(db)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	// JSON 응답
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(users)
}

위 예제에서는 models.GetUsers 함수를 사용하여 데이터베이스로부터 사용자 목록을 가져오고, json.NewEncoder를 사용하여 가져온 데이터를 JSON 응답으로 변환하여 반환한다. 필요한 경우 데이터 조회 또는 조작을 위해 해당 데이터 모델 패키지를 사용하여 구현할 수 있다.

결론

Go 언어를 사용하여 RESTful API를 구현할 때, 간결하고 확장 가능한 아키텍처를 설계하는 것이 중요하다. 패키지 구조, 라우팅 기능, 데이터베이스 연결, 핸들러 함수를 잘 구성하여 유지 보수하기 쉽고 확장 가능한 코드를 작성할 수 있다.

참고: Build Web Application with Golang