Next.js 를 사용하여 개발중인 웹 어플리케이션에서 Toast UI 에디터를 이용해서 이미지를 첨부해야하는데 이 이미지를 blob 으로 DB에 그대로 넣으면 용량이 너무 크기에 .. 고민을 하다가 오라클 클라우드에서 제공하는 Bucket을 알게 되었다.
참고할만한 레퍼런스가 많이 없어서 혼자 삽질을 엄청했다.
목차
- Oracle Cloud Bucket 이란?
- Bucket 생성
- IAM 사용자 생성
- 정책 수립
- 소스 코드 예시
1. Oracle Cloud Bucket 이란?
간단하게 요약하자면 오라클 클라우드의 객체 스토리지 서비스로 다양한 유형의 파일(이미지, 동영상, 문서)과 데이터(DB 백업, 로그등)를 저장하는데 사용되는 컨테이너이다. 디렉토리 구조로 관리되고 있어 직관적이고 데이터를 유연하게 저장하고 관리할 수 있다.
오라클 클라우드 버킷은 크게 두가지 종류가 있는데 이미지, 동영상, 문서 와 같은 비구조적인 데이터를 관리하는데 용이한 오브젝트 스토리지와 백업보존, 로그 등의 장기보존이 필요한 데이터를 저장하는데 용이한 아카이브 스토리지가 있다. 이번 포스팅은 오브젝트 스토리지를 사용하여 이미지를 올리고 지우는 방법에 대한 포스팅이다.
프리티어에서는 오브젝트 스토리지와 아카이브 스토리지를 합하여 총 20GB를 무료로 사용할수 있다. 구글링해보니 오브젝트 스토리지만으로 20GB를 사용하는 것도 가능하다고 한다.
2. Bucket 생성
1) 버킷 생성
메뉴 > 스토리지 > 오브젝트 스토리지 및 아카이브 스토리지 > 버킷을 클릭하여 버킷 화면으로 이동한 뒤 구획을 이전 포스팅에서 생성했었던 구획으로 변경하고 버킷생성 버튼을 클릭한다.
버킷 생성 화면에서는 원하는 버킷이름을 입력하고 스토리지 계층은 오브젝트 스토리지를 사용할 것이므로 기본으로 설정되어 있는 표준 값을 건들지 않고 나머지 설정 값들도 기본 설정값을 사용한다.
생성버튼을 클릭하면 위와 같이 성공적으로 버킷이 만들어진다.
2) 객체
버킷을 생성하고 나면 하단에 객체 영역이 보이는데 해당 영역에서 버킷에 있는 비정형데이터(동영상, 이미지, 문서 등)을 조회하고 업로드, 다운로드, 삭제 등의 관리 작업을 할 수 있다.
업로드시 그냥 파일을 업로드 할 수 도 있지만 위와 같이 접두어를 붙여서 업로드를 하게 되면 디렉토리 구조로 파일이 저장되는 것을 확인할 수 있다.
우측의 점세개 버튼을 클릭하면 객체를 다운로드하거나 삭제를 할 수 있는데 해당 객체에 접근할수 있는 URL은 객체 세부정보 보기를 클릭하면 확인할 수 있다.
3) 가시성편집
외부에서 버킷에 파일을 업로드하거나 다운로드할 수 있도록 가시성 편집을 클릭하여 전용 -> 공용으로 설정을 바꾼 후 변경사항을 저장한다.
✔︎주의
공용으로 바꿀 시 버킷 내 모든 자원들을 외부에서 접근이 가능하고 업로드 및 다운로드, 삭제도 가능해진다. 이는 보안상 좋지 않으므로 오라클 클라우드에서는 사전인증된 요청 사용을 권하고 있다. 사전 인증된 요청을 생성하여 사용하면 버킷 내 특정 자원 또는 특정 접두어가 붙은 객체만 접근이 가능하도록 제한 할 수 있고 읽기 및 쓰기 권한 부여, 만료일자등을 설정할 수 있다.
3. IAM 사용자 생성
위에서 생성한 버킷에 접근하기 위해서 사용자를 만들고 사용자가 버킷에 접근할 수 있도록 정책을 만들어줘야 한다.
1) 도메인 생성
사용자를 생성하기 위해서 IAM ID 도메인을 먼저 생성해야므로 도메인 화면으로 이동한 후 구획을 변경하고 도메인생성버튼을 클릭한다.
도메인 생성시 원하는 이름을 입력하고 도메인 유형은 사용가능(무료)으로 선택했다. 나머지 유형들은 FreeTier기간이 지나면 과금이 될 수 있을거 같아 사용가능으로 선택하였다.
2) 사용자 생성
도메인 생성을 완료하였다면 해당 도메인을 클릭하여 도메인 세부정보 화면으로 이동 후 왼쪽 탭에서 사용자를 클릭하여 사용자를 생성한다.
이름, 성, 이메일을 입력 후 그룹을 지정해야 하는데 도메인 생성시 default로 생성된 그룹으로 지정해줘도 되고 도메인 항목중 그룹 탭에서 그룹을 따로 만들어서 지정을 해줘도 된다. 이번 포스팅에서는 기본으로 생성된 그룹에 지정하여 진행했다.
3) API 키 추출 및 OCI Config 파일생성
사용자를 생성한후 해당 사용자의 api 키를 발급받고 api 키 경로와 사용자 정보가 담긴 config 파일을 생성해야 한다. config 파일을 이용하여 본인의 개발하고 있는 웹어플리케이션 내에서 버킷에 접근할수 있는 권한을 제공한다.
사용자 생성이 완료되면 해당 사용자를 클릭하여 사용자 세부정보 화면으로 이동 후 왼쪽 하단의 리소스 탭에서 API 키를 클릭한다.
API 키 항목을 선택하고 API 키 추가 를 클릭하여 API 전용키와 공용 키를 다운받은후 추가 버튼을 클릭하여 API 키를 생성한다.
생성된 API 키의 좌측의 점 세개 버튼을 클릭하여 구성파일 보기를 클릭한다.
구성 파일 미리보기 내용을 복사해서 config 파일 내용 안에 붙여 넣는다. config 파일이 없다면 새로 생성해서 해당내용을 입력한다.
key_file 에 다운받은 API 전용키 경로를 넣어주면 된다. config 파일의 경로는 반드시 ~/.oci 폴더에 있을 필요는 없다. config파일을 읽는 npm에서 다운받을 수 있는 oci-common 모듈의 경우 config파일의 경로를 매개변수로 전달해줄 수 있기도 하고 어차피 VM 인스턴스 스에서 웹어플리케이션을 서버에 올릴 거라면 API 키와 config 파일을 SFTP 프로그램으로 인스턴스쪽으로 넘겨줘야 한다.
4. 정책수립
이제 마지막으로 위에서 생성한 사용자에게 버킷에 접근할 수 있도록 정책을 생성해주면 된다.
적당한 정책이름과 설명을 입력 후 정책 작성기에서 정책 사용 사례에서 저장 영역 관리를 선택후 공통 정책 템플리트에서 오브젝트에 관한 정책 3가지(쓰기, 다운로드하기, 관리하기)를 선택한다. 정책이 하나씩밖에 안만들어져서 총 3개를 만들어야한다. 그룹은 위에서 생성한 도메인을 선택하고 도메인에 속한 사용자가의 그룹과 구획을 선택해주면 된다.
5. 소스 코드 예시
코드에서 사용하기 전에 위에서 생성한 API 키와 config 파일을 SFTP 프로그램을 사용하여 VM 인스턴스에 적당한 경로에 복사한다.
필자는 파일질라를 이용하여 적당한 경로에 옮겨놨다.
파일질라 좌측 상단에 사이트 관리자 버튼을 클릭하여 접속정보를 입력한다.
프로토콜 : SFTP 선택
호스트 : VM 인스턴스 공용 IP
로그온 유형 : 키파일
사용자 : opc
키파일 : ssh 전용키 파일 경로
입력후 연결버튼을 클릭하여 해당 파일을 옮겨주자.
소스코드 예시
import { NextApiRequest, NextApiResponse } from 'next';
import { ObjectStorageClient } from 'oci-objectstorage';
import { IncomingForm } from 'formidable';
import fs from 'fs';
export const config = {
api: {
bodyParser: false,
},
};
export default async function UploadImgFile(request: NextApiRequest, response: NextApiResponse) {
const common = require('oci-common');
const path = require('path');
//config 파일 경로
const ociConfigFilePath = path.join(process.cwd(), '/api_config/config');
const form = new IncomingForm();
await new Promise((resolve, reject) => {
form.parse(request, (err, fields, files) => {
if (err) {
reject(response.status(500).json({ result: err }));
} else {
resolve(files);
}
});
}).then(async (res: any) => {
//config 파일을 읽고 버킷접근권한을 제공
const provider = new common.ConfigFileAuthenticationDetailsProvider(ociConfigFilePath);
const objectStorageClient = new ObjectStorageClient({ authenticationDetailsProvider: provider });
//버킷 접속 정보
const namespace = process.env.CLOUD_BUCKET_NAME_SPACE;
const bucketName = process.env.CLOUD_BUCKET_NAME;
//업로드할 객체이름
const objectName = res.file[0].originalFilename;
const filePath = res.file[0].filepath;
//버킷에 업로드하기 위한 파라미터 작성
const putObjectRequest = {
namespaceName: namespace,
bucketName: bucketName,
objectName: objectName,
contentLength: res.file[0].size,
putObjectBody: fs.readFileSync(filePath),
};
// 버킷 업로드
const putObjectResponse = await objectStorageClient.putObject(putObjectRequest);
return response.status(200).json(putObjectResponse);
});
}
우선 버킷에 접근하기 위해 권한을 제공받아야하므로 아래의 두가지 모듈을 설치한다.
npm i oci-objectstorage
npm i oci-common
oci-common.ConfigFileAuthenticationDetailsProvider 을 사용하여 config 파일을 읽고 권한을 부여 받은뒤 oci-objectstoarage 에서 ObjectStorageClient (사용자)를 생성하여 버킷 접속정보와 객체를 putObject 파라미터로 보내서 업로드한다.