🎮

Appendix 2. Django ImageField

Created
2020/12/26 05:38
Tags
이번에는 Django의 ImageField를 통해 이미지를 저장하고, 저장된 이미지를 DRF를 통해 통신해보도록 하자. 우선은 Django settings를 통해 media 파일 경로 및 URL을 설정하고, DRF를 통해 해당 이미지로 통할 수 있는 URL를 얻어내면 될 것 같다. 그리고 왠지 Nginx 설정으로 마무리를 해야할 것만 같다.

Django Settings

Django의 ImageField 관련 설정을 시작해보자. 우선 ImageField를 이용하기 위해서는 Pillow 라이브러리가 필요하다. 다음의 명령어로 설치할 수 있다.
pip install Pillow
Plain Text
복사
이제 다음과 같이 model class에 ImageField를 추가해주자.
# models.py class News(models.Model): ... image = models.ImageField(default=None)
Python
복사
그 다음 media 파일들을 관리하기 위해 다음과 같은 설정을 Django settings 파일에 추가해 주자.
# settings/common.py ... MEDIA_URL = '/media/' # media 파일에 관한 요청을 해당 url로 받겠다는 뜻이다. MEDIA_ROOT = os.path.join(BASE_DIR, 'media') # 편한 대로 설정한 후 해당 경로에 'media'라는 디렉토리를 생성한다. ...
Python
복사
이제 어드민에 모델을 등록한 후, 이미지를 업로드하여 데이터를 생성하면 위에서 지정한 MEDIA_ROOT 디렉토리에 이미지가 저장된다. 그런데, 해당 URL(ex. localhost:8000/media/some_img.png)로 접근하면 404 페이지가 뜨는데, 다음과 같이 URL configuration을 해 주어야 한다.
# mysite/urls.py from django.conf import settings from django.conf.urls.static import static ... urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Plain Text
복사
이제 해당 주소로 가면 이미지가 제대로 보인다!

Django REST Framework

이제 업로드된 이미지를 API를 통해 통신하고자 한다. 여기서는 Django REST Framework(DRF)를 사용해보기로 한다. 사실 할 줄 아는 게 그것밖에 없다.
다음과 같이 설정해주면 된다.
class NewsSerializer(serializers.ModelSerializer): image = serializers.ImageField(use_url=True) class Meta: model = News fields = "__all__"
Python
복사
이렇게 하면 serializer가 image 파일의 url을 보내 준다. 적절한 view를 구성한 후 요청을 보내면 된다. 정말 간단하다! 이제 서버에 업로드한 후 다시 한 번 도전해보자.

Media 디렉토리 권한 설정

migration부터 이미지를 읽어오는 것까지는 추가적인 작업 없이도 성공할 수 있었다. 하지만, Django admin을 통해 이미지를 업로드해보려 하니 역시나 에러가 발생했다. [Erno 13] ~~~ permission denied. 아마 설정한 media 디렉토리에 파일을 새로 쓸 수 있는 권한이 주어져있지 않은 것 같다. 권한을 모두에게 열어 버리면 인생이 편하겠지만, 프로덕션 단계에서 그러면 안 되니 조금 더 찾아보았다.
다음과 같이 권한을 설정해주면 된다. 간단히 말해 새로운 유저 그룹을 만들고, Nginx를 돌리고 있는 유저를 그 그룹에 집어 넣어 media 파일을 쓸 수 있는 권한을 부여하는 것이다.
sudo groupadd srv-users # srv-users라는 이름의 그룹을 생성한다. sudo adduser deploy srv-users # deploy라는 유저를 srv-users 그룹에 추가한다. sudo chgrp -R srv-users [PATH_TO_MEDIA_DIR] # media 디렉토리의 유저 그룹을 srv-users로 변경한다. sudo chmod -R 770 [PATH_TO_MEDIA_DIR] # 소유자(root)와 유저 그룹에 770 권한을 부여한다.
Plain Text
복사
참고로 deploy 유저는 Django를 배포할 때 생성한 /etc/nginx/nginx.conf에 명시된 유저이다. 다음 포스트를 참고하자.
또 참고로 권한에 대해 말하자면, 소유자|그룹|공개 순으로 권한을 설정하는데, 각각 r = 4, w = 2, x = 1의 권한을 더해 설정해주면 된다. 예컨대 모두에게 rwx권한을 부여하려면 777이고, 소유자에게는 모든 권한을, 그룹에게는 읽기 권한을, 공개로는 아무 권한도 주지 않는다면 740이 된다.
이제 Nginx와 uWSGI 서비스를 재시작한 후 다시 시도해 보니 성공했다!

Trouble Shooting

우리의 전지전능한 Django이지만 production 단계에서의 media file serving은 안전하지 않은 방법이기 때문에 제공하지 않는다고 한다. 그렇기 때문에 DEBUG = True인 상태에서 미디어 파일에 대한 요청을 보내면 이번에는 무려 404 Not Found 에러를 줄 것이다. 이거 원인 찾느라 정말 애먹었다...
어쨌거나 S3를 이용하는 방법 등 다양한 옵션이 있는 것 같지만, 시험기간이라 바쁘기도 하니 media 파일에 대한 요청이 들어오면 Nginx가 바로 해당 디렉토리로 연결해주는 설정을 하였다. 다음과 같은 코드를 Nginx configuration에 추가해 주자.
location /media/ { alias PATH_TO_MEDIA_FILES; }
Plain Text
복사
이제 예전에 했던 것처럼 configuration을 site-availablesite-enabled에 카피해주면 드디어 미디어 파일을 볼 수 있다...

Refs

E.O.D.