두 함수 db_connect_
와 db_connect
는 동일한 목적(데이터베이스 연결 풀 생성)을 가지고 있지만, 에러 처리 방식에서 큰 차이가 있습니다. 이 차이를 분석하고, Rust에서 Result
와 async/await
를 사용하는 방법에 대해 설명하겠습니다.
db_connect_
pub async fn db_connect_() -> PgPool {
dotenv().ok();
let url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set");
let pool = PgPoolOptions::new().connect(&url).await.expect("Failed to connect to the database");
info!("Connected to the database");
pool
}
expect
를 사용하여 에러 발생 시 프로그램을 즉시 종료합니다.std::env::var("DATABASE_URL").expect("DATABASE_URL must be set")
: 환경 변수가 없으면 프로그램이 패닉(panic) 상태로 종료됩니다.PgPoolOptions::new().connect(&url).await.expect("Failed to connect to the database")
: 데이터베이스 연결 실패 시 프로그램이 패닉 상태로 종료됩니다.PgPool
을 직접 반환합니다.db_connect
pub async fn db_connect() -> Result<PgPool, sqlx::Error> {
dotenv().ok();
let url = std::env::var("DATABASE_URL").map_err(|e| {
tracing::error!("Failed to read DATABASE_URL: {}", e);
sqlx::Error::Configuration(e.into())
})?;
let pool = PgPoolOptions::new()
.connect(&url)
.await
.map_err(|e| {
tracing::error!("Failed to connect to the database: {}", e);
e
})?;
info!("Connected to the database");
Ok(pool)
}
Result
를 사용하여 에러를 호출자에게 전달합니다.std::env::var("DATABASE_URL").map_err(...)
: 환경 변수가 없으면 에러를 변환하고 로깅합니다.PgPoolOptions::new().connect(&url).await.map_err(...)
: 데이터베이스 연결 실패 시 에러를 변환하고 로깅합니다.Result<PgPool, sqlx::Error>
를 반환합니다.Result
처리 방법Result
란?Result
는 Rust에서 에러 처리를 위한 열거형(enum)입니다.Result<T, E>
는 성공 시 Ok(T)
를, 실패 시 Err(E)
를 반환합니다.unwrap
:
Result
가 Ok
인 경우 값을 반환하고, Err
인 경우 패닉을 발생시킵니다.let url = std::env::var("DATABASE_URL").unwrap();
expect
:
unwrap
과 동일하지만, 패닉 메시지를 지정할 수 있습니다.let url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set");
?
연산자:
Result
가 Ok
인 경우 값을 반환하고, Err
인 경우 현재 함수에서 빠져나가 에러를 전파합니다.let url = std::env::var("DATABASE_URL")?;
map_err
:
Result
가 Err
인 경우 에러를 변환합니다.let url = std::env::var("DATABASE_URL").map_err(|e| sqlx::Error::Configuration(e.into()))?;
async/await
와 Result
async/await
란?async
는 비동기 함수를 정의할 때 사용합니다.await
는 비동기 함수의 결과를 기다릴 때 사용합니다.Result
와 함께 사용Result
를 반환할 수 있습니다.await
와 ?
를 함께 사용하여 비동기 작업의 에러를 처리할 수 있습니다.예:
pub async fn db_connect() -> Result<PgPool, sqlx::Error> {
let url = std::env::var("DATABASE_URL")?; // 동기 작업
let pool = PgPoolOptions::new().connect(&url).await?; // 비동기 작업
Ok(pool)
}
unwrap
또는 expect
let url = std::env::var("DATABASE_URL").unwrap();
?
연산자let url = std::env::var("DATABASE_URL")?;
map_err
let url = std::env::var("DATABASE_URL").map_err(|e| {
tracing::error!("Failed to read DATABASE_URL: {}", e);
sqlx::Error::Configuration(e.into())
})?;
db_connect_
:
expect
를 사용하여 에러 발생 시 프로그램이 종료됩니다.db_connect
:
Result
를 사용하여 에러를 호출자에게 전파합니다.map_err
를 사용하여 에러를 변환하고 로깅합니다.Rust에서의 에러 처리:
Result
를 사용하여 에러를 명시적으로 처리합니다.?
연산자를 사용하여 에러를 전파합니다.map_err
를 사용하여 에러를 변환하거나 로깅합니다.async/await
:
await
와 ?
를 함께 사용하여 비동기 작업의 에러를 처리합니다.이를 통해 Rust에서 안정적이고 유지보수 가능한 코드를 작성할 수 있습니다! 🚀