본문 바로가기
카테고리 없음

Rust와 데이터베이스 연동 | Diesel을 이용한 예제

by mystory55801 2025. 6. 9.

Rust에서 데이터베이스를 사용하려면? Diesel을 소개합니다

Rust는 성능과 안전성을 제공하는 시스템 프로그래밍 언어이지만, 웹 개발이나 애플리케이션 개발 시 데이터베이스 연동도 필수적입니다. Rust에서 가장 널리 사용되는 ORM(Object Relational Mapping) 도구 중 하나는 Diesel입니다.

Diesel은 Rust스러운 타입 안정성과 컴파일 타임 검사를 제공하여 런타임 에러를 줄이고 생산성을 높여줍니다. 이 글에서는 Diesel을 사용해 PostgreSQL 데이터베이스에 연결하고, 간단한 CRUD 예제를 구현해 보겠습니다.

환경 준비: Diesel 설치 및 설정

먼저, Diesel CLI를 설치하고 프로젝트를 초기화해야 합니다.


$ cargo install diesel_cli --no-default-features --features postgres

Diesel CLI는 마이그레이션 관리 및 데이터베이스 초기화를 도와주는 도구입니다. PostgreSQL을 사용하므로 해당 feature를 명시합니다.

다음으로, Cargo.toml 파일에 필요한 의존성을 추가합니다.


[dependencies]
diesel = { version = "2.1", features = ["postgres"] }
dotenvy = "0.15"

dotenvy.env 파일에 설정된 DB 정보를 읽기 위해 사용됩니다.

데이터베이스 초기화 및 마이그레이션

Diesel CLI를 사용해 데이터베이스를 초기화합니다.


$ diesel setup

그 전에 .env 파일을 생성하고 다음 내용을 추가합니다:


DATABASE_URL=postgres://postgres:password@localhost/mydb

그리고 Diesel 마이그레이션을 생성합니다:


$ diesel migration generate create_users

마이그레이션 폴더에 생성된 up.sql과 down.sql 파일에 아래 SQL을 작성합니다:


-- up.sql
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name VARCHAR NOT NULL,
    email VARCHAR NOT NULL UNIQUE
);

-- down.sql
DROP TABLE users;

마이그레이션 적용:


$ diesel migration run

스키마 및 모델 정의

Diesel은 Rust 코드와 DB 스키마를 연결하기 위해 매크로 기반 구조를 사용합니다. 먼저 schema.rs를 자동 생성합니다.


$ diesel print-schema > src/schema.rs

이제 models.rs 파일에 사용자 모델을 정의합니다.


use diesel::prelude::*;
use crate::schema::users;

#[derive(Queryable)]
pub struct User {
    pub id: i32,
    pub name: String,
    pub email: String,
}

#[derive(Insertable)]
#[diesel(table_name = users)]
pub struct NewUser<'a> {
    pub name: &'a str,
    pub email: &'a str,
}

DB 연결 설정 및 삽입 함수 작성

DB 연결 및 삽입 기능을 main.rs에 작성해보겠습니다.


mod schema;
mod models;

use diesel::prelude::*;
use dotenvy::dotenv;
use std::env;
use models::{User, NewUser};

fn establish_connection() -> PgConnection {
    dotenv().ok();
    let db_url = env::var("DATABASE_URL").expect("DATABASE_URL not set");
    PgConnection::establish(&db_url).expect("DB 연결 실패")
}

fn create_user(conn: &mut PgConnection, name: &str, email: &str) -> User {
    use schema::users;

    let new_user = NewUser { name, email };

    diesel::insert_into(users::table)
        .values(&new_user)
        .returning((users::id, users::name, users::email))
        .get_result(conn)
        .expect("삽입 실패")
}

fn main() {
    let mut conn = establish_connection();
    let user = create_user(&mut conn, "Alice", "alice@example.com");
    println!("새 사용자: {} ({})", user.name, user.email);
}

전체 프로젝트 구조 요약


├── src
│   ├── main.rs
│   ├── models.rs
│   ├── schema.rs
├── migrations
│   ├── create_users/
│       ├── up.sql
│       ├── down.sql
├── .env
├── Cargo.toml

이 구조는 Diesel과 PostgreSQL을 사용한 Rust 프로젝트의 기본 뼈대입니다.

결론: Rust에서 안전하게 DB 다루기

Diesel은 Rust의 타입 시스템을 활용하여 런타임 에러를 컴파일 타임에 잡을 수 있는 ORM입니다. 마이그레이션 시스템, 쿼리 빌더, 자동 스키마 생성을 통해 효율적이고 안전한 데이터베이스 연동이 가능합니다.

이 글에서 살펴본 예제는 기본적인 CRUD 중 생성(Create)에 해당하며, 이후 조회(Read), 수정(Update), 삭제(Delete)도 Diesel의 쿼리 빌더 문법을 통해 간단히 구현할 수 있습니다.

실전 웹 개발에서는 actix-web 또는 axum 같은 웹 프레임워크와 함께 사용하면 강력한 백엔드 API를 구성할 수 있습니다.