MinIO는 오픈소스 기반의 고성능 객체 스토리지 서버입니다. AWS S3와 호환되는 API를 제공하여 클라우드 네이티브 애플리케이션을 위한 완벽한 스토리지 솔루션으로 자리잡고 있습니다.
MinIO는 S3 API와 완벽하게 호환됩니다. 즉, 기존 S3 클라이언트 라이브러리를 그대로 사용할 수 있어 학습 곡선이 낮고 마이그레이션이 쉽습니다.
클라우드 스토리지 비용이 부담되시나요? MinIO는 온프레미스나 프라이빗 클라우드에서 직접 운영할 수 있어 장기적으로 비용을 크게 절감할 수 있습니다.
로컬 개발 환경에서 S3와 동일한 API를 사용하며 테스트할 수 있습니다. 실제 AWS 계정 없이도 개발과 테스트가 가능합니다.
Go 언어로 작성되어 가볍고 빠르며, 멀티 테넌시와 고가용성을 지원합니다.
클라우드 네이티브 아키텍처에 최적화되어 있어 컨테이너 환경에서 쉽게 배포하고 관리할 수 있습니다.
Docker를 이용하면 MinIO를 몇 분 안에 실행할 수 있습니다.
docker run -d \
-p 9000:9000 \
-p 9001:9001 \
--name minio \
-e MINIO_ROOT_USER=minioadmin \
-e MINIO_ROOT_PASSWORD=minioadmin \
-v ~/minio/data:/data \
minio/minio server /data --console-address ":9001"
브라우저에서 http://localhost:9001로 접속합니다.
로그인 정보:
이제 MinIO가 정상적으로 작동하는 것을 확인했습니다!
실제 애플리케이션에서 MinIO를 어떻게 사용하는지 알아보겠습니다.
npm install minio
const Minio = require('minio');
const minioClient = new Minio.Client({
endPoint: 'localhost',
port: 9000,
useSSL: false,
accessKey: 'minioadmin',
secretKey: 'minioadmin'
});
async function createBucket(bucketName) {
try {
const exists = await minioClient.bucketExists(bucketName);
if (exists) {
console.log(`버킷 '${bucketName}'이 이미 존재합니다.`);
} else {
await minioClient.makeBucket(bucketName, 'us-east-1');
console.log(`버킷 '${bucketName}'이 생성되었습니다.`);
}
} catch (err) {
console.error('버킷 생성 중 오류:', err);
}
}
createBucket('my-bucket');
async function uploadFile(bucketName, objectName, filePath) {
try {
const metaData = {
'Content-Type': 'application/octet-stream'
};
await minioClient.fPutObject(bucketName, objectName, filePath, metaData);
console.log(`파일 '${objectName}'이 업로드되었습니다.`);
} catch (err) {
console.error('파일 업로드 중 오류:', err);
}
}
uploadFile('my-bucket', 'test.txt', './test.txt');
async function downloadFile(bucketName, objectName, downloadPath) {
try {
await minioClient.fGetObject(bucketName, objectName, downloadPath);
console.log(`파일 '${objectName}'이 다운로드되었습니다.`);
} catch (err) {
console.error('파일 다운로드 중 오류:', err);
}
}
downloadFile('my-bucket', 'test.txt', './downloaded-test.txt');
async function listObjects(bucketName) {
try {
const stream = minioClient.listObjects(bucketName, '', true);
stream.on('data', (obj) => {
console.log('파일:', obj.name, '크기:', obj.size);
});
stream.on('error', (err) => {
console.error('목록 조회 중 오류:', err);
});
} catch (err) {
console.error('오류:', err);
}
}
listObjects('my-bucket');
async function deleteFile(bucketName, objectName) {
try {
await minioClient.removeObject(bucketName, objectName);
console.log(`파일 '${objectName}'이 삭제되었습니다.`);
} catch (err) {
console.error('파일 삭제 중 오류:', err);
}
}
deleteFile('my-bucket', 'test.txt');
async function getPresignedUrl(bucketName, objectName, expirySeconds = 3600) {
try {
const url = await minioClient.presignedGetObject(
bucketName,
objectName,
expirySeconds
);
console.log('다운로드 URL:', url);
return url;
} catch (err) {
console.error('URL 생성 중 오류:', err);
}
}
getPresignedUrl('my-bucket', 'test.txt', 7200); // 2시간 유효
const express = require('express');
const multer = require('multer');
const Minio = require('minio');
const fs = require('fs');
const app = express();
const upload = multer({ dest: 'uploads/' });
const minioClient = new Minio.Client({
endPoint: 'localhost',
port: 9000,
useSSL: false,
accessKey: 'minioadmin',
secretKey: 'minioadmin'
});
const BUCKET_NAME = 'uploads';
// 버킷 초기화
(async () => {
const exists = await minioClient.bucketExists(BUCKET_NAME);
if (!exists) {
await minioClient.makeBucket(BUCKET_NAME, 'us-east-1');
}
})();
// 파일 업로드 엔드포인트
app.post('/upload', upload.single('file'), async (req, res) => {
try {
const file = req.file;
const objectName = `${Date.now()}-${file.originalname}`;
await minioClient.fPutObject(
BUCKET_NAME,
objectName,
file.path,
{ 'Content-Type': file.mimetype }
);
// 임시 파일 삭제
fs.unlinkSync(file.path);
// Presigned URL 생성
const url = await minioClient.presignedGetObject(BUCKET_NAME, objectName);
res.json({
success: true,
message: '파일이 업로드되었습니다.',
filename: objectName,
url: url
});
} catch (err) {
res.status(500).json({ success: false, error: err.message });
}
});
app.listen(3000, () => {
console.log('서버가 3000번 포트에서 실행 중입니다.');
});
기본 계정 정보를 반드시 변경하세요.
docker run -d \
-p 9000:9000 \
-p 9001:9001 \
--name minio \
-e MINIO_ROOT_USER=your_secure_username \
-e MINIO_ROOT_PASSWORD=your_secure_password_min_8_chars \
-v ~/minio/data:/data \
minio/minio server /data --console-address ":9001"
프로덕션에서는 반드시 HTTPS를 사용하세요.
const minioClient = new Minio.Client({
endPoint: 'minio.yourdomain.com',
port: 443,
useSSL: true, // HTTPS 사용
accessKey: process.env.MINIO_ACCESS_KEY,
secretKey: process.env.MINIO_SECRET_KEY
});
민감한 정보는 환경변수로 관리하세요.
require('dotenv').config();
const minioClient = new Minio.Client({
endPoint: process.env.MINIO_ENDPOINT,
port: parseInt(process.env.MINIO_PORT),
useSSL: process.env.MINIO_USE_SSL === 'true',
accessKey: process.env.MINIO_ACCESS_KEY,
secretKey: process.env.MINIO_SECRET_KEY
});
MinIO는 S3 호환 객체 스토리지가 필요한 모든 프로젝트에 훌륭한 선택입니다. 특히 다음과 같은 경우에 적극 추천합니다: