사이트를 운영할 때는, 사용자가 파일을 올리고 다운로드 할 수 있는 저장소가 필요합니다.
이를 위해서 AWS 는 S3라는 저장소를 제공하고 있습니다.
오늘은 이 S3를 프리티어로 세팅해서 사용하는 방법을 알아보도록 하겠습니다.
우선은 아마존 콘솔 창에 로그인을 해줍시다.
이후, 왼쪽 검색창에서 S3 를 검색하면 S3 세팅을 위한 화면으로 이동이 가능합니다.
이런 식으로 구성된 화면을 볼 수 있습니다.
오른쪽 상단을 보면, 버킷 생성이라는 박스가 있고 그 내부에 버킷 만들기라는 버튼이 있습니다.
저 버튼을 눌러주세요.
이런 식으로 각종 정보를 설정하여 버킷을 생성 가능합니다.
버킷 이름의 경우는 “my-bucket” 과 같이 하이폰을 넣어 이름을 지정하는 것이 가능합니다.
또는 기존의 버킷 설정을 그대로 가져오기 위해 아래에 있는 버킷 선택을 눌러줄 수도 있습니다.
이외 설정은 아래와 같이 작성을 했습니다.
생성은 됐습니다.
이제 이 버킷을 이용하기 위한 설정을 진행 하겠습니다.
처음 S3를 생성하기 위해 검색했던 것과 같이 검색창에 IAM을 검색하면 가장 상단에 나타나는 것을 볼 수 있습니다.
지것을 눌러 이동합시다.
이런 식으로 IAM 대시보드에 접속을 할 수 있습니다.
여기 대시보드에서 왼쪽을 보면 각종 설정을 위한 메뉴창이 있는 것을 볼 수 있습니다.
여기 메뉴창에서 “역할” 을 선택하면 역할 설정을 위한 페이지로 넘어갑니다.
여기서 EC2 가 S3에 접근을 허용할 수 있도록 설정을 할 겁니다.
왼쪽에 있는 “역할 생성” 버튼을 눌러주세요.
서비스 또는 사용 사례를 위와 같이 EC2로 설정을 해주시고 넘어갑시다.
넘어가면 권한을 줄 수가 있는데요.
검색창에 s3를 치면, s3와 관련된 여러 권한들이 나타납니다.
FullAccess 를 선택하고 넘어갑시다.
이후에는 적절한 이름과, 설명을 넣어두고 하단 우측에 있는 “역할 생성” 버튼을 눌러줍시다.
이제 역할은 생성이 되었고, 이 역할을 내 EC2에 부여할 차례입니다.
기존에 생성했던 EC2 인스턴스에 들어오고, 작업에서 “보안” 을 선택 이후 “IAM 역할 수정”을 선택합시다.
여기서 아까 생성했던 IAM 역할을 선택하고 IAM 역할 업데이트를 해줍시다.
그럼 이제 실제 내 프론트엔드에서 S3로 파일을 어떻게 업로드 하면 되는지 살펴보겠습니다.
우선은 이를 위해서 다시 나의 S3 설정으로 가줍시다.
여기서 버킷을 선택하고 위와 같이 권한 탭으로 이동해서 퍼블릭 액세스 차단 부분을 편집해줍시다.
기존에는 모든 퍼블릭 액세스가 차단이 되어 있는데요.
이걸 해제하고 변경 사항을 저장합시다.
저장 후 다시 이전 화면으로 넘어가 아래로 내려가면, CORS 설정이 가능합니다.
여기서 CORS 섹션 오른쪽에 있는 편집을 클릭해줍시다.
여기 내부에 JSON 코드를 넣어 CORS 설정이 가능합니다.
내 프론트엔드에서 백엔드 라우터를 이용하여 S3 에 파일을 업로드 다운로드를 가능하게 하려면…
[
{
"AllowedHeaders": ["*"],
"AllowedMethods": ["GET", "PUT", "POST", "DELETE", "HEAD"],
"AllowedOrigins": ["http://example.com"],
"ExposeHeaders": ["ETag"],
"MaxAgeSeconds": 3000
}
]
위와 같이 코드를 넣어두고 저장하면 됩니다.
여기서 example.com 대신에 본인의 사이트 URL을 넣어주면 될 겁니다.
이후 다시 콘솔창으로 이동해서 IAM 설정을 추가할 겁니다.
다음과 같이 IAM 에서 사용자를 추가할 건데요.
이 사용자를 통해서 S3로 접근을 하기 위함입니다.
원하는 이름을 넣고, 사용자 유형은 IAM 사용자를 생성하고 싶음을 클릭해주세요.
그럼 해당 사용자의 패스워드를 설정 가능합니다.
그리고 “권한” 설정은 일전에 EC2 에 설정했을 때와 마찬가지로 S3 Full Access 를 할당해주세요.
결과적으로…
콘솔 로그인 URL, 사용자 이름, 콘솔 암호를 알아냈다면 성공입니다.
사용자가 생성이 됐다면 해당 사용자를 클릭하면 다음과 같이 설정을 볼 수 있습니다.
여기서 보안자격증명 섹션에서 여러 보안 정보들을 설정할 수 있는데요.
여기서 엑세스 key 와 id 를 설정하여야 합니다.
멀티 팩터 인증 아래 섹션을 보면, 액세스 키 박스가 있습니다.
여기서 액세스 키를 만들어 줍시다.
저는 위와 같이 선택을 하고 넘어갔습니다.
결과적으로 “액세스키” “비밀 액세스키” 를 확인하고 이 정보를 안전한 곳에 저장하시면 됩니다.
그리고 내가 접근한 S3의 버킷 이름과 AWS 리전을 확인합시다.
그럼 우리는 총 4개의 정보를 확실히 알 수가 있습니다.
1. 액세스 키
2. 비밀 액세스 키
3. AWS 리전
4. 버킷의 이름
이 4가지를 환경변수로 설정을 해줄 것입니다.
환경변수 설정하는 방법은 다음 포스팅을 참고해주세요.
환경 변수 설정을 위해서 SSH 로 내 EC2로 접속.
EC2 내에서 환경 변수 파일이 있는 디렉토리로 이동.
이동한 경로에서 “nano .env” 이용해서 기존에 작성되었던 환경변수 파일을 열기.
까지 수행을 하면 됩니다.
그리고 오픈한 환경변수 파일에 다음과 같이 추가를 해줍시다.
# .env 파일 내용
AWS_ACCESS_KEY_ID=얻은액세스키ID
AWS_SECRET_ACCESS_KEY=얻은비밀액세스키
AWS_REGION=사용하는AWS서비스리전
S3_BUCKET_NAME=사용하려는S3버킷이름
위 내용을 넣고 컨트롤 + X 누르고 Y를 눌러서 변경 내용을 저장합시다.
그럼 이제 거의 다 왔습니다.
SSH 에서 내 백엔드 코드를 넣은 위치로 이동합시다.
이동한 상태에서 “npm install aws-sdk” 를 사용하여 해당 모듈을 다운로드 해줍시다.
이 방법 역시 아까 위 쪽에 버튼으로 이동 가능하게 한 포스팅에 내용이 있습니다.
require('dotenv').config();
const AWS = require('aws-sdk');
// 환경변수에서 자격 증명을 설정합니다.
AWS.config.update({
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
region: process.env.AWS_REGION
});
// S3 객체를 생성합니다.
const s3 = new AWS.S3();
// 나머지 코드...
백엔드 코드의 앞부분에 다음과 같이 작성이 필요합니다.
설정해둔 환경 변수를 이용해서 AWS S3에 접근을 가능케 하는 코드입니다.
그렇다면 이제 프론트엔드 코드를 하나 만들어 봅시다.
import React, { useState } from "react";
const Test = () => {
const [file, setFile] = useState(null);
const handleFileChange = (event) => {
setFile(event.target.files[0]);
};
const handleUpload = async (event) => {
event.preventDefault();
if (!file) {
alert("Please select a file first!");
return;
}
// 백엔드에서 사전 서명된 URL 요청
const response = await fetch(
`/api/s3Url?fileName=${encodeURIComponent(
file.name
)}&fileType=${encodeURIComponent(file.type)}`
);
if (!response.ok) {
alert("Failed to get signed URL.");
return;
}
const data = await response.json();
const url = data.url;
// 사전 서명된 URL을 사용하여 파일 업로드
const s3Response = await fetch(url, {
method: "PUT",
headers: {
"Content-Type": file.type,
},
body: file,
});
if (s3Response.ok) {
alert("File uploaded successfully!");
} else {
const errorText = await s3Response.text();
console.error("Failed to upload file:", errorText);
alert("Failed to upload file. See console for more details.");
}
};
return (
);
};
export default Test;
파일을 선택하고 버튼을 통해서 해당 파일을 업로드 가능하게 하는 로직입니다.
여기서 API 는 upload 라는 API 라우터를 사용합니다.
이제 이 백엔드 라우터를 작성해봅시다.
const s3 = new AWS.S3();
// 로그: AWS S3 객체가 성공적으로 생성되었는지 확인
console.log("AWS S3 configured with region:", s3.config.region);
app.get("/api/s3Url", (req, res) => {
const params = {
Bucket: process.env.S3_BUCKET_NAME,
Key: `uploads/${Date.now()}_${req.query.fileName}`,
Expires: 300, // URL의 유효 시간 설정 (초 단위)
ContentType: req.query.fileType, // 올바른 파일 타입 설정
};
s3.getSignedUrl("putObject", params, (err, url) => {
if (err) {
console.error("Error creating signed URL", err);
return res.status(500).json({ error: "Error creating signed URL" });
}
res.json({ url });
});
});
라우터는 위와 같이 설정을 마쳤습니다.
참고로 위 라우터를 사용하기 위해서는 다음의 모듈 설치가 필요 합니다.
npm install multer multer-s3
모듈 설치 및 프론트엔드 설정, 백엔드 라우터 설정을 마쳤다면 이제 끝입니다.
실제로 작동이 되는지 확인을 해보겠습니다.
먼저 아직 업로드를 하기 이전 상태인 S3 의 화면입니다.
그럼 방금 만든 프론트엔드 화면을 보겠습니다.
이런 조잡한 필드인데요.
파일 선택으로 특정한 파일을 선택하고, 그 파일을 Upload File 이라는 버튼을 누르면 올릴 수 있도록 할 겁니다.
아무거나 하나 선택해서 넣어볼게요.
이렇게 특정 png 파일을 선택했습니다.
그리고 Upload File 버튼을 눌러보겠습니다.
요런 식으로 파일이 성공적으로 업로드 되었다는 메시지가 뜹니다.
다시 한 번 S3 페이지로 돌아가서 확인을 해보겠습니다.
uploads 라는 경로가 생긴 것을 볼 수 있습니다.
이곳에 우리가 업로드한 파일이 업로드 되었다는 겁니다.
저걸 클릭해서 경로 내부로 들어갑시다.
방금 업로드 한 png 파일이 올바르게 S3 로 들어간 것을 볼 수 있습니다.