지난 글에서는 golang-migrate를 이용해 DB 버전을 관리하는 방법에 대해 알아보았다. 이번 글에서는 지난 글에서 예고한 대로 golang-migrate에 sqlc를 더해 DB 스키마 - Go언어 코드간 연동과 DB 마이그레이션을 동시에 진행하는 방법에 대해 소개하고자 한다.
사용 방법
1. 설정
사실 이부분을 제외하면 golang-migrate를 쓸 때와 크게 바뀌는 점이 없다. 우선 프로젝트의 루트에 sqlc 설정 파일인 sqlc.yaml파일을 다음과 같이 작성한다.
version: "2"
sql:
- schema: {마이그레이션 파일 경로}
queries: {쿼리 파일 경로}
engine: "postgresql"
...
sql의 schema 항목만 golang-migration에 쓰이는 마이그레이션 파일 경로로 잘 지정하고 나머지는 sqlc 공식 페이지를 참조해서 취향껏 작성하면 된다.
2. 마이그레이션 파일 작성
golang-migrate를 사용하듯이 진행하면 된다.
우선 위에서 지정했던 마이그레이션 경로에 들어가서 아래 커맨드를 실행해서 파일을 생성한다.
migrate create -ext sql -dir {마이그레이션 파일 경로} -seq {설명}
이후 생성된 두 파일에 각각 알맞는 sql 쿼리를 집어넣는다.
3. 마이그레이션 적용
golang-migrate CLI를 사용하여 데이터베이스에 마이그레이션을 적용한다.
migrate -source {마이그레이션 저장 폴더} -database {DB 주소} up
4. sqlc를 이용한 코드 생성
sqlc는 golang-migrate를 공식적으로 지원한다. 아래 명령어로 sqlc를 실행하면 해당 디렉토리 내의 모든 다운(Down) 마이그레이션 파일은 무시하고 모든 업(Up) 마이그레이션 파일을 순차적으로 읽어 최종 스키마 정보를 Go언어 코드로 반환한다.
sqlc generate
주의사항
golang-migrate를 통해 마이그레이션을 하면 반드시 4번 절차를 진행해야 Go언어 코드에 반영된다.
사소한 주의사항으로는 sqlc는 텍스트 기반(시스템 내에서 쓰는 정렬 방식)으로 파일의 순서를 정하는 반면 golang-migrate는 앞의 번호를 기반으로 파일의 순서를 정한다는 것이다. 이러한 특성으로 인해 자릿수가 다를 때 서로 순서를 다르게 인식할 위험이 있다. 예를 들어 10_migration_up.sql보다 9_migration_up.sql이 있다면 sqlc는 10번을, golang-migrate는 9번을 앞 순서로 인식할 것이다. 두 툴 모두 순서가 중요한 만큼 이는 치명적인 문제이다.
위의 문제에 관해서는 수동으로 파일을 생성한다면 앞에 고정된 자릿수가 되도록 0을 붙이는 식으로(두 방식 모두 000010번은 000009번보다 뒤이다.) 해결해야 한다. 다행히도 migrate create 명령어로 생성된 파일은 6자리 수가 되도록 앞에 0을 붙인다. 따라서 굳이 수동으로 파일을 생성하는 것보다 생성 명령어를 쓰는 것을 권장한다.
결론
golang-migrate와 sqlc를 함께 사용하여 데이터베이스 스키마의 버전 관리와 코드 생성을 동시에 진행하는 방법에 대해 알아보았다. 개발 생산성을 올리는 방법에는 여러가지가 있지만 새로운 자동화 도구를 쓰는 것이 필자의 경험상 체감이 잘되었다. 결국 문제는 이러한 도구가 있다는 것을 모른다는 것이다. 이 글은 절차에 관해서 생략된 부분도 있고 구체적인 예시가 아닌 명세 위주의 설명인지라 설명이 부실하다고 느낄 여지가 있다. 하지만 이 글을 읽고 go-migrate와 sqlc를 어떻게 쓰는지 검색하게 된다면, 그로써 이 글은 역할을 다했다고 생각한다.