AWS Graviton(ARM)에서 Python Oracle 연결 오류 DPI-1047 해결 — python-oracledb Thin 모드
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 계열이 훨씬 편한 등 환경 요소에 영향을 많이 받는다.)
4. 해결 방법 — python-oracledb 'Thin' 모드
그림 1. 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이든 동일하게 작동한다. (그래서 요즘은
cx_Oracle을 거의 쓰지 않고oracledb만 사용한다고 한다.) - 직접 통신 — 시스템 라이브러리를 거치지 않고 Oracle Net Protocol로 DB와 직접 대화한다.
| 드라이버 | 특징 | 권장 환경 | SQLAlchemy URL 스키마 |
|---|---|---|---|
cx_Oracle |
C 라이브러리 기반 | x86_64 (레거시) | oracle+cx_oracle:// |
oracledb |
Thin 모드 지원 | ARM(aarch64), Cloud | oracle+oracledb:// |
먼저 라이브러리를 설치한다.
pip install oracledb
4.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()처리를 해줬다.
4.2 드라이버 직접(Native) 연동
① cx_Oracle 방식 (전통적인 Thick 모드) — C 라이브러리에 의존하므로 코드 레벨에서 라이브러리 경로를 초기화해야 하며, 아키텍처가 맞지 않으면 여기서 바로 에러가 터진다.
import cx_Oracle
import os
# Instant Client를 불러와야 함
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)
② python-oracledb 방식 (최신 Thin 모드 — 권장) — 라이브러리 경로 지정 자체가 필요 없다. 아키텍처와 상관없이 순수 Python 코드로만 동작한다.
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는 그 과정이 완전히 생략된다. 별도의 라이브러리 초기화(init_oracle_client)가 전혀 필요 없고, x86·ARM 아키텍처와 무관하게 즉시 실행된다.
AWS EC2를 ARM 아키텍처로 운영한다면, Python–Oracle DB 연동에서 python-oracledb 드라이버는 필수 요소다.
📦 이 글은 제가 운영하던 티스토리 블로그에서 옮겨온(migration) 글입니다. 원문: taehyuklee.tistory.com/32
댓글