2026년 7월 21일 화요일

src/main.rs



use std::path::Path;
use tokio::fs::File;
use tokio::io::AsyncWriteExt; // 비동기 쓰기를 위한 트레이트

mod gspread;
use crate::gspread::{SpreadsheetExporter, create_hub};

/// 생성된 SQL 문을 비동기적으로 .sql 파일에 저장
async fn save_sql_to_file_async(sql: &str, file_name: &str) -> tokio::io::Result<()> {
    // 1. 파일 경로 설정
    let path = Path::new(file_name);

    // 2. 비동기 파일 생성 (Tokio fs 사용)
    let mut file = File::create(path).await?;

    // 3. 비동기 데이터 쓰기 (전체 데이터를 안전하게 기록)
    file.write_all(sql.as_bytes()).await?;

    // 4. 버퍼 비우기 및 동기화 (권장 관례)
    file.flush().await?;

    println!("✅ [Async] SQL 파일 저장 완료: {:?}", path.display());
    Ok(())
}

#[tokio::main]
async fn main() -> tokio::io::Result<()> {
    rustls::crypto::aws_lc_rs::default_provider()
        .install_default()
        .expect("Failed to install crypto provider");

    let hub = create_hub("./sheets-xxxxxx-xxxx.json").await;
    let exporter =
        SpreadsheetExporter::new(hub, "xxxxxx-xx-xxxxxx".into());

    let schema = exporter.export_schema().await;
    save_sql_to_file_async(&schema, "output_schema.sql").await?;

    let data = exporter.export_data().await;
    save_sql_to_file_async(&data, "output_data.sql").await?;

    println!("{}\n{}", schema, data);

    Ok(())
}


database.py

import os from contextlib import contextmanager # contextmanager 임포트 from typing import Generator from dotenv...