일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- img upload
- 에러
- js
- 리액트
- GIT
- fire base
- 문자열 대소문자
- react native CLI
- 리엑트 네이티브 아이콘
- 리액트 네이티브 에러
- 리액트 네이티브
- react native 개발
- babel.config.js
- react native 세팅
- AWS
- Project
- PongWorld
- React
- error
- react native font
- aws bucket 정책
- Next.js
- react native
- firebase 라이브러리
- 백준
- react native picker
- AWS Access Key
- 문자열 대소문자 구별
- s3 upload
- Access Key 생성
- Today
- Total
밝을희 클태
[ Next.JS ] AWS S3에 이미지(image)를 업로드, 미리보기 본문
환경
Next.js 14 APP Router
AWS SDK for Javascript v3
https://gaebarsaebal.tistory.com/79
[ AWS ] S3 버킷(bucket) 생성, 사용자 추가, 액세스 키 만들기
전에 작성한 글이 있는데 너무 대충 설명한 거 같아서 다시 써야겠다.버킷 만들기1. aws에서 s3를 검색해서 들어와 버킷 만들기로 들어간다.2. 버킷 이름을 적는다.3. 나는 현재 계정에서만 사용할
gaebarsaebal.tistory.com
S3 bucket 설정은 이 전 포스팅에서 다룬다.
나는 S3 이미지 업로드를 서버에서 할 것이다. 클라이언트에서 할 수도 있지만 클라이언트에서 하면 AWS key가 노출될 위험이 있고 Presigned URL을 사용해 key의 노출을 막을 수 있지만 더 많은 작업을 해줘야 해서 서버에서 바로 업로드하려고 한다.
일단 API endpoint를 만들자
# /root/.env.local AWS_ACCESS_KEY_ID=IAM(보안 자격 증명) user에서 발급받은 access key AWS_SECRET_ACCESS_KEY=IAM(보안 자격 증명) user에서 발급받은 secret access key AWS_REGION=S3 bucket 국가 ex) ap-northeast-2 S3_BUCKET_NAME=bucket name
$ npm install @aws-sdk/client-s3
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3'; import { NextResponse } from 'next/server'; const s3Client = new S3Client({ region: process.env.AWS_REGION, credentials: { accessKeyId: process.env.AWS_ACCESS_KEY_ID, secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, }, }); export async function POST(req) { try { const formData = await req.formData(); const files = formData.getAll('files'); const uploadPromises = []; const uploadedUrls = []; for (const file of files) { // 각 파일에 대해 루프를 시작 files는 formData.getAll('files')를 통해 가져온 파일 리스트 const arrayBuffer = await file.arrayBuffer(); // 파일을 ArrayBuffer로 변환 ArrayBuffer는 바이너리 데이터를 저장할 수 있는 일반적인 버퍼 const buffer = Buffer.from(arrayBuffer); // ArrayBuffer를 Node.js Buffer 객체로 변환, Node.js Buffer 객체는 S3에 업로드할 수 있는 형태의 데이터 const uploadParams = { Bucket: process.env.S3_BUCKET_NAME, // 업로드할 S3 버킷의 이름. 환경 변수로 설정된 값을 사용 Key: `${Date.now()}_${file.name}`, // S3에 저장될 객체의 키(파일 이름) 여기서는 파일 이름 앞에 현재 타임스탬프를 붙여서 고유한 파일 이름을 생성 Body: buffer, // 업로드할 파일의 내용 Buffer 객체를 사용 ContentType: file.type, // 클라이언트에서 업로드된 파일의 타입을 그대로 사용 }; const command = new PutObjectCommand(uploadParams); // S3에 파일을 업로드하는 명령을 생성 const uploadPromise = s3Client.send(command) .then(() => { const url = `https://${process.env.S3_BUCKET_NAME}.s3.${process.env.AWS_REGION}.amazonaws.com/${uploadParams.Key}`; // 파일이 성공적으로 업로드된 후 해당 파일의 URL을 생성 // S3 버킷의 URL 형식을 사용 'https://{버킷 이름}.s3.{리전}.amazonaws.com/{파일 키}' uploadedUrls.push(url); // 생성된 URL을 uploadedUrls 배열에 추가 }) .catch(error => { console.error(`Error uploading file ${file.name}:`, error); }); uploadPromises.push(uploadPromise); // 각 업로드 작업을 Promise 배열에 추가 } await Promise.all(uploadPromises); return NextResponse.json({ uploadedUrls }, { status: 200 }); } catch (error) { return NextResponse.json({ error: '업로드중 문제 발생' }, { status: 500 }); } }
그다음 클라이언트 코드로 와서 이미지를 선택해서 담을 Hook을 만들어준다.
imageUrls는 사용자가 선택한 이미지를 미리 보기 위해 사용되고
imageFiles는 AWS S3에 업로드하기 위해 사용된다.
const [uploadImages, setUploadImages] = useState({ imageFiles: [], imageUrls: [], });
그리고 Input을 만들어서 image만 선택할 수 있게 해 주고 이미지 선택을 완료했을 때 handleImageUpload 함수를 실행시켜 준다.
URL.createObjectURL(file)는 각 파일 객체에 대해 브라우저가 해당 파일을 참조할 수 있는 임시 URL을 생성한다.
이제 이미지를 사용자에게 미리 보여주고 싶으면 imageUrls를 src에 주면 된다.
const handleImageUpload = useCallback( e => { if (!e.target.files) return; const files = e.target.files; const filesArray = Array.from(files); const newArray = filesArray.map(file => URL.createObjectURL(file)); setUploadImages({ imageFiles: [...uploadImages.imageFiles, ...filesArray], imageUrls: [...uploadImages.imageUrls, ...newArray], }); }, [uploadImages], ); <input type="file" multiple accept="image/*" onChange={handleImageUpload} id="images" hidden />
이제 이미지를 처음에 만든 API endpoint로 formdata를 보내서 서버에서 업로드를 해준다.
이미지 업로드에 성공했으면 S3 bucket에 올라간 이미지 URL들이 반환될 거고
실패했으면 error mag를 반환할 것이다.
const handleUpload = async () => { const formData = new FormData(); uploadImages.imageFiles.forEach(file => { formData.append('files', file); }); try { const res = await fetch('/api/upload/product', { method: 'POST', body: formData, }); const data = await res.json(); if (res.ok) { ... } else { ... } } catch (error) { ... } };
이미지 업로드에 성공하면 bucket에 이렇게 객체들이 생성이 돼있다.

'NextJS' 카테고리의 다른 글
[ Next.JS ] Input 태그에서 HEIC 확장자를 jpeg로 변환하기 (0) | 2024.06.15 |
---|---|
[ Next.js] Image태그의 sizes (1) | 2024.06.12 |
[NextJS] 스크롤 애니메이션 구현하기 IntersectionObserver API (1) | 2023.12.03 |