Today I Learned
(24.07.22)[15주차] MinIO 활용 정리
프로젝트 구성에 있어서 데이터를 저장하고, 조회, 그리고 수정도 할 수 있게끔 기능을 추가를 했다.
DI 배포 파이프라인에 따라서 AWS S3를 사용해야하지만,
개발 단계에서 테스트용으로 직접적으로 사용하는데에는 비용적으로 부담이 크고, 빠르게 변경을 할 수 없다는 단점이 있다.
이 때, 오픈 소스 객체 스토리지 서버인 MinIO를 활용하여 개발을 진행하려고 한다.
이를 위해 아래에는 MinIO를 활용하기 위해 정리하고 학습한 내용이다.
MinIO
- 오픈 소스 객체 스토리지 서버를 제공해주는 소프트 웨어
- 오픈 소스 이므로 커뮤니티를 통한 정보와 문서가 제공되고 있음
- 쉬운 튜토리얼이 가능 : WebUI 제공
- Amazon S3 API와 호환이 가능
- 실제 S3에 배포 전 기능을 그대로 활용해서 개발, 테스트를 실제 환경과 똑같은 시뮬레이션을 통해서 진행이 가능
- Object Storage 형태이기 때문에 직접적으로 접근하여 수정이 아닌 덮어쓰는 방식으로 사용
- 저장 단위가 객체(데이터, 메타데이터, 식별자)
- 객체 키를 사용해서 파일 업로드시 기존 객체는 새 객체로 덮어써지는 방식 → 동일 객체에 대해 여러 버전을 관리가 가능
- 전송중인 데이터, 저장 데이터를 암호화 해서 다룰 수 있는 높은 보안성
- Kubernetes, Docker, 다양한 OS 환경에 구분없이 적용 가능
- 따라서, 로컬 개발도 가능
참고 : https://min.io/
MinIO 환경 모드
Stand-alone 단독 모드
version: "3"
services:
minio:
image: minio/minio:latest // dockerhub 사용
container_name: minio
# restart: always
ports:
- '9000:9000' // 파일 업로드 다운로드 포트
- '9001:9001' // WebUI 사용할수 있는 포트
environment:
- MINIO_ROOT_USER=minio // 개인설정
- MINIO_ROOT_PASSWORD=miniopass // 개인설정
command: server --address ":9000" --console-address ":9001" /data
volumes:
- ~/docker-repo/minio:/var/lib/minio
volumes:
minio_data:
external: true
- MinIO 기본 실행 모드, 단일 서버 인스턴스에서 MinIO 실행 방식
- 따라서, 로컬 개발, 테스트 / 단일 서버에서 실행 가능
- docker-compose 파일을 사용해서 docker을 통해서 Container 실행을 통해 MinIO 실행
- HTTP 방식으로 위의 command에 따라서 http://localhost:9000 으로 접속해서 WebUI를 통해서 컨트롤 가능
- HTTPS 로 사용시 따로 사용자가 인증서 발급을 진행해야함
Distributed Mode 분산모드
version: "3"
services:
**minio1**:
image: minio/minio:latest
container_name: minio1
ports:
- '9000:9000'
- '9001:9001'
environment:
- MINIO_ROOT_USER=minio
- MINIO_ROOT_PASSWORD=miniopass
command: server <http://minio1/data> <http://minio2/data>
volumes:
- ~/docker-repo/minio1:/data
**minio2**:
image: minio/minio:latest
container_name: minio2
ports:
- '9002:9000'
- '9003:9001'
environment:
- MINIO_ROOT_USER=minio
- MINIO_ROOT_PASSWORD=miniopass
command: server <http://minio1/data> <http://minio2/data>
volumes:
- ~/docker-repo/minio2:/data
networks:
default:
driver: bridge
- MinIO의 클러스터링 기능을 통해 다수의 서버 인스턴스로 분산해서 운영할 수 있게끔 하는 모드
- 따라서, 고가용성과 데이터 복제 기능을 사용할 수 있음
- 대규모 환경과 데이터 안정성을 더 우선순위로 다룰 때 사용
- 단독 모드의 설정에서 services의 minio를 minio1, minio2 … 이런 방식으로 여러개를 작성해서 Docker로 실행할 수 있음
- → 컨테이너를 여러개 만드는 것
MinIO 데이터 관련 모드
- 관련하여 따로 설정을 해줘야함
FS, File System 모드
- Storage Backend Modes
- MinIO 서버가 실행이 될 경우, 파일 시스템을 Storage BE로 사용을 하는 모드
- 로컬 파일 이나 네트워크 파일 시스템을 따로 저장소로 활용이 가능
- 여러 MinIO 인스턴스가 다른 환경에서 동일한 FS로 활용할 수 있음
- MinIO가 아닌 FS를 통한 객체 수정이 가능 → 보안에 위험
EC, Erasure Code 모드
- 데이터 자체를 나눠서 저장공간을 분리해서 저장하고, 복구를 할 수 있도록 하는 방법
- 따라서 단독모드에서 사용하기 어려움
- 고가용성과 데이터 안전성을 우선이 될 떄 사용이 가능
S3 환경 테스트를 위한 MinIO 활용
- AWS S3세팅 처럼 Bucket을 생성하고, 이를 최상단 폴더 처럼 판단해서 사용을 할 수 있음
MinioClient 세팅
- Gradle 주입
dependencies {
implementation 'io.minio:minio:8.3.4'
}
- MinioClient를 위한 Config구성
@Configuration
public class MinioConfig {
@Bean
public MinioClient minioClient() {
return MinioClient.builder()
.endpoint("<http://localhost:9000>") //minio port 주소
.credentials("minio", "miniopass") //아이디 비밀번호
.build();
}
}
- 주입을 통해 파일을 업로드 시킬 수 있는 클라이언트
Java Spring → docker에 의한 Container의 MinIO
// 간단한 작동 로직을 알기 위한 연습용 Controller
@RestController
public class FileUploadController {
@Autowired
private MinioClient minioClient; // Client 주입
@Autowired
private FileRecordRepository fileRecordRepository; // 특정 Repository
@PostMapping("/upload")
public ResponseEntity<String> uploadFile(@RequestBody MyRequest myRequest) {
try {
// JSON 데이터에서 특정 필드 값을 추출
String content = myRequest.getFieldToSave();
// 파일로 저장할 내용을 ByteArrayInputStream으로 변환
ByteArrayInputStream inputStream = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
String fileName = "myfolder/myfile.txt"; // 저장할 파일 이름 (폴더 경로 포함)
**// MinIO에 파일을 업로드**
**minioClient.putObject(
PutObjectArgs.builder()
.bucket("mybucket")
.object(fileName)
.stream(inputStream, inputStream.available(), -1)
.contentType("text/plain")
.build()
);**
// 파일 정보를 DB에 저장 (선택 사항, 객체와 파일간의 관계를 명확하게 하기 위한 작업)
FileRecord fileRecord = new FileRecord();
fileRecord.setFileName(fileName);
fileRecord.setSomeOtherField(myRequest.getSomeOtherField());
fileRecordRepository.save(fileRecord);
return ResponseEntity.ok("파일 업로드 성공");
} catch (Exception e) {
return ResponseEntity.status(500).body("파일 업로드 실패");
}
}
// 저장할 파일의 정보를 가지고 오는 임의의 클래스
static class MyRequest {
private String fieldToSave;
private String someOtherField;
public String getFieldToSave() {
return fieldToSave;
}
public void setFieldToSave(String fieldToSave) {
this.fieldToSave = fieldToSave;
}
public String getSomeOtherField() {
return someOtherField;
}
public void setSomeOtherField(String someOtherField) {
this.someOtherField = someOtherField;
}
}
}
해당 MinIO는 기본적으로 코드를 첨부해서 게시글을 만들때, DB에 무리를 주지 않고 따로 코드를 관리하기 위해서 분리를 한 상태를 위해서 사용을 한다.
Sparta 최종 프로젝트에서의 테스트에 사용을 할 예정이고, 기타 잘 작동이 될 경우, 사진이나 미디어를 첨부할 수 있는 용도로 사용할 수 있도록 응용할 계획
'Today I Learned' 카테고리의 다른 글
(24.07.24)[15주차] Sprint Data JPA Tuple 객체의 사용 (2) | 2024.07.24 |
---|---|
(24.07.23)[15주차] MinIO 활용 정리 - 코드 분석 (0) | 2024.07.23 |
(24.07.15)[14주차] 프로젝트 중 동시성 제어를 위한 Redisson 활용 (1) | 2024.07.15 |
(24.07.09)[13주차] @DataJpaTest 슬라이스 테스트에서의 빈 등록 (0) | 2024.07.09 |
(24.07.04)[12주차] Redis 강의 학습 (0) | 2024.07.04 |