본문 바로가기
Golang/Backend master class with Golang

Backend Master Class with Golang - Postgres setup, db migration

by 데브겸 2023. 9. 18.

Golang으로 백엔드 개발을 해보고 싶다고 생각하던 중 귀한 자료를 발견

https://www.youtube.com/watch?v=rx6CPDK_5mU&list=PLy_6D98if3ULEtXtNSY_2qN21VCKgoQAE 

 

Gin, Postgres, Redis, gRPC와 이것저것을 다 합하여 개발해보는 강의가 무료로 풀려 있어 찍먹해보려고 한다.

모든 내용을 기록하지는 않고 (경험상 그러면 시간이 너무 오래 걸림;;) 필요하거나 나중에도 보면 좋을 내용들 위주로 정리할 예정

 

 

Postgres 이해하기

 

DB는 Postgres를 Docker로 띄워 진행한다.

 

Postgres는 다른 DB와 구조가 조금 달라서 처음에 감을 잡기 살짝 어려웠던 것 같다. 구조는 아래와 같다.

출처: http://www.gurubee.net/lecture/2942

 

최상단은 Cluster이며, 그 아래 Users/Groups (DB 사용자들과 권한으 관리하는 곳), Databases (테이블을 포함한 오브젝트들을 포괄하는 상위 오브젝트 집합 구조), Tablespaces (오브젝트가 저장되는 파일시스템의 위치를 정의해 놓은 것) 가 있다.

 

이 중에서 사용자들이 가장 많이 사용하는 곳은 Database. 

 

다른 DB와 달리 Postgres에서는 Database와 Schema를 구분한다. Schema는 Table의 집합이며, Database를 논리적으로 나누는 개념이다. (Database가 물리적으로 구분된 공간, Schema는 논리적으로 구분된 공간이라고 볼 수 있다)

 

따라서 Database가 Schema의 상위 개념이기 때문에, 접속시 Database -> Schema 순으로 접속한다. 또 권한 부여시 Database -> Schema -> Table 구성 요소 순서로 부여해야 한다.

 

여튼 아래의 명령으로 컨테이너 안 Postgres에 simple_bank 이름을 지닌 데이터베이스를 만든다

$ docker exec -it postgres /bin/bash

/ # createdb --username=root --owner=root simple_bank
/ # psql simple_bank

simple_bank=#

 

 

DB Migration

데이터베이스 마이그레이션은 데이터베이스를 교체하거나 하나로 합치거나 하는 등의 작업을 말하는데, 이때는 데이터베이스의 스키마 버전 관리 및 적용의 맥락으로 쓰였다. 코드 형상관리를 깃으로 하는 것처럼, db 변경 사항은 migration tool으로 관리할 수 있다.

이번 실습에서는 golang-migrate를 사용하여 DB Migration을 진행하였다 (brew install 해서 사용)

https://github.com/golang-migrate/migrate/tree/master/cmd/migrate

 

db/migration 폴더를 만들고 아래 명령어를 통해 migration up / migration down 스크립트를 만들어주었다.

$ migrate create -ext sql -dir db/migration -seq init_schema

 

-- init_schema.up.sql

CREATE TABLE "accounts" (
  "id" bigserial PRIMARY KEY,
  "owner" varchar NOT NULL,
  "balance" bigint NOT NULL,
  "currency" varchar NOT NULL,
  "created_at" timestamptz NOT NULL DEFAULT (now())
);

CREATE TABLE "entries" (
  "id" bigserial PRIMARY KEY,
  "account_id" bigint,
  "amount" bigint NOT NULL,
  "created_at" timestamptz NOT NULL DEFAULT (now())
);

CREATE TABLE "transfers" (
  "id" bigserial PRIMARY KEY,
  "from_account_id" bigint,
  "to_account_id" bigint,
  "amount" bigint NOT NULL,
  "created_at" timestamptz NOT NULL DEFAULT (now())
);

CREATE INDEX ON "accounts" ("owner");

CREATE INDEX ON "entries" ("account_id");

CREATE INDEX ON "transfers" ("from_account_id");

CREATE INDEX ON "transfers" ("to_account_id");

CREATE INDEX ON "transfers" ("from_account_id", "to_account_id");

COMMENT ON COLUMN "entries"."amount" IS 'can be negative';

COMMENT ON COLUMN "transfers"."amount" IS 'must be positive';

ALTER TABLE "entries" ADD FOREIGN KEY ("account_id") REFERENCES "accounts" ("id");

ALTER TABLE "transfers" ADD FOREIGN KEY ("from_account_id") REFERENCES "accounts" ("id");

ALTER TABLE "transfers" ADD FOREIGN KEY ("to_account_id") REFERENCES "accounts" ("id");

 

-- init_schema.down.sql

DROP TABLE IF EXISTS entries;
DROP TABLE IF EXISTS transfers;
DROP TABLE IF EXISTS accounts;

 

위 스크립트를 사용하고 있는 postgres에 적용하기 위해 아래 명령 사용 (postgres container가 기본적으로 ssl을 지원하지 않기 때문에 sslmode=disable 파라미터 적기)

$ migrate -path 마이그레이션업스크립트위치 -database "디비URL?sslmode=disable" -verbose up
$ migrate -path 마이그레이션다운스크립트위치 -database "디비URL?sslmode=disable" -verbose down