s3이미지 업로드 후 리뷰 완성!
2025. 5. 1. 02:06ㆍ프론트엔드/REACT
728x90
✅ 전체 흐름 요약
[1단계] 이미지 선택
↓
[2단계] presigned URL 요청 (GET)
↓
[3단계] 받은 URL로 S3에 PUT 업로드 (binary)
↓
[4단계] s3Key를 포함해 리뷰 등록 API 요청 (POST)
✅ 각 단계 상세 설명
📸 1단계. 사용자 이미지 파일 선택
<input type="file" accept="image/*" onChange={handleImageUpload} />
- 상태에 저장: setImage(file)
- 파일 객체는 File 타입
🌐 2단계. presigned URL 요청 (GET)
const response = await axiosInstance.get("/api/auth/user/post/presigned", {
params: {
originalFileName: image.name,
contentType: image.type,
},
});
✅ 서버 응답 예시
{
"code": "GEN-000",
"status": 200,
"data": {
"s3Key": "seoulfest/post/media/20250413_abc.jpg",
"presignedUrl": "https://seoulfest.s3...signedURL..."
}
}
- presignedUrl: 실제 업로드할 주소
- s3Key: 이걸 나중에 mediaList에 넣어서 리뷰 등록 시 사용함
📤 3단계. presigned URL로 S3 업로드 (PUT 요청, binary 전송)
await axios.put(presignedUrl, image, {
headers: {
"Content-Type": image.type,
},
});
- Content-Type이 꼭 있어야 함 (image/jpeg, image/png 등)
- 응답 status가 200이면 성공
📝 4단계. 리뷰 등록 요청 (POST)
await axiosInstance.post("/api/auth/user/reviews", {
eventId: 1277, // 또는 URL param에서 가져온 값
content: "후기 내용",
rating: 4.5,
mediaList: [
{
s3Key: "seoulfest/post/media/20250413_abc.jpg",
order: 0,
}
]
});
이미지가 없으면 mediaList: [] 또는 필드 자체 생략도 가능 (백엔드 정책에 따라)
✅ 전체 코드 흐름 예시 (핵심만 요약)
const handleSubmit = async () => {
let mediaList = [];
if (image) {
// 1. presigned URL 요청
const res = await axiosInstance.get("/api/auth/user/post/presigned", {
params: {
originalFileName: image.name,
contentType: image.type,
},
});
const { presignedUrl, s3Key } = res.data.data;
// 2. S3 업로드
await axios.put(presignedUrl, image, {
headers: { "Content-Type": image.type },
});
mediaList.push({ s3Key, order: 0 });
}
// 3. 리뷰 등록 요청
await axiosInstance.post("/api/auth/user/reviews", {
eventId: 1277,
content: review,
rating: rating,
mediaList,
});
};
✅ 백엔드 관점 요약 (참고용)
🔸 /post/presigned (GET)
- S3에 PUT할 수 있는 URL을 생성해서 클라이언트에 넘겨줌
- 클라이언트가 직접 S3로 전송 (백엔드가 중간에 안 끼는 방식)
🔸 /reviews (POST)
- 리뷰 등록, s3Key만 받음 (S3에 파일이 있는지 신뢰함)
728x90
'프론트엔드 > REACT' 카테고리의 다른 글
| 동적로딩[카카오 맵 동적로딩 문제 해결] (0) | 2025.04.09 |
|---|---|
| 컴포넌트 인터페이스와 Props (0) | 2025.04.01 |
| React와 Chart.js로 구현하는 레이더 차트: RadarChart 컴포넌트 분석[FC] (0) | 2025.04.01 |
| QRReader 컴포넌트[FC] (0) | 2025.04.01 |
| [CATSPOT]층별 학교 강의실 구조 설정 & 시간표 연동 BA2 페이지 구현기 (0) | 2025.03.27 |