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

AWS Graviton ARM 인스턴스에서 발생하는 DPI-1047 에러와 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

이 글 공유𝕏f

댓글