
백엔드 개발에는 반복되는 코드가 늘 따라붙는다. 특히 데이터베이스 쿼리와 API 서버 주변이 그렇다. 그 코드를 손으로 쓰는 건 느리고 실수도 쉽다. 코드 생성 도구(codegen)는 선언적인 명세에서 타입 안전한 Go 코드를 자동으로 만들어 준다. 유지 보수할 코드도 줄어든다.
이 글에서는 두 가지 도구를 다룬다.
sqlc는 .sql 파일을 읽고, 타입이 있는 매개변수와 결과로 쿼리를 실행하는 Go 함수를 생성한다.
sqlc.yaml에서 입력과 출력을 설정한다.sqlc generate를 실행한다.users 테이블이 있다고 하자.
-- schema.sql
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL
);이메일로 사용자를 찾는 쿼리는 다음과 같다.
-- queries.sql
-- name: GetUserByEmail :one
SELECT id, name, email FROM users WHERE email = $1;sqlc.yaml 설정.
version: "1"
packages:
- name: "db"
path: "./db"
queries: "./queries.sql"
schema: "./schema.sql"
engine: "postgresql"실행:
sqlc generate그러면 이런 메서드가 생성된다.
func (q *Queries) GetUserByEmail(ctx context.Context, email string) (User, error)백엔드에서는 이렇게 쓴다.
user, err := dbQueries.GetUserByEmail(ctx, "alice@example.com")
if err != nil {
// handle error
}
fmt.Println("User:", user.Name)SQL 문자열을 손으로 다루고 행을 스캔하던 작업이 사라진다. 코드가 더 깔끔하고 안전해진다.
oapi-codegen은 OpenAPI 명세에서 Go 서버 코드와 클라이언트 코드를 생성한다. 인터페이스와 요청·응답 타입을 만들어 준다. 남는 일은 비즈니스 로직 구현뿐이다.
oapi-codegen을 실행한다.작은 OpenAPI 명세 api.yaml을 준비한다.
openapi: 3.0.0
info:
title: User API
version: 1.0.0
paths:
/users/{email}:
get:
summary: Get user by email
parameters:
- name: email
in: path
required: true
schema:
type: string
responses:
"200":
description: User found
content:
application/json:
schema:
$ref: "#/components/schemas/User"
"404":
description: User not found
components:
schemas:
User:
type: object
properties:
id:
type: integer
name:
type: string
email:
type: string서버 코드를 생성한다.
oapi-codegen -generate types,server -package api -o api.gen.go api.yaml이러면 요청·응답 타입(User struct)과 메서드를 가진 ServerInterface가 만들어진다.
GetUsersEmail(ctx context.Context, email string) (api.User, error)인터페이스를 구현한다.
type ServerImpl struct {
db *db.Queries
}
func (s *ServerImpl) GetUsersEmail(ctx context.Context, email string) (api.User, error) {
user, err := s.db.GetUserByEmail(ctx, email)
if err != nil {
return api.User{}, err
}
return api.User{
Id: int64(user.ID),
Name: user.Name,
Email: user.Email,
}, nil
}서버를 연결한다.
router := api.NewRouter(&ServerImpl{db: dbQueries})
http.ListenAndServe(":8080", router)sqlc와 oapi-codegen을 함께 쓰면 Go 백엔드에서 데이터베이스 접근과 API 서버 코드를 자동화할 수 있다. 써야 할 보일러플레이트가 줄고 실행 중 오류도 줄어든다. 집중할 곳은 애플리케이션의 핵심 로직이다.
© Melvin Laplanche - All rights reserved.