Nuxt 를 배워보자

Nuxt.js에서 MariaDB와 연결해 SELECT 데이터 리턴하기

_Blue_Sky_ 2025. 3. 9. 13:28
728x90

 
 
안녕하세요, Nuxt 개발자 여러분! 이번에는 Nuxt 3의 서버 핸들러(defineEventHandler)에서 MariaDB 데이터베이스에 연결하고, SELECT 쿼리를 실행해 결과를 클라이언트에 리턴하는 방법을 알아보겠습니다. MariaDB는 MySQL과 호환되는 오픈소스 데이터베이스로, Node.js 환경에서 쉽게 통합할 수 있습니다. 단계별로 상세히 설명할게요!
1. 기본 환경 설정
MariaDB에서 데이터를 가져오려면 먼저 프로젝트에 데이터베이스 연결 라이브러리를 설치하고, Nuxt의 서버 환경에서 이를 사용해야 합니다.
1.1. 프로젝트 구조
 
my-nuxt-project/
├── pages/
│   └── index.vue
├── server/
│   └── api/
│       └── getData.js
├── nuxt.config.ts
└── package.json
1.2. 의존성 설치
MariaDB와 연결하려면 mysql2 패키지를 사용하겠습니다(mariadb 패키지도 가능하지만, mysql2가 더 널리 사용됨). 터미널에서 설치합니다:
 
npm install mysql2
  • mysql2: MariaDB와 MySQL을 지원하는 Node.js 드라이버로, Promise 기반 비동기 작업을 제공합니다.
1.3. MariaDB 준비
로컬 또는 원격에 MariaDB 서버가 실행 중이어야 합니다. 예를 들어:
  • 데이터베이스: mydb
  • 테이블: users (컬럼: id, name, email)
  • 샘플 데이터:
    CREATE TABLE users (
      id INT AUTO_INCREMENT PRIMARY KEY,
      name VARCHAR(255),
      email VARCHAR(255)
    );
    INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com'), ('Bob', 'bob@example.com');
MariaDB가 준비되었다고 가정하고 진행하겠습니다.
2. 서버 API 작성: MariaDB 연결 및 SELECT
server/api/getData.js 파일에서 MariaDB에 연결하고, SELECT 쿼리를 실행해 데이터를 리턴합니다.
 

 

 
 
2.1. 코드 예시
 
import mysql from 'mysql2/promise';

export default defineEventHandler(async (event) => {
  // 데이터베이스 연결 설정
  const dbConfig = {
    host: 'localhost',       // MariaDB 호스트
    user: 'root',            // MariaDB 사용자 이름
    password: 'yourpassword', // MariaDB 비밀번호
    database: 'mydb',        // 사용할 데이터베이스
  };

  let connection;

  try {
    // MariaDB 연결
    connection = await mysql.createConnection(dbConfig);

    // SELECT 쿼리 실행
    const [rows] = await connection.execute('SELECT * FROM users');

    // 결과 리턴
    return {
      success: true,
      data: rows,
    };
  } catch (error) {
    // 에러 처리
    return {
      success: false,
      error: '데이터 조회 실패',
      details: error.message,
    };
  } finally {
    // 연결 종료
    if (connection) await connection.end();
  }
});
코드 설명:
  • mysql.createConnection: MariaDB와 연결을 생성합니다. mysql2/promise를 사용해 비동기 처리를 쉽게 합니다.
  • connection.execute: SELECT * FROM users 쿼리를 실행. [rows]는 쿼리 결과를 배열로 반환합니다.
  • 리턴 형식: 성공 시 { success: true, data: [...] }, 실패 시 에러 메시지를 포함한 객체를 리턴.
  • finally 블록: 연결을 안전하게 종료해 리소스 누수를 방지.
2.2. 동작 확인
  • npm run dev로 Nuxt 개발 서버를 실행합니다.
  • 브라우저에서 http://localhost:3000/api/getData에 접속하면 JSON 응답을 확인할 수 있습니다:
    {
      "success": true,
      "data": [
        { "id": 1, "name": "Alice", "email": "alice@example.com" },
        { "id": 2, "name": "Bob", "email": "bob@example.com" }
      ]
    }
3. 프론트엔드에서 데이터 사용
pages/index.vue에서 API를 호출해 데이터를 표시합니다.
 
<template>
  <div>
    <h1>MariaDB 사용자 목록</h1>
    <ul>
      <li v-for="user in users" :key="user.id">
        {{ user.name }} ({{ user.email }})
      </li>
    </ul>
    <button @click="fetchData">데이터 가져오기</button>
  </div>
</template>

<script setup>
import { ref } from 'vue';

const users = ref([]);

const fetchData = async () => {
  const response = await $fetch('/api/getData');
  if (response.success) {
    users.value = response.data;
  } else {
    console.error(response.error, response.details);
  }
};
</script>
  • $fetch: Nuxt의 기본 HTTP 클라이언트로 API 호출.
  • users.value: 응답 데이터를 반영해 화면에 렌더링.
4. 개선: 연결 풀 사용
위 예시는 요청마다 연결을 생성하고 종료하는데, 실제 프로덕션 환경에서는 비효율적입니다. mysql2의 풀(Pool)을 사용하면 연결을 재사용해 성능을 높일 수 있습니다.
4.1. 연결 풀 설정
server/api/getData.js를 다음과 같이 수정합니다
 
import mysql from 'mysql2/promise';

// 연결 풀 생성 (전역으로 재사용)
const pool = mysql.createPool({
  host: 'localhost',
  user: 'root',
  password: 'yourpassword',
  database: 'mydb',
  connectionLimit: 10, // 최대 연결 수
});

export default defineEventHandler(async (event) => {
  try {
    // 풀에서 연결 가져오기
    const connection = await pool.getConnection();

    // 쿼리 실행
    const [rows] = await connection.execute('SELECT * FROM users');

    // 연결 해제 (풀로 반환)
    connection.release();

    return {
      success: true,
      data: rows,
    };
  } catch (error) {
    return {
      success: false,
      error: '데이터 조회 실패',
      details: error.message,
    };
  }
});
  • createPool: 연결 풀을 생성해 요청마다 새 연결을 만드는 대신 기존 연결을 재사용.
  • getConnection: 풀에서 연결을 가져옴.
  • release: 연결을 종료하지 않고 풀에 반환.

 

728x90
 

const [rows] = await connection.execute('SELECT * FROM users');const rows = await connection.execute('SELECT * FROM users');의 차이는 mysql2/promise가 반환하는 값의 구조에서 비롯됩니다.

  • const [rows] = await ...: execute[rows, fields] 배열을 반환합니다. rows는 쿼리 결과(레코드 배열), fields는 메타데이터(컬럼 정보)입니다. [rows]는 구조 분해 할당으로 첫 번째 요소(rows)만 추출합니다.
  • const rows = await ...: 전체 [rows, fields] 배열을 rows 변수에 할당합니다. 결과적으로 rows[0]으로 데이터에 접근해야 합니다.
차이점 요약:
  • 첫 번째는 바로 데이터(rows)를 얻음.
  • 두 번째는 [데이터, 메타데이터]를 통째로 받아 추가 접근(rows[0])이 필요.
추천: fields가 필요 없으면 첫 번째 방식([rows])이 더 깔끔합니다.
 
4.2. 주의
Nuxt의 개발 모드(npm run dev)에서는 HMR(Hot Module Replacement)로 인해 모듈이 재로드될 수 있으니, 풀을 전역으로 관리하거나 별도 파일로 분리하는 것이 좋습니다.
5. 환경 변수 사용
하드코딩된 DB 설정(host, user, password)은 보안상 좋지 않습니다. .env 파일과 nuxt.config.ts로 환경 변수를 설정하세요.
5.1. .env 파일
 
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=yourpassword
DB_NAME=mydb
5.2. nuxt.config.ts
 
export default defineNuxtConfig({
  runtimeConfig: {
    dbHost: process.env.DB_HOST,
    dbUser: process.env.DB_USER,
    dbPassword: process.env.DB_PASSWORD,
    dbName: process.env.DB_NAME,
  },
});
5.3. API에서 사용
 
import mysql from 'mysql2/promise';

export default defineEventHandler(async (event) => {
  const config = useRuntimeConfig();
  const dbConfig = {
    host: config.dbHost,
    user: config.dbUser,
    password: config.dbPassword,
    database: config.dbName,
  };

  let connection;
  try {
    connection = await mysql.createConnection(dbConfig);
    const [rows] = await connection.execute('SELECT * FROM users');
    return { success: true, data: rows };
  } catch (error) {
    return { success: false, error: error.message };
  } finally {
    if (connection) await connection.end();
  }
});
  • useRuntimeConfig: Nuxt의 런타임 설정을 가져옴.
6. 주의사항
  • 보안: SELECT 쿼리에 사용자 입력을 사용할 경우 SQL 인젝션을 방지하려면 매개변수화된 쿼리(?)를 사용하세요:
    await connection.execute('SELECT * FROM users WHERE id = ?', [userId]);
  • 성능: 대량 데이터 조회 시 LIMIT/OFFSET으로 페이징을 구현하세요.
  • 배포: Vercel 같은 서버리스 환경에서는 풀 대신 단일 연결을 고려해야 할 수 있습니다.
마무리
Nuxt의 defineEventHandler에서 MariaDB 데이터를 조회하려면 mysql2로 연결하고, SELECT 결과를 JSON으로 리턴하면 됩니다. 연결 풀과 환경 변수를 사용하면 더 안전하고 효율적인 코드를 작성할 수 있어요. 이제 여러분의 Nuxt 앱에서 DB 데이터를 자유롭게 활용해보세요!
 
728x90