response format을 url로 설정 후 이미지 생성 시 OpenAI의 url이 나온는데, 이는 우리의 리소스가 아니기 때문에 해당 url을 저장해도 될까? 라는 고민이 있었다. 결론적으로, 외부에서 관리되는 OpenAI의 URL을 그대로 사용하면 리소스 관리 측면에서 여러 제약이 생긴다는 것이다.
OpenAI 서버가 만약 URL을 변경하거나 만료 정책을 적용하면, 서비스 안정성에 영향을 줄 수 있다.
따라서 이미지 자체를 우리의 S3에 업로드한 뒤, 생성되는 객체 자체의 url을 데이터베이스에 저장하기로 했다.
이미지를 Base64 문자열로 인코딩
순서는 다음과 같다.
1. AI 요청에 대한 응답으로 Base64로 인코딩 된 문자열을 받는다. (response options 변경)
2. Base64 인코딩 문자열을 디코딩하여 바이트 배열로 변환한다.
3. 이를 S3에 파일 형태로 업로드한다.
1. AI 요청에 대한 응답 옵션 변경
변경 전
private static OpenAiImageOptions imageOptions() {
return OpenAiImageOptions.builder()
.withModel(OpenAiImageApi.ImageModel.DALL_E_3.getValue())
.withResponseFormat("url")
...
}
변경 후
private static OpenAiImageOptions imageOptions() {
return OpenAiImageOptions.builder()
.withModel(OpenAiImageApi.ImageModel.DALL_E_3.getValue())
.withResponseFormat("b64_json")
...
}
2&3. Base64 인코딩 문자열을 디코딩하여 바이트 배열로 변환 후, S3에 파일 형태로 업로드한다.
`S3Service.java`
/* Base64 이미지를 S3에 업로드 */
public String uploadBase64ImageToS3(AiImageUploadRequest aiImageUploadRequest) {
String fileName = FileNameUtils.buildFileName("sample.png");
// Base64 문자열을 바이트 배열로 디코딩
byte[] decodedBytes = Base64.getDecoder().decode(aiImageUploadRequest.b64Json());
// 바이트 배열을 InputStream으로 변환
InputStream inputStream = new ByteArrayInputStream(decodedBytes);
return uploadFileToS3(fileName, inputStream, decodedBytes.length);
}
private String uploadFileToS3(String fileName, InputStream inputStream, long contentLength) {
UUID randomUUID = UUID.randomUUID();
PutObjectRequest putObjectRequest = PutObjectRequest.builder()
.bucket(bucketName)
.key(DIRECTORY_PATH + randomUUID + fileName)
.contentType(getContentType(fileName))
.build();
s3Client.putObject(putObjectRequest, RequestBody.fromInputStream(inputStream, contentLength));
GetUrlRequest getUrlRequest = GetUrlRequest.builder()
.bucket(bucketName)
.key(DIRECTORY_PATH + randomUUID + fileName)
.build();
return s3Client.utilities().getUrl(getUrlRequest).toString();
}
`AiImageUploadRequest.java`
public record AiImageUploadRequest (String b64Json)
{
}
3. 응답 결과
이제 외부 리소스가 아닌, 우리의 s3 버킷에 있는 객체 url을 반환한다.
참고
'✍️ 개발 기록' 카테고리의 다른 글
[👀 Owing] OpenAI ChatGPT로 프롬프트 생성하기 (feat. 프롬프트 작성팁) (0) | 2024.11.12 |
---|---|
[👀 Owing] Spring AI 도입기 🤖 (0) | 2024.11.07 |
[👀 Owing] PostgreSQL 도입기 (feat. MySQL과의 차이) (0) | 2024.11.05 |
[👀 Owing] Java Record 도입기 ☕️ (0) | 2024.11.05 |
[👀 Owing] 멀티모듈 - 모듈 간 순환참조 이슈 해결 과정 💥 (0) | 2024.11.05 |