온룸 파일 다운로드 관련 이슈와 해결한 방법
내보내기 const downloadConsultingReportAsync = createAsyncThunk( '사용자/DOWNLOAD_APPLICATION', 비동기(고객: 문자열) => { const 응답 = await axios({ URL: `https://api.ownroom.link/api/consultings/report/download?nickname=${고객}`, 메소드: `get`, 헤더: { 권한 부여: `Bearer ${getCookie('token')}`, }, }); const a = document.createElement('a'); a.href = 응답.data.url; a.click(); { ...response.data }를 반환합니다. } );
들어가며
온룸 프로젝트에는 컨설턴트와 고객 간에 보고서/신청서 파일을 교환할 수 있는 기능이 있다. 아래 사진처럼 폼에 파일을 올리고 저장을 하면, 마이페이지 상에서 진행되고 있는 컨설팅 현황을 살펴볼 수가 있고, 이를 다운로드할 수도 있다.
이 기능을 개발하면서 생겼던 문제와 해결했던 방법을 이 글을 통해 다뤄보고자 한다.
무엇이 문제였나
내가 해결에 참여했던 문제는 문제 3인데, 이를 위해 앞서 설명이 필요해서 문제 1, 2에 대해 간략히 설명해보려고 한다.
문제1: S3에 파일 업로드 시 파일명 중복관련 문제
온룸 프로젝트는 AWS S3를 이용해서 파일을 관리한다. S3에 파일을 업로드하면 해당 파일을 다운로드할 수 있는 객체 url이 생성된다.
해당 url에 접속해서 파일을 다운로드하면 파일명 그대로 파일을 다운로드할 수 있다. 그런데 이렇게 하면 동일한 파일명으로 업로드했을 때 문제가 생긴다. 이 문제를 해결하기 위하여 uuid로 파일을 저장하기로 했다.
문제2: uuid로 업로드 시 클라이언트 사이드에서 파일명이 uuid로 보이는 문제
문제 1을 해결하기 위해 uuid를 도입했더니 고객이 실제로 받는 파일에 그대로 uuid가 노출되는 문제가 생겼다. 이를 해결하기 위해서 데이터 구조 상에서 원본 파일명을 따로 저장하고, 서버에서 S3로부터 올바른 파일명으로 다운받아온 후 클라이언트에게 응답을 주고 서버 내 파일을 삭제하는 방향으로 구현이 수정되었다.
문제3: 다운로드가 안 되는 문제가 발생
사실 문제 1, 2는 백엔드 파트에서 처리한 사항이고, 협업 당시 저런 식으로 구사했다는 것은 잘 몰랐다. 그런데 막상 백엔드에서 전달해준 api문서대로 다운로드 버튼을 누르면 axios로 서버에 다운로드 요청을 보내도록 구현을 했는데, 아래 형태의 응답이 돌아왔다.
무언가 인코딩 되었는데 디코딩이 잘 안 된 것 같이 보였다. 우리 팀의 백엔드 개발자는 인코딩 된 것은 아마 with open('~','rb')에서 바이너리로 인코딩 된 형태가 넘어가는 것 같다고 했다.
백엔드 개발자의 말로는 강제로 다운로드가 진행되게끔 코딩을 했다고 했고, 로컬 환경에서 테스트해봤을 때는 잘 수행이 된다고 했다. 어떤 방식으로 테스트가 진행되는 지 몰랐기 때문에 테스트 방식을 물어봤고, 백엔드 개발자는 테스트 영상을 직접 찍어서 전달해주었다. 전달받은 영상은 아래와 같다.
정말로 다운이 잘 되는 것을 확인할 수 있었다. 그런데, 내가 구현했던 방식과 백엔드 개발자가 보여준 테스트 영상에는 한 가지 큰 차이점이 있었다. 바로 POST 요청을 하는 것이 아니라 직접 주소창에 쳐서 확인을 했다는 점이다. 왜 뜬금없이 POST 요청에 대한 언급이 나왔냐면, 그때 당시 전달받은 API문서에는 POST로 토큰을 헤더에 넣고 Body에 userId를 넣어서 요청을 보내도록 가이드가 나왔기 때문이다.
내가 직접 백엔드 로직을 작성하지는 않았지만, 이 문제 해결에 기여하고 싶었다. 그래서 프론트 사이드에서 이 문제를 해결할 방법이 있는지 고민해보았다.
일단 이상하게 인코딩된 응답으로 무언가를 하는 것은 불가능해 보였고, 현재 구현되어 있는 기능 -테스트 영상에서 나왔던, 특정 url에 진입하면 다운로드가 진행되는 기능-을 활용하고 싶었다. 그래서 프론트 사이드로 응답을 줄 때 파일을 넘기는 것이 아니라, 저 해당하는 url을 body에 실어서 넘기고 프론트 사이드에서 내부적으로 a 태그를 만들어서 접근하면 어떻겠냐는 제안을 했다.
그 결과 제한된 시간 안에 기능 구현에 성공할 수 있었다.
솔루션 코드
아래는 프론트 사이드에서 문제 해결을 위해 작성한 코드이다.
export const downloadConsultingReportAsync = createAsyncThunk(
'user/DOWNLOAD_APPLICATION',
async (customer: string) => {
const response = await axios({
url: `https://api.ownroom.link/api/consultings/report/download?nickname=${customer}`,
method: `get`,
headers: {
Authorization: `Bearer ${getCookie('token')}`,
},
});
const a = document.createElement('a');
a.href = response.data.url;
a.click();
return { ...response.data };
}
);
백엔드 개발자가 테스트환경에 맞게 API를 바꿔주었다. POST에서 GET으로, 응답 body에 다운로드가 진행되는 url을 실어서 주도록 API가 변경되었다. 나는 프론트에서 document.createElement를 이용하여 내부적으로 링크를 만들고 그 링크가 클릭되도록 하는 방식으로 구현했다.
마치며
이것은 일종의 우회적인 구현방법이지만, 당일에 바로 기능을 시연해야하는 상황이었기에 백엔드 내에서 해결이 안된다면 이렇게라도 구현을 해야한다고 생각했다. 구현 방식의 수정 이후 기능은 정상적으로 잘 작동하였고, 우리 조는 성공적으로 발표를 마칠 수 있었다.😊 나중에 알게 된 사실이지만 근본적인 원인은 백엔드에서 mimetype을 잘못 지정했던 데 있었다. 그 부분이 백엔드 차원에서 해결되었다면 나는 문제를 겪어보지 못했겠지만, 문제적인 상황에 함께 놓이고 프론트 나름대로의 해결 방법을 제시하고 도전해보았기에 한 걸음 더 성장할 수 있었던 것 같다.👍
'Dev Log' 카테고리의 다른 글
gitlab에서 github으로 미러링 과정 중 인증 문제 해결하기 (0) | 2022.08.07 |
---|---|
플러터로 웹뷰 세팅하기 (0) | 2022.08.01 |
TypeScript Object, object, {} 비교 (0) | 2021.11.26 |
오픈소스에 기여하는 법 : MDN 문서에 기여하기 (0) | 2021.11.10 |
크롬 글자 일그러짐 현상 해결법 (0) | 2021.11.09 |
댓글
이 글 공유하기
다른 글
-
gitlab에서 github으로 미러링 과정 중 인증 문제 해결하기
gitlab에서 github으로 미러링 과정 중 인증 문제 해결하기
2022.08.07 -
플러터로 웹뷰 세팅하기
플러터로 웹뷰 세팅하기
2022.08.01 -
TypeScript Object, object, {} 비교
TypeScript Object, object, {} 비교
2021.11.26 -
오픈소스에 기여하는 법 : MDN 문서에 기여하기
오픈소스에 기여하는 법 : MDN 문서에 기여하기
2021.11.10