Skip to content

Conversation

@1224kang
Copy link
Contributor

@1224kang 1224kang commented Jan 9, 2026

🔀 변경 내용

  • 제휴 관련 전반적인 기능 수정

✅ 작업 항목

  • 학생회가 제휴 게시글 등록 기능에서 연관관계에 Place entity 외래키 설정 및 로직 수정
  • 내 위치 기준으로 장소 검색 반환하도록 수정
  • 현재 진행중인 제휴에 대해 거리 가까운 순으로 조회할 수 있도록 함
  • 지도에서 핀으로 제휴 찍기 기능 구현
  • 제휴 장소 상세 조회
  • 제휴 태그 조회(리스트)

📸 스크린샷 (선택)

📎 참고 이슈

관련 이슈 번호 #31

Summary by CodeRabbit

  • 새로운 기능

    • 제휴 장소 기능 추가: 사용자 위치 기반 제휴 리스트, 지도(핀) 및 상세 조회 제공
    • 제휴 게시물 생성 연동: 장소 정보(위치, 이미지 등)를 포함한 파트너십 표시
  • 개선 사항

    • 장소 검색 정확도 향상: 현위치 기반 지오코딩 보정으로 검색 결과 개선
    • 장소/게시물 응답에 더 풍부한 장소 정보(이름, 좌표, 이미지 등) 포함
  • 문서

    • API 예시 요청 바디에 중첩된 장소 구조 및 미디어 필드 반영

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

@coderabbitai
Copy link

coderabbitai bot commented Jan 9, 2026

Caution

Review failed

The pull request is closed.

Walkthrough

PostRequest의 place를 문자열에서 SavedPlaceInfo DTO로 변경하고 StudentCouncilPost.place를 Place 엔티티로 마이그레이션했으며, Partnership 도메인(엔티티/서비스/컨트롤러/DTO), 지오코더 통합(GeoCoderClient/AddressResponse/예외), 지도 기반 검색 및 관련 저장소 쿼리, Kakao OAuth 코드 기반 로그인 변경 등을 추가/확장했습니다.

Changes

Cohort / File(s) 변경 요약
DTO 변경
src/main/java/.../councilpost/application/dto/request/PostRequest.java, src/main/java/.../councilpost/application/dto/response/GetPostResponse.java, src/main/java/.../councilpost/application/dto/response/PostListItemResponse.java, src/main/java/.../place/application/dto/response/SavedPlaceInfo.java
요청 DTO: place 타입 String → SavedPlaceInfo. 응답 DTO: place 필드 이름/타입 변경 (placeName, placeId). SavedPlaceInfo 주석 보강.
도메인 엔티티 추가/수정
src/main/java/.../councilpost/domain/entity/StudentCouncilPost.java, src/main/java/.../partnership/domain/entity/Partnership.java, src/main/java/.../partnership/domain/entity/PartnershipStatus.java
StudentCouncilPost.place → Place ManyToOne 매핑으로 변경; Partnership 엔티티 및 상태 enum 추가.
서비스 레이어 변경/추가
src/main/java/.../councilpost/application/service/StudentCouncilPostService.java, src/main/java/.../place/application/service/PlaceService.java, src/main/java/.../partnership/application/service/PartnershipService.java
PlaceService 주입·findOrCreatePlace 사용으로 포스트 생성/수정 로직 변경; Partnership 생성/조회 로직 추가; Place 검색에 위경도 기반 흐름 추가.
매퍼 레이어
src/main/java/.../councilpost/application/mapper/StudentCouncilPostMapper.java, src/main/java/.../place/application/mapper/PlaceMapper.java
매핑 로직: place → placeId/placeName 사용으로 수정; createStudentCouncilPost 시그니처 변경(Place 인자); Partnership 관련 매핑 메서드 추가.
저장소/쿼리 추가/수정
src/main/java/.../councilpost/domain/repository/PostImageRepository.java, src/main/java/.../councilpost/domain/repository/StudentCouncilPostRepository.java, src/main/java/.../partnership/domain/repository/PartnershipRepository.java, src/main/java/.../place/domain/repository/PlaceRepository.java, src/main/java/.../place/domain/repository/LikedPlacesRepository.java
파트너십/이미지/핀/스크롤 조회용 JPQL 쿼리 및 메서드 추가, LikedPlaces 쿼리 변경(아이드셋/existsByUserAndPlace).
프레젠테이션(컨트롤러/응답코드/문서)
src/main/java/.../partnership/presentation/PartnershipController.java, src/main/java/.../place/presentation/PlaceController.java, src/main/java/.../councilpost/presentation/StudentCouncilPostController.java, src/main/java/.../partnership/presentation/PartnershipResponseCode.java, src/main/java/.../place/presentation/PlaceResponseCode.java
Partnership API (/list, /map, /detail) 추가; Place 검색 엔드포인트에 lat/lng 파라미터 추가 및 /places(지오코더) 엔드포인트 추가; 예시 페이로드에 복합 place 객체 반영.
인프라(클라이언트) 및 예외
src/main/java/.../place/infrastructure/geocoder/GeoCoderClient.java, src/main/java/.../place/application/exception/GeoCoderException.java, src/main/java/.../place/application/dto/response/geocoder/AddressResponse.java
VWorld 지오코더 클라이언트 추가, AddressResponse DTO 및 GeoCoderException 추가, 설정(application-local.yml)에 API 키 추가.
유틸리티
src/main/java/.../global/util/jwt/GeoUtil.java
거리 계산(Haversine) 유틸 추가.
OAuth 변경
src/main/java/.../user/application/service/KakaoOauthService.java, src/main/java/.../user/presentation/AuthController.java
Kakao 로그인: 액세스 토큰 기반 → authorization code 기반으로 변경(getToken 헬퍼 추가), 컨트롤러 파라미터 이름 변경.
기타 DTO/응답 추가
여러 files under src/main/java/.../place/application/dto/response/partnership/* and src/main/java/.../partnership/application/dto/response/*
Partnership 관련 다양한 응답 레코드(PartnershipResponse, PartnershipPinResponse, PartnershipMapResponse 등) 및 PostImageSummary 등 추가.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant PostController as StudentCouncilPostController
    participant PostService as StudentCouncilPostService
    participant PlaceService
    participant PostMapper as StudentCouncilPostMapper
    participant PostRepo as StudentCouncilPostRepository
    participant PartnershipService

    Client->>PostController: POST /api/council-post (PostRequest with SavedPlaceInfo)
    PostController->>PostService: create(councilId, dto, ...)
    PostService->>PlaceService: findOrCreatePlace(dto)
    PlaceService-->>PostService: Place
    PostService->>PostMapper: createStudentCouncilPost(writer, place, dto, ...)
    PostMapper-->>PostService: StudentCouncilPost
    PostService->>PostRepo: save(post)
    PostRepo-->>PostService: saved post
    PostService->>PartnershipService: create(post, place)
    PartnershipService-->>PostService: Partnership
    PostService-->>PostController: GetPostResponse
    PostController-->>Client: CommonResponse<GetPostResponse>
Loading
sequenceDiagram
    participant Client
    participant PlaceController
    participant GeoCoderClient as GeoCoderClient (VWorld)
    participant PlaceService
    participant NaverAPI as Naver Map API
    participant PlaceMapper

    Client->>PlaceController: GET /places (lat,lng)
    PlaceController->>GeoCoderClient: getAddress(lat,lng)
    GeoCoderClient-->>PlaceController: AddressResponse
    PlaceController->>PlaceService: search(lat,lng,keyword)
    PlaceService->>NaverAPI: search(composedAddress + keyword)
    NaverAPI-->>PlaceService: place results
    PlaceService->>PlaceMapper: toSavedPlaceInfo(...)
    PlaceMapper-->>PlaceService: SavedPlaceInfo list
    PlaceService-->>PlaceController: List<SavedPlaceInfo>
    PlaceController-->>Client: ResponseEntity<List<SavedPlaceInfo>>
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 분

Possibly related PRs

Suggested reviewers

  • jjaeroong

Poem

🐰 나는 깡총 토끼, 코드 밭을 밟고,
문자였던 장소를 엔티티로 심었네.
지오코더로 길을 묻고, 파트너십 꽃 피우니,
캠퍼스 지도가 더 반짝이네 ✨
당근 대신 리뷰 하나 부탁해요 🥕

✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 56e345b and 23604f1.

📒 Files selected for processing (39)
  • src/main/java/com/campus/campus/domain/councilpost/application/dto/request/PostRequest.java
  • src/main/java/com/campus/campus/domain/councilpost/application/dto/response/GetPostResponse.java
  • src/main/java/com/campus/campus/domain/councilpost/application/dto/response/PostListItemResponse.java
  • src/main/java/com/campus/campus/domain/councilpost/application/mapper/StudentCouncilPostMapper.java
  • src/main/java/com/campus/campus/domain/councilpost/application/service/StudentCouncilPostService.java
  • src/main/java/com/campus/campus/domain/councilpost/domain/entity/StudentCouncilPost.java
  • src/main/java/com/campus/campus/domain/councilpost/domain/repository/PostImageRepository.java
  • src/main/java/com/campus/campus/domain/councilpost/domain/repository/StudentCouncilPostRepository.java
  • src/main/java/com/campus/campus/domain/councilpost/presentation/StudentCouncilPostController.java
  • src/main/java/com/campus/campus/domain/partnership/application/dto/response/PartnershipPinResponse.java
  • src/main/java/com/campus/campus/domain/partnership/application/service/PartnershipService.java
  • src/main/java/com/campus/campus/domain/partnership/domain/entity/Partnership.java
  • src/main/java/com/campus/campus/domain/partnership/domain/entity/PartnershipStatus.java
  • src/main/java/com/campus/campus/domain/partnership/domain/repository/PartnershipRepository.java
  • src/main/java/com/campus/campus/domain/partnership/presentation/PartnershipController.java
  • src/main/java/com/campus/campus/domain/partnership/presentation/PartnershipResponseCode.java
  • src/main/java/com/campus/campus/domain/place/application/dto/response/SavedPlaceInfo.java
  • src/main/java/com/campus/campus/domain/place/application/dto/response/geocoder/AddressResponse.java
  • src/main/java/com/campus/campus/domain/place/application/dto/response/partnership/PartnershipMapResponse.java
  • src/main/java/com/campus/campus/domain/place/application/dto/response/partnership/PartnershipMapSummary.java
  • src/main/java/com/campus/campus/domain/place/application/dto/response/partnership/PartnershipPlaceSummary.java
  • src/main/java/com/campus/campus/domain/place/application/dto/response/partnership/PartnershipResponse.java
  • src/main/java/com/campus/campus/domain/place/application/dto/response/partnership/PartnershipScrollResponse.java
  • src/main/java/com/campus/campus/domain/place/application/dto/response/partnership/PostImageSummary.java
  • src/main/java/com/campus/campus/domain/place/application/exception/ErrorCode.java
  • src/main/java/com/campus/campus/domain/place/application/exception/GeoCoderException.java
  • src/main/java/com/campus/campus/domain/place/application/mapper/PlaceMapper.java
  • src/main/java/com/campus/campus/domain/place/application/service/PlaceService.java
  • src/main/java/com/campus/campus/domain/place/domain/repository/LikedPlacesRepository.java
  • src/main/java/com/campus/campus/domain/place/domain/repository/PlaceRepository.java
  • src/main/java/com/campus/campus/domain/place/infrastructure/geocoder/GeoCoderClient.java
  • src/main/java/com/campus/campus/domain/place/infrastructure/naver/NaverDirectionsClient.java
  • src/main/java/com/campus/campus/domain/place/presentation/PlaceController.java
  • src/main/java/com/campus/campus/domain/place/presentation/PlaceResponseCode.java
  • src/main/java/com/campus/campus/domain/user/application/service/KakaoOauthService.java
  • src/main/java/com/campus/campus/domain/user/presentation/AuthController.java
  • src/main/java/com/campus/campus/global/config/PermitUrlConfig.java
  • src/main/java/com/campus/campus/global/util/jwt/GeoUtil.java
  • src/main/resources/application-local.yml

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.

@1224kang 1224kang merged commit d70f613 into dev Jan 9, 2026
0 of 2 checks passed
@1winhyun 1winhyun added ♻️Refactor 리팩토링 ✨Feat 새로운 기능 개발 labels Jan 9, 2026
Copy link
Member

@1winhyun 1winhyun left a comment

Choose a reason for hiding this comment

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

수고하셨습니다!!

PostCategory category,
String title,
String place,
Long placeId,
Copy link
Member

Choose a reason for hiding this comment

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

해당 response의 경우 필요한 부분은 placeId가 아닌 placeName입니다. 프론트에 보내줘야할 응답값은 해당 장소가 어디인지가 아닌 해당 장소의 이름이기 때문입니다!!

post.getTitle(),
post.getPlace(),
post.isEvent() ? post.getStartDateTime() : post.getEndDateTime(),
post.getPlace().getPlaceId(),
Copy link
Member

Choose a reason for hiding this comment

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

따라서 해당 부분 또한 getPlaceName()이 되어야합니다.

Comment on lines +102 to +104
//
// public StudentCouncilPost createStudentCouncilPost(StudentCouncil writer, PostRequest dto,
// LocalDateTime startDateTime, LocalDateTime endDateTime, Place place) {
Copy link
Member

Choose a reason for hiding this comment

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

해당 주석은 삭제해도 될 것 같아요!!

Comment on lines +83 to +84
//제휴 엔티티 생성
partnershipService.create(post, place);
Copy link
Member

Choose a reason for hiding this comment

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

이 부분은 삭제해주시면 될 것 같아요!!

Comment on lines +107 to +113
private boolean isLiked(Place place, User user) {
return likedPlacesRepository.existsByUserAndPlace(user, place);
}

private List<String> getImgUrls(StudentCouncilPost post) {
return postImageRepository.findImageUrlsByPost(post);
}
Copy link
Member

Choose a reason for hiding this comment

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

해당 메서드는 private 메서드이기에 가장 하단 부분에 위치한다면 전체적인 코드의 가독성이 높아질 수 있을 것 같아요!!

Copy link
Member

Choose a reason for hiding this comment

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

해당 dto는 사용되지 않는 것 같은데 확인 후 삭제 부탁드려요!

private String resolveTag(StudentCouncilPost post, User user) {
CouncilType councilType = post.getWriter().getCouncilType();
return switch (councilType) {
case SCHOOL_COUNCIL -> "총학생회";
Copy link
Member

Choose a reason for hiding this comment

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

'총학생회'와 같이 이름을 하드코딩하지 말고 다음과 같이 user에서 가져오는 형식으로 부탁드려요!!
case SCHOOL_COUNCIL -> user.getSchool().getSchoolName();

Comment on lines +94 to +100
public String toStringAddress(AddressResponse nowAddress) {
return nowAddress.getResponse().getResult().stream()
.filter(r -> "road".equalsIgnoreCase(r.getType()) || "parcel".equalsIgnoreCase(r.getType()))
.findFirst()
.map(AddressResponse.Result::getText)
.orElse(null);
}
Copy link
Member

Choose a reason for hiding this comment

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

해당 로직은 PlaceService 내 private 메서드로 구현 부탁드려요!!

Comment on lines +113 to +120
//이미 Place 존재하는지 확인
Optional<Place> existing = placeRepository.findByPlaceKey(placeKey);
if (existing.isPresent()) {
return existing.get();
}

//저장되어 있지 않는 Place의 경우, 객체 생성 후 저장
return placeRepository.save(placeMapper.createPlace(place));
Copy link
Member

Choose a reason for hiding this comment

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

해당 부분은
return existing.orElseGet(() -> placeRepository.save(placeMapper.createPlace(place))); 이런식으로 단일식으로 간소화되어 표현할 수 있을 것 같아요!!

Comment on lines +31 to +49
AddressResponse response = webClient.get()
.uri(uriBuilder -> uriBuilder
.path("/req/address")
.queryParam("service", "address")
.queryParam("request", "getAddress")
.queryParam("key", apiKey)
.queryParam("point", lng + "," + lat)
.queryParam("crs", "epsg:4326")
.queryParam("type", "both")
.queryParam("format", "json")
.build())
.retrieve()
.onStatus(
status -> status.isError(),
res -> Mono.error(new GeoCoderException())
)
.bodyToMono(AddressResponse.class).block();

return response;
Copy link
Member

Choose a reason for hiding this comment

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

해당 코드는 변수 인라인화 및 람다->메서드 참조 방식을 통해 다음과 같이 간소화될 수 있을 것 같아요!!

return webClient.get()
			.uri(uriBuilder -> uriBuilder
				.path("/req/address")
				.queryParam("service", "address")
				.queryParam("request", "getAddress")
				.queryParam("key", apiKey)
				.queryParam("point", lng + "," + lat)
				.queryParam("crs", "epsg:4326")
				.queryParam("type", "both")
				.queryParam("format", "json")
				.build())
			.retrieve()
			.onStatus(
				HttpStatusCode::isError,
				res -> Mono.error(new GeoCoderException())
			)
			.bodyToMono(AddressResponse.class).block();

@1winhyun 1winhyun changed the title Feat/#31-test 제휴게시글 관련 기능 구현 Feat/#31 제휴게시글 관련 기능 구현 Jan 9, 2026
@our-campUS our-campUS deleted a comment from coderabbitai bot Jan 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨Feat 새로운 기능 개발 ♻️Refactor 리팩토링

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants