프로젝트 대략적인 구조를 보면 backend
프로젝트 하위에 config
라는 이름의 프로젝트 루트 디렉토리가 있다. 해당 디렉토리에 모든 앱에서 사용할 공통 예외처리를 exceptions.py라는 모듈에서 관리 중이다.
exceptions.py 모듈을 사용하기 위해, 모든 앱에서 from backend.config.exceptions import *
처럼 선언하여 사용했다. 개발 서버에선 PYTHONPATH 설정을 Django 프로젝트 루트 디렉토리로 설정하여 정상적으로 실행됐다. 하지만 운영환경에서 문제가 생겼다.
아래는 Django 프로젝트 하위의 Dockerfile 내용이다. Docker container 생성 시 backend 디렉토리 하위의 내용을 WORKDIR로 옮긴 후 실행한다. 따라서 backend 디렉토리가 존재하지 않는다.
FROM python:3.9
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
WORKDIR /usr/src/app
COPY . /usr/src/app
RUN pip install --upgrade pip
RUN pip install --no-cache-dir -r requirements.txt
RUN pip install gunicorn
따라서 from backend.config.exceptions import *
처럼 절대 경로를 사용하여 import 하는 방식이 아닌 from ..config.exceptions import *
와 같이 상대 경로로 모듈 import를 시도했다. 하지만 아래와 같은 에러가 발생했다.
해당 에러는 상대 import를 사용할 때 발생하는 에러로, Python 모듈이나 패키지 내에서 상위 디렉토리로의 상대 import를 시도할 때 발생한다고 한다.
사실 해결법은 굉장히 간단했다. 결론부터 말하자면 Django 설정 파일의 INSTALLED_APPS에 프로젝트 디렉토리를 추가하면 된다.
INSTALLED_APPS = [
...
'config', # 프로젝트 루트 디렉토리
...
]
하지만 Django의 INSTALLED_APPS 설정에 프로젝트 루트 디렉토리를 직접 추가하는 것은 일반적인 관행이 아니다. INSTALLED_APPS는 주로 Django 애플리케이션을 등록하는 데 사용되며, 각 앱은 해당 앱의 models.py, admin.py, apps.py 등을 포함하는 독립적인 디렉토리이다.
프로젝트 루트 디렉토리는 보통 앱이 아니기 때문에 INSTALLED_APPS에 추가하는 것은 적합하지 않지만 프로젝트 루트 디렉토리 내의 파일을 다른 앱에서 참조하고자 한다면, 절대 임포트를 사용하여 해당 파일을 임포트할 수 있다.
만약 프로젝트 루트 디렉토리에 특정 기능을 수행하는 모듈이나 서브 패키지를 만들고 싶다면, 별도의 Django 앱으로 만들고 INSTALLED_APPS에 등록하는 것이 좋다. 이렇게 하면 해당 디렉토리를 Django의 앱 구조 내에서 적절하게 관리할 수 있다.