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
'Nuxt 를 배워보자' 카테고리의 다른 글
Nuxt.js로 메인 화면과 5개의 탭으로 구성된 블로그 예제 만들기 (0) | 2025.03.22 |
---|---|
Nuxt에서 RESTful API 호출: 다양한 방법 총정리 (0) | 2025.03.22 |
Nuxt.js에서 defineEventHandler로 Oracle DB 데이터 조회하기 (0) | 2025.03.09 |
Nuxt.js 프로젝트에서 로컬 파일 시스템(예: 텍스트 파일, 이미지, JSON 등)에 접근하는 방법 (0) | 2025.03.09 |
Nuxt.js와 Axios로 데이터 그리드 구현 및 클릭 시 input에 바인딩하기 (0) | 2025.03.04 |