[React Native] S3 연동 이미지 업로드
카테고리 : Development
태그: development, - React-Native - reactnative - react-native-url-polyfill - react-native-image-picker - aws-sdk/client-s3 - aws-sdk/lib-storage - buffer - react-native-get-random-values - react-native-fs - IAM 설정 - AmazonS3FullAccess - 버킷 생성 - 버킷 권한 설정 - 이미지 업로드 - react native S3 연동 - 업로드 URL 반환
태그: development, - React-Native - reactnative - react-native-url-polyfill - react-native-image-picker - aws-sdk/client-s3 - aws-sdk/lib-storage - buffer - react-native-get-random-values - react-native-fs - IAM 설정 - AmazonS3FullAccess - 버킷 생성 - 버킷 권한 설정 - 이미지 업로드 - react native S3 연동 - 업로드 URL 반환
🔥 1. 사전 설치
yarn add react-native-url-polyfill
yarn add react-native-image-picker
yarn add @aws-sdk/client-s3
yarn add @aws-sdk/lib-storage
yarn add buffer
yarn add react-native-get-random-values
yarn add react-native-fs
yarn add -D @aws-sdk/types
yarn add @types/react-native-get-random-values
**react-native-image-picker
: 앨범 접근 및 카메라 허용 ⇒ 이미지 업로드니 당연히 필요****react-native-url-polyfill
: URL 객체를 사용할 때 호환성 관리****@aws-sdk/client-s3
: S3 버킷을 생성하거나 삭제하고, 버킷 내 객체 관리 및 업로드에 필요****@aws-sdk/lib-storage
: Amazon S3 (Simple Storage Service)와 같은 스토리지 서비스를 통해 파일을 업로드****buffer
: 파일, 이미지, 네트워크 통신 등 RN에서 이진 데이터를 위함****react-native-get-random-values
: 무작위 바이트를 생성 작업****react-native-fs
: 이미지 파일 읽기 쓰기**
🔥 2. IAM 설정
1. 사용자 생성
2. 세부 정보 지정
3. 권한 설정 (AmazonS3FullAccess)
4. 사용자 생성
5. 액세스 키 다운로드
.csv
파일을 다운로드- 다운로드 기회는 한번
🔥 3. 버킷 생성
1. 사용자 생성
2. 리전 선택
3. 객체 소유권
- AWS S3 버킷에서 객체(파일)의 소유권은 업로드를 수행한 IAM 사용자(계정)에게 자동으로 할당된다. 객체의 소유권은 기본적으로 업로드한 IAM 사용자에게 속함
- ACL(Access Control List)은 AWS S3 버킷의 객체에 대한 액세스 권한을 관리하는 기능 ⇒ 업로드된 객체에 대한 공개 읽기 액세스를 허용
- 업로드를 수행한 IAM 사용자에게 자동으로 할당
4. 퍼블릭 엑세스 설정
- S3에 접근할 수 있는 URL을 입력하여 이미지가 정상적으로 업로드
- 실무에선 모든 퍼블릭 액세스 차단
- 버킷에 저장되는 객체를 자동으로 암호화해 주는 설정
5. 암호화 설정
6. 버킷 만든 후 권한 설정
7. 버킷 권한 설정
{
{
"Version": "2012-10-17",
"Id": "Policy1686890931481",
"Statement": [
{
"Effect": "Allow",
"Principal": "",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::your-storage"
}
]
}
- 정책 타입 선택
- 버킷 정책이 적용될 대상 (전체: *)
- 버킷이 수행할 액션 (GetObject, PutObject 선택)
- 버킷에 어떤 리소스에 적용할지 (버킷이름/*)
8. 이미지 업로드 테스트
🔥 3. 실제 코드 반영
1. 이미지 등록 후 S3에 업로드
import {
ImageLibraryOptions,
ImagePickerResponse,
launchImageLibrary,
} from "react-native-image-picker";
const chooseImage = async () => {
const options: ImageLibraryOptions = {
mediaType: "photo", // 추가: 원하는 미디어 타입('photo', 'video' 등)을 지정합니다.
};
launchImageLibrary(options, async (response: ImagePickerResponse) => {
// 이미지 라이브러리로부터의 응답 처리
if (response.didCancel) {
console.log("사용자가 이미지 선택을 취소했습니다.");
} else if (response.errorCode === "camera_unavailable") {
console.log("카메라 사용이 불가능 합니다");
} else if (response.errorCode === "permission") {
console.log("카메라 권한 설정이 잘못되었습니다");
} else {
if (response.assets && response.assets.length > 0) {
const { uri, fileName, type: fileType } = response.assets[0];
try {
const uploaded = await uploadToS3(uri, fileName, fileType);
if (uploaded) {
console.log("S3 이미지 업로드 완료:", uploaded);
setCertificateImage(uploaded);
}
// 업로드 성공 후 추가 작업을 수행할 수 있습니다.
} catch (error) {
console.error("S3 이미지 업로드 실패:", error);
}
} else {
// 선택된 이미지가 없는 경우의 처리
}
}
});
};
2. 이미지 등록 후 S3에 업로드
const chooseImage = () => {
const options: ImageLibraryOptions = {
mediaType: "photo", // 추가: 원하는 미디어 타입('photo', 'video' 등)을 지정.
};
launchImageLibrary(options, (response: ImagePickerResponse) => {
// 이미지 라이브러리로부터의 응답 처리
if (response.didCancel) {
console.log("사용자가 이미지 선택을 취소했습니다.");
} else if (response.errorCode === "camera_unavailable") {
console.log("카메라 사용이 불가능 합니다");
} else if (response.errorCode === "permission") {
console.log("카메라 권한 설정이 잘못되었습니다");
} else {
console.log(response);
const selectedImageUri = response.assets && response.assets[0]?.uri;
if (selectedImageUri) {
setSelectedImage(selectedImageUri);
setProfile(selectedImageUri.uri);
} else {
// 선택된 이미지가 없는 경우의 처리
}
}
});
};
3. 업로드 후 URL 반환
import { S3Client } from "@aws-sdk/client-s3";
import "react-native-url-polyfill/auto";
import "react-native-get-random-values";
import { Upload } from "@aws-sdk/lib-storage";
import { Buffer } from "buffer";
import RNFS from "react-native-fs";
import { AwsCredentialIdentity } from "@aws-sdk/types";
import Config from "react-native-config";
const options = {
keyPrefix: "uploads/",
bucket: Config.BUCKET,
region: Config.REGION,
successActionStatus: 201,
};
let credentials: AwsCredentialIdentity = {
accessKeyId: Config.ACCESSKEYID || "",
secretAccessKey: Config.SECRETACCESSKEY || "",
};
const client = new S3Client({
region: options.region,
credentials: credentials,
});
export async function uploadToS3(uri: any, name: any, type: any) {
try {
const file = {
uri: uri,
name: name,
type: type,
};
const fileData = await RNFS.readFile(uri, "base64");
const upload = new Upload({
client: client,
params: {
Bucket: Config.BUCKET,
Key: "uploads/" + file.name,
Body: Buffer.from(fileData, "base64"),
ContentType: "image/*",
},
});
const response = await upload.done();
console.log("response?", response);
if (response && response.Location) {
return response.Location.replace(
`${Config.BUCKET}.s3.ap-northeast-2.amazonaws.com`,
`s3.ap-northeast-2.amazonaws.com/${Config.BUCKET}`
);
}
} catch (error) {
console.log("에러>", error);
return false;
}
}