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' 모드

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!")
Tip: JSON이나 .env 파일에서 정보를 불러올 때 눈에 보이지 않는 공백이나 줄바꿈(\n)이 포함되면 접속에 실패한 경우가 있었습니다. 예를 들어 비밀번호 마지막이 !와 같은 특수문자로 끝나는 경우. 따라서 마지막에 strip() 처리를 해주었습니다.
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 드라이버는 필수적인 요소입니다.