관계형 데이터베이스 접근
관계형 데이터베이스 접근 (Accessing relational databases)
Go를 쓰면 앱 안에 아주 다양한 데이터베이스와 데이터 접근 방식을 담아낼 수 있어요. 이 섹션의 주제들은 표준 라이브러리의 database/sql 패키지를 사용해 관계형 데이터베이스에 접근하는 방법을 설명합니다.
출처: Go 공식 문서
시작 전에 기본기를 다지고 싶다면 튜토리얼 Accessing a relational database부터 봐도 좋아요. Go는 그 외에도 관계형 데이터베이스에 더 높은 수준으로 접근하게 해주는 ORM 라이브러리, 그리고 관계형이 아닌 NoSQL 데이터 저장소까지 여러 데이터 접근 기술을 지원합니다.
- ORM 라이브러리.
database/sql패키지가 저수준의 데이터 접근 로직을 담당한다면, ORM을 쓰면 그보다 더 높은 추상화 수준에서 데이터 저장소에 접근할 수 있어요. Go에서 널리 쓰이는 두 ORM 라이브러리는 GORM과 ent입니다. - NoSQL 데이터 저장소. Go 커뮤니티는 MongoDB, Couchbase를 포함한 대부분의 NoSQL 데이터 저장소용 드라이버를 만들어 두었어요. pkg.go.dev에서 더 찾아볼 수 있습니다.
지원되는 데이터베이스 관리 시스템
Go는 MySQL, Oracle, Postgres, SQL Server, SQLite 등 가장 흔한 관계형 데이터베이스 관리 시스템을 모두 지원합니다. 전체 드라이버 목록은 SQLDrivers 페이지에서 확인할 수 있어요.
쿼리 실행 또는 데이터 변경 함수
database/sql 패키지에는 실행하려는 데이터베이스 작업 종류에 맞게 설계된 함수들이 들어 있어요. 예를 들어 Query나 QueryRow로 쿼리를 실행할 수 있지만, 단 한 줄의 결과만 기대하는 경우에는 QueryRow가 딱 맞죠 — 한 줄짜리 sql.Rows를 돌려주는 오버헤드를 생략할 수 있거든요. INSERT, UPDATE, DELETE 같은 SQL 문으로 데이터베이스를 변경할 때는 Exec 함수를 쓰면 됩니다. 더 자세한 내용은 아래 문서를 참고하세요.
트랜잭션 (Transactions)
sql.Tx를 통해 데이터베이스 작업을 트랜잭션으로 실행하는 코드를 작성할 수 있어요. 트랜잭션에서는 여러 작업을 함께 수행하고, 마지막에 모든 변경을 한 번에 적용하는 commit을 하거나, 변경을 모두 버리는 rollback으로 마무리합니다. 트랜잭션에 대한 자세한 내용은 Executing transactions 문서를 참고하세요.
쿼리 취소 (Query cancellation)
클라이언트 연결이 끊기거나 작업이 원하는 시간보다 오래 걸리는 것처럼, 데이터베이스 작업을 취소하고 싶을 때가 있죠. 그럴 때 context.Context를 사용할 수 있습니다. Context를 인자로 받는 database/sql 함수를 쓰면 작업에 타임아웃이나 데드라인을 지정할 수 있고, 애플리케이션 전체로 SQL 문을 실행하는 함수까지 취소 요청을 전파해 더 이상 필요 없는 리소스를 정리할 수도 있어요. 자세한 내용은 Canceling in-progress operations 문서를 참고하세요.
관리되는 커넥션 풀 (Managed connection pool)
sql.DB 데이터베이스 핸들을 쓰면 코드의 필요에 따라 커넥션을 만들고 정리하는 내장 커넥션 풀과 연결되는 셈이에요. sql.DB를 통한 핸들이 Go에서 데이터베이스에 접근하는 가장 흔한 방법입니다. 자세한 내용은 Opening a database handle를 참고하세요.
database/sql 패키지가 커넥션 풀을 관리해 주지만, 더 세밀한 제어가 필요할 때는 Setting connection pool properties에서 설명하는 대로 커넥션 풀 속성을 설정할 수 있습니다.
단 하나의 커넥션을 독점으로 예약해야 하는 작업에는 database/sql이 제공하는 sql.Conn을 쓰면 돼요. sql.Tx로 트랜잭션을 쓰는 게 어울리지 않을 때 특히 유용합니다. 예를 들어 다음 같은 경우가 있어요.
- DDL로 스키마를 바꾸는 작업 — 여기엔 트랜잭션 의미론을 담은 로직이 포함될 수 있죠.
sql패키지의 트랜잭션 함수와 SQL 트랜잭션 문을 섞어 쓰는 건 좋지 않은 방법입니다. Executing transactions 문서에서 자세히 설명해요. - 임시 테이블을 만드는 쿼리 잠금 작업.
자세한 내용은 Using dedicated connections을 참고하세요.