-
Notifications
You must be signed in to change notification settings - Fork 0
Refactor/#33 장소 검색 기능 개선 #34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 7 commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
75298d8
feat: 가상 스레드 생성 config 구현
1winhyun e9836b7
refactor: 장소 검색 기능 순차 처리에서 병렬 처리로 수정
1winhyun aa5e582
feat: api 동작 시간 체크용 어노테이션 구현
1winhyun a808706
refactor: 기존 PlaceKey와 관련하여 DB 쿼리를 5번 요청하는 방식에서 PlaceKey를 미리 리스트로 모아 …
1winhyun ef51644
refactor: GooglePlaceClient에 semaphore를 적용하여 동시성 제한을 걸어 시스템이 버틸 수 있도록 수정
1winhyun d79630a
refactor: 사용되지 않는 private 메서드 삭제 및 timeout 시간 증가
1winhyun 2d31949
refactor: 머지 전 @LogExecutionTime 어노테이션 삭제
1winhyun e6f79f4
refactor: 구글에서 검색결과가 0건일 때 방어 로직 추가 (IndexOutOfBoundsException 방지)
1winhyun d786dbb
refactor: 기존 acquire() 무한대기 방식에서 tryAcquire()를 적용하여 일정시간이 지나면 포기 및 빈 …
1winhyun File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
12 changes: 12 additions & 0 deletions
12
...java/com/campus/campus/domain/place/application/dto/response/SearchCandidateResponse.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| package com.campus.campus.domain.place.application.dto.response; | ||
|
|
||
| import com.campus.campus.domain.place.application.dto.response.naver.NaverSearchResponse; | ||
|
|
||
| public record SearchCandidateResponse( | ||
| NaverSearchResponse.Item item, | ||
| String name, | ||
| String address, | ||
| String placeKey, | ||
| String naverPlaceUrl | ||
| ) { | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ | |
|
|
||
| import java.time.Duration; | ||
| import java.util.List; | ||
| import java.util.concurrent.Semaphore; | ||
|
|
||
| import org.springframework.beans.factory.annotation.Value; | ||
| import org.springframework.stereotype.Component; | ||
|
|
@@ -21,6 +22,8 @@ public class GooglePlaceClient { | |
| private final WebClient webClient; | ||
| private final String apiKey; | ||
|
|
||
| private final Semaphore googleApiSemaphore = new Semaphore(20); | ||
|
|
||
| public GooglePlaceClient( | ||
| @Value("${map.google.places.api-key}") String apiKey | ||
| ) { | ||
|
|
@@ -34,26 +37,35 @@ public GooglePlaceClient( | |
| * 장소 이름 + 주소를 기준으로 google places에서 이미지 URL 목록을 가져옴 | ||
| */ | ||
| public List<String> fetchImages(String name, String address, int limit) { | ||
|
|
||
| String placeId = findPlaceId(name, address); | ||
| if (placeId == null) { | ||
| return List.of(); | ||
| try{ | ||
| googleApiSemaphore.acquire(); | ||
| } catch (InterruptedException e){ | ||
| throw new RuntimeException("Google API 대기 중 인터럽트 발생", e); | ||
| } | ||
coderabbitai[bot] marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| //placee details -> photo reference | ||
| List<String> photoRefs = getPhotoReferences(placeId); | ||
| if (photoRefs.isEmpty()) { | ||
| return List.of(); | ||
| try{ | ||
| String placeId = findPlaceId(name, address); | ||
| if (placeId == null) { | ||
| return List.of(); | ||
| } | ||
|
|
||
| //placee details -> photo reference | ||
coderabbitai[bot] marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| List<String> photoRefs = getPhotoReferences(placeId); | ||
| if (photoRefs.isEmpty()) { | ||
| return List.of(); | ||
| } | ||
|
|
||
| //imageURL 생성 | ||
| List<String> imageUrls = photoRefs.stream() | ||
| .limit(3) | ||
| .map(this::buildPhotoUrl) | ||
| .toList(); | ||
|
Comment on lines
+60
to
+64
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 메서드 파라미터 Line 62에서 🔎 제안하는 수정 방안 List<String> imageUrls = photoRefs.stream()
- .limit(3)
+ .limit(limit)
.map(this::buildPhotoUrl)
.toList();🤖 Prompt for AI Agents |
||
|
|
||
| log.info("imageUrls: {}", imageUrls); | ||
| return imageUrls; | ||
| } finally { | ||
| googleApiSemaphore.release(); | ||
| } | ||
|
|
||
| //imageURL 생성 | ||
| List<String> imageUrls = photoRefs.stream() | ||
| .limit(3) | ||
| .map(this::buildPhotoUrl) | ||
| .toList(); | ||
|
|
||
| log.info("imageUrls: {}", imageUrls); | ||
| return imageUrls; | ||
| } | ||
|
|
||
| /* | ||
|
|
||
30 changes: 30 additions & 0 deletions
30
src/main/java/com/campus/campus/global/annotation/stopwatch/ExecutionTimeAspect.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| package com.campus.campus.global.annotation.stopwatch; | ||
|
|
||
| import org.aspectj.lang.ProceedingJoinPoint; | ||
| import org.aspectj.lang.annotation.Around; | ||
| import org.aspectj.lang.annotation.Aspect; | ||
| import org.springframework.stereotype.Component; | ||
| import org.springframework.util.StopWatch; | ||
|
|
||
| import lombok.extern.slf4j.Slf4j; | ||
|
|
||
| @Aspect | ||
| @Component | ||
| @Slf4j | ||
| public class ExecutionTimeAspect { | ||
|
|
||
| @Around("@annotation(LogExecutionTime)") | ||
| public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { | ||
| StopWatch stopWatch = new StopWatch(); | ||
| stopWatch.start(); | ||
|
|
||
| Object proceed = joinPoint.proceed(); // 실제 메서드 실행 | ||
|
|
||
| stopWatch.stop(); | ||
| log.info("⏱️ [Performance] Method: {} | Execution Time: {} ms", | ||
| joinPoint.getSignature().toShortString(), | ||
| stopWatch.getTotalTimeMillis()); | ||
|
|
||
| return proceed; | ||
| } | ||
| } |
11 changes: 11 additions & 0 deletions
11
src/main/java/com/campus/campus/global/annotation/stopwatch/LogExecutionTime.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| package com.campus.campus.global.annotation.stopwatch; | ||
|
|
||
| import java.lang.annotation.ElementType; | ||
| import java.lang.annotation.Retention; | ||
| import java.lang.annotation.RetentionPolicy; | ||
| import java.lang.annotation.Target; | ||
|
|
||
| @Target(ElementType.METHOD) // 메서드에 붙이는 어노테이션 | ||
| @Retention(RetentionPolicy.RUNTIME) // 런타임까지 유지 | ||
| public @interface LogExecutionTime { | ||
| } |
15 changes: 15 additions & 0 deletions
15
src/main/java/com/campus/campus/global/config/executor/PlaceSearchExecutorConfig.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| package com.campus.campus.global.config.executor; | ||
|
|
||
| import java.util.concurrent.ExecutorService; | ||
| import java.util.concurrent.Executors; | ||
|
|
||
| import org.springframework.context.annotation.Bean; | ||
| import org.springframework.context.annotation.Configuration; | ||
|
|
||
| @Configuration | ||
| public class PlaceSearchExecutorConfig { | ||
| @Bean(destroyMethod = "close") | ||
| public ExecutorService placeSearchExecutor() { | ||
| return Executors.newVirtualThreadPerTaskExecutor(); | ||
| } | ||
| } |
This file was deleted.
Oops, something went wrong.
18 changes: 0 additions & 18 deletions
18
src/main/java/com/campus/campus/test/TestResponseCode.java
This file was deleted.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: our-campUS/our-campUS-BE
Length of output: 159
🏁 Script executed:
# Check PlaceService.java structure and imports head -50 src/main/java/com/campus/campus/domain/place/application/service/PlaceService.javaRepository: our-campUS/our-campUS-BE
Length of output: 2583
🏁 Script executed:
Repository: our-campUS/our-campUS-BE
Length of output: 608
🏁 Script executed:
# View GooglePlaceClient implementation cat -n src/main/java/com/campus/campus/domain/place/infrastructure/google/GooglePlaceClient.javaRepository: our-campUS/our-campUS-BE
Length of output: 5211
🏁 Script executed:
Repository: our-campUS/our-campUS-BE
Length of output: 1174
🏁 Script executed:
Repository: our-campUS/our-campUS-BE
Length of output: 50
🏁 Script executed:
Repository: our-campUS/our-campUS-BE
Length of output: 1476
🏁 Script executed:
Repository: our-campUS/our-campUS-BE
Length of output: 1833
🏁 Script executed:
Repository: our-campUS/our-campUS-BE
Length of output: 327
타임아웃된 작업이 ExecutorService에서 계속 실행되는 문제가 있습니다.
completeOnTimeout은 4초 후 CompletableFuture를 완료하지만 기존 작업을 취소하지 않습니다.convertToSavedPlaceInfo내에서 호출되는googleClient.fetchImages()가 4초 이상 걸리면, ExecutorService의 스레드에서 계속 실행되어 다음과 같은 문제가 발생합니다:또한 타임아웃 및 에러 발생 시 로깅이 없어 모니터링 및 디버깅이 어렵습니다.
다만 PR 설명의 Semaphore(동시 실행 수 20개 제한)는 GooglePlaceClient에 정상적으로 구현되어 있으며, try-finally 블록에서 적절히 해제되고 있습니다. 따라서 Semaphore 자체는 문제가 아니며, ExecutorService 스레드의 지속 실행이 주요 이슈입니다.
🔎 로깅 추가 및 태스크 취소 개선 제안
참고: 완전한 태스크 취소를 위해서는
googleClient.fetchImages내부에서 Thread.interrupted() 확인 또는 CompletableFuture 취소 신호를 전파하는 메커니즘이 필요합니다.