Skip to content

Commit a22fd5c

Browse files
committed
refactor : ImageRepository 를 ImageStorage 로 변경
1 parent 37acef8 commit a22fd5c

File tree

17 files changed

+115
-110
lines changed

17 files changed

+115
-110
lines changed

src/main/java/eatda/repository/image/ImageDomain.java renamed to src/main/java/eatda/domain/ImageDomain.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package eatda.repository.image;
1+
package eatda.domain;
22

33
import lombok.Getter;
44
import lombok.RequiredArgsConstructor;

src/main/java/eatda/repository/image/ImageRepository.java

Lines changed: 0 additions & 39 deletions
This file was deleted.

src/main/java/eatda/service/article/ArticleService.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import eatda.controller.article.ArticleResponse;
44
import eatda.controller.article.ArticlesResponse;
55
import eatda.repository.article.ArticleRepository;
6-
import eatda.repository.image.ImageRepository;
6+
import eatda.storage.image.ImageStorage;
77
import java.util.List;
88
import lombok.RequiredArgsConstructor;
99
import org.springframework.data.domain.PageRequest;
@@ -14,7 +14,7 @@
1414
public class ArticleService {
1515

1616
private final ArticleRepository articleRepository;
17-
private final ImageRepository imageRepository;
17+
private final ImageStorage imageStorage;
1818

1919
public ArticlesResponse getAllArticles(int size) {
2020
PageRequest pageRequest = PageRequest.of(0, size);
@@ -24,7 +24,7 @@ public ArticlesResponse getAllArticles(int size) {
2424
article.getTitle(),
2525
article.getSubtitle(),
2626
article.getArticleUrl(),
27-
imageRepository.getPresignedUrl(article.getImageKey())
27+
imageStorage.getPresignedUrl(article.getImageKey())
2828
))
2929
.toList();
3030

src/main/java/eatda/service/store/CheerService.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@
66
import eatda.controller.store.CheerRegisterRequest;
77
import eatda.controller.store.CheerResponse;
88
import eatda.controller.store.CheersResponse;
9+
import eatda.domain.ImageDomain;
910
import eatda.domain.member.Member;
1011
import eatda.domain.store.Cheer;
11-
import eatda.repository.image.ImageDomain;
12-
import eatda.repository.image.ImageRepository;
1312
import eatda.domain.store.Store;
1413
import eatda.exception.BusinessErrorCode;
1514
import eatda.exception.BusinessException;
1615
import eatda.repository.member.MemberRepository;
1716
import eatda.repository.store.CheerRepository;
1817
import eatda.repository.store.StoreRepository;
18+
import eatda.storage.image.ImageStorage;
1919
import java.util.List;
2020
import lombok.RequiredArgsConstructor;
2121
import org.springframework.data.domain.Pageable;
@@ -34,7 +34,7 @@ public class CheerService {
3434
private final MemberRepository memberRepository;
3535
private final StoreRepository storeRepository;
3636
private final CheerRepository cheerRepository;
37-
private final ImageRepository imageRepository;
37+
private final ImageStorage imageStorage;
3838

3939
@Transactional
4040
public CheerResponse registerCheer(CheerRegisterRequest request, MultipartFile image, long memberId) {
@@ -43,12 +43,12 @@ public CheerResponse registerCheer(CheerRegisterRequest request, MultipartFile i
4343

4444
List<StoreSearchResult> searchResults = mapClient.searchShops(request.storeName());
4545
StoreSearchResult result = storeSearchFilter.filterStoreByKakaoId(searchResults, request.storeKakaoId());
46-
String imageKey = imageRepository.upload(image, ImageDomain.CHEER);
46+
String imageKey = imageStorage.upload(image, ImageDomain.CHEER);
4747

4848
Store store = storeRepository.findByKakaoId(result.kakaoId())
4949
.orElseGet(() -> storeRepository.save(result.toStore())); // TODO 상점 조회/저장 동시성 이슈 해결
5050
Cheer cheer = cheerRepository.save(new Cheer(member, store, request.description(), imageKey));
51-
return new CheerResponse(cheer, imageRepository.getPresignedUrl(imageKey), store);
51+
return new CheerResponse(cheer, imageStorage.getPresignedUrl(imageKey), store);
5252
}
5353

5454
private void validateRegisterCheer(Member member, String storeKakaoId) {
@@ -69,7 +69,7 @@ public CheersResponse getCheers(int size) {
6969
private CheersResponse toCheersResponse(List<Cheer> cheers) {
7070
return new CheersResponse(cheers.stream()
7171
.map(cheer -> new CheerPreviewResponse(cheer, cheer.getStore(),
72-
imageRepository.getPresignedUrl(cheer.getImageKey())))
72+
imageStorage.getPresignedUrl(cheer.getImageKey())))
7373
.toList());
7474
}
7575
}

src/main/java/eatda/service/store/StoreService.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
import eatda.controller.store.StoreSearchResponses;
1010
import eatda.controller.store.StoresResponse;
1111
import eatda.domain.store.Store;
12-
import eatda.repository.image.ImageRepository;
1312
import eatda.repository.store.CheerRepository;
1413
import eatda.repository.store.StoreRepository;
14+
import eatda.storage.image.ImageStorage;
1515
import java.util.List;
1616
import java.util.Optional;
1717
import lombok.RequiredArgsConstructor;
@@ -26,7 +26,7 @@ public class StoreService {
2626
private final StoreSearchFilter storeSearchFilter;
2727
private final StoreRepository storeRepository;
2828
private final CheerRepository cheerRepository;
29-
private final ImageRepository imageRepository;
29+
private final ImageStorage imageStorage;
3030

3131
// TODO : N+1 문제 해결
3232
public StoresResponse getStores(int size) {
@@ -38,7 +38,7 @@ public StoresResponse getStores(int size) {
3838

3939
private Optional<String> getStoreImageUrl(Store store) {
4040
return cheerRepository.findRecentImageKey(store)
41-
.map(imageRepository::getPresignedUrl);
41+
.map(imageStorage::getPresignedUrl);
4242
}
4343

4444
public StoreSearchResponses searchStores(String query) {

src/main/java/eatda/service/story/StoryService.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@
77
import eatda.controller.story.StoryRegisterRequest;
88
import eatda.controller.story.StoryRegisterResponse;
99
import eatda.controller.story.StoryResponse;
10+
import eatda.domain.ImageDomain;
1011
import eatda.domain.member.Member;
1112
import eatda.domain.story.Story;
1213
import eatda.exception.BusinessErrorCode;
1314
import eatda.exception.BusinessException;
14-
import eatda.repository.image.ImageDomain;
15-
import eatda.repository.image.ImageRepository;
1615
import eatda.repository.member.MemberRepository;
1716
import eatda.repository.story.StoryRepository;
17+
import eatda.storage.image.ImageStorage;
1818
import java.util.List;
1919
import lombok.RequiredArgsConstructor;
2020
import org.springframework.data.domain.Page;
@@ -30,7 +30,7 @@ public class StoryService {
3030

3131
private static final int PAGE_START_NUMBER = 0;
3232

33-
private final ImageRepository imageRepository;
33+
private final ImageStorage imageStorage;
3434
private final MapClient mapClient;
3535
private final StoryRepository storyRepository;
3636
private final MemberRepository memberRepository;
@@ -40,7 +40,7 @@ public StoryRegisterResponse registerStory(StoryRegisterRequest request, Multipa
4040
Member member = memberRepository.getById(memberId);
4141
List<StoreSearchResult> searchResponses = mapClient.searchShops(request.query());
4242
FilteredSearchResult matchedStore = filteredSearchResponse(searchResponses, request.storeKakaoId());
43-
String imageKey = imageRepository.upload(image, ImageDomain.STORY);
43+
String imageKey = imageStorage.upload(image, ImageDomain.STORY);
4444

4545
Story story = Story.builder()
4646
.member(member)
@@ -81,7 +81,7 @@ public StoriesResponse getPagedStoryPreviews(int size) {
8181
orderByPage.getContent().stream()
8282
.map(story -> new StoriesResponse.StoryPreview(
8383
story.getId(),
84-
imageRepository.getPresignedUrl(story.getImageKey())
84+
imageStorage.getPresignedUrl(story.getImageKey())
8585
))
8686
.toList()
8787
);
@@ -99,7 +99,7 @@ public StoryResponse getStory(long storyId) {
9999
story.getAddressDistrict(),
100100
story.getAddressNeighborhood(),
101101
story.getDescription(),
102-
imageRepository.getPresignedUrl(story.getImageKey())
102+
imageStorage.getPresignedUrl(story.getImageKey())
103103
);
104104
}
105105
}

src/main/java/eatda/repository/image/CachePreSignedUrlRepository.java renamed to src/main/java/eatda/storage/image/CachePreSignedUrlStorage.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package eatda.repository.image;
1+
package eatda.storage.image;
22

33
import eatda.repository.CacheSetting;
44
import java.util.Optional;
@@ -7,13 +7,13 @@
77
import org.springframework.stereotype.Component;
88

99
@Component
10-
public class CachePreSignedUrlRepository {
10+
public class CachePreSignedUrlStorage {
1111

1212
private static final String CACHE_NAME = CacheSetting.IMAGE.getName();
1313

1414
private final Cache cache;
1515

16-
public CachePreSignedUrlRepository(CacheManager cacheManager) {
16+
public CachePreSignedUrlStorage(CacheManager cacheManager) {
1717
this.cache = cacheManager.getCache(CACHE_NAME);
1818
}
1919

src/main/java/eatda/repository/image/S3ImageRepository.java renamed to src/main/java/eatda/storage/image/ExternalImageStorage.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
package eatda.repository.image;
1+
package eatda.storage.image;
22

3+
import eatda.domain.ImageDomain;
34
import eatda.exception.BusinessErrorCode;
45
import eatda.exception.BusinessException;
56
import java.io.IOException;
@@ -17,7 +18,7 @@
1718
import software.amazon.awssdk.services.s3.presigner.model.GetObjectPresignRequest;
1819

1920
@Component
20-
public class S3ImageRepository {
21+
public class ExternalImageStorage {
2122

2223
private static final Set<String> ALLOWED_CONTENT_TYPES = Set.of("image/jpg", "image/jpeg", "image/png");
2324
private static final String DEFAULT_CONTENT_TYPE = "bin";
@@ -29,7 +30,7 @@ public class S3ImageRepository {
2930
private final String bucket;
3031
private final S3Presigner s3Presigner;
3132

32-
public S3ImageRepository(
33+
public ExternalImageStorage(
3334
S3Client s3Client,
3435
@Value("${spring.cloud.aws.s3.bucket}") String bucket,
3536
S3Presigner s3Presigner) {
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package eatda.storage.image;
2+
3+
import eatda.domain.ImageDomain;
4+
import java.util.Optional;
5+
import lombok.RequiredArgsConstructor;
6+
import org.springframework.lang.Nullable;
7+
import org.springframework.stereotype.Component;
8+
import org.springframework.web.multipart.MultipartFile;
9+
10+
@Component
11+
@RequiredArgsConstructor
12+
public class ImageStorage {
13+
14+
private final ExternalImageStorage externalImageStorage;
15+
private final CachePreSignedUrlStorage cachePreSignedUrlStorage;
16+
17+
18+
public String upload(MultipartFile file, ImageDomain domain) {
19+
String imageKey = externalImageStorage.upload(file, domain);
20+
21+
String preSignedUrl = externalImageStorage.getPresignedUrl(imageKey);
22+
cachePreSignedUrlStorage.put(imageKey, preSignedUrl);
23+
return imageKey;
24+
}
25+
26+
@Nullable
27+
public String getPresignedUrl(@Nullable String imageKey) {
28+
if (imageKey == null || imageKey.isEmpty()) {
29+
return null;
30+
}
31+
32+
Optional<String> cachedUrl = cachePreSignedUrlStorage.get(imageKey);
33+
if (cachedUrl.isPresent()) {
34+
return cachedUrl.get();
35+
}
36+
37+
String preSignedUrl = externalImageStorage.getPresignedUrl(imageKey);
38+
cachePreSignedUrlStorage.put(imageKey, preSignedUrl);
39+
return preSignedUrl;
40+
}
41+
}

src/test/java/eatda/controller/BaseControllerTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@
1616
import eatda.fixture.CheerGenerator;
1717
import eatda.fixture.MemberGenerator;
1818
import eatda.fixture.StoreGenerator;
19-
import eatda.repository.image.ImageRepository;
2019
import eatda.repository.member.MemberRepository;
2120
import eatda.repository.store.CheerRepository;
2221
import eatda.repository.store.StoreRepository;
2322
import eatda.service.story.StoryService;
23+
import eatda.storage.image.ImageStorage;
2424
import io.restassured.RestAssured;
2525
import io.restassured.builder.RequestSpecBuilder;
2626
import io.restassured.filter.Filter;
@@ -81,7 +81,7 @@ public class BaseControllerTest {
8181
private MapClient mapClient;
8282

8383
@MockitoBean
84-
private ImageRepository imageRepository;
84+
private ImageStorage imageStorage;
8585

8686
@MockitoBean
8787
protected StoryService storyService; // TODO 실 객체로 변환
@@ -113,8 +113,8 @@ final void mockingClient() throws URISyntaxException {
113113
);
114114
doReturn(searchResults).when(mapClient).searchShops(anyString());
115115

116-
doReturn(MOCKED_IMAGE_URL).when(imageRepository).getPresignedUrl(anyString());
117-
doReturn(MOCKED_IMAGE_KEY).when(imageRepository).upload(any(), any());
116+
doReturn(MOCKED_IMAGE_URL).when(imageStorage).getPresignedUrl(anyString());
117+
doReturn(MOCKED_IMAGE_KEY).when(imageStorage).upload(any(), any());
118118
}
119119

120120
protected final RequestSpecification given() {

0 commit comments

Comments
 (0)