개발새발 로그

React : 이미지 서버에 업로드하기 - multer, FormData(), Gateway Timeout 오류 해결 본문

MERN

React : 이미지 서버에 업로드하기 - multer, FormData(), Gateway Timeout 오류 해결

이즈흐 2023. 6. 25. 23:37

게시글을 작성하면서 이미지 파일도 올리고 싶다면 어떻게 해야 할까?

 

먼저 우리는 클라이언트에서 이미지를 넣으면 서버에 저장하는 방법을 알아보자

 

 

클라이언트에서 이미지를 올리면 서버에 저장하고 서버에 저장한 후 다시 저장한 이미지를 클라이언트에서 띄워주어야 한다.

 

작동 순서를 그림으로 그려보았다.

이미지 업로드 후 게시글 제출

이미지 DB에 저장 후 게시글 상세페이지에서 이미지 출력

 

 

 

📋작동순서

1. 이미지 업로드를 위한 컴포넌트생성

  -이미지 input태그를 따로 컴포넌트에 만들어서 작성한다. (ImageUpload.js)

  -input태그에서 이미지만 선택할 수 있도록 하기 위해 속성 accept에accept="image/*"를 작성한다.

2. 이미지 컴포넌트에서 이미지를 업로드하면 onChange를 이용해 서버에 이미지를 보내준다.

  -이미지 데이터를 보내줄 때 FormData()에 저장해야 한다.

3. 서버에서 이미지를 로컬에 저장하고 다시 이미지의 경로를 클라이언트에게 전송

4. 경로를 받아서 Post 모델에 저장

    -Post DB에서 image 타입을 추가한다

    -setImage를 ImageUpload에 Props 해서 이미지경로를 setImage 할 수 있도록 한다.

    -만약 게시글을 작성완료하면 게시글에서 setState 되었던 정보들로 인해 서버에 Image 경로가 저장된다.

5. 게시글 상세페이지에서 해당 이미지경로 가져와서 보여줌

 

Multer 사용법

https://github.com/expressjs/multer/blob/master/doc/README-ko.md

 

GitHub - expressjs/multer: Node.js middleware for handling `multipart/form-data`.

Node.js middleware for handling `multipart/form-data`. - GitHub - expressjs/multer: Node.js middleware for handling `multipart/form-data`.

github.com

FormData()

https://developer.mozilla.org/en-US/docs/Web/API/FormData

 

FormData - Web APIs | MDN

The FormData interface provides a way to construct a set of key/value pairs representing form fields and their values, which can be sent using the fetch(), XMLHttpRequest.send() or navigator.sendBeacon() methods. It uses the same format a form would use if

developer.mozilla.org

 

 

 

1. 이미지 업로드를 위한 컴포넌트생성

  -이미지 input태그를 따로 컴포넌트에 만들어서 작성한다. (ImageUpload.js)

  -input태그에서 이미지만 선택할 수 있도록 하기 위해 속성 accept에 accept="image/*"accept="image/*"를 작성한다.

2. 이미지 컴포넌트에서 이미지를 업로드하면 onChange를 이용해 서버에 이미지를 보내준다.

  -이미지 데이터를 보내줄 때 FormData()에 저장해야 한다.

-서버로 데이터 전송

3. 서버에서 이미지를 로컬에 저장하고 다시 이미지의 경로를 클라이언트에게 전송

-받아온 데이터 multer로 데이터를 이미지 경로로 정제 후 클라이언트로 보내주고, 로컬에는 image폴더에 저장한다.

클라이언트로 이미지 경로를 보냄

 

4. 경로를 받아서 Post 모델에 저장

    -Post DB에서 image 타입을 추가한다

    -setImage를 ImageUpload에 Props 해서 이미지경로를 setImage 할 수 있도록 한다.

Upload.js에서 setState를 props해준다.
props로 받은 것

     -아까 위에서 서버에 요청 보내서 받은 이미지 경로 setImage로 저장함

     -만약 게시글을 작성완료하면 게시글에서 setState 되었던 정보들로 인해 DB에 Image 경로가 저장된다.

몽고DB에 저장됨

 

 

 

 

🧨추가적인 부분

1. 이미지 로컬에 저장하는(multer) 부분에서 아래와 같이 경로를 지정해 줘야 로컬에 잘 저장한다.

2. 이미지 경로로 정제(multer)하는 부분에서 아래와 같이 바꿔줘야 이미지가 잘 들어간다.

3. 게시글 상세페이지에서 이제 이미지 경로 DB에 저장한 거 불러와서 이미지 띄워주려면 아래와 같이 작성해야 한다. 또한 null일 경우에도 방어코드 작성해야한다.

 

 

 

 

💢어려웠던 부분

1. multer 한글 깨짐 오류

-multer 1.5 버전에서는 한글 깨짐이 발생한다고 한다. 

npm i multer@1.4.4

 로 다시 설치해 주면 해결된다.

 

 

2. 게시글 작성화면에서 이미지 업로드 후 다시 파일 선택 후 취소 누르면 생기는 오류

 

  - 이 문제는 먼저 이미지파일을 선택하면 처음에는 서버에 잘 저장된다.

  -하지만 만약 이미지 파일 선택을 다시 눌러서 취소를 누르면 아래와 같은 오류가 뜬다.

POST http://localhost:3000/api/post/image/upload 504 (Gateway Timeout)

서버에서의 오류 출력

 

☝해당 오류의 이유

-먼저 파일을 처음 넣을 때는 잘 작동되지만 파일선택을 다시 누르고 취소를 누르면 위와 같은 오류가 뜬다.

-이는 취소를 눌러서 onChange가 발생했지만 안에 파일이 없으므로 빈 값이 서버로 전송된다.

-서버는 현재 아래와 같이 데이터를 받아서 클라이언트에 보내준다.

일단 빈값이어도 onChange로 인해 서버로 요청이 들어가게 되고 빈값이 전송되게 된다.

빈값으로 인해 multer는 저장할 이미지가 없게 되지만 요청을 정확하게 받았으므로 응답이 성공하게 된다.

그래서 위 코드에서 응답성공으로 데이터를 보내는데 정작 res.req.file.path에는 path라는 데이터 자체가 없게 된다.

그래서 위와 같이 504 오류가 뜨게 되고 다시 이미지를 넣는다 해도 계속 504 오류가 뜨게 된다.

 

📝해결방법

-아래와 같이path가 아닌 res.req.file을 보내주면 된다.

-이는 path라는 있을 수도 있고 없을 수도 있는 데이터가 아닌 undefined면 undefined를 줄 수 있다.

-그리고 클라이언트에서도 데이터가 없을 수도 있음을 유의해서 방어코드를 작성한다.

-이렇게 하면 만약 파일선택해서 이미지를 없앴어도 undefined를 서버에서 보내 주기 때문에 오류를 방지할 수 있다.

 

즉 이미지를 넣으면 정확한 file 데이터를 서버에서 보내주고, 클라이언트에서는 file에 데이터가 있으므로 setImage를 수행한다.

만약 이미지를 취소하면 빈 값이 전송되고 서버에서도 빈 값을 받고 다시 undefined를 보내준다. 하지만 클라이언트에서는 undefined는 받지 않게 된다.

728x90
반응형
LIST