[SQLAlchemy] AWS Graviton(ARM)에서 Python Oracle DB 연결 오류 DPI-1047 해결 | SQLAlchemy, oracledb
1. AWS EC2 ARM 아키텍처 변경 시 발생하는 이슈
최근 가성비 좋은 AWS Graviton(ARM/aarch64) 인스턴스로 교체하는 기업이 늘고 있습니다. 하지만 기존 x86_64 환경에서 잘 작동하던 Python 코드를 그대로 옮기면, Oracle DB 연동 시 DPI-1047 에러를 마주하게 됩니다.
이 에러가 발생하는 근본적인 원인과 최신 드라이버인 python-oracledb를 통한 완벽한 해결책을 정리하고자 합니다.
2. DPI-1047 에러란?
SQLAlchemy나 cx_Oracle을 통해 연결 시 발생하는 이 에러는 "Oracle Client 라이브러리를 찾을 수 없음"을 의미합니다.
sqlalchemy.exc.DatabaseError: (cx_Oracle.DatabaseError) DPI-1047: Cannot locate a 64-bit Oracle Client library:
"libclntsh.so: cannot open shared object file: No such file or directory".
3. (이유) 왜 ARM 서버에서만 발생할까?
이 문제는 서버 CPU 아키텍처와 라이브러리 간의 불일치 때문에 발생합니다.
- cx_Oracle의 의존성: 기존 cx_Oracle 드라이버는 C 기반의 Oracle Instant Client 라이브러리가 시스템에 설치되어 있어야만 동작합니다. (이렇게 Client설치해서 연동하는 방식을 Thick모드라 합니다)
- 아키텍처의 불일치: Oracle은 오랫동안 ARM(aarch64)용 Instant Client 라이브러리를 공식 지원하지 않았거나 설정이 매우 까다로웠습니다. 결국 x86_64 전용 라이브러리를 ARM 환경에서 로드하려다 보니 시스템이 이를 인식하지 못해 발생하는 아키텍처 불일치 문제입니다.
(Oracle DB는 CPU 아키텍처 외에도 설치할때 Ubuntu보다 RHEL이나 CentOS계열이 훨씬 편하기도 하는 등 여러 버전을 타기도 합니다. 그만큼 경험상 Oracle DB는 환경적인 요소에 영향을 많이 받았습니다)
4. 해결 방법 python-oracledb 'Thin' 모드
그림1. AWS Graviton ARM 인스턴스에서 발생하는 DPI-1047 에러와 python-oracledb Thin 모드
Oracle은 이러한 아키텍처 문제를 해결하기 위해 cx_Oracle의 후속작인 python-oracledb를 출시했습니다. 특히 이 드라이버의 Thin 모드는 ARM 서버에서 Python 서버운영시 필수 요소입니다. (Instant Client필요 없이 해당 라이브러리 내에서 연동하는 방식을 Thin모드라 합니다)
- Instant Client 미필요: C 라이브러리 의존성 없이 100% 순수 Python으로 재작성되었습니다.
- Architecture Agnostic: 아키텍처를 타지 않습니다. x86이든 ARM이든 동일하게 작동합니다. (그래서 요즘 ox_Oracle은 거의 사용하지 않고 oracledb만 사용한다고 합니다)
- 직접 통신: 시스템 라이브러리를 거치지 않고 Oracle Net Protocol을 통해 DB와 직접 대화합니다.
| 드라이버 | 특징 | 권장 환경 | SQLAlchemy URL 스키마 |
|---|---|---|---|
| cx_Oracle | C 라이브러리 기반 | x86_64 (레거시) | oracle+cx_oracle:// |
| oracledb | Thin 모드 지원 | ARM(aarch64), Cloud | oracle+oracledb:// |
4.1 SQLAlchemy 예제 및 설정
1. 라이브러리 설치
pip install oracledb
2. 코드 구현 예제
2.1 SQLAlchemy URL 연동
cx_Oracle사용시 아래와 같이 oracle+cx_oracle:// 로 시작하는 것을 확인할 수 있습니다.
# [x86_64 전용 / ARM에서는 에러 발생 확률 높음]
# 시스템의 libclntsh.so 파일을 찾아 헤매는 방식
SQLALCHEMY_DATABASE_URL = f"oracle+cx_oracle://{user}:{password}@{host}:{port}/?service_name={service_name}"
oracledb방식 (권장 방식 SQLAlchemy URL로 연동시)
from sqlalchemy import create_engine
# JSON/환경변수 로드 시 보이지 않는 공백 제거는 필수입니다.
user = db.get("user").strip()
password = db.get("password").strip()
host = db.get("host").strip()
port = db.get("port")
service_name = db.get("service_name").strip()
# python-oracledb Thin 모드용 URL 스키마 사용
SQLALCHEMY_DATABASE_URL = f"oracle+oracledb://{user}:{password}@{host}:{port}/?service_name={service_name}"
engine = create_engine(SQLALCHEMY_DATABASE_URL)
# 연결 테스트
with engine.connect() as conn:
print("Connected to Oracle DB successfully on ARM(aarch64) server!")
2.2 Native 연동 (Driver Library 호출)
1. cx_Oracle 방식 (전통적인 Thick 모드 방식)
C 라이브러리에 의존하기 때문에, 코드 레벨에서 라이브러리 경로를 초기화해주는 과정이 필요하며 아키텍처가 맞지 않으면 여기서 바로 에러가 터집니다. (cx_Oracle 방식: 복잡한 초기화)
import cx_Oracle
import os
# instantclinet를 불러와야 함
lib_dir = "/opt/oracle/instantclient_21_10"
try:
# 라이브러리 수동 초기화 (Thick 모드 필수 과정)
cx_Oracle.init_oracle_client(lib_dir=lib_dir)
except Exception as e:
print(f"라이브러리 로드 실패 (DPI-1047 발생): {e}")
# 접속 정보
dsn = cx_Oracle.makedsn("host", 1521, service_name="sn")
conn = cx_Oracle.connect(user="user", password="password", dsn=dsn)
2. python-oracledb (최신 Thin 모드 방식) - (권장 방식)
라이브러리 경로 지정 자체가 필요 없습니다. 아키텍처와 상관없이 순수 파이썬 코드로만 동작합니다.
import oracledb
try:
# 별도의 설정 없이 바로 연결 (기본이 Thin 모드)
conn = oracledb.connect(
user="user",
password="password",
host="host",
port=1521,
service_name="sn"
)
print("Thin 모드로 접속 성공!")
except Exception as e:
print(f"접속 실패: {e}")
보시다시피 cx_Oracle은 시스템에 설치된 Oracle Client 라이브러리를 직접 호출해야 하는 번거로움이 있지만, python-oracledb는 그런 과정이 완전히 생략됩니다. oracledb드라이버를 사용시 별도의 라이브러리 초기화 과정(init_oracle_client)이 전혀 필요 없으며 x86, ARM 아키텍처 상관없이 즉시 실행 가능합니다.
AWS EC2를 ARM 아키텍처로 사용시, Python-Oracle DB연동에 있어 python-oracledb 드라이버는 필수적인 요소입니다.
📦 블로그 이전 글입니다. 원본: taehyuklee.tistory.com/32
댓글