요즘 사용하는 채팅어플은 단순히 텍스트 전송을 넘어 이미지나 파일을 공유하는 기능이 필수이다. 그래서 Django와 React를 사용하여 이미지 전송 기능을 구현했다. 이 글에서는 이미지 전송 방법에 대해 고민하고 구현하는 과정을 담았다.
이미지 전송 로직
처음에는 웹소켓(WebSocket)으로 직접 이미지 파일을 전송하려고 했다.
- 웹소켓으로 이미지 파일 전송
- 이미지 파일 저장
- 이미지 URL 반환
하지만, 웹소켓은 텍스트 기반 통신이므로 이미지 파일을 Base64로 인코딩해야 했다. 이 과정에서 파일 크기가 커지면 서버 부하와 연결 지연 문제가 발생할 수 있다는 점을 발견했다.
이러한 문제를 해결하기 위해 HTTP 요청을 통해 이미지를 업로드하고, 저장된 이미지의 URL을 반환한 뒤 이를 웹소켓으로 전송하는 방식으로 변경했다.
- 클라이언트에서 HTTP 요청으로 이미지 업로드
- 서버에서 이미지 파일 저장 후 URL 반환
- 반환된 URL을 웹소켓으로 상대방에게 전송
구현하기
Django 백엔드 서버
1. 미디어 파일 설정
#setting.py
...
MEDIA_URL = '/media/' # 미디어 파일 접근 URL
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
...
#config/urls.py
...
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
미디어 파일 저장 경로와 URL르 설정.
2. 이미지 저장 API
- 모델 정의
#models.py
class Message(models.Model):
...
image = models.FileField(upload_to="chat_images/",blank=True, null=True)
upload_to를 통해 이미지를 저장할 디렉토리를 설정합니다. 여기서는 media/chat_images/에 파일이 저장된다.
-뷰 정의
#views.py
def post(self, request):
...
#이미지 파일 가져오기
image = request.FILES.get('image')
#메시지 저장 이미지 저장
message = Message.objects.create(
chat_room=room,
sender_user=user,
image=image)
#이미지 URL생성
image_url = request.build_absolute_uri(message.image.url)
return Response({'image_url': image_url}, status=status.HTTP_200_OK)
POST 요청을 들어온 이미지 파일을 저장하고 URL을 반환한다.
React 프론트엔드
1. 이미지 업로드 및 URL 요청
const handelImage = async (image) => {
...
const response = await apiClient.post('/api/chat/message/create/', {
'image': image
}, {
headers: {
"Content-Type": "multipart/form-data", // 파일 업로드 시 필수
},
});
return response.data.image_url;
...
};
Django 서버에 이미지 URL를 요청한다. Content-Type을 multipart/form-data로 설정해야 Django 서버에서 request.FILES로 파일을 처리할 수 있다.
HTML에 form 태그에 enctype = "multipart/form-data" 가 같은 의미로 "파일이나 이미지를 서버로 전송할 때 인코딩 되면 파일의 경로명만 전송되고 파일 내용이 전송되지 않기 때문에 모든 문자를 인코딩하지 않음을 명시하는 옵션이다"
2. 웹소켓으로 이미지 URL 전송
const sendMessage = async () => {
let image_url = null;
if (image) {
image_url = await handelImage(image); // 이미지 URL 생성
}
// 메시지 전송
chatSocketRef.current.send(
JSON.stringify({ message, image: image_url, sender_user })
);
...
};
요청받은 URL를 웹소켓으로 전송해 준다.
마무리
HTTP와 웹소켓을 결합하면 두 프로토콜의 장점을 극대화해서 이미지 전송 방식을 구현했다. 이 방법 이외에서 Celey를 이용하는 방법과 이미지를 서버에서 실시간으로 처리하거나, 웹소켓만을 사용한 Base64 이미지 전송 방식을 비교하는 것도 좋은 공부가 될 거 같다.
구현 프로젝트 : https://github.com/Byeong98/chat
'Python > Django' 카테고리의 다른 글
Django에서 MySQL 연동하기 (0) | 2025.01.07 |
---|---|
[Django]WebSocket을 활용한 실시간 랭킹 구현 (0) | 2024.12.07 |
[Django] ORM N+1 문제 해결 : 지연로딩 (0) | 2024.12.01 |
[Django]데이터베이스 vs Redis: 실시간 접속자 관리 성능 비교와 최적화 (0) | 2024.11.30 |
Django와 React 연결 시 발생하는 CORS 문제 해결 방법 (0) | 2024.11.24 |