From 217e215e5487b53db7d64fe3d809c47289cd83ae Mon Sep 17 00:00:00 2001 From: dujinkim Date: Wed, 28 May 2025 00:30:18 +0000 Subject: (김준회) 오라클 DB 연결을 위한 처리 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/oracle-db/README.md | 134 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/oracle-db/db.ts | 69 +++++++++++++++++++++++++ 2 files changed, 203 insertions(+) create mode 100644 lib/oracle-db/README.md create mode 100644 lib/oracle-db/db.ts (limited to 'lib/oracle-db') diff --git a/lib/oracle-db/README.md b/lib/oracle-db/README.md new file mode 100644 index 00000000..ed59cf2e --- /dev/null +++ b/lib/oracle-db/README.md @@ -0,0 +1,134 @@ +# oracledb / knex.js + +필요로 하는 oracle DB Select 대상이 있어 작성. + +## 주의점 + +1. 클라이언트 사이드에서 직접 호출할 수 없음 +2. js require 는 필요한 것만 가져와야 하는데, webpack이나 turbopack이 이를 지원하지 않음. + +- oracledb 및 knex에서 사용하지 않는 의존성들은 무시해야 하는데, 항상 번들링하려고 함. +- 없는 의존성을 번들링하려고 하니 문제가 발생함. + +### 문제1 해결하기 + +client 컴포넌트에서 oracledb / knex.js 라이브러리를 직접 사용하는 경우, fs 등 node 에 포함된 서버 라이브러리를 처리할 수 없음. +서버측 함수를 클라측에서 호출하는 문제이므로 여러 해결 방법이 있음. 권장되는 방식은 서버 액션으로 분리하는 것임. + +1. (추천) 서버 액션으로 분리하기 +2. API 호출로 분리하기 +3. 커스텀 훅 만들어서 서버측 사이클 만들기 + +### 문제2 해결하기 + +[관련 깃허브 이슈](https://github.com/oracle/node-oracledb/issues/1691) + +next.js 설정을 변경해야 함. +사용하지 않는 의존성들에 대해서는 resolveAlias를 추가해 에러를 던지지 않도록 처리하면 됨. + +참고: + +```ts +import type { NextConfig } from "next"; + +const nextConfig: NextConfig = { + webpack: (config) => { + // turbo의 resolveAlias와 동일한 설정을 webpack에 적용 + config.resolve.alias = { + ...config.resolve.alias, + '@azure/app-configuration': false, + '@azure/identity': false, + '@azure/keyvault-secrets': false, + 'oci-common': false, + 'oci-objectstorage': false, + 'oci-secrets': false, + // knex 관련 데이터베이스 드라이버들 + 'better-sqlite3': false, + 'mysql': false, + 'mysql2': false, + 'pg-query-stream': false, + 'sqlite3': false, + 'tedious': false, + }; + + return config; + }, + experimental: { + turbo: { + resolveAlias: { + '@azure/app-configuration': 'data:text/javascript,export default {};', + '@azure/identity': 'data:text/javascript,export default {};', + '@azure/keyvault-secrets': 'data:text/javascript,export default {};', + 'oci-common': 'data:text/javascript,export default {};', + 'oci-objectstorage': 'data:text/javascript,export default {};', + 'oci-secrets': 'data:text/javascript,export default {};', + // knex 관련 데이터베이스 드라이버들 + 'better-sqlite3': 'data:text/javascript,export default {};', + 'mysql': 'data:text/javascript,export default {};', + 'mysql2': 'data:text/javascript,export default {};', + 'pg-query-stream': 'data:text/javascript,export default {};', + 'sqlite3': 'data:text/javascript,export default {};', + 'tedious': 'data:text/javascript,export default {};', + }, + } + }, +}; + +export default nextConfig; +``` + +## oracledb / knex.js 사용 방법 + +1. oracledb로 SQL 직접 사용하기 + +```ts + // Oracle DB 연결 설정 + const connection = await oracledb.getConnection({ + user: process.env.ORACLE_USER, + password: process.env.ORACLE_PASSWORD, + connectString: process.env.ORACLE_CONNECTION_STRING + + }); + + // 쿼리 수행 + const result = await connection.execute('SELECT 1 FROM DUAL'); + + // 연결 종료 + await connection.close(); +``` + +2. knex.js에서 SQL 직접 사용하기 + +```ts +export const oracleKnex = knex({ + client: 'oracledb', + connection: { + user: process.env.ORACLE_USER, + password: process.env.ORACLE_PASSWORD, + connectString: process.env.ORACLE_CONNECTION_STRING, + }, + pool: { min: 0, max: 5 } +}); + +sql = 'SELECT 1 FROM DUAL;' +const result = await oracleKnex.raw(sql); +``` + +3. knex.js에서 쿼리빌더 사용하기 + +```ts +export const oracleKnex = knex({ + client: 'oracledb', + connection: { + user: process.env.ORACLE_USER, + password: process.env.ORACLE_PASSWORD, + connectString: process.env.ORACLE_CONNECTION_STRING, + }, + pool: { min: 0, max: 5 } +}); + +const result = await knex +.qb +.select('column1', 'column2', 'column3') +.from('table_name') +``` diff --git a/lib/oracle-db/db.ts b/lib/oracle-db/db.ts new file mode 100644 index 00000000..62321df0 --- /dev/null +++ b/lib/oracle-db/db.ts @@ -0,0 +1,69 @@ +import knex from 'knex'; +// import oracledb from 'oracledb'; +// eslint-disable-next-line @typescript-eslint/no-require-imports +const oracledb = require('oracledb'); + +// Knex Oracle 연결 생성 +export const oracleKnex = knex({ + client: 'oracledb', + connection: { + user: process.env.ORACLE_USER, + password: process.env.ORACLE_PASSWORD, + connectString: process.env.ORACLE_CONNECTION_STRING, + }, + pool: { min: 0, max: 5 } +}); + +// OracleDB 직접 연결 생성 함수 +export async function getOracleConnection() { + try { + const connection = await oracledb.getConnection({ + user: process.env.ORACLE_USER, + password: process.env.ORACLE_PASSWORD, + connectString: process.env.ORACLE_CONNECTION_STRING + }); + + return connection; + } catch (error) { + console.error('Oracle DB 연결 오류:', error); + throw error; + } +} + +// 연결을 테스트하는 함수 +export async function testOracleConnection() { + try { + const connection = await getOracleConnection(); + const result = await connection.execute('SELECT 1 FROM DUAL'); + await connection.close(); + return { + success: true, + message: 'Oracle DB 연결 성공', + data: result.rows + }; + } catch (error: unknown) { + return { + success: false, + message: 'Oracle DB 연결 실패', + error: error instanceof Error ? error.message : '알 수 없는 오류' + }; + } +} + +// Knex를 사용하여 Oracle 연결 테스트 +export async function testKnexOracleConnection() { + try { + const result = await oracleKnex.raw('SELECT 1 FROM DUAL'); + return { + success: true, + message: 'Knex Oracle DB 연결 성공', + data: result + }; + } catch (error: unknown) { + return { + success: false, + message: 'Knex Oracle DB 연결 실패', + error: error instanceof Error ? error.message : '알 수 없는 오류' + }; + } +} \ No newline at end of file -- cgit v1.2.3