Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ out/
/newrelic
.secrets
.env
.env.local
.env.dev
.env.redis
.env.redis.dev
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/com/newzet/api/article/domain/Article.java
Original file line number Diff line number Diff line change
Expand Up @@ -101,5 +101,9 @@ public Article share() {
this.deletedAt
);
}

public boolean isSaveInStorage() {
return contentUrl.endsWith(".html");
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import com.newzet.api.article.business.service.ArticleService;
import com.newzet.api.article.controller.dto.ArticleContentResponse;
import com.newzet.api.article.domain.Article;
import com.newzet.api.common.s3.S3Service;
import com.newzet.api.common.storage.StorageService;

import lombok.RequiredArgsConstructor;

Expand All @@ -18,19 +18,19 @@
public class ArticleOrchestrator {

private final ArticleService articleService;
private final S3Service s3Service;
private final StorageService storageService;

public ArticleContentResponse getSharedArticle(UUID articleId) {
Article sharedArticle = articleService.getSharedArticle(articleId);
String content = s3Service.getContentAsString(sharedArticle.getContentUrl());
String content = storageService.getContent(sharedArticle.getContentUrl(), sharedArticle.isSaveInStorage());
return new ArticleContentResponse(sharedArticle.getTitle(), content,
sharedArticle.isLike());
}

@Transactional
public ArticleContentResponse getArticle(UUID articleId) {
Article article = articleService.getArticle(articleId);
String content = s3Service.getContentAsString(article.getContentUrl());
String content = storageService.getContent(article.getContentUrl(), article.isSaveInStorage());
return ArticleContentResponse.of(article.getTitle(), content,
article.isLike());
}
Expand Down
43 changes: 0 additions & 43 deletions src/main/java/com/newzet/api/common/s3/S3Service.java

This file was deleted.

63 changes: 63 additions & 0 deletions src/main/java/com/newzet/api/common/storage/StorageService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.newzet.api.common.storage;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.AmazonS3Exception;
import com.amazonaws.services.s3.model.GetObjectRequest;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectInputStream;
import com.newzet.api.common.exception.InternalErrorException;
import com.newzet.api.config.storage.StorageConfig;

import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class StorageService {

private final AmazonS3 awsS3Client;
private final AmazonS3 supabaseS3Client;
private final StorageConfig storageConfig;
Comment on lines +21 to +25
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

지금은 꼭 필요할 것 같지는 않습니다만
확장성을 고려해서 포트 기반 구현체로 추후 리팩터링 과정에서 도입해도 좋을 것 같네영


public StorageService(@Qualifier("awsS3Client") AmazonS3 awsS3Client,
@Qualifier("supabaseS3Client") AmazonS3 supabaseS3Client,
StorageConfig storageConfig) {
this.awsS3Client = awsS3Client;
this.supabaseS3Client = supabaseS3Client;
this.storageConfig = storageConfig;
}

public String getContent(String key, boolean isSaveInStorage) {
AmazonS3 client;
String bucketName;

if (isSaveInStorage) {
client = supabaseS3Client;
bucketName = storageConfig.getSupabaseBucketName();
} else {
client = awsS3Client;
bucketName = storageConfig.getAwsBucketName();
}

GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, key);

try (S3Object s3Object = client.getObject(getObjectRequest);
S3ObjectInputStream inputStream = s3Object.getObjectContent()) {

byte[] contentBytes = inputStream.readAllBytes();
return new String(contentBytes, StandardCharsets.UTF_8);

} catch (AmazonS3Exception e) {
log.error("Storage에서 객체를 가져오는 중 오류가 발생했습니다. Key: {}", key, e);
throw new InternalErrorException("아티클을 불러오는 과정에서 에러가 발생하였습니다.");
} catch (IOException e) {
log.error("Storage 파일 내용을 읽는 중 I/O 오류가 발생했습니다.", e);
throw new InternalErrorException("아티클을 불러오는 과정에서 에러가 발생하였습니다.");
}
}
}
38 changes: 0 additions & 38 deletions src/main/java/com/newzet/api/config/s3/S3Config.java

This file was deleted.

65 changes: 65 additions & 0 deletions src/main/java/com/newzet/api/config/storage/StorageConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.newzet.api.config.storage;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;

import lombok.Getter;

@Configuration
@Getter
public class StorageConfig {

// AWS S3 Credentials
@Value("${cloud.aws.s3.bucket}")
private String awsBucketName;
@Value("${cloud.aws.region.static}")
private String awsRegion;
@Value("${cloud.aws.credentials.access-key}")
private String awsAccessKey;
@Value("${cloud.aws.credentials.secret-key}")
private String awsSecretKey;

// Supabase S3-compatible Storage Credentials
@Value("${cloud.supabase.storage.bucket}")
private String supabaseBucketName;
@Value("${cloud.supabase.storage.region}")
private String supabaseRegion;
@Value("${cloud.supabase.storage.endpoint-url}")
private String supabaseEndpointUrl;
@Value("${cloud.supabase.storage.credentials.access-key}")
private String supabaseAccessKey;
@Value("${cloud.supabase.storage.credentials.secret-key}")
private String supabaseSecretKey;

@Bean
@Qualifier("awsS3Client")
public AmazonS3 awsS3Client() {
AWSCredentials credentials = new BasicAWSCredentials(awsAccessKey, awsSecretKey);
return AmazonS3ClientBuilder.standard()
.withRegion(awsRegion)
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.build();
}

@Bean
@Qualifier("supabaseS3Client")
public AmazonS3 supabaseS3Client() {
AWSCredentials credentials = new BasicAWSCredentials(supabaseAccessKey, supabaseSecretKey);
AwsClientBuilder.EndpointConfiguration endpointConfig =
new AwsClientBuilder.EndpointConfiguration(supabaseEndpointUrl, supabaseRegion);

return AmazonS3ClientBuilder.standard()
.withEndpointConfiguration(endpointConfig)
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.build();
}
}
2 changes: 2 additions & 0 deletions src/main/java/com/newzet/api/welcome/api/WelcomeApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import org.springframework.web.bind.annotation.RequestMapping;

import com.newzet.api.common.auth.annotation.Login;
import com.newzet.api.common.auth.annotation.RequireAuth;
import com.newzet.api.common.auth.domain.AuthUser;
import com.newzet.api.common.response.SuccessResponse;

Expand All @@ -15,6 +16,7 @@
public interface WelcomeApi {

@PostMapping("/welcome")
@RequireAuth
@Operation(summary = "welcome 메일 전송",
description = "welcome 메일을 전송한다.")
SuccessResponse<Object> sendWelcomeMail(@Login AuthUser authUser);
Expand Down
11 changes: 10 additions & 1 deletion src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,13 @@ cloud:
static: ${S3_REGION}
credentials:
access-key: ${S3_ACCESS_KEY}
secret-key: ${S3_SECRET_KEY}
secret-key: ${S3_SECRET_KEY}

supabase:
storage:
bucket: ${SUPABASE_BUCKET_NAME}
endpoint-url: ${SUPABASE_ENDPOINT_URL}
region: ${SUPABASE_REGION}
credentials:
access-key: ${SUPABASE_ACCESS_KEY}
secret-key: ${SUPABASE_SECRET_KEY}
Comment on lines +75 to +82
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

추가된 값 배포 전에 노션에 최신화 부탁드립니다! 서버단에 바로 적용하겠습니다

100 changes: 0 additions & 100 deletions src/test/java/com/newzet/api/common/s3/S3ServiceTest.java

This file was deleted.

Loading
Loading