이미지 리사이징 방식 논의 #175
Replies: 2 comments
-
|
resizing 을 생각하지 못했네요. 제가 생각하는 방식은 비동기 - rabbitMq 를 통한 이벤트 발행입니다. 스프링에서는 rabbitmq 의 저장 이벤트를 구독하고 있다가 리사이징되지 않은 파일이 저장되었다고 판단하면 비동기 워커가 리사이징을 수행합니다. Minio 는 메시지 저장 이벤트를 AMQP 로 보낼 수 있습니다. 마찬가지로 스프링은 해당 이벤트를 수신 받을 수 있고요. 스레드 풀 낭비가 걱정된다면, Tomcat 과 격리된 스레드 풀을 새로 정의하여 해당 워커에 적용하면 될 듯 합니다.
===== no need process ===== 추가제안 사항.
위에 단계는 있어보이게 영어로 적어봤습니다. |
Beta Was this translation helpful? Give feedback.
-
|
좋습니다. 그러면 현재 pr올라와 있는 rabbitmq 설정을 merge하고 나서 진행하도록 하겠습니다. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
이 논의는 이미지 리사이징 방법에 대해 논의합니다
현재 사진 업로드 방식?
현재 사진 업로드는 클라이언트가 presigned url을 받아 직접 MinIO에 업로드하고 있습니다. 그 후, 업로드에 성공한다면 Spring 서버에게 성공했음을 알리는 API를 사용해 업로드 성공했음을 알리도록 설계할 예정입니다.
sequenceDiagram autonumber actor Client participant Server as Spring Server participant DB as Database participant MinIO as Object Storage (MinIO) participant Worker as Async Worker (@Async) Note over Client, Server: 1단계: 업로드 준비 Client->>Server: 1. Presigned URL 요청 Server->>DB: 2. Image 엔티티 생성 (Status: PENDING) DB-->>Server: Entity ID 반환 Server-->>Client: 3. Presigned URL & Image ID 반환 Note over Client, MinIO: 2단계: 실제 파일 업로드 Client->>MinIO: 4. 원본 파일 업로드 (PUT) MinIO-->>Client: 200 OK Note over Client, Server: 3단계: 성공 보고 및 유효성 검증 Client->>Server: 5. 업로드 완료 보고 API (Image ID) Server->>MinIO: 6. 파일 존재 여부 확인 (HeadObject) alt 파일 존재함 (Success) Server->>DB: 7. 상태 변경 (PENDING -> PROCESSING) Server-->>Client: 8. 204 No Content 응답 Note over Server, Worker: 4단계: 비동기 리사이징 Server-)Worker: 9. 리사이징 작업 트리거 (비동기) Worker->>MinIO: 10. 원본 다운로드 & 리사이징 후 재업로드 Worker->>DB: 11. 최종 상태 변경 (COMPLETE) & 경로 업데이트 else 파일 없음 (Fail) Server-->>Client: 12. 400 Bad Request (Invalid Upload) end그렇다면 문제가 되는 것이 이미지 리사이즈입니다.
누가 리사이즈를 진행?
만약 Spring 서버가 클라이언트로부터 이미지를 받아 업로드하는 구조였다면, small, medium, large에 해당하는 사진을 모두 업로드 하면 되니 문제가 되지 않습니다.
하지만 우리는 클라이언트가 사진을 업로드하고 있습니다. 이때 클라이언트가 올린 사진은 기존에 우리가 정한 small, medium, large 규격에 맞지 않을 수 있기 때문에, 원본 사진은 별도로 남겨두고, 리사이즈 이미지를 3개를 추가해야 합니다. (Gemini 피셜)
클라이언트 측에서 리사이즈하는건 옳지 않다고 하니(Gemini 피셜: 사용 기기마다 성능이 다름), 서버에서 리사이즈를 진행해야 합니다.
언제 리사이즈를 진행?
앞서 말씀드린 것처럼 클라이언트는 업로드에 성공한다면 Spring 서버에게 성공했음을 알리는 API를 사용해 업로드 성공했음을 알려야 합니다. (presigned url만 발급해줘서는 사진이 업로드됐음을 보장할 수 없기 때문) 따라서 이미지 리사이즈는 아래 순서로 진행할 예정입니다.
3-1. 유효한 사진이라면 이미지 리사이징 작업을 진행하고, 204 no content로 응답합니다.
3-2. 유효하지 않은 사진이라면 400 에러를 반환함. (확장자가 유효하지 않거나, 파일 크기가 너무 큼)
이때 이미지 리사이징은 동기적으로 진행할 수 있고, 비동기적으로 진행할 수 있습니다.
동기? 비동기? 혹은 리사이징 서버 구축?
동기
동기적으로 진행하는 경우 small, medium, large 사이즈를 모두 리사이징하고 MinIO에 업로드한 후에 API 응답을 내립니다.
UX 관점에서 응답까지 비교적 오랜 시간을 기다려야 합니다. (이건 카카오톡에서도 기다리는 시간이 있으니 어느정도 감수해야 한다고 생각하긴 합니다)
리사이즈 동안 스레드를 오래 사용하므로 동시에 많은 요청이 들어올 경우, Tomcat 스레드가 고갈되어 로그인과 같은 아예 다른 API 호출도 못할 수 있습니다.
모바일 환경에서는 네트워크가 불안정합니다. 서버가 리사이징을 열심히 하고 있는데 유저가 터널에 들어가서 연결이 끊기면, 서버는 처리를 다 하고도 결과를 전달할 곳이 없어 에러가 발생할 수 있습니다.
비동기
비동기로 동작하는 경우 204 API 응답을 먼저 내리고, 이미지 리사이즈를 진행합니다.
리사이징 서버 구축
이건 아예 다른 방식인데, MinIO에 이미지가 업로드되면 Webhook을 통해 리사이징 서버에 리사이즈 요청을 보낼 수 있다고 합니다.
그래서 결론이 뭐임?
리사이징 서버 구축은 추후 도입으로 하면 좋을 것 같은데, 동기 비동기 뭐로 할지 고민입니다. 의견 공유 부탁드립니다.
Beta Was this translation helpful? Give feedback.
All reactions