From 41ef309e0a62a50b86d4cf3d9e7065bb63fba2a8 Mon Sep 17 00:00:00 2001 From: tobbot16 Date: Mon, 15 Dec 2025 09:40:39 +0900 Subject: [PATCH 1/6] =?UTF-8?q?feat:=20build=ED=95=98=EA=B8=B0=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20commit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../location/dto/LocationRequestDto.java | 4 ++ .../location/dto/LocationResponseDto.java | 6 +++ .../domain/location/entity/Location.java | 5 ++- .../repository/LocationRepository.java | 2 + .../location/service/LocationService.java | 42 +++++++++++++++++++ .../global/error/code/LocationErrorCode.java | 17 ++++++++ 6 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/LocationRequestDto.java create mode 100644 src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/LocationResponseDto.java create mode 100644 src/main/java/com/back/web7_9_codecrete_be/global/error/code/LocationErrorCode.java diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/LocationRequestDto.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/LocationRequestDto.java new file mode 100644 index 00000000..86ed8128 --- /dev/null +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/LocationRequestDto.java @@ -0,0 +1,4 @@ +package com.back.web7_9_codecrete_be.domain.location.dto; + +public class LocationRequestDto { +} diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/LocationResponseDto.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/LocationResponseDto.java new file mode 100644 index 00000000..3a04c799 --- /dev/null +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/LocationResponseDto.java @@ -0,0 +1,6 @@ +package com.back.web7_9_codecrete_be.domain.location.dto; + +public class LocationResponseDto { + + +} diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/entity/Location.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/entity/Location.java index a70fdba4..524a3693 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/entity/Location.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/entity/Location.java @@ -1,6 +1,7 @@ package com.back.web7_9_codecrete_be.domain.location.entity; +import com.back.web7_9_codecrete_be.domain.users.entity.User; import jakarta.persistence.*; import lombok.Getter; import lombok.NoArgsConstructor; @@ -18,11 +19,11 @@ public class Location { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; // TODO : 추후 user Entity 보고 확인 예정 우선 주석 처리 -/* + @ManyToOne @JoinColumn(name="user_id", nullable = false) private User user; -*/ + @Column(length = 255) private String address; diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/repository/LocationRepository.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/repository/LocationRepository.java index 7c68fd91..503294af 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/repository/LocationRepository.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/repository/LocationRepository.java @@ -4,4 +4,6 @@ import org.springframework.data.jpa.repository.JpaRepository; public interface LocationRepository extends JpaRepository { + + } diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/service/LocationService.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/service/LocationService.java index f4217e5b..9122ad54 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/service/LocationService.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/service/LocationService.java @@ -1,6 +1,15 @@ package com.back.web7_9_codecrete_be.domain.location.service; +import com.back.web7_9_codecrete_be.domain.location.dto.LocationRequestDto; +import com.back.web7_9_codecrete_be.domain.location.dto.LocationResponseDto; +import com.back.web7_9_codecrete_be.domain.location.entity.Location; import com.back.web7_9_codecrete_be.domain.location.repository.LocationRepository; +import com.back.web7_9_codecrete_be.domain.users.entity.User; +import com.back.web7_9_codecrete_be.domain.users.repository.UserRepository; +import com.back.web7_9_codecrete_be.global.error.code.AuthErrorCode; +import com.back.web7_9_codecrete_be.global.error.code.ErrorCode; +import com.back.web7_9_codecrete_be.global.error.code.LocationErrorCode; +import com.back.web7_9_codecrete_be.global.error.exception.BusinessException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -9,5 +18,38 @@ public class LocationService { private final LocationRepository locationRepository; + private final UserRepository userRepository; + + public LocationResponseDto getLocation(LocationRequestDto locationRequestDto, Long memberId){ + + } + + public LocationResponseDto saveLocation(LocationRequestDto locationRequestDto, Long memberId){ + User user = getLocation + } + + public LocationResponseDto modifyLocation(LocationRequestDto locationRequestDto, Long memberId){ + + } + + public void removeLoctaion(LocationRequestDto locationRequestDto, Long userId, Long locationId){ + Location location = getLocationEntity(locationId); + locationRepository.delete(location); + } + + + public Location getLocationEntity(Long locationId){ + return locationRepository.findById(locationId).orElseThrow( + () -> new BusinessException(LocationErrorCode.LOCATION_NOT_FOUND) + ); + } + + public User getLocationById(Long userId){ + return userRepository.findById(userId).orElseThrow( + () -> new BusinessException(AuthErrorCode.UNAUTHORIZED_USER) + ); + } + + } diff --git a/src/main/java/com/back/web7_9_codecrete_be/global/error/code/LocationErrorCode.java b/src/main/java/com/back/web7_9_codecrete_be/global/error/code/LocationErrorCode.java new file mode 100644 index 00000000..a6f3f86b --- /dev/null +++ b/src/main/java/com/back/web7_9_codecrete_be/global/error/code/LocationErrorCode.java @@ -0,0 +1,17 @@ +package com.back.web7_9_codecrete_be.global.error.code; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; + +@Getter +@RequiredArgsConstructor +public enum LocationErrorCode implements ErrorCode{ + + LOCATION_NOT_FOUND(HttpStatus.NOT_FOUND, "L-100", "위치를 찾을 수 없습니다."); + + private final HttpStatus status; + private final String code; + private final String message; + +} From 12c92b2f22f9c37f035e97540d14cfc166486091 Mon Sep 17 00:00:00 2001 From: tobbot16 Date: Tue, 16 Dec 2025 00:57:42 +0900 Subject: [PATCH 2/6] =?UTF-8?q?feat:=20=20push=EB=A5=BC=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20=EC=9E=84=EC=8B=9C=20=EC=A0=80=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../location/dto/LocationRequestDto.java | 4 - .../location/dto/LocationResponseDto.java | 6 - .../domain/location/dto/dummy.txt | 0 .../dto/request/LocationModifyRequestDto.java | 14 ++ .../dto/request/LocationRequestDto.java | 9 ++ .../dto/request/LocationSaveRequestDto.java | 4 + .../response/LocationModifyResponseDto.java | 4 + .../dto/response/LocationResponseDto.java | 10 ++ .../dto/response/LocationSaveResponseDto.java | 4 + .../domain/location/entity/Location.java | 10 ++ .../repository/LocationRepository.java | 1 + .../location/service/LocationService.java | 137 +++++++++++------- 12 files changed, 138 insertions(+), 65 deletions(-) delete mode 100644 src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/LocationRequestDto.java delete mode 100644 src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/LocationResponseDto.java delete mode 100644 src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/dummy.txt create mode 100644 src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/request/LocationModifyRequestDto.java create mode 100644 src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/request/LocationRequestDto.java create mode 100644 src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/request/LocationSaveRequestDto.java create mode 100644 src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/response/LocationModifyResponseDto.java create mode 100644 src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/response/LocationResponseDto.java create mode 100644 src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/response/LocationSaveResponseDto.java diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/LocationRequestDto.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/LocationRequestDto.java deleted file mode 100644 index 86ed8128..00000000 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/LocationRequestDto.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.back.web7_9_codecrete_be.domain.location.dto; - -public class LocationRequestDto { -} diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/LocationResponseDto.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/LocationResponseDto.java deleted file mode 100644 index 3a04c799..00000000 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/LocationResponseDto.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.back.web7_9_codecrete_be.domain.location.dto; - -public class LocationResponseDto { - - -} diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/dummy.txt b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/dummy.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/request/LocationModifyRequestDto.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/request/LocationModifyRequestDto.java new file mode 100644 index 00000000..16384617 --- /dev/null +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/request/LocationModifyRequestDto.java @@ -0,0 +1,14 @@ +package com.back.web7_9_codecrete_be.domain.location.dto.request; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class LocationModifyRequestDto { + + private double changelat; + private double changelon; + + +} diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/request/LocationRequestDto.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/request/LocationRequestDto.java new file mode 100644 index 00000000..40857d45 --- /dev/null +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/request/LocationRequestDto.java @@ -0,0 +1,9 @@ +package com.back.web7_9_codecrete_be.domain.location.dto.request; + +public class LocationRequestDto { + + private double lat; + + private double lon; + +} diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/request/LocationSaveRequestDto.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/request/LocationSaveRequestDto.java new file mode 100644 index 00000000..931e499e --- /dev/null +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/request/LocationSaveRequestDto.java @@ -0,0 +1,4 @@ +package com.back.web7_9_codecrete_be.domain.location.dto.request; + +public class LocationSaveRequestDto { +} diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/response/LocationModifyResponseDto.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/response/LocationModifyResponseDto.java new file mode 100644 index 00000000..d85291b4 --- /dev/null +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/response/LocationModifyResponseDto.java @@ -0,0 +1,4 @@ +package com.back.web7_9_codecrete_be.domain.location.dto.response; + +public class LocationModifyResponseDto { +} diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/response/LocationResponseDto.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/response/LocationResponseDto.java new file mode 100644 index 00000000..05a5a45f --- /dev/null +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/response/LocationResponseDto.java @@ -0,0 +1,10 @@ +package com.back.web7_9_codecrete_be.domain.location.dto.response; + +public class LocationResponseDto { + + private double lat; + + private double lon; + + private String address; +} diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/response/LocationSaveResponseDto.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/response/LocationSaveResponseDto.java new file mode 100644 index 00000000..9eaf03ac --- /dev/null +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/response/LocationSaveResponseDto.java @@ -0,0 +1,4 @@ +package com.back.web7_9_codecrete_be.domain.location.dto.response; + +public class LocationSaveResponseDto { +} diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/entity/Location.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/entity/Location.java index 524a3693..0f1a2caa 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/entity/Location.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/entity/Location.java @@ -33,4 +33,14 @@ public class Location { private double lat; private double lon; + + public double setlat(double lat){ + this.lat = lat; + return lat; + } + + public double setlon(double lon){ + this.lon = lon; + return lon; + } } diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/repository/LocationRepository.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/repository/LocationRepository.java index 503294af..4b3ad77b 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/repository/LocationRepository.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/repository/LocationRepository.java @@ -6,4 +6,5 @@ public interface LocationRepository extends JpaRepository { + Location findByUserId(Long userId); } diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/service/LocationService.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/service/LocationService.java index 9122ad54..ecb9d4d2 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/service/LocationService.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/service/LocationService.java @@ -1,55 +1,82 @@ -package com.back.web7_9_codecrete_be.domain.location.service; - -import com.back.web7_9_codecrete_be.domain.location.dto.LocationRequestDto; -import com.back.web7_9_codecrete_be.domain.location.dto.LocationResponseDto; -import com.back.web7_9_codecrete_be.domain.location.entity.Location; -import com.back.web7_9_codecrete_be.domain.location.repository.LocationRepository; -import com.back.web7_9_codecrete_be.domain.users.entity.User; -import com.back.web7_9_codecrete_be.domain.users.repository.UserRepository; -import com.back.web7_9_codecrete_be.global.error.code.AuthErrorCode; -import com.back.web7_9_codecrete_be.global.error.code.ErrorCode; -import com.back.web7_9_codecrete_be.global.error.code.LocationErrorCode; -import com.back.web7_9_codecrete_be.global.error.exception.BusinessException; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class LocationService { - - private final LocationRepository locationRepository; - private final UserRepository userRepository; - - public LocationResponseDto getLocation(LocationRequestDto locationRequestDto, Long memberId){ - - } - - public LocationResponseDto saveLocation(LocationRequestDto locationRequestDto, Long memberId){ - User user = getLocation - } - - public LocationResponseDto modifyLocation(LocationRequestDto locationRequestDto, Long memberId){ - - } - - public void removeLoctaion(LocationRequestDto locationRequestDto, Long userId, Long locationId){ - Location location = getLocationEntity(locationId); - locationRepository.delete(location); - } - - - public Location getLocationEntity(Long locationId){ - return locationRepository.findById(locationId).orElseThrow( - () -> new BusinessException(LocationErrorCode.LOCATION_NOT_FOUND) - ); - } - - public User getLocationById(Long userId){ - return userRepository.findById(userId).orElseThrow( - () -> new BusinessException(AuthErrorCode.UNAUTHORIZED_USER) - ); - } - - - -} +//package com.back.web7_9_codecrete_be.domain.location.service; +// +//import com.back.web7_9_codecrete_be.domain.location.dto.request.LocationModifyRequestDto; +//import com.back.web7_9_codecrete_be.domain.location.dto.request.LocationRequestDto; +//import com.back.web7_9_codecrete_be.domain.location.dto.response.LocationResponseDto; +//import com.back.web7_9_codecrete_be.domain.location.entity.Location; +//import com.back.web7_9_codecrete_be.domain.location.repository.LocationRepository; +//import com.back.web7_9_codecrete_be.domain.users.entity.User; +//import com.back.web7_9_codecrete_be.domain.users.repository.UserRepository; +//import com.back.web7_9_codecrete_be.global.error.code.AuthErrorCode; +//import com.back.web7_9_codecrete_be.global.error.code.LocationErrorCode; +//import com.back.web7_9_codecrete_be.global.error.exception.BusinessException; +//import lombok.RequiredArgsConstructor; +//import org.springframework.stereotype.Service; +// +//@Service +//@RequiredArgsConstructor +//public class LocationService { +// +// private final LocationRepository locationRepository; +// private final UserRepository userRepository; +// +// public LocationResponseDto getLocation(LocationRequestDto locationRequestDto, Long userId){ //내 위치 불러오기 +// +// User user = getUserEntity(userId); +//// Location location = getLocationByUserId(userId); +// Location location =locationRepository.findByUserId(userId); +// if(location == null){ +// throw new BusinessException(LocationErrorCode.LOCATION_NOT_FOUND); +// } +// return LocationResponseDto +// } +// +// public LocationResponseDto saveLocation(LocationRequestDto locationRequestDto, Long locationId){ //내 위치 저장 +// //예외 처리할 것: 내 위치가 저장되어있는지 확인 +// //로그인 되어있는지 확인 +// //추가하면 좋을것? 이게 대한민국의 좌표인지 +//// Location location = locationRepository.findByUser(locationId); +//// +//// if(location.isPresent()){ +//// +//// } +// +// } +// +// +// public LocationResponseDto modifyLocation(LocationModifyRequestDto locationModifyRequestDto, Long locationId){ //내 위치 수정 +// +// Location location = getLocationEntity(locationId); +// double changelat = locationModifyRequestDto.getChangelat(); +// double changelon = locationModifyRequestDto.getChangelon(); +// location.setlat(changelat); +// location.setlon(changelon); +// locationRepository.save(location); +// } +// +// public void removeLoctaion(LocationRequestDto locationRequestDto, Long userId, Long locationId){ //내 위치 삭제 +// Location location = getLocationEntity(locationId); +// locationRepository.delete(location); +// } +// +// +// public Location getLocationEntity(Long locationId){ +// return locationRepository.findById(locationId).orElseThrow( +// () -> new BusinessException(LocationErrorCode.LOCATION_NOT_FOUND) +// ); +// } +// +// public User getUserEntity(Long userId){ +// return userRepository.findById(userId).orElseThrow( +// () -> new BusinessException(AuthErrorCode.UNAUTHORIZED_USER) +// ); +// } +// +// public Location getLocationByUserId(Long userId){ +// return locationRepository.findById(userId).orElseThrow( +// () -> new BusinessException(LocationErrorCode.LOCATION_NOT_FOUND) +// ); +// } +// +// +//} From 6bbd1d2ef8530af8db62ade12af2f2bda320fdb1 Mon Sep 17 00:00:00 2001 From: tobbot16 Date: Tue, 16 Dec 2025 14:13:55 +0900 Subject: [PATCH 3/6] =?UTF-8?q?feat:=20location=20CRUD=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/KakaoTestController.java | 17 +- .../controller/LocationController.java | 43 ++++- .../location/controller/TmapController.java | 4 +- .../location/dto/KakaoCoordinateResponse.java | 35 ++++ .../dto/request/LocationModifyRequestDto.java | 14 -- .../dto/request/LocationRequestDto.java | 3 + .../dto/request/LocationSaveRequestDto.java | 4 - .../response/LocationModifyResponseDto.java | 4 - .../dto/response/LocationResponseDto.java | 17 ++ .../dto/response/LocationSaveResponseDto.java | 4 - .../domain/location/entity/Location.java | 27 ++- .../repository/LocationRepository.java | 5 +- .../location/service/KakaoLocalService.java | 37 ++++ .../location/service/LocationService.java | 166 ++++++++++-------- .../global/error/code/LocationErrorCode.java | 6 +- .../global/security/SecurityConfig.java | 1 + 16 files changed, 269 insertions(+), 118 deletions(-) create mode 100644 src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/KakaoCoordinateResponse.java delete mode 100644 src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/request/LocationModifyRequestDto.java delete mode 100644 src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/request/LocationSaveRequestDto.java delete mode 100644 src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/response/LocationModifyResponseDto.java delete mode 100644 src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/response/LocationSaveResponseDto.java diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/controller/KakaoTestController.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/controller/KakaoTestController.java index aefab7d9..d71b7087 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/controller/KakaoTestController.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/controller/KakaoTestController.java @@ -2,27 +2,38 @@ import com.back.web7_9_codecrete_be.domain.location.dto.KakaoLocalResponse; import com.back.web7_9_codecrete_be.domain.location.service.KakaoLocalService; +import com.back.web7_9_codecrete_be.global.rsData.RsData; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController -@RequestMapping("/api/test") +@RequestMapping("/api/v1/location/kakao") @RequiredArgsConstructor public class KakaoTestController { private final KakaoLocalService kakaoLocalService; - @GetMapping("/kakao-restaurants") + @GetMapping("/restaurants") public List testKakaoRestaurants() { - // ✅ 테스트용 하드코딩 좌표 (서울 시청 근처) + //테스트용 하드코딩 좌표 (서울 시청 근처) double lat = 37.5665; double lng = 126.9780; return kakaoLocalService.searchNearbyRestaurants(lat, lng); } + + @GetMapping("/coord2address") + public RsData coord2Address( + @RequestParam double lat, + @RequestParam double lon + ) { + String addressName = kakaoLocalService.coordinateToAddressName(lat, lon); + return RsData.success("좌표를 주소로 변환했습니다.", addressName); + } } diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/controller/LocationController.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/controller/LocationController.java index fe1872d0..4945c1ad 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/controller/LocationController.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/controller/LocationController.java @@ -1,15 +1,52 @@ package com.back.web7_9_codecrete_be.domain.location.controller; +import com.back.web7_9_codecrete_be.domain.location.dto.request.LocationRequestDto; +import com.back.web7_9_codecrete_be.domain.location.dto.response.LocationResponseDto; import com.back.web7_9_codecrete_be.domain.location.service.LocationService; +import com.back.web7_9_codecrete_be.domain.users.entity.User; +import com.back.web7_9_codecrete_be.global.rq.Rq; +import com.back.web7_9_codecrete_be.global.rsData.RsData; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @RestController -@RequestMapping("/api/v1/location") +@RequestMapping("/api/v1/location/my") @RequiredArgsConstructor public class LocationController { private final LocationService locationService; + private final Rq rq; + @GetMapping() + public RsData getMyLocation( + ){ + User user = rq.getUser(); + return RsData.success("내 위치정보를 조회합니다", locationService.getLocation(user)); + } + + + @PostMapping() + public RsData saveMyLocation( + @RequestBody LocationRequestDto locationRequestDto + ){ + User user = rq.getUser(); + return RsData.success("내 위치정보를 저장했습니다.", locationService.saveLocation(locationRequestDto, user)); + } + + + @PatchMapping + public RsData modifyMyLocation( + @RequestBody LocationRequestDto locationRequestDto + ){ + User user = rq.getUser(); + return RsData.success("내 위치정보를 수정했습니다.", locationService.modifyLocation(locationRequestDto, user)); + } + + @DeleteMapping + public RsData deleteMyLocation( + ){ + User user = rq.getUser(); + locationService.removeLocation(user); + return RsData.success("내 위치정보를 삭제했습니다.", null); + } } diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/controller/TmapController.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/controller/TmapController.java index 46551541..5c50e4cc 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/controller/TmapController.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/controller/TmapController.java @@ -9,12 +9,12 @@ @RestController @RequiredArgsConstructor -@RequestMapping("/api/tmap") +@RequestMapping("/api/v1/location") public class TmapController { private final TmapService tmapService; - @GetMapping("/transit") + @GetMapping("/tmap/transit") public String getTransit( @RequestParam double startX, @RequestParam double startY, diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/KakaoCoordinateResponse.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/KakaoCoordinateResponse.java new file mode 100644 index 00000000..8480d215 --- /dev/null +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/KakaoCoordinateResponse.java @@ -0,0 +1,35 @@ +package com.back.web7_9_codecrete_be.domain.location.dto; + +import lombok.Data; + +import java.util.List; +@Data +public class KakaoCoordinateResponse { //좌표 -> 주소로 바꾸는 response + + private List documents; + + @Data + public static class Document { + private Address address; + private RoadAddress road_address; + } + + @Data + public static class Address { + private String address_name; + private String region_1depth_name; + private String region_2depth_name; + private String region_3depth_name; + private String mountain_yn; + private String main_address_no; + private String sub_address_no; + } + + @Data + public static class RoadAddress { + private String address_name; + private String road_name; + private String building_name; + private String zone_no; + } +} diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/request/LocationModifyRequestDto.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/request/LocationModifyRequestDto.java deleted file mode 100644 index 16384617..00000000 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/request/LocationModifyRequestDto.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.back.web7_9_codecrete_be.domain.location.dto.request; - -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -public class LocationModifyRequestDto { - - private double changelat; - private double changelon; - - -} diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/request/LocationRequestDto.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/request/LocationRequestDto.java index 40857d45..43e24c4f 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/request/LocationRequestDto.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/request/LocationRequestDto.java @@ -1,5 +1,8 @@ package com.back.web7_9_codecrete_be.domain.location.dto.request; +import lombok.Data; + +@Data public class LocationRequestDto { private double lat; diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/request/LocationSaveRequestDto.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/request/LocationSaveRequestDto.java deleted file mode 100644 index 931e499e..00000000 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/request/LocationSaveRequestDto.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.back.web7_9_codecrete_be.domain.location.dto.request; - -public class LocationSaveRequestDto { -} diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/response/LocationModifyResponseDto.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/response/LocationModifyResponseDto.java deleted file mode 100644 index d85291b4..00000000 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/response/LocationModifyResponseDto.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.back.web7_9_codecrete_be.domain.location.dto.response; - -public class LocationModifyResponseDto { -} diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/response/LocationResponseDto.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/response/LocationResponseDto.java index 05a5a45f..e18bdc1e 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/response/LocationResponseDto.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/response/LocationResponseDto.java @@ -1,5 +1,13 @@ package com.back.web7_9_codecrete_be.domain.location.dto.response; +import com.back.web7_9_codecrete_be.domain.location.entity.Location; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +@AllArgsConstructor public class LocationResponseDto { private double lat; @@ -7,4 +15,13 @@ public class LocationResponseDto { private double lon; private String address; + + + public static LocationResponseDto from(Location location) { + return new LocationResponseDto( + location.getLat(), + location.getLon(), + location.getAddress() + ); + } } diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/response/LocationSaveResponseDto.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/response/LocationSaveResponseDto.java deleted file mode 100644 index 9eaf03ac..00000000 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/response/LocationSaveResponseDto.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.back.web7_9_codecrete_be.domain.location.dto.response; - -public class LocationSaveResponseDto { -} diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/entity/Location.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/entity/Location.java index 0f1a2caa..eae569fc 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/entity/Location.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/entity/Location.java @@ -34,13 +34,32 @@ public class Location { private double lon; - public double setlat(double lat){ + + @PrePersist + public void prePersist() { + this.modified_date = LocalDateTime.now(); // ⭐ insert 때도 채움 + } + + @PreUpdate + public void preUpdate() { + this.modified_date = LocalDateTime.now(); + } + + protected Location(User user, double lat, double lon, String address) { + this.user = user; this.lat = lat; - return lat; + this.lon = lon; + this.address = address; + } + + public static Location create(User user, double lat, double lon, String addressName) { + return new Location(user, lat, lon, addressName); } - public double setlon(double lon){ + public void update(double lat, double lon, String address) { + + this.lat = lat; this.lon = lon; - return lon; + this.address = address; } } diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/repository/LocationRepository.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/repository/LocationRepository.java index 4b3ad77b..3c526aa9 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/repository/LocationRepository.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/repository/LocationRepository.java @@ -1,10 +1,13 @@ package com.back.web7_9_codecrete_be.domain.location.repository; import com.back.web7_9_codecrete_be.domain.location.entity.Location; +import com.back.web7_9_codecrete_be.domain.users.entity.User; import org.springframework.data.jpa.repository.JpaRepository; public interface LocationRepository extends JpaRepository { - Location findByUserId(Long userId); + Location findByUser(User user); + + boolean existsByUser(User user); } diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/service/KakaoLocalService.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/service/KakaoLocalService.java index e6ff9ffb..061210dc 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/service/KakaoLocalService.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/service/KakaoLocalService.java @@ -1,6 +1,9 @@ package com.back.web7_9_codecrete_be.domain.location.service; +import com.back.web7_9_codecrete_be.domain.location.dto.KakaoCoordinateResponse; import com.back.web7_9_codecrete_be.domain.location.dto.KakaoLocalResponse; +import com.back.web7_9_codecrete_be.global.error.code.LocationErrorCode; +import com.back.web7_9_codecrete_be.global.error.exception.BusinessException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.web.reactive.function.client.WebClient; @@ -29,4 +32,38 @@ public List searchNearbyRestaurants(double lat, dou .block() // 동기 호출 (필요하면 비동기로 변경 가능) .getDocuments(); } + + public String coordinateToAddressName(double lat, double lng) { + + KakaoCoordinateResponse response = kakaoWebClient.get() + .uri(uriBuilder -> uriBuilder + .path("/v2/local/geo/coord2address.json") + .queryParam("x", lng) + .queryParam("y", lat) + .build() + ) + .retrieve() + .bodyToMono(KakaoCoordinateResponse.class) + .block(); + + if (response == null || response.getDocuments() == null || response.getDocuments().isEmpty()) { + throw new BusinessException(LocationErrorCode.ADDRESS_NOT_FOUND); + } + + KakaoCoordinateResponse.Document doc = response.getDocuments().get(0); + + String addressName = null; + if (doc.getRoad_address() != null && doc.getRoad_address().getAddress_name() != null) { + addressName = doc.getRoad_address().getAddress_name(); + } else if (doc.getAddress() != null) { + addressName = doc.getAddress().getAddress_name(); + } + + if (addressName == null || addressName.isBlank()) { + throw new BusinessException(LocationErrorCode.ADDRESS_NOT_FOUND); + } + + return addressName; + } + } \ No newline at end of file diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/service/LocationService.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/service/LocationService.java index ecb9d4d2..612c2f68 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/service/LocationService.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/service/LocationService.java @@ -1,82 +1,92 @@ -//package com.back.web7_9_codecrete_be.domain.location.service; -// -//import com.back.web7_9_codecrete_be.domain.location.dto.request.LocationModifyRequestDto; -//import com.back.web7_9_codecrete_be.domain.location.dto.request.LocationRequestDto; -//import com.back.web7_9_codecrete_be.domain.location.dto.response.LocationResponseDto; -//import com.back.web7_9_codecrete_be.domain.location.entity.Location; -//import com.back.web7_9_codecrete_be.domain.location.repository.LocationRepository; -//import com.back.web7_9_codecrete_be.domain.users.entity.User; -//import com.back.web7_9_codecrete_be.domain.users.repository.UserRepository; -//import com.back.web7_9_codecrete_be.global.error.code.AuthErrorCode; -//import com.back.web7_9_codecrete_be.global.error.code.LocationErrorCode; -//import com.back.web7_9_codecrete_be.global.error.exception.BusinessException; -//import lombok.RequiredArgsConstructor; -//import org.springframework.stereotype.Service; -// -//@Service -//@RequiredArgsConstructor -//public class LocationService { -// -// private final LocationRepository locationRepository; -// private final UserRepository userRepository; -// -// public LocationResponseDto getLocation(LocationRequestDto locationRequestDto, Long userId){ //내 위치 불러오기 -// -// User user = getUserEntity(userId); -//// Location location = getLocationByUserId(userId); -// Location location =locationRepository.findByUserId(userId); -// if(location == null){ -// throw new BusinessException(LocationErrorCode.LOCATION_NOT_FOUND); -// } -// return LocationResponseDto -// } -// -// public LocationResponseDto saveLocation(LocationRequestDto locationRequestDto, Long locationId){ //내 위치 저장 -// //예외 처리할 것: 내 위치가 저장되어있는지 확인 -// //로그인 되어있는지 확인 -// //추가하면 좋을것? 이게 대한민국의 좌표인지 -//// Location location = locationRepository.findByUser(locationId); -//// -//// if(location.isPresent()){ -//// -//// } -// -// } -// -// -// public LocationResponseDto modifyLocation(LocationModifyRequestDto locationModifyRequestDto, Long locationId){ //내 위치 수정 -// -// Location location = getLocationEntity(locationId); -// double changelat = locationModifyRequestDto.getChangelat(); -// double changelon = locationModifyRequestDto.getChangelon(); -// location.setlat(changelat); -// location.setlon(changelon); -// locationRepository.save(location); -// } -// -// public void removeLoctaion(LocationRequestDto locationRequestDto, Long userId, Long locationId){ //내 위치 삭제 -// Location location = getLocationEntity(locationId); -// locationRepository.delete(location); -// } -// -// -// public Location getLocationEntity(Long locationId){ -// return locationRepository.findById(locationId).orElseThrow( -// () -> new BusinessException(LocationErrorCode.LOCATION_NOT_FOUND) -// ); -// } -// -// public User getUserEntity(Long userId){ +package com.back.web7_9_codecrete_be.domain.location.service; + +import com.back.web7_9_codecrete_be.domain.location.dto.KakaoLocalResponse; +import com.back.web7_9_codecrete_be.domain.location.dto.request.LocationRequestDto; +import com.back.web7_9_codecrete_be.domain.location.dto.response.LocationResponseDto; +import com.back.web7_9_codecrete_be.domain.location.entity.Location; +import com.back.web7_9_codecrete_be.domain.location.repository.LocationRepository; +import com.back.web7_9_codecrete_be.domain.users.entity.User; +import com.back.web7_9_codecrete_be.domain.users.repository.UserRepository; +import com.back.web7_9_codecrete_be.global.error.code.AuthErrorCode; +import com.back.web7_9_codecrete_be.global.error.code.LocationErrorCode; +import com.back.web7_9_codecrete_be.global.error.exception.BusinessException; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class LocationService { + + private final LocationRepository locationRepository; + private final KakaoLocalService kakaoLocalService; + + + @Transactional(readOnly = true) + public LocationResponseDto getLocation(User user){ //내 위치 불러오기 + + Location location =locationRepository.findByUser(user); + if(location == null){ + throw new BusinessException(LocationErrorCode.LOCATION_NOT_FOUND); + } + + return LocationResponseDto.from(location); + } + + @Transactional + public LocationResponseDto saveLocation(LocationRequestDto locationRequestDto, User user){ //내 위치 저장 + //예외 처리할 것: 내 위치가 저장되어있는지 확인 //로그인 되어있는지 확인 //추가하면 좋을것? 이게 대한민국의 좌표인지 + validateKoreaCoordinate(locationRequestDto.getLat(), locationRequestDto.getLon()); + + if (locationRepository.existsByUser(user)) { + throw new BusinessException(LocationErrorCode.LOCATION_ALREADY_EXISTS); + } + String addressName = kakaoLocalService.coordinateToAddressName(locationRequestDto.getLat(), locationRequestDto.getLon()); + if (addressName == null || addressName.isBlank()) { + throw new BusinessException(LocationErrorCode.LOCATION_NOT_EXIST_IN_KAKAO); + } + Location location = Location.create(user, locationRequestDto.getLat(), locationRequestDto.getLon(), addressName); + locationRepository.save(location); + return LocationResponseDto.from(location); + } + + @Transactional + public LocationResponseDto modifyLocation(LocationRequestDto locationRequestDto, User user){ //내 위치 수정 + + Location location = locationRepository.findByUser(user); + if(location == null) + throw new BusinessException(LocationErrorCode.LOCATION_NOT_FOUND); + + String addressName = kakaoLocalService.coordinateToAddressName(locationRequestDto.getLat(), locationRequestDto.getLon()); + + if (addressName == null || addressName.isBlank()) { + throw new BusinessException(LocationErrorCode.LOCATION_NOT_EXIST_IN_KAKAO); + } + + location.update(locationRequestDto.getLat(), locationRequestDto.getLon(), addressName); + location.preUpdate(); + return LocationResponseDto.from(location); + } + + @Transactional + public void removeLocation(User user){ //내 위치 삭제 + Location location = locationRepository.findByUser(user); + if(location == null){ + throw new BusinessException(LocationErrorCode.LOCATION_NOT_FOUND); + } + locationRepository.delete(location); + } + +// public User getUserEntity(Long userId){ //userId를 이용해서 User 객체 가져오기 // return userRepository.findById(userId).orElseThrow( // () -> new BusinessException(AuthErrorCode.UNAUTHORIZED_USER) // ); // } -// -// public Location getLocationByUserId(Long userId){ -// return locationRepository.findById(userId).orElseThrow( -// () -> new BusinessException(LocationErrorCode.LOCATION_NOT_FOUND) -// ); -// } -// -// -//} + + + private void validateKoreaCoordinate(double lat, double lon) { + if (lat < 33.0 || lat > 39.5 || lon < 124.0 || lon > 132.0) { + throw new BusinessException(LocationErrorCode.INVALID_KOREA_COORDINATE); + } + } +} diff --git a/src/main/java/com/back/web7_9_codecrete_be/global/error/code/LocationErrorCode.java b/src/main/java/com/back/web7_9_codecrete_be/global/error/code/LocationErrorCode.java index a6f3f86b..f760dd23 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/global/error/code/LocationErrorCode.java +++ b/src/main/java/com/back/web7_9_codecrete_be/global/error/code/LocationErrorCode.java @@ -8,7 +8,11 @@ @RequiredArgsConstructor public enum LocationErrorCode implements ErrorCode{ - LOCATION_NOT_FOUND(HttpStatus.NOT_FOUND, "L-100", "위치를 찾을 수 없습니다."); + LOCATION_NOT_FOUND(HttpStatus.NOT_FOUND, "L-100", "위치(좌표)를 찾을 수 없습니다."), + ADDRESS_NOT_FOUND(HttpStatus.NOT_FOUND, "L-101" , "위치(주소)를 찾을 수 없습니다."), + LOCATION_ALREADY_EXISTS(HttpStatus.NOT_FOUND, "L-102", "이미 저장되어있는 위치입니다."), + INVALID_KOREA_COORDINATE(HttpStatus.NOT_FOUND, "L-103" , "한국 좌표가 아닙니다"), + LOCATION_NOT_EXIST_IN_KAKAO(HttpStatus.NOT_FOUND, "L-104", "해당 좌표는 카카오에 등록되어있지 않습니다."); private final HttpStatus status; private final String code; diff --git a/src/main/java/com/back/web7_9_codecrete_be/global/security/SecurityConfig.java b/src/main/java/com/back/web7_9_codecrete_be/global/security/SecurityConfig.java index be26824b..70ebb226 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/global/security/SecurityConfig.java +++ b/src/main/java/com/back/web7_9_codecrete_be/global/security/SecurityConfig.java @@ -52,6 +52,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti "/v3/api-docs/**", // Swagger "/swagger-ui/**", // Swagger UI "/h2-console/**", // H2 Console + "/api/v1/location/**", //location 정보 조회 도메인(임시) "/api/v1/concerts/**", // concert 정보 조회 도메인 "/api/v1/artists/**" // artist 정보 저장 도메인(임시) ).permitAll() From 383cb11ae00ffb2eacb391ee558ee9191763b940 Mon Sep 17 00:00:00 2001 From: tobbot16 Date: Tue, 16 Dec 2025 14:21:34 +0900 Subject: [PATCH 4/6] =?UTF-8?q?feat:=20errorCode=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/location/service/LocationService.java | 2 +- .../global/error/code/LocationErrorCode.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/service/LocationService.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/service/LocationService.java index 612c2f68..262dcaa2 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/service/LocationService.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/service/LocationService.java @@ -72,7 +72,7 @@ public LocationResponseDto modifyLocation(LocationRequestDto locationRequestDto, public void removeLocation(User user){ //내 위치 삭제 Location location = locationRepository.findByUser(user); if(location == null){ - throw new BusinessException(LocationErrorCode.LOCATION_NOT_FOUND); + throw new BusinessException(LocationErrorCode.LOCATION_NOT_HAVE); } locationRepository.delete(location); } diff --git a/src/main/java/com/back/web7_9_codecrete_be/global/error/code/LocationErrorCode.java b/src/main/java/com/back/web7_9_codecrete_be/global/error/code/LocationErrorCode.java index f760dd23..c18a2bcd 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/global/error/code/LocationErrorCode.java +++ b/src/main/java/com/back/web7_9_codecrete_be/global/error/code/LocationErrorCode.java @@ -12,7 +12,8 @@ public enum LocationErrorCode implements ErrorCode{ ADDRESS_NOT_FOUND(HttpStatus.NOT_FOUND, "L-101" , "위치(주소)를 찾을 수 없습니다."), LOCATION_ALREADY_EXISTS(HttpStatus.NOT_FOUND, "L-102", "이미 저장되어있는 위치입니다."), INVALID_KOREA_COORDINATE(HttpStatus.NOT_FOUND, "L-103" , "한국 좌표가 아닙니다"), - LOCATION_NOT_EXIST_IN_KAKAO(HttpStatus.NOT_FOUND, "L-104", "해당 좌표는 카카오에 등록되어있지 않습니다."); + LOCATION_NOT_EXIST_IN_KAKAO(HttpStatus.NOT_FOUND, "L-104", "해당 좌표는 카카오에 등록되어있지 않습니다."), + LOCATION_NOT_HAVE(HttpStatus.NOT_FOUND, "L-105", "저장되어있는 좌표가 없어서 삭제가 불가능합니다."); private final HttpStatus status; private final String code; From 0c93b289e9d077ad17b782ca6d8be7a5b725234f Mon Sep 17 00:00:00 2001 From: tobbot16 Date: Tue, 16 Dec 2025 15:15:35 +0900 Subject: [PATCH 5/6] =?UTF-8?q?feat:=20Tmap,=20kakao=20swagger=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/KakaoTestController.java | 29 ++++++++-- .../controller/LocationController.java | 7 +++ .../location/controller/TmapController.java | 58 +++++++++++++++++-- .../location/dto/KakaoCoordinateResponse.java | 38 +++++++++++- .../location/dto/KakaoLocalResponse.java | 23 +++++++- .../domain/location/dto/TmapResponse.java | 20 ++++++- .../dto/request/LocationRequestDto.java | 8 ++- .../dto/response/LocationResponseDto.java | 9 ++- 8 files changed, 171 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/controller/KakaoTestController.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/controller/KakaoTestController.java index d71b7087..6bec1d56 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/controller/KakaoTestController.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/controller/KakaoTestController.java @@ -3,14 +3,18 @@ import com.back.web7_9_codecrete_be.domain.location.dto.KakaoLocalResponse; import com.back.web7_9_codecrete_be.domain.location.service.KakaoLocalService; import com.back.web7_9_codecrete_be.global.rsData.RsData; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.util.List; +@Tag(name = "Location - Kakao", description = "카카오 로컬 API 연동(주변 음식점 조회, 좌표→주소 변환) 관련 엔드포인트") @RestController @RequestMapping("/api/v1/location/kakao") @RequiredArgsConstructor @@ -18,19 +22,34 @@ public class KakaoTestController { private final KakaoLocalService kakaoLocalService; + @Operation( + summary = "주변 음식점 조회(테스트)", + description = "테스트용 하드코딩 좌표(서울 시청 근처)로 카카오 로컬에서 주변 음식점을 조회합니다., 하드코딩 좌표 : lat - 37.5665, lng -126.9780" + ) + @ApiResponse(responseCode = "200", description = "조회 성공", + content = @Content(schema = @Schema(implementation = KakaoLocalResponse.Document.class))) @GetMapping("/restaurants") public List testKakaoRestaurants() { - //테스트용 하드코딩 좌표 (서울 시청 근처) double lat = 37.5665; double lng = 126.9780; return kakaoLocalService.searchNearbyRestaurants(lat, lng); } + + @Operation( + summary = "좌표를 주소로 변환", + description = "위도(lat), 경도(lon)를 받아 카카오 API로 주소명(address_name)을 반환합니다." + ) + @ApiResponse(responseCode = "200", description = "변환 성공", + content = @Content(schema = @Schema(implementation = RsData.class))) @GetMapping("/coord2address") public RsData coord2Address( + @Parameter(description = "위도(latitude)", example = "37.5665", required = true) @RequestParam double lat, + + @Parameter(description = "경도(longitude)", example = "126.9780", required = true) @RequestParam double lon ) { String addressName = kakaoLocalService.coordinateToAddressName(lat, lon); diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/controller/LocationController.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/controller/LocationController.java index 4945c1ad..b38a28c3 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/controller/LocationController.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/controller/LocationController.java @@ -6,18 +6,22 @@ import com.back.web7_9_codecrete_be.domain.users.entity.User; import com.back.web7_9_codecrete_be.global.rq.Rq; import com.back.web7_9_codecrete_be.global.rsData.RsData; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/api/v1/location/my") @RequiredArgsConstructor +@Tag(name = "Location", description = "위치(Location) 관련 API") public class LocationController { private final LocationService locationService; private final Rq rq; @GetMapping() + @Operation(summary = "사용자 위치 조회", description = "사용자의 위치 정보를 조회합니다.") public RsData getMyLocation( ){ User user = rq.getUser(); @@ -26,6 +30,7 @@ public RsData getMyLocation( @PostMapping() + @Operation(summary = "사용자 위치 저장", description = "사용자의 위치 정보를 저장합니다.") public RsData saveMyLocation( @RequestBody LocationRequestDto locationRequestDto ){ @@ -35,6 +40,7 @@ public RsData saveMyLocation( @PatchMapping + @Operation(summary = "사용자 위치 수정", description = "사용자의 위치 정보를 수정합니다.") public RsData modifyMyLocation( @RequestBody LocationRequestDto locationRequestDto ){ @@ -43,6 +49,7 @@ public RsData modifyMyLocation( } @DeleteMapping + @Operation(summary = "사용자 위치 삭제", description = "사용자의 위치 정보를 삭제합니다.") public RsData deleteMyLocation( ){ User user = rq.getUser(); diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/controller/TmapController.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/controller/TmapController.java index 5c50e4cc..6119270f 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/controller/TmapController.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/controller/TmapController.java @@ -1,12 +1,19 @@ package com.back.web7_9_codecrete_be.domain.location.controller; import com.back.web7_9_codecrete_be.domain.location.service.TmapService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; +@Tag( + name = "Location - Tmap", + description = "Tmap 대중교통 길찾기 API 연동" +) @RestController @RequiredArgsConstructor @RequestMapping("/api/v1/location") @@ -14,13 +21,54 @@ public class TmapController { private final TmapService tmapService; + @Operation( + summary = "대중교통 경로 조회", + description = """ + 출발지(startX, startY)와 도착지(endX, endY) 좌표를 기반으로 + Tmap 대중교통 API를 호출하여 경로 정보를 조회합니다. + """ + ) + @ApiResponse( + responseCode = "200", + description = "경로 조회 성공", + content = @Content( + mediaType = "application/json", + schema = @Schema( + description = "Tmap 대중교통 경로 조회 결과(JSON 문자열)" + ) + ) + ) @GetMapping("/tmap/transit") public String getTransit( + + @Parameter( + description = "출발지 경도 (longitude)", + example = "126.9780", + required = true + ) @RequestParam double startX, + + @Parameter( + description = "출발지 위도 (latitude)", + example = "37.5665", + required = true + ) @RequestParam double startY, + + @Parameter( + description = "도착지 경도 (longitude)", + example = "127.0276", + required = true + ) @RequestParam double endX, + + @Parameter( + description = "도착지 위도 (latitude)", + example = "37.4979", + required = true + ) @RequestParam double endY ) { return tmapService.getRoute(startX, startY, endX, endY); } -} \ No newline at end of file +} diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/KakaoCoordinateResponse.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/KakaoCoordinateResponse.java index 8480d215..d2dab475 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/KakaoCoordinateResponse.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/KakaoCoordinateResponse.java @@ -1,35 +1,71 @@ package com.back.web7_9_codecrete_be.domain.location.dto; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.util.List; + @Data -public class KakaoCoordinateResponse { //좌표 -> 주소로 바꾸는 response +@Schema(description = "카카오 좌표 → 주소 변환 응답 DTO") +public class KakaoCoordinateResponse { + @Schema( + description = "주소 변환 결과 목록", + example = "[]" + ) private List documents; @Data + @Schema(description = "좌표 변환 결과 문서") public static class Document { + + @Schema(description = "지번 주소 정보") private Address address; + + @Schema(description = "도로명 주소 정보") private RoadAddress road_address; } @Data + @Schema(description = "지번 주소 상세 정보") public static class Address { + + @Schema(description = "전체 지번 주소", example = "서울 중구 태평로1가 31") private String address_name; + + @Schema(description = "시/도", example = "서울") private String region_1depth_name; + + @Schema(description = "구", example = "중구") private String region_2depth_name; + + @Schema(description = "동", example = "태평로1가") private String region_3depth_name; + + @Schema(description = "산 여부 (Y/N)", example = "N") private String mountain_yn; + + @Schema(description = "본번", example = "31") private String main_address_no; + + @Schema(description = "부번", example = "0") private String sub_address_no; } @Data + @Schema(description = "도로명 주소 상세 정보") public static class RoadAddress { + + @Schema(description = "전체 도로명 주소", example = "서울 중구 세종대로 110") private String address_name; + + @Schema(description = "도로명", example = "세종대로") private String road_name; + + @Schema(description = "건물명", example = "서울시청") private String building_name; + + @Schema(description = "우편번호", example = "04524") private String zone_no; } } diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/KakaoLocalResponse.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/KakaoLocalResponse.java index c66f8318..46dcaf31 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/KakaoLocalResponse.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/KakaoLocalResponse.java @@ -1,20 +1,37 @@ package com.back.web7_9_codecrete_be.domain.location.dto; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.util.List; @Data +@Schema(description = "카카오 로컬 API 장소 검색 응답 DTO") public class KakaoLocalResponse { + + @Schema(description = "장소 검색 결과 목록") private List documents; @Data + @Schema(description = "카카오 장소 정보") public static class Document { + + @Schema(description = "장소명", example = "디라이프 스타일키친 광화문점") private String place_name; - private String x; // longitude - private String y; // latitude + + @Schema(description = "경도(longitude)", example = "126.97826128583668") + private String x; + + @Schema(description = "위도(latitude)", example = "37.56842610180289") + private String y; + + @Schema(description = "도로명 주소", example = "서울 중구 세종대로 136") private String road_address_name; + + @Schema(description = "지번 주소", example = "서울 중구 태평로1가 84") private String address_name; + + @Schema(description = "카카오 장소 상세 URL", example = "http://place.map.kakao.com/444516464") private String place_url; } -} \ No newline at end of file +} diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/TmapResponse.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/TmapResponse.java index 2e248d8a..87121037 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/TmapResponse.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/TmapResponse.java @@ -1,15 +1,31 @@ package com.back.web7_9_codecrete_be.domain.location.dto; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @Data +@Schema(description = "Tmap 대중교통 경로 조회 요청 DTO") public class TmapResponse { + @Schema(description = "출발지 경도 (longitude)", example = "126.9780") private String startX; + + @Schema(description = "출발지 위도 (latitude)", example = "37.5665") private String startY; + + @Schema(description = "도착지 경도 (longitude)", example = "127.0276") private String endX; + + @Schema(description = "도착지 위도 (latitude)", example = "37.4979") private String endY; - private int count; //최대 응답 결과 개수 - private String format; //출력포멧 : jsom, xml + @Schema(description = "최대 응답 결과 개수", example = "5") + private int count; + + @Schema( + description = "응답 포맷 (json / xml)", + example = "json", + allowableValues = {"json", "xml"} + ) + private String format; } diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/request/LocationRequestDto.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/request/LocationRequestDto.java index 43e24c4f..ae83bb9d 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/request/LocationRequestDto.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/request/LocationRequestDto.java @@ -1,12 +1,16 @@ package com.back.web7_9_codecrete_be.domain.location.dto.request; -import lombok.Data; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; -@Data +@Getter +@Schema(description = "위치 요청 DTO") public class LocationRequestDto { + @Schema(description = "위도", example = "37.566535") private double lat; + @Schema(description = "경도", example = "126.9779692") private double lon; } diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/response/LocationResponseDto.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/response/LocationResponseDto.java index e18bdc1e..075576ac 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/response/LocationResponseDto.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/dto/response/LocationResponseDto.java @@ -1,19 +1,22 @@ package com.back.web7_9_codecrete_be.domain.location.dto.response; import com.back.web7_9_codecrete_be.domain.location.entity.Location; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; -@Setter + @Getter @AllArgsConstructor +@Schema(description = "위치 응답 DTO") public class LocationResponseDto { + @Schema(description = "위도", example = "37.566535") private double lat; - + @Schema(description = "경도", example = "126.9779692") private double lon; - + @Schema(description = "주소", example = "서울특별시 중구 세종대로 110") private String address; From 0b01e1d5d38fc6b9730e8ee0b762fcc13a04a6b8 Mon Sep 17 00:00:00 2001 From: tobbot16 Date: Tue, 16 Dec 2025 16:32:44 +0900 Subject: [PATCH 6/6] =?UTF-8?q?feat:=20=EC=B9=B4=EC=B9=B4=EC=98=A4?= =?UTF-8?q?=EB=A7=B5=20=EA=B7=BC=EC=B2=98=20=EC=9D=8C=EC=8B=9D=EC=A0=90,?= =?UTF-8?q?=20=EC=B9=B4=ED=8E=98=20=EB=B6=88=EB=9F=AC=EC=98=A4=EB=8A=94=20?= =?UTF-8?q?api=EC=97=90=EC=84=9C=20=EA=B0=92=EC=9D=84=20post=20=ED=98=95?= =?UTF-8?q?=C3=AC=C2=8B=EC=8B=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/KakaoTestController.java | 42 +++++++++++++++++++ .../location/service/KakaoLocalService.java | 19 +++++++++ 2 files changed, 61 insertions(+) diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/controller/KakaoTestController.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/controller/KakaoTestController.java index 6bec1d56..cc46af58 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/controller/KakaoTestController.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/controller/KakaoTestController.java @@ -29,6 +29,7 @@ public class KakaoTestController { @ApiResponse(responseCode = "200", description = "조회 성공", content = @Content(schema = @Schema(implementation = KakaoLocalResponse.Document.class))) @GetMapping("/restaurants") + public List testKakaoRestaurants() { double lat = 37.5665; @@ -37,6 +38,47 @@ public List testKakaoRestaurants() { return kakaoLocalService.searchNearbyRestaurants(lat, lng); } + @Operation( + summary = "주변 음식점 조회(테스트)", + description = "테스트용 좌표(서울 시청 근처)로 카카오 로컬에서 주변 음식점을 조회합니다, 좌표는 입력하면 됩니다." + + "예시 : http://localhost:8080/api/v1/location/kakao/restaurant?lat=37.5665&lng=126.9780" + ) + @PostMapping("/restaurant") + public List KakaoRestaurants( + @RequestParam double lat, + @RequestParam double lng + ){ + return kakaoLocalService.searchNearbyRestaurants(lat, lng); + } + + @Operation( + summary = "주변 카페 조회(테스트)", + description = "테스트용 하드코딩 좌표(서울 시청 근처)로 카카오 로컬에서 주변 카페를 조회합니다., 하드코딩 좌표 : lat - 37.5665, lng -126.9780" + ) + @ApiResponse(responseCode = "200", description = "조회 성공", + content = @Content(schema = @Schema(implementation = KakaoLocalResponse.Document.class))) + @GetMapping("/cafes") + public List testKakaoCafes() { + + double lat = 37.5665; + double lng = 126.9780; + + return kakaoLocalService.searchNearbyCafes(lat, lng); + } + + @Operation( + summary = "주변 카페 조회(테스트)", + description = "테스트용 좌표(서울 시청 근처)로 카카오 로컬에서 주변 카페를 조회합니다, 좌표는 입력하면 됩니다." + + "예시 : http://localhost:8080/api/v1/location/kakao/cafes?lat=37.5665&lng=126.9780" + ) + @PostMapping("/cafes") + public List KakaoCafes( + @RequestParam double lat, + @RequestParam double lng + ){ + return kakaoLocalService.searchNearbyCafes(lat, lng); + } + @Operation( summary = "좌표를 주소로 변환", diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/location/service/KakaoLocalService.java b/src/main/java/com/back/web7_9_codecrete_be/domain/location/service/KakaoLocalService.java index 061210dc..b8299297 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/location/service/KakaoLocalService.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/location/service/KakaoLocalService.java @@ -25,6 +25,25 @@ public List searchNearbyRestaurants(double lat, dou .queryParam("y", lat) .queryParam("x", lng) .queryParam("radius", 1000) // 반경 1km + .queryParam("sort", "distance") + .build() + ) + .retrieve() + .bodyToMono(KakaoLocalResponse.class) + .block() // 동기 호출 (필요하면 비동기로 변경 가능) + .getDocuments(); + } + public List searchNearbyCafes(double lat, double lng) { + + return kakaoWebClient.get() + .uri(uriBuilder -> uriBuilder + .path("/v2/local/search/keyword.json") + .queryParam("query", "카페") + .queryParam("category_group_code", "CE7") + .queryParam("y", lat) + .queryParam("x", lng) + .queryParam("radius", 1000) // 반경 1km + .queryParam("sort", "distance") .build() ) .retrieve()