이미지 업로드가 계속 실패하는 문제 때문에 오랜 시간 붙잡고 있다가 결국 해결해서 정리함
(ReactNative Cli TypeScript 프로젝트)
▼ S3와 IAM 관련 설정은 아래 게시글을 참고 ▼
[FN] AWS S3, AWS IAM
게시글을 작성 후 Firebase database에 게시글 데이터는 잘 저장이 된다.이제 게시글에 사용자가 이미지를 등록하는 기능을 추가하려고 하는데. Firebase Storage도 있지만,나는 AWS S3를 사용하여 구현하
codingco.tistory.com
▼ image-picker(사진 선택) 관련 설명은 아래 게시글을 참고 ▼
[FN] 게시판 개발 일지[3] / image-picker
이전 글에서 AWS S3 관련 설정을 다했으니 이제는 게시글에 사진을 등록하고 불러오고 등 구현해보자과정은 사용자가 게시글을 작성할 때 사진을 등록 -> 게시글 작성 -> 사진은 AWS S3에 업로드 ->
codingco.tistory.com
1. .env
선택된 사진을 AWS S3에 업로드하기 위해서는 프로젝트 루트 폴더에 .env 라는 파일을 만들고 거기에 민감한 엑세스 키, 비밀 키를 정의하고 .gitignore에 .env 를 정의하여 깃허브에 올라가지 않도록 해야한다.
깃허브에 민감한 정보를 push 하면서 깃허브에서 자동으로 막아버림..
.env
S3_BUCKET=
REGION=
AWS_ACCESS=
AWS_SECRET=
다음으로는 types 폴더를 하나 생성하고 env.d.ts 파일을 생성해서 아래 코드처럼 작성 후 ImageUploader.tsx 에서 @env를 import 하여 사용한다.
.env.d.ts
declare module '@env' {
export const S3_BUCKET: string;
export const REGION: string;
export const AWS_ACCESS: string;
export const AWS_SECRET: string;
}
이후에는 babel.config.js 코드를 수정한다. 추가하기전에 dotenv는 install 해주고 아래처럼 dotenv 코드를 추가해야함.
babel.config.js
module.exports = {
presets: ['module:@react-native/babel-preset'],
plugins: [
'@babel/plugin-transform-class-static-block',
[
'module:react-native-dotenv',
{
moduleName: '@env',
path: '.env',
safe: false,
allowUndefined: true,
},
],
],
};
마지막으로 tsconfig.json 코드를 아래처럼 paths를 추가해준다.
{
"extends": "@react-native/typescript-config/tsconfig.json",
"compilerOptions": {
"lib": ["esnext", "dom"],
"strict": true,
"baseUrl": "./",
"paths": {
"@env": ["node_modules/react-native-dotenv"]
}
}
}
2. 게시글 작성 페이지
게시글 작성 페이지에서 이미지 업로드 관련 import 해야할 부분은 다음과 같다.
- ImageUploader : 이미지 선택, 삭제, 수정 컴포넌트
- @aws-sdk/client-s3 : AWS S3와 상호작용할 때 사용
- '@env' : 앞에서 설명했듯이 S3 버킷 관련 민감한 정보들을 .env에 정의하고 가져와서 사용
- RNFS : S3에 업로드할 때 이미지를 Base64로 변환해야 하는데, 이를 도와줌
- Buffer : Base64로 변환된 이미지 데이터를 바이너리 형태로 변환 / S3 업로드할 때 사용해야 할 수도
그리고 가장 애를 많이 먹었던 url 관련 업로드 실패 에러를 해결해 준 react-native-url-polyfill, react-native-get-random-values, uuid 이 세가지 때문에 이미지 업로드 성공
import ImageUploader from "../component/MeetingComponent/ImageUploader";
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
import { S3_BUCKET, REGION, AWS_ACCESS, AWS_SECRET } from '@env';
import RNFS from 'react-native-fs';
import { Buffer } from "buffer";
import 'react-native-url-polyfill/auto';
import 'react-native-get-random-values';
import { v4 as uuidv4 } from 'uuid';
.env에 정의한 값들로 S3Client를 초기화 해준다.
const s3Client = new S3Client({
region: REGION,
credentials: {
accessKeyId: AWS_ACCESS,
secretAccessKey: AWS_SECRET,
},
});
- imageUri : 선택한 이미지의 경로를 전달 받음.
- imageUri.split('/').pop() : 이미지 URI 마지막 부분을 가져와서 파일 이름을 추출함
- file:// 을 제거하여 로컬 경로로 변환
- RNFS.readFile : AWS S3에 업로드하기 위해 파일을 Base64 문자열로 변환
- binaryData : Base64 인코딩된 데이터를 버퍼(Binary) 형식으로 변환 / AWS S3 업로드 시 텍스트가 아닌 바이너리 데이터를 전송해야 함.
- result : S3로 이미지 업로드 실행하고 성공하면 result에 업로드 결과 저장
- 성공 시 이미지 URL 반환 / 반환된 URL은 firestore database에 저장하여 나중에 게시판이나 게시글에서 이미지를 불러올 때 사용
const uploadImageToS3 = async (imageUri: string) => {
try {
console.log('선택된 이미지 경로:', imageUri);
const fileName = imageUri.split('/').pop();
const filePath = imageUri.replace('file://', '');
const base64Image = await RNFS.readFile(filePath, 'base64');
const binaryData = Buffer.from(base64Image, 'base64');
const uploadParams = {
Bucket: S3_BUCKET,
Key: fileName,
Body: binaryData,
ContentType: 'image/jpeg',
};
const result = await s3Client.send(new PutObjectCommand(uploadParams));
console.log("이미지 업로드 성공:", result);
Alert.alert("이미지 업로드 성공", `파일 이름: ${fileName}`);
return `https://${S3_BUCKET}.s3.${REGION}.amazonaws.com/${fileName}`;
}
사진을 선택하고 게시글을 선택했을 때 정상적으로 S3에 이미지가 업로드된다. fn_logo는 이미지를 선택하지 않고 작성된 게시글에 띄울 기본 이미지이다.
Firestore Database에도 게시글 내용들뿐만 아니라 S3에 업로드된 이미지 url을 잘 저장함 - 나중에 이미지를 불러올 때 이미지 url을 불러오면 된다
사진을 선택하지 않은 게시글과 사진을 선택한 게시글이 게시판에 잘 출력된다
'ReactNative :' 카테고리의 다른 글
[FN] 공연 정보 조회 페이지 UI 수정 (1) | 2025.04.05 |
---|---|
[FN] 공연 정보 조회 / KOPIS 공연 정보 Open API 가져오기, XML - JSON 파싱 (0) | 2025.04.05 |
[JH] 학생을 위한 개발 가이드 (9) | 2025.01.25 |
[FN] 게시판 개발 일지[3] / image-picker (7) | 2025.01.24 |
[FN] React Native cli 개발 환경 구축 / 윈도우, 안드로이드 스튜디오 (8) | 2025.01.17 |