Skip to content

AI서버 장소추출 구현완료에 따른 콜백 api 개발 필요#17

Merged
Cassiiopeia merged 4 commits intomainfrom
20260127_16_AI서버_장소추출_구현완료에_따른_콜백_api_개발_필요
Jan 28, 2026

Hidden character warning

The head ref may contain hidden characters: "20260127_16_AI\uc11c\ubc84_\uc7a5\uc18c\ucd94\ucd9c_\uad6c\ud604\uc644\ub8cc\uc5d0_\ub530\ub978_\ucf5c\ubc31_api_\uac1c\ubc1c_\ud544\uc694"
Merged

AI서버 장소추출 구현완료에 따른 콜백 api 개발 필요#17
Cassiiopeia merged 4 commits intomainfrom
20260127_16_AI서버_장소추출_구현완료에_따른_콜백_api_개발_필요

Conversation

@Cassiiopeia
Copy link
Contributor

@Cassiiopeia Cassiiopeia commented Jan 28, 2026

Summary by CodeRabbit

업데이트 사항

  • 새로운 기능

    • AI 콜백 페이로드 대폭 확장: 콘텐츠·SNS 메타데이터(유형, URL, 작성자, 캡션, 해시태그, 게시시간, 좋아요·댓글 수, 이미지 등), 장소 상세(주소, 도로명, 영업시간, 편의시설, 이미지 등), 추출 통계 및 오류메시지 지원
    • 플랫폼 고유 ID 기반 중복 참조 생성 및 연동
  • 개선 사항

    • SNS 캡션 길이 확대 및 메타데이터 저장 강화
    • 장소 평점 검증 강화(0.0~5.0) 및 장소 검색·중복 판별/연결 로직 개선
    • 쿼리 및 배포 헬스체크 대상 경로 최적화

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Jan 28, 2026

Walkthrough

AI 콜백 요청 및 처리 흐름을 확장해 SNS 메타데이터, 장소 상세, 추출 통계를 수용하도록 DTO·엔티티를 확장하고 AiCallbackService의 성공/실패 분기 및 장소 생성·중복검사 로직을 재구현합니다.

Changes

Cohort / File(s) 변경 요약
AI Callback DTO 구조 확장
MS-AI/src/main/java/kr/suhsaechan/mapsy/ai/dto/AiCallbackRequest.java
contentId(UUID), snsInfo(SnsInfoCallback), placeDetails(List<PlaceDetailCallback>), statistics(ExtractionStatistics), errorMessage 등 필드 추가. ContentInfoSnsInfoCallback, PlaceInfoPlaceDetailCallback로 명칭·구조 변경 및 대폭 필드 확장.
AI Callback 처리 로직 재구현
MS-SNS/src/main/java/kr/suhsaechan/mapsy/sns/service/AiCallbackService.java
콜백 분기 정리(processSuccessCallback/processFailedCallback), SNS 매핑 유틸(updateContentWithSnsInfo), PlaceDetail 기반 생성·조회·갱신 헬퍼 추가(createOrGetPlaceFromPlaceDetail, createNewPlace, updatePlaceFromPlaceDetail, createPlacePlatformReferenceIfNotExists 등). NAVER placeId 우선 중복검사, name+lat/lng 폴백, 통계 로깅 및 알림 호출 반영.
SNS Content 엔티티 확장
MS-SNS/src/main/java/kr/suhsaechan/mapsy/sns/entity/Content.java
caption 길이 1000→2000, contentType, likesCount, commentsCount, postedAt, hashtags(varchar[]), imageUrls(text[]), authorProfileImageUrl 등 필드 추가 및 배열 매핑 도입.
Place 엔티티 확장
MS-Place/src/main/java/kr/suhsaechan/mapsy/place/entity/Place.java
roadAddress, visitorReviewCount, blogReviewCount, businessHours, openHoursDetail, holidayInfo, homepageUrl, naverMapUrl, reservationAvailable, subwayInfo, directionsText, amenities, tvAppearances, menuInfo, imageUrl 등 다수 필드 추가. country@Builder.Default("KR"), rating 정밀도·범위 제약 강화.
Place 플랫폼 참조 조회 추가
MS-Place/src/main/java/kr/suhsaechan/mapsy/place/repository/PlacePlatformReferenceRepository.java
Optional<PlacePlatformReference> findByPlacePlatformAndPlacePlatformId(PlacePlatform, String) 메소드 추가(플랫폼 ID 기반 중복 검사 지원).
PlaceKeyword 쿼리 수정
MS-Place/src/main/java/kr/suhsaechan/mapsy/place/repository/PlaceKeywordRepository.java
JPQL에서 JOIN FETCH 제거, Place 직접 반환하도록 쿼리 변경(논리·조건 유지).
워크플로우 설정 변경
.github/workflows/PROJECT-SPRING-SYNOLOGY-PR-PREVIEW.yaml
PR 프리뷰 워크플로우의 기본 헬스 체크 경로를 /actuator/health/docs/swagger 로 변경.

Sequence Diagram(s)

sequenceDiagram
    participant AI as AI Server
    participant Service as AiCallbackService
    participant ContentRepo as ContentRepository
    participant PlacePlatformRepo as PlacePlatformReferenceRepository
    participant PlaceRepo as PlaceRepository
    participant DB as Database

    AI->>Service: POST /ai/callback (AiCallbackRequest)
    Service->>ContentRepo: findById(contentId)
    ContentRepo->>DB: SELECT Content
    DB-->>ContentRepo: Content
    ContentRepo-->>Service: Content

    alt resultStatus == SUCCESS
        Service->>Service: updateContentWithSnsInfo(snsInfo)
        Service->>ContentRepo: save(content)
        loop for each placeDetail
            Service->>PlacePlatformRepo: findByPlacePlatformAndPlacePlatformId(platform, platformId)
            PlacePlatformRepo->>DB: SELECT PlacePlatformReference
            DB-->>PlacePlatformRepo: reference?
            alt reference exists
                PlacePlatformRepo->>PlaceRepo: findById(placeId)
                PlaceRepo->>DB: SELECT Place
            else
                Service->>Service: createNewPlace(placeDetail)
                Service->>PlaceRepo: save(new Place)
                PlaceRepo->>DB: INSERT Place
                Service->>PlacePlatformRepo: save(reference)
                PlacePlatformRepo->>DB: INSERT PlacePlatformReference
            end
            Service->>Service: updatePlaceFromPlaceDetail(place, placeDetail)
            Service->>PlaceRepo: save(place)
            Service->>Service: createContentPlace(content, place, position)
        end
        Service->>Service: logStatistics(contentId, statistics)
    else resultStatus == FAILED
        Service->>Service: mark content as FAILED (errorMessage)
        Service->>ContentRepo: save(content)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

Possibly related PRs

  • 🚀 Deploy 20260119-v0.1.13 #7: AiCallbackService의 콜백 처리·장소 처리 흐름을 수정한 PR과 코드 레벨로 연관 — PlaceDetail/SnsInfo 기반 처리 재도입과 겹치는 변경 지점 존재.
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목은 AI 서버 장소 추출 구현 완료에 따른 콜백 API 개발이라는 주요 변경 사항을 명확하게 설명하고 있으며, 제공된 코드 변경 사항들(AiCallbackRequest, Place, Content 엔티티 확장 및 콜백 서비스 개선)과 일치합니다.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@MS-AI/src/main/java/kr/suhsaechan/mapsy/ai/dto/AiCallbackRequest.java`:
- Around line 35-37: The DTO AiCallbackRequest currently allows snsInfo to be
null despite the schema note; add validation so SUCCESS requests require it:
either annotate the snsInfo field in AiCallbackRequest with `@NotNull`(message =
"SUCCESS 상태에서는 snsInfo가 필수입니다.") (or implement a conditional validator
annotation) to enforce at binding time, or modify
AiCallbackService.updateContentWithSnsInfo() to check if
("SUCCESS".equals(request.getResultStatus()) && request.getSnsInfo() == null)
and throw a suitable CustomException with that message; reference
AiCallbackRequest.snsInfo and AiCallbackService.updateContentWithSnsInfo() when
applying the change.

In `@MS-SNS/src/main/java/kr/suhsaechan/mapsy/sns/service/AiCallbackService.java`:
- Around line 583-625: The createMemberPlaces(Content, Place) method is never
invoked; decide whether to remove it or wire it into the success callback: if it
was omitted by mistake, call createMemberPlaces(content, place) from
processSuccessCallback after the Place is created/persisted (look for the code
path that has Content and Place available and invoke the method there); if it
was intentionally kept for a future feature, add a clear Javadoc/TODO comment
above createMemberPlaces and/or annotate with `@SuppressWarnings`("unused") to
indicate it is intentionally unused and prevent stale-code confusion.
- Around line 355-361: The createNewPlace method currently substitutes null
coordinates with BigDecimal.ZERO which can incorrectly create a real-world (0,0)
location; change the handling in createNewPlace(PlaceDetailCallback) so that
when placeDetail.getLatitude() or getLongitude() is null you set the
Place.latitude/longitude to null (not BigDecimal.ZERO) and update the Place
entity to allow nullable BigDecimal fields, or alternatively validate and throw
an IllegalArgumentException (or log a warning) if coordinates are required by
the business logic; update the Place class to use nullable BigDecimal types and
adjust any consumers of Place.latitude/longitude to handle nulls, or implement
the validation path inside createNewPlace and ensure PlaceDetailCallback and
callers conform to the chosen approach.
- Around line 464-482: The PlacePlatformReference entity lacks a DB-level unique
constraint on the (placePlatform, placePlatformId) pair, which can allow
duplicate mappings under concurrency; update the PlacePlatformReference entity
class to add a table-level unique constraint for columnNames
{"placePlatform","placePlatformId"} (using `@Table`(uniqueConstraints = ...) with
a `@UniqueConstraint`) so the database enforces uniqueness, then run the
appropriate migration to apply the constraint; verify related code paths such as
createPlacePlatformReferenceIfNotExists and any repository methods (e.g.,
findByPlacePlatformAndPlacePlatformId) still behave correctly and handle
unique-constraint violations if they surface.
🧹 Nitpick comments (2)
MS-AI/src/main/java/kr/suhsaechan/mapsy/ai/dto/AiCallbackRequest.java (1)

31-33: resultStatus를 enum으로 변경하는 것을 고려해 주세요.

현재 String 타입으로 "SUCCESS", "FAILED" 외의 값도 허용됩니다. 서비스 레이어에서 검증하고 있지만, enum 타입을 사용하면 컴파일 타임 안전성과 API 문서화가 개선됩니다.

♻️ 제안 (선택 사항)
public enum ResultStatus {
    SUCCESS, FAILED
}

`@Schema`(description = "처리 결과 상태", example = "SUCCESS")
`@NotNull`(message = "resultStatus는 필수입니다.")
private ResultStatus resultStatus;
MS-SNS/src/main/java/kr/suhsaechan/mapsy/sns/service/AiCallbackService.java (1)

136-144: position 값 처리 관련 확인 필요

positioncreateContentPlace 호출 전에 증가(position++)하지만, 중복 체크로 인해 실제 저장되지 않는 경우에도 position이 증가합니다. 이로 인해 position 값에 갭이 발생할 수 있습니다.

의도된 동작이라면 무시해도 되지만, 연속적인 position이 필요하다면 수정이 필요합니다.

♻️ 연속적인 position이 필요한 경우
-      int position = 0;
+      int position = 0;
       for (PlaceDetailCallback placeDetail : placeDetails) {
         try {
           // Place 생성 또는 조회
           Place place = createOrGetPlaceFromPlaceDetail(placeDetail);
           savedPlaces.add(place);

-          // ContentPlace 연결 (순서 포함)
-          createContentPlace(content, place, position++);
+          // ContentPlace 연결 (순서 포함)
+          boolean created = createContentPlace(content, place, position);
+          if (created) {
+            position++;
+          }

Comment on lines +35 to +37
@Schema(description = "SNS 콘텐츠 정보 (SUCCESS 시 필수)")
@Valid
private SnsInfoCallback snsInfo;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

rg -n "snsInfo" --type=java -A 3 -B 1 MS-AI/src/main/java

Repository: MapSee-Lab/MapSy-BE

Length of output: 521


🏁 Script executed:

# Look specifically for AiCallbackService to see how it validates snsInfo
fd "AiCallbackService" --type f -e java

Repository: MapSee-Lab/MapSy-BE

Length of output: 138


🏁 Script executed:

# Also search for validation logic related to SUCCESS status
rg -n "SUCCESS|resultStatus" --type=java -A 2 -B 2 MS-AI/src/main/java

Repository: MapSee-Lab/MapSy-BE

Length of output: 1018


🏁 Script executed:

cat -n MS-SNS/src/main/java/kr/suhsaechan/mapsy/sns/service/AiCallbackService.java

Repository: MapSee-Lab/MapSy-BE

Length of output: 26976


🏁 Script executed:

# Also check if there are any validation exception classes or error handlers
rg -n "snsInfo.*null|SnsInfoCallback|AiCallback" --type=java MS-SNS/src/main/java -A 2 -B 1

Repository: MapSee-Lab/MapSy-BE

Length of output: 9671


SUCCESS 상태일 때 snsInfo 필수 검증 부재

snsInfo가 "(SUCCESS 시 필수)"로 문서화되었으나, 현재 구현은 null 값을 허용합니다. AiCallbackService.updateContentWithSnsInfo()에서 null 체크는 있지만 단순히 경고를 로깅하고 처리를 계속하므로 API 계약을 위반합니다.

다음 중 하나를 권장합니다:

  • DTO에 @NotNull(message = "SUCCESS 상태에서는 snsInfo가 필수입니다.")를 추가하고, 조건부 검증이 필요하면 @ConditionalValidation 또는 커스텀 validator 구현
  • 또는 서비스 레이어에서 if ("SUCCESS".equals(request.getResultStatus()) && request.getSnsInfo() == null) 체크 후 명시적으로 CustomException 발생
🤖 Prompt for AI Agents
In `@MS-AI/src/main/java/kr/suhsaechan/mapsy/ai/dto/AiCallbackRequest.java` around
lines 35 - 37, The DTO AiCallbackRequest currently allows snsInfo to be null
despite the schema note; add validation so SUCCESS requests require it: either
annotate the snsInfo field in AiCallbackRequest with `@NotNull`(message = "SUCCESS
상태에서는 snsInfo가 필수입니다.") (or implement a conditional validator annotation) to
enforce at binding time, or modify AiCallbackService.updateContentWithSnsInfo()
to check if ("SUCCESS".equals(request.getResultStatus()) && request.getSnsInfo()
== null) and throw a suitable CustomException with that message; reference
AiCallbackRequest.snsInfo and AiCallbackService.updateContentWithSnsInfo() when
applying the change.

Comment on lines +355 to +361
private Place createNewPlace(PlaceDetailCallback placeDetail) {
BigDecimal latitude = placeDetail.getLatitude() != null
? BigDecimal.valueOf(placeDetail.getLatitude())
: BigDecimal.ZERO;
BigDecimal longitude = placeDetail.getLongitude() != null
? BigDecimal.valueOf(placeDetail.getLongitude())
: BigDecimal.ZERO;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

좌표 기본값 (0,0) 처리 개선 제안

좌표가 null일 때 BigDecimal.ZERO로 기본값 설정 시, 실제로 (0,0) 위치(아프리카 기니만)에 장소가 생성됩니다. 한국 기반 서비스에서 이는 의미적으로 부정확합니다.

좌표 없이 저장이 가능하다면 nullable로 변경하거나, 좌표가 필수라면 AI 서버에서 반드시 제공하도록 요구하는 것이 좋습니다.

💡 대안 제안

옵션 1: 좌표 필드를 nullable로 변경 (Place 엔티티 수정 필요)

옵션 2: 좌표 없는 경우 경고 로그 추가

   private Place createNewPlace(PlaceDetailCallback placeDetail) {
-    BigDecimal latitude = placeDetail.getLatitude() != null
-            ? BigDecimal.valueOf(placeDetail.getLatitude())
-            : BigDecimal.ZERO;
-    BigDecimal longitude = placeDetail.getLongitude() != null
-            ? BigDecimal.valueOf(placeDetail.getLongitude())
-            : BigDecimal.ZERO;
+    BigDecimal latitude = placeDetail.getLatitude() != null
+            ? BigDecimal.valueOf(placeDetail.getLatitude())
+            : BigDecimal.ZERO;
+    BigDecimal longitude = placeDetail.getLongitude() != null
+            ? BigDecimal.valueOf(placeDetail.getLongitude())
+            : BigDecimal.ZERO;
+
+    if (placeDetail.getLatitude() == null || placeDetail.getLongitude() == null) {
+      log.warn("Creating place with missing coordinates: name={}, placeId={}",
+              placeDetail.getName(), placeDetail.getPlaceId());
+    }
🤖 Prompt for AI Agents
In `@MS-SNS/src/main/java/kr/suhsaechan/mapsy/sns/service/AiCallbackService.java`
around lines 355 - 361, The createNewPlace method currently substitutes null
coordinates with BigDecimal.ZERO which can incorrectly create a real-world (0,0)
location; change the handling in createNewPlace(PlaceDetailCallback) so that
when placeDetail.getLatitude() or getLongitude() is null you set the
Place.latitude/longitude to null (not BigDecimal.ZERO) and update the Place
entity to allow nullable BigDecimal fields, or alternatively validate and throw
an IllegalArgumentException (or log a warning) if coordinates are required by
the business logic; update the Place class to use nullable BigDecimal types and
adjust any consumers of Place.latitude/longitude to handle nulls, or implement
the validation path inside createNewPlace and ensure PlaceDetailCallback and
callers conform to the chosen approach.

Comment on lines +464 to 482
private void createPlacePlatformReferenceIfNotExists(Place place, String naverPlaceId) {
if (naverPlaceId == null) {
return;
}

// ContentPlace 엔티티 생성
ContentPlace contentPlace = ContentPlace.builder()
.content(content)
.place(place)
.position(0) // AI 서버 응답에서는 순서 정보 없음
.build();

// ContentPlace 저장
contentPlaceRepository.save(contentPlace);
log.debug("Created ContentPlace: contentId={}, placeId={}", content.getId(), place.getId());
// 이미 존재하는지 확인
Optional<PlacePlatformReference> existing = placePlatformReferenceRepository
.findByPlaceAndPlacePlatform(place, PlacePlatform.NAVER);

if (existing.isEmpty()) {
PlacePlatformReference reference = PlacePlatformReference.builder()
.place(place)
.placePlatform(PlacePlatform.NAVER)
.placePlatformId(naverPlaceId)
.build();
placePlatformReferenceRepository.save(reference);
log.debug("Created PlacePlatformReference: placeId={}, naverPlaceId={}", place.getId(), naverPlaceId);
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

find . -type f -name "*.java" | grep -i placplatform | head -20

Repository: MapSee-Lab/MapSy-BE

Length of output: 45


🏁 Script executed:

fd -e java -type f | xargs grep -l "PlacePlatformReference" | head -10

Repository: MapSee-Lab/MapSy-BE

Length of output: 233


🏁 Script executed:

rg -n "class PlacePlatformReference" -A 30 --type=java

Repository: MapSee-Lab/MapSy-BE

Length of output: 4366


🏁 Script executed:

cat -n MS-Place/src/main/java/kr/suhsaechan/mapsy/place/entity/PlacePlatformReference.java

Repository: MapSee-Lab/MapSy-BE

Length of output: 1590


🏁 Script executed:

find . -type f -name "*PlacePlatformReferenceRepository*"

Repository: MapSee-Lab/MapSy-BE

Length of output: 162


🏁 Script executed:

cat -n MS-SNS/src/main/java/kr/suhsaechan/mapsy/sns/service/AiCallbackService.java | sed -n '400,550p'

Repository: MapSee-Lab/MapSy-BE

Length of output: 6386


🏁 Script executed:

cat MS-Place/src/main/java/kr/suhsaechan/mapsy/place/repository/PlacePlatformReferenceRepository.java

Repository: MapSee-Lab/MapSy-BE

Length of output: 1504


🏁 Script executed:

rg -n "createOrGetPlaceFromPlaceDetail" -A 50 -B 5 MS-SNS/src/main/java/kr/suhsaechan/mapsy/sns/service/AiCallbackService.java | head -100

Repository: MapSee-Lab/MapSy-BE

Length of output: 4240


데이터베이스 레벨에서 (placePlatform, placePlatformId) 복합 유니크 제약 필요

현재 PlacePlatformReference 엔티티에는 (placePlatform, placePlatformId) 조합에 대한 유니크 제약이 없습니다. 애플리케이션 로직에서는 createOrGetPlaceFromPlaceDetail의 Step 1에서 findByPlacePlatformAndPlacePlatformId로 먼저 확인하므로 정상 흐름에서는 중복이 방지되지만, 동시성 이슈나 데이터 부정합이 발생할 경우 같은 NAVER ID가 여러 Place에 연결될 수 있습니다.

PlacePlatformReference 엔티티에 다음과 같은 유니크 제약을 추가하세요:

`@Table`(uniqueConstraints = {
  `@UniqueConstraint`(columnNames = {"placePlatform", "placePlatformId"})
})

이렇게 하면 데이터베이스 레벨에서 같은 플랫폼 ID가 중복되는 것을 원천적으로 방지할 수 있습니다.

🤖 Prompt for AI Agents
In `@MS-SNS/src/main/java/kr/suhsaechan/mapsy/sns/service/AiCallbackService.java`
around lines 464 - 482, The PlacePlatformReference entity lacks a DB-level
unique constraint on the (placePlatform, placePlatformId) pair, which can allow
duplicate mappings under concurrency; update the PlacePlatformReference entity
class to add a table-level unique constraint for columnNames
{"placePlatform","placePlatformId"} (using `@Table`(uniqueConstraints = ...) with
a `@UniqueConstraint`) so the database enforces uniqueness, then run the
appropriate migration to apply the constraint; verify related code paths such as
createPlacePlatformReferenceIfNotExists and any repository methods (e.g.,
findByPlacePlatformAndPlacePlatformId) still behave correctly and handle
unique-constraint violations if they surface.

Comment on lines 583 to 625
private void createMemberPlaces(Content content, Place place) {
// 1. Content를 요청한 모든 회원 조회 (Member Fetch Join으로 N+1 방지)
List<ContentMember> contentMembers = contentMemberRepository.findAllByContentWithMember(content);

log.info("Creating MemberPlace for {} members (contentId={}, placeId={})",
contentMembers.size(), content.getId(), place.getId());
contentMembers.size(), content.getId(), place.getId());

// 2. 각 회원에 대해 MemberPlace 생성
int createdCount = 0;
int skippedCount = 0;

for (ContentMember contentMember : contentMembers) {
try {
// 3. 이미 존재하는지 확인 (중복 방지)
Optional<MemberPlace> existing = memberPlaceRepository
.findByMemberAndPlaceAndDeletedAtIsNull(contentMember.getMember(), place);
.findByMemberAndPlaceAndDeletedAtIsNull(contentMember.getMember(), place);

if (existing.isPresent()) {
log.debug("MemberPlace already exists: memberId={}, placeId={}",
contentMember.getMember().getId(), place.getId());
contentMember.getMember().getId(), place.getId());
skippedCount++;
continue;
}

// 4. MemberPlace 생성 및 저장
MemberPlace memberPlace = MemberPlace.builder()
.member(contentMember.getMember())
.place(place)
.savedStatus(PlaceSavedStatus.TEMPORARY)
.sourceContentId(content.getId())
.build();
.member(contentMember.getMember())
.place(place)
.savedStatus(PlaceSavedStatus.TEMPORARY)
.sourceContentId(content.getId())
.build();

memberPlaceRepository.save(memberPlace);
createdCount++;

log.debug("MemberPlace created: id={}, memberId={}, placeId={}, status=TEMPORARY",
memberPlace.getId(), contentMember.getMember().getId(), place.getId());
memberPlace.getId(), contentMember.getMember().getId(), place.getId());

} catch (Exception e) {
log.error("Failed to create MemberPlace for memberId={}, placeId={}: {}",
contentMember.getMember().getId(), place.getId(), e.getMessage());
// 실패해도 계속 진행 (다른 회원들의 MemberPlace는 생성)
contentMember.getMember().getId(), place.getId(), e.getMessage());
}
}

log.info("MemberPlace creation completed: {} created, {} skipped (contentId={}, placeId={})",
createdCount, skippedCount, content.getId(), place.getId());
createdCount, skippedCount, content.getId(), place.getId());
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

rg -n "createMemberPlaces" --type=java

Repository: MapSee-Lab/MapSy-BE

Length of output: 208


🏁 Script executed:

rg -n "processSuccessCallback" --type=java -A 30

Repository: MapSee-Lab/MapSy-BE

Length of output: 5958


🏁 Script executed:

sed -n '105,300p' MS-SNS/src/main/java/kr/suhsaechan/mapsy/sns/service/AiCallbackService.java

Repository: MapSee-Lab/MapSy-BE

Length of output: 6943


createMemberPlaces 메서드가 코드베이스에서 호출되지 않습니다.

이 메서드는 정의되어 있지만 어디에서도 호출되지 않는 사용되지 않는 코드입니다. 특히 processSuccessCallback 메서드에서도 호출되지 않습니다.

의도적으로 미래의 기능을 위해 남겨둔 것이라면 주석을 추가하거나, 호출이 누락된 것이라면 적절한 위치에서 호출하거나 제거해 주세요.

🤖 Prompt for AI Agents
In `@MS-SNS/src/main/java/kr/suhsaechan/mapsy/sns/service/AiCallbackService.java`
around lines 583 - 625, The createMemberPlaces(Content, Place) method is never
invoked; decide whether to remove it or wire it into the success callback: if it
was omitted by mistake, call createMemberPlaces(content, place) from
processSuccessCallback after the Place is created/persisted (look for the code
path that has Content and Place available and invoke the method there); if it
was intentionally kept for a future feature, add a clear Javadoc/TODO comment
above createMemberPlaces and/or annotate with `@SuppressWarnings`("unused") to
indicate it is intentionally unused and prevent stale-code confusion.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/PROJECT-SPRING-SYNOLOGY-PR-PREVIEW.yaml (1)

42-42: 문서화된 기본값과 실제 설정값 불일치

Line 42의 주석에는 기본값이 /actuator/health로 명시되어 있지만, 실제 설정값(line 110)은 /docs/swagger입니다. 문서 정합성을 위해 주석도 함께 업데이트하거나, 위 제안대로 /actuator/health를 유지하시기 바랍니다.

🤖 Fix all issues with AI agents
In @.github/workflows/PROJECT-SPRING-SYNOLOGY-PR-PREVIEW.yaml:
- Around line 110-112: HEALTH_CHECK_PATH is set to the Swagger UI path which can
cause unreliable health checks; change the value of HEALTH_CHECK_PATH back to
the dedicated Spring Boot endpoint '/actuator/health' while leaving
API_DOCS_PATH as '/docs/swagger' and keep HEALTH_CHECK_LOG_PATTERN unchanged so
the workflow uses the proper health endpoint for liveness checks (update the
HEALTH_CHECK_PATH entry in the workflow where HEALTH_CHECK_PATH is defined).

Comment on lines +110 to 112
HEALTH_CHECK_PATH: '/docs/swagger'
HEALTH_CHECK_LOG_PATTERN: 'Started .* in [0-9.]+ seconds'
API_DOCS_PATH: '/docs/swagger'
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Swagger 엔드포인트를 Health Check 경로로 사용 시 신뢰성 저하 가능성

/actuator/health는 Spring Boot의 전용 헬스체크 엔드포인트로, 애플리케이션 상태(DB 연결, 외부 서비스 등)를 확인하여 {"status":"UP"} 형태의 JSON을 반환합니다. 반면 /docs/swagger는 Swagger UI HTML 페이지로:

  • Swagger UI 로딩이 health endpoint보다 느릴 수 있음
  • Swagger 페이지가 표시되더라도 실제 애플리케이션이 완전히 정상 동작하는지 보장하지 않음 (false positive 가능)

API_DOCS_PATH는 이미 배포 완료 코멘트에 표시 용도로 사용되고 있으므로, HEALTH_CHECK_PATH는 기존 /actuator/health로 유지하는 것이 더 신뢰성 있는 헬스체크가 됩니다.

🔧 제안: 기존 health endpoint 유지
-  HEALTH_CHECK_PATH: '/docs/swagger'
+  HEALTH_CHECK_PATH: '/actuator/health'
   HEALTH_CHECK_LOG_PATTERN: 'Started .* in [0-9.]+ seconds'
   API_DOCS_PATH: '/docs/swagger'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
HEALTH_CHECK_PATH: '/docs/swagger'
HEALTH_CHECK_LOG_PATTERN: 'Started .* in [0-9.]+ seconds'
API_DOCS_PATH: '/docs/swagger'
HEALTH_CHECK_PATH: '/actuator/health'
HEALTH_CHECK_LOG_PATTERN: 'Started .* in [0-9.]+ seconds'
API_DOCS_PATH: '/docs/swagger'
🤖 Prompt for AI Agents
In @.github/workflows/PROJECT-SPRING-SYNOLOGY-PR-PREVIEW.yaml around lines 110 -
112, HEALTH_CHECK_PATH is set to the Swagger UI path which can cause unreliable
health checks; change the value of HEALTH_CHECK_PATH back to the dedicated
Spring Boot endpoint '/actuator/health' while leaving API_DOCS_PATH as
'/docs/swagger' and keep HEALTH_CHECK_LOG_PATTERN unchanged so the workflow uses
the proper health endpoint for liveness checks (update the HEALTH_CHECK_PATH
entry in the workflow where HEALTH_CHECK_PATH is defined).

@Cassiiopeia Cassiiopeia merged commit 197cbfc into main Jan 28, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant