회사 그룹웨어에 기능을 추가하는 업무를 하다가 프론트 코드를 수정했다. 그런데 브라우저에서 확인해보니 적용이 안되어 있어서 네트워크를 확인해봤더니 프로덕션용 서버에서 정적 파일들을 받아오고 있었다. 그래서 settings 파일을 확인해봤는데, STATIC_URL, STATIC_DIRS, STATIC_ROOT 모두 아무 문제가 없었다.
뭐가 문제지 싶어 찾아보다가 선배께 여쭤보고 나서야 문제의 원인을 알 수 있었다. STATIC_STORAGE가 프로덕션용으로 설정되어 있었다. 해당 코드를 지워서 디폴트 설정으로 바꿔주고 나니 정적 파일들을 로컬에서 받아오는 걸 확인할 수 있었다.
부끄럽지만 그 동안 튜토리얼만 따라하면서 STATIC_ROOT/URL/DIRS를 지정해줘서 서버가 동작은 하지만 정작 얘네가 각각 무슨 역할들을 하는지는 잘 몰랐다. 이 기회에 장고의 정적 파일 핸들링 옵션들을 찾아보면서 정리해보았다.
장고 세팅 파일에서 정적 파일을 설정할 수 있는 옵션은 총 다섯 가지가 있다.
이 중 익숙한 위의 세 가지부터 살펴보자.
STATIC_URL
정적 파일을 서비스하는 주소이다. 설정 시 반드시 trailing slash(맨 마지막에 위치하는 슬래시)를 포함해야 한다.
STATIC_ROOT
STATIC_URL이 참고하는 디렉토리의 경로이다.
STATIC_DIRS
STATIC_ROOT가 참고하는 디렉토리의 경로이다.
간단하게 적어놓았는데, 좀 더 풀어서 설명해보고자 한다.
STATIC_DIRS는 개발 단계에서 장고 서버가 정적 파일을 찾아서 서비스하기 위해 접근하는 경로라고 할 수 있다. 즉, DEBUG=True 모드에서는 STATIC_DIRS를 지정해놓고 여기에 정적 파일들을 넣어 놓으면 장고가 해당 디렉토리에서 정적 파일들을 가져와 화면에 띄워준다.
그런데, DEBUG=False 모드에서는 장고 서버가 직접 정적 파일에 접근하는 게 아니라 웹 서버가 정적 파일을 찾아 서비스한다. 이 때 웹 서버는 STATIC_DIRS가 아니라, STATIC_ROOT를 참고한다. 즉, STATIC_DIRS와 STATIC_ROOT는 둘 다 서버가 정적 파일을 찾기 위해 참조하는 경로라고 할 수 있는데, 다만 개발 환경에서 사용하는지 프로덕션 환경에서 사용하는지의 차이가 있는 것이다.
이 때 한 가지 의문이 들 수 있다. 프로덕션 환경에서 웹 서버가 STATIC_ROOT를 참조해 정적 파일을 서비스하기 위해서는 STATIC_ROOT에 STATIC_DIRS에 있는 파일들이 똑같이 들어있어야 한다. 그렇다면 STATIC_DIRS와 STATIC_ROOT의 경로가 똑같아야 하는 건가?
답은 'NO'이다. 보통 프로덕션 환경에서 python manage.py collectstatic
명령 후 runserver
를 하게 되는데, 이 collectstatic
명령어가 하는 일이 바로 이 부분이다. collectstatic
명령어는 STATIC_DIRS의 정적 파일들을 찾아서 STATIC_ROOT에 복사한다. 그래서 두 경로는 같을 필요가 없다.
정리하자면, 프로덕션 환경에서 서버는 정적 파일들을 서비스하기 위해 STATIC_ROOT에서 파일들을 찾고, STATIC_ROOT는 STATIC_DIRS의 경로에 위치한 정적 파일들을 모아 저장해두는 방식이라고 할 수 있다. 그리고 STATIC_URL은 프로덕션 환경에서 웹 서버가 정적 파일을 서비스하기 위한 경로로, 서버가 얘를 통해 STATIC_ROOT를 참고하는 것이다.
즉, 프로덕션 환경에서의 정적 파일 서비스 방식을 간단히 도식화하면
STATIC_URL --참조--> STATIC_ROOT --참조--> STATIC_DIRS
가 된다.
그렇다면 STATIC_ROOT는 문자열인 반면 STATIC_DIRS는 iterable인 이유도 알 수 있다. 정적 파일들이 한 곳에 모여있을 수도 있지만 여러 App에 흩어져 있을 수도 있기 때문에 STATIC_DIRS가 iterable로 설정되어야 하는 것이고, STATIC_ROOT는 여러 군데에 흩어져 있는 정적 파일들을 모아 서비스하는 경로이기 때문에 문자열 형태인 것이라고 할 수 있을 것 같다.
이제 남은 두 옵션들을 살펴보자.
STATICFILES_STORAGE
얘는 간단히 말해 collectstatic
명령을 했을 때, 어디서 정적 파일들을 찾을 것인지, 즉 로컬 서버의 경로에서 찾을 것인지 아니면 CDN이나 클라우드 서버에서 찾을 것인지를 설정하는 항목이다. 앞서 언급한 그룹웨어 이슈에서는 얘가 클라우드 서버를 참조하도록 설정되어 있었기 때문에 로컬의 변경 사항이 반영되지 않았던 거였다.
디폴트가 django.contrib.staticfiles.storage.StaticFilesStorage
로, 로컬 경로를 참조하도록 되어 있고, 프로덕션 모드에서는 따로 프로덕션용 서버를 참조하도록 설정해주어야 한다.
STATICFILES_FINDERS
얘도 마찬가지로 collectstatic
명령을 했을 때, 어디서 정적 파일들을 찾을 것인지를 설정하는 항목이다. STATICFILES_STORAGE가 백엔드 서버 단위라면 STATICFILES_FINDERS는 서버 내부의 디렉토리 단위에서 참조할 경로를 설정하는 옵션이다.
디폴트로 STATIC_DIRS에 지정된 디렉토리와 INSTALLED_APPS에 들어있는 각 앱 내부의 'static'이라는 이름의 디렉토리의 파일들을 찾는다.
아직까지는 얘를 따로 설정하는 건 보지 못했다.
내가 이해한 부분으로만 적어 보았다. 지금 회사에 입사해서 매일 엄청나게 많은 걸 배우고 있는데, 게으름을 너무 많이 피워서 정리를 하지 않고 있다. 회고도 해야 하는데... 어떻게 하면 부지런해질 수 있을까?!