이번 글에서는 Oracle의 Pro*C를 사용하여 데이터 접근 계층을 구축하고, 이를 C#에서 호출하여 활용하는 방법에 대해 다룰 것입니다. Pro*C는 C 언어에 SQL 문을 통합할 수 있는 Oracle의 특별한 확장입니다. 이를 통해 C언어 기반의 프론트엔드 애플리케이션과 데이터베이스 간의 데이터 흐름을 원활하게 처리할 수 있습니다. 본 글에서는 Pro*C의 기본 개념부터, C#과의 연동 방법까지 단계별로 살펴보겠습니다.
1. Pro*C란?
Pro*C는 Oracle 데이터베이스와 C 프로그램 간의 데이터 처리를 가능하게 하는 도구입니다. 프로그래머는 SQL 문을 C 코드 내에 직접 삽입할 수 있으며, 이를 통해 데이터베이스와의 연동을 수월하게 처리할 수 있습니다.
1.1 Pro*C의 장점
- SQL 문이 C 코드 내에 통합되어 있어 데이터 접근이 용이하다.
- 성능 최적화가 가능하다 (C 언어의 성능을 활용).
- Oracle 데이터베이스와의 밀접한 통합.
2. Pro*C 환경 설정
Pro*C를 사용하기 위해서는 Oracle Client 및 Pro*C 실행 환경을 설정해야 합니다. 이 과정은 운영체제 및 Oracle 버전에 따라 다를 수 있습니다. 아래 절차를 따르면 Pro*C 환경을 설정할 수 있습니다.
2.1 Oracle Client 설치
Oracle Client가 설치된 후, Pro*C가 포함된 SDK를 설치해야 합니다. 설치 후, 환경 변수 PATH에 Oracle의 bin 디렉토리를 추가하세요.
2.2 Pro*C 컴파일러 설정
Pro*C 컴파일러가 정상적으로 작동하는지 확인하기 위해 간단한 테스트 코드를 작성합니다.
/* Sample.pcc */
#include <stdio.h>
#include <sqlca.h>
void main() {
EXEC SQL BEGIN DECLARE SECTION;
char username[20], password[20];
EXEC SQL END DECLARE SECTION;
// 사용자 입력 받기
printf("Username: ");
scanf("%s", username);
printf("Password: ");
scanf("%s", password);
EXEC SQL CONNECT :username IDENTIFIED BY :password;
// 연결 종료
EXEC SQL COMMIT;
EXEC SQL DISCONNECT;
}
3. C#에서 Pro*C 함수 호출하기
C#에서 Pro*C로 작성한 데이터 접근 로직을 호출하기 위해서 다음과 같은 방법을 사용합니다. C#과 C 프로그램 간의 호출을 위해서 DLL을 생성하고 이를 C#에서 참조하는 구조를 취합니다.
3.1 DLL 생성하기
Pro*C 코드로부터 DLL을 생성하는 과정은 아래와 같습니다.
// Pro*C 코드가 Compile하고 Link하여 DLL 생성
proc cc Sample.pcc -o Sample.dll
3.2 C#에서 DLL 참조하기
C# 프로젝트에서 생성된 Sample.dll을 참조합니다. 이를 위해 Visual Studio에서 “참조 추가”를 통해 DLL을 선택합니다.
3.3 C#에서 호출하기
C# 코드에서 P/Invoke를 사용하여 Pro*C 함수 호출을 위해 다음과 같이 작성합니다.
using System;
using System.Runtime.InteropServices;
class Program {
[DllImport("Sample.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void ConnectToDatabase();
static void Main(string[] args) {
ConnectToDatabase();
Console.WriteLine("데이터베이스 연결 완료");
}
}
4. 데이터 접근 로직 작성하기
Pro*C를 사용하여 데이터를 검색하고 삽입하는 로직을 작성해봅시다.
4.1 데이터 검색 로직
다음 코드는 테이블에서 데이터를 검색하는 예제입니다.
EXEC SQL BEGIN DECLARE SECTION;
char name[50];
int id;
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT name INTO :name FROM employees WHERE id = :id;
printf("Employee Name: %s\n", name);
4.2 데이터 삽입 로직
아래 코드는 새로운 데이터를 삽입하는 예제입니다.
EXEC SQL BEGIN DECLARE SECTION;
char name[50];
int id;
EXEC SQL END DECLARE SECTION;
// 사용자로부터 입력받음
printf("Enter ID: ");
scanf("%d", &id);
printf("Enter Name: ");
scanf("%s", name);
EXEC SQL INSERT INTO employees(id, name) VALUES(:id, :name);
EXEC SQL COMMIT;
5. 예외 처리 및 오류 관리
Pro*C 코드에서 발생할 수 있는 오류를 관리하기 위해 SQLCA 구조체를 활용합니다. SQLCA는 SQL 문 실행 결과와 에러 상태를 포함하는 구조체입니다.
EXEC SQL SELECT COUNT(*) INTO :count FROM employees;
if (sqlca.sqlcode != 0) {
printf("오류 발생: %d\n", sqlca.sqlcode);
}
6. C#에서 예외 처리
C#에서 DLL을 호출할 때 발생하는 예외를 핸들링하는 방법에 대해 설명합니다. 예외 발생 시 적절한 메시지를 사용자에게 보여줄 수 있도록 조치합니다.
try {
ConnectToDatabase();
} catch (System.Exception ex) {
Console.WriteLine("오류 발생: " + ex.Message);
}
7. 성능 최적화
Pro*C와 C#을 활용하여 구축한 데이터 접근 계층의 성능을 높이기 위한 다양한 방법을 소개합니다. SQL 쿼리를 최적화하고 커넥션 풀을 사용하는 등의 전략이 포함됩니다.
7.1 SQL 쿼리 최적화
효율적인 쿼리를 작성하기 위해 인덱스 활용, JOIN 사용 시 최적화된 연산 등을 고려해야 합니다.
7.2 커넥션 풀 사용하기
C# 애플리케이션에서는 ADO.NET의 Connection Pooling 기능을 사용하여 데이터베이스 연결을 효율적으로 관리할 수 있습니다.
8. 결론
Pro*C와 C#을 이용한 데이터 접근 계층 구축은 데이터베이스와의 상호작용을 효율적으로 처리할 수 있게 해줍니다. 이제 여러분은 Pro*C의 기본 개념부터 C#과의 연동, حتى 성능 최적화까지 데이터 접근 계층을 구축하는 방법을 익혔습니다. 이를 통해 견고하고 효율적인 애플리케이션을 개발할 수 있기를 바랍니다.