Programming/Frontend

Next.js 13 (App Router)에서 MultiPart Form 처리 && 파일 업로드

sangsangjin 2023. 6. 15. 09:40

최근 사내 프로젝트로 Next.js를 이용하고 있다.

Next.js 13이 나오면서 기존 Pages Router가 아니라 새로운 App Router를 바로 적용하게 되었다.

(어짜피 Pages Router로 개발해도 나중에 App Router로 다 바꿔야 할 것 같아서;;)

 

나에게 Next.js가 가장 좋았던 점은 API Route가 있어서 간단한 API는 바로 같은 디렉토리에서 개발할 수 있다는 것이었다.

React랑 Express가 적절히 잘 버무려진 느낌.

 

Docs 읽어보면 Pages Router 대비해서 바뀐게 꽤 몇개 있는데, 적용하는게 그다지 어렵지 않고, Docs도 친절히 잘 설명해주고 있는게 대부분이었다.

 

하지만 구글링해보면 대부분 Page Router에 대한 글이고, App Router로 적용하면서 겪었던 문제에 대한 글은 많이 보이지 않아서, 공유 차원으로 몇자 적어본다.


MultiPar Form 처리

문제가 되었던 부분은 MultiPart Form을 활용한 파일 업로드 기능 구현이었다.

외부 API를 사용해야 했기 때문에 나의 로직은 다음과 같았다.

 

Next.js Front (app/(component)/FileUploader.js) => Next.js Back (api/attachments/route.js) => 외부 API

 

FileUploader에서 MultiPartForm을 활용하여 route.js로 보내고 받은 파일을 그대로 외부 API를 이용해서 첨부파일을 보내줄 계획이었다.

 

결론 부터 말하자면

FileUploader.js에서는 기존 Front 개발하는 것 처럼, MultiPart-Form으로 보내면 되고,

const attachmentData = new FormData();
selectedFiles.forEach(( file ) => attachmentData.append('file', file));
await axios.post(
    `http://${ config[env].host }:${ config[env].port }/api/attachments`,
    attachmentData, {
        headers: {
            'Content-Type': 'multipart/form-data'
        }
    });

 

route.js에서 NextRequest를 받을때

export async function POST( NextRequest ) {
    try {
        const formData = await NextRequest.formData();
        const files = formData.getAll('file');

 

다음과 같이 NextRequest.formData()를 이용해서 받아주면 된다.

 

formidable이라 multer를 사용하려고 했지만 모두 잘 되지 않았고, multer의 경우 미들웨어 사용을 위해, next-connect까지 설치해서 시도하다가, 가장 간단한 방법을 찾아내서 공유한다.

 

https://codersteps.com/articles/building-a-file-uploader-from-scratch-with-next-js-app-directory

 

Building a File Uploader from scratch with Next.js app directory

I will teach you how you can upload a file using the Next.js app directory and the new api handlers in the route.ts file with a practical step-by-step.

codersteps.com

 

Next.js에서 파일 업로드 기능이 대부분 Pages Router이고, Chat GPT도 예전 데이터로 학습한 것이라, App Router에 대한 정확한 답변을 얻기 어려웠다.

 

누군가는 도움이 되기를 바라며.