From d7aa8122f72fd3cda7845dafa2eba7fbfe6ae8c3 Mon Sep 17 00:00:00 2001 From: chanrhan Date: Sat, 22 Nov 2025 22:04:51 +0900 Subject: [PATCH 1/5] =?UTF-8?q?refactor:=20=EC=A7=80=EB=8F=84=20=EB=A7=88?= =?UTF-8?q?=EC=BB=A4=20=EC=A1=B0=ED=9A=8C=20API=20=EB=B9=84=EC=A6=88?= =?UTF-8?q?=EB=8B=88=EC=8A=A4=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95(vi?= =?UTF-8?q?ew=20=EC=82=AC=EC=9A=A9=20=EC=95=88=ED=95=A8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../album/controller/AlbumController.java | 10 ++ .../domain/album/dto/AlbumPhotoItem.java | 30 ++++++ .../domain/album/dto/AlbumPhotoItems.java | 12 +++ .../dto/request/AlbumPhotoMarkersRequest.java | 27 ++++++ .../dto/response/AlbumPhotoItemsResponse.java | 18 ++-- .../response/AlbumPhotoMarkersResponse.java | 44 +++++++++ .../album/model/view/AlbumPhotoView.java | 59 ------------ .../album/model/view/AlbumPhotoViews.java | 21 ----- .../repository/AlbumPhotoRepository.java | 52 ++++++++--- .../domain/album/service/AlbumService.java | 22 ++++- .../photo/controller/PhotoController.java | 10 +- .../{ => request}/DeletePhotosRequest.java | 2 +- ...sRequest.java => PhotoMarkersRequest.java} | 5 +- .../dto/response/MapMarkersResponse.java | 91 ------------------- .../dto/response/PhotoMarkersResponse.java | 42 +++++++++ .../photo/repository/PhotoRepository.java | 21 +++++ .../domain/photo/service/PhotoService.java | 17 ++-- 17 files changed, 266 insertions(+), 217 deletions(-) create mode 100644 src/main/java/kr/kro/photoliner/domain/album/dto/AlbumPhotoItem.java create mode 100644 src/main/java/kr/kro/photoliner/domain/album/dto/AlbumPhotoItems.java create mode 100644 src/main/java/kr/kro/photoliner/domain/album/dto/request/AlbumPhotoMarkersRequest.java create mode 100644 src/main/java/kr/kro/photoliner/domain/album/dto/response/AlbumPhotoMarkersResponse.java delete mode 100644 src/main/java/kr/kro/photoliner/domain/album/model/view/AlbumPhotoView.java delete mode 100644 src/main/java/kr/kro/photoliner/domain/album/model/view/AlbumPhotoViews.java rename src/main/java/kr/kro/photoliner/domain/photo/dto/{ => request}/DeletePhotosRequest.java (63%) rename src/main/java/kr/kro/photoliner/domain/photo/dto/request/{MapMarkersRequest.java => PhotoMarkersRequest.java} (89%) delete mode 100644 src/main/java/kr/kro/photoliner/domain/photo/dto/response/MapMarkersResponse.java create mode 100644 src/main/java/kr/kro/photoliner/domain/photo/dto/response/PhotoMarkersResponse.java diff --git a/src/main/java/kr/kro/photoliner/domain/album/controller/AlbumController.java b/src/main/java/kr/kro/photoliner/domain/album/controller/AlbumController.java index 52c8a90..6439e17 100644 --- a/src/main/java/kr/kro/photoliner/domain/album/controller/AlbumController.java +++ b/src/main/java/kr/kro/photoliner/domain/album/controller/AlbumController.java @@ -5,9 +5,11 @@ import kr.kro.photoliner.domain.album.dto.request.AlbumDeleteRequest; import kr.kro.photoliner.domain.album.dto.request.AlbumItemCreateRequest; import kr.kro.photoliner.domain.album.dto.request.AlbumItemDeleteRequest; +import kr.kro.photoliner.domain.album.dto.request.AlbumPhotoMarkersRequest; import kr.kro.photoliner.domain.album.dto.request.AlbumTitleUpdateRequest; import kr.kro.photoliner.domain.album.dto.response.AlbumCreateResponse; import kr.kro.photoliner.domain.album.dto.response.AlbumPhotoItemsResponse; +import kr.kro.photoliner.domain.album.dto.response.AlbumPhotoMarkersResponse; import kr.kro.photoliner.domain.album.dto.response.AlbumsResponse; import kr.kro.photoliner.domain.album.service.AlbumService; import lombok.RequiredArgsConstructor; @@ -91,4 +93,12 @@ public ResponseEntity deleteAlbumItems( albumService.deleteAlbumItems(albumId, request); return ResponseEntity.noContent().build(); } + + @GetMapping("/{albumId}/markers") + public ResponseEntity getAlbumPhotoMarkers( + @PathVariable Long albumId, + @RequestBody @Valid AlbumPhotoMarkersRequest request + ) { + return ResponseEntity.ok(albumService.getAlbumPhotoMarkers(albumId, request)); + } } diff --git a/src/main/java/kr/kro/photoliner/domain/album/dto/AlbumPhotoItem.java b/src/main/java/kr/kro/photoliner/domain/album/dto/AlbumPhotoItem.java new file mode 100644 index 0000000..6b6036a --- /dev/null +++ b/src/main/java/kr/kro/photoliner/domain/album/dto/AlbumPhotoItem.java @@ -0,0 +1,30 @@ +package kr.kro.photoliner.domain.album.dto; + +import java.time.LocalDateTime; +import java.util.Objects; +import org.locationtech.jts.geom.Point; + +public record AlbumPhotoItem( + Long id, + Long photoId, + String fileName, + String filePath, + String thumbnailPath, + LocalDateTime capturedDt, + Point location +) { + + public Double getLatitude() { + if (Objects.isNull(location)) { + return null; + } + return location.getX(); + } + + public Double getLongitude() { + if (Objects.isNull(location)) { + return null; + } + return location.getY(); + } +} diff --git a/src/main/java/kr/kro/photoliner/domain/album/dto/AlbumPhotoItems.java b/src/main/java/kr/kro/photoliner/domain/album/dto/AlbumPhotoItems.java new file mode 100644 index 0000000..e535ca3 --- /dev/null +++ b/src/main/java/kr/kro/photoliner/domain/album/dto/AlbumPhotoItems.java @@ -0,0 +1,12 @@ +package kr.kro.photoliner.domain.album.dto; + +import java.util.List; + +public record AlbumPhotoItems( + List photoItems +) { + + public int count() { + return photoItems.size(); + } +} diff --git a/src/main/java/kr/kro/photoliner/domain/album/dto/request/AlbumPhotoMarkersRequest.java b/src/main/java/kr/kro/photoliner/domain/album/dto/request/AlbumPhotoMarkersRequest.java new file mode 100644 index 0000000..e5bc102 --- /dev/null +++ b/src/main/java/kr/kro/photoliner/domain/album/dto/request/AlbumPhotoMarkersRequest.java @@ -0,0 +1,27 @@ +package kr.kro.photoliner.domain.album.dto.request; + +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import org.locationtech.jts.geom.Coordinate; + +public record AlbumPhotoMarkersRequest( + @Min(0) @Max(90) + double swLat, + + @Min(0) @Max(180) + double swLng, + + @Min(0) @Max(90) + double neLat, + + @Min(0) @Max(180) + double neLng +) { + public Coordinate getSouthWestCoordinate() { + return new Coordinate(swLng, swLat); + } + + public Coordinate getNorthEastCoordinate() { + return new Coordinate(neLng, neLat); + } +} diff --git a/src/main/java/kr/kro/photoliner/domain/album/dto/response/AlbumPhotoItemsResponse.java b/src/main/java/kr/kro/photoliner/domain/album/dto/response/AlbumPhotoItemsResponse.java index 6b28cfd..ab36a6f 100644 --- a/src/main/java/kr/kro/photoliner/domain/album/dto/response/AlbumPhotoItemsResponse.java +++ b/src/main/java/kr/kro/photoliner/domain/album/dto/response/AlbumPhotoItemsResponse.java @@ -2,14 +2,14 @@ import java.time.LocalDateTime; import java.util.List; -import kr.kro.photoliner.domain.album.model.view.AlbumPhotoView; +import kr.kro.photoliner.domain.album.dto.AlbumPhotoItem; import org.springframework.data.domain.Page; public record AlbumPhotoItemsResponse( List items ) { - public static AlbumPhotoItemsResponse from(Page albumPhotoViews) { + public static AlbumPhotoItemsResponse from(Page albumPhotoViews) { return new AlbumPhotoItemsResponse( albumPhotoViews.stream() .map(InnerAlbumPhotoItem::from) @@ -26,14 +26,14 @@ public record InnerAlbumPhotoItem( LocalDateTime capturedDt ) { - public static InnerAlbumPhotoItem from(AlbumPhotoView albumPhotoView) { + public static InnerAlbumPhotoItem from(AlbumPhotoItem albumPhotoItem) { return new InnerAlbumPhotoItem( - albumPhotoView.getId(), - albumPhotoView.getPhotoId(), - albumPhotoView.getFileName(), - albumPhotoView.getFilePath(), - albumPhotoView.getThumbnailPath(), - albumPhotoView.getCapturedDt() + albumPhotoItem.id(), + albumPhotoItem.photoId(), + albumPhotoItem.fileName(), + albumPhotoItem.filePath(), + albumPhotoItem.thumbnailPath(), + albumPhotoItem.capturedDt() ); } } diff --git a/src/main/java/kr/kro/photoliner/domain/album/dto/response/AlbumPhotoMarkersResponse.java b/src/main/java/kr/kro/photoliner/domain/album/dto/response/AlbumPhotoMarkersResponse.java new file mode 100644 index 0000000..294d209 --- /dev/null +++ b/src/main/java/kr/kro/photoliner/domain/album/dto/response/AlbumPhotoMarkersResponse.java @@ -0,0 +1,44 @@ +package kr.kro.photoliner.domain.album.dto.response; + +import java.time.LocalDateTime; +import java.util.List; +import kr.kro.photoliner.domain.album.dto.AlbumPhotoItem; +import kr.kro.photoliner.domain.album.dto.AlbumPhotoItems; + +public record AlbumPhotoMarkersResponse( + Integer count, + List albumPhotoMarkers +) { + + public static AlbumPhotoMarkersResponse from(AlbumPhotoItems albumPhotoItems) { + return new AlbumPhotoMarkersResponse( + albumPhotoItems.count(), + albumPhotoItems.photoItems().stream() + .map(InnerAlbumPhotoMarker::from) + .toList() + ); + } + + public record InnerAlbumPhotoMarker( + Long id, + Long photoId, + String filePath, + String thumbnailPath, + LocalDateTime capturedDt, + Double lat, + Double lng + ) { + + public static InnerAlbumPhotoMarker from(AlbumPhotoItem albumPhotoItem) { + return new InnerAlbumPhotoMarker( + albumPhotoItem.id(), + albumPhotoItem.photoId(), + albumPhotoItem.filePath(), + albumPhotoItem.thumbnailPath(), + albumPhotoItem.capturedDt(), + albumPhotoItem.getLatitude(), + albumPhotoItem.getLongitude() + ); + } + } +} diff --git a/src/main/java/kr/kro/photoliner/domain/album/model/view/AlbumPhotoView.java b/src/main/java/kr/kro/photoliner/domain/album/model/view/AlbumPhotoView.java deleted file mode 100644 index 8028d98..0000000 --- a/src/main/java/kr/kro/photoliner/domain/album/model/view/AlbumPhotoView.java +++ /dev/null @@ -1,59 +0,0 @@ -package kr.kro.photoliner.domain.album.model.view; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.Id; -import jakarta.persistence.Table; -import java.time.LocalDateTime; -import java.util.Objects; -import lombok.Getter; -import org.hibernate.annotations.Immutable; -import org.locationtech.jts.geom.Point; - -@Entity -@Immutable -@Getter -@Table(name = "vw_album_photos") -public class AlbumPhotoView { - @Id - @Column(name = "id") - private Long id; - - @Column(name = "photo_id", nullable = false) - private Long photoId; - - @Column(name = "file_name") - private String fileName; - - @Column(name = "file_path") - private String filePath; - - @Column(name = "thumbnail_path") - private String thumbnailPath; - - @Column(name = "captured_dt") - private LocalDateTime capturedDt; - - @Column(name = "location") - private Point location; - - @Column(name = "album_id") - private Long albumId; - - @Column(name = "user_id") - private Long userId; - - public Double getLatitude() { - if (Objects.isNull(location)) { - return null; - } - return location.getX(); - } - - public Double getLongitude() { - if (Objects.isNull(location)) { - return null; - } - return location.getY(); - } -} diff --git a/src/main/java/kr/kro/photoliner/domain/album/model/view/AlbumPhotoViews.java b/src/main/java/kr/kro/photoliner/domain/album/model/view/AlbumPhotoViews.java deleted file mode 100644 index 812e03b..0000000 --- a/src/main/java/kr/kro/photoliner/domain/album/model/view/AlbumPhotoViews.java +++ /dev/null @@ -1,21 +0,0 @@ -package kr.kro.photoliner.domain.album.model.view; - -import java.util.List; -import java.util.Objects; - -public record AlbumPhotoViews( - List albumPhotoViews -) { - - public List filterIncludedInAlbum(Long albumId) { - return albumPhotoViews.stream() - .filter(albumPhotoView -> Objects.equals(albumPhotoView.getAlbumId(), albumId)) - .toList(); - } - - public List filterExcludedFromAlbum(Long albumId) { - return albumPhotoViews.stream() - .filter(albumPhotoView -> !Objects.equals(albumPhotoView.getAlbumId(), albumId)) - .toList(); - } -} diff --git a/src/main/java/kr/kro/photoliner/domain/album/repository/AlbumPhotoRepository.java b/src/main/java/kr/kro/photoliner/domain/album/repository/AlbumPhotoRepository.java index 09158a8..4936acb 100644 --- a/src/main/java/kr/kro/photoliner/domain/album/repository/AlbumPhotoRepository.java +++ b/src/main/java/kr/kro/photoliner/domain/album/repository/AlbumPhotoRepository.java @@ -1,30 +1,54 @@ package kr.kro.photoliner.domain.album.repository; import java.util.List; -import kr.kro.photoliner.domain.album.model.view.AlbumPhotoView; -import kr.kro.photoliner.domain.album.model.view.AlbumPhotoViews; +import kr.kro.photoliner.domain.album.dto.AlbumPhotoItem; +import kr.kro.photoliner.domain.album.dto.AlbumPhotoItems; +import kr.kro.photoliner.domain.album.model.PhotoItem; import org.locationtech.jts.geom.Point; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; -public interface AlbumPhotoRepository extends JpaRepository { - Page findByAlbumId(Long albumId, Pageable pageable); +public interface AlbumPhotoRepository extends JpaRepository { + @Query(""" + select new kr.kro.photoliner.domain.album.dto.AlbumPhotoItem( + pi.id, + pi.photoId, + p.fileName, + p.filePath, + p.thumbnailPath, + p.capturedDt, + p.location + ) + from PhotoItem pi + inner join Photo p on p.id = pi.photoId + where pi.album.id = :albumId + """) + Page findByAlbumId(Long albumId, Pageable pageable); @Query(""" - select apv - from AlbumPhotoView apv - where apv.userId = :userId - and function('st_x', apv.location) between function('st_x', :sw) and function('st_x', :ne) - and function('st_y', apv.location) between function('st_y', :sw) and function('st_y', :ne) - order by apv.capturedDt desc + select new kr.kro.photoliner.domain.album.dto.AlbumPhotoItem( + pi.id, + pi.photoId, + p.fileName, + p.filePath, + p.thumbnailPath, + p.capturedDt, + p.location + ) + from PhotoItem pi + left outer join Photo p on p.id = pi.photoId + where pi.album.id = :albumId + and function('st_x', p.location) between function('st_x', :sw) and function('st_x', :ne) + and function('st_y', p.location) between function('st_y', :sw) and function('st_y', :ne) + order by p.capturedDt """) - List findByUserIdInBox(Long userId, Point sw, Point ne); + List findByAlbumIdInBox(Long albumId, Point sw, Point ne); - default AlbumPhotoViews getByUserIdInBox(Long userId, Point sw, Point ne) { - return new AlbumPhotoViews( - findByUserIdInBox(userId, sw, ne) + default AlbumPhotoItems getByAlbumIdInBox(Long albumId, Point sw, Point ne) { + return new AlbumPhotoItems( + findByAlbumIdInBox(albumId, sw, ne) ); } } diff --git a/src/main/java/kr/kro/photoliner/domain/album/service/AlbumService.java b/src/main/java/kr/kro/photoliner/domain/album/service/AlbumService.java index ed2b411..b05b778 100644 --- a/src/main/java/kr/kro/photoliner/domain/album/service/AlbumService.java +++ b/src/main/java/kr/kro/photoliner/domain/album/service/AlbumService.java @@ -1,15 +1,18 @@ package kr.kro.photoliner.domain.album.service; +import kr.kro.photoliner.domain.album.dto.AlbumPhotoItem; +import kr.kro.photoliner.domain.album.dto.AlbumPhotoItems; import kr.kro.photoliner.domain.album.dto.request.AlbumCreateRequest; import kr.kro.photoliner.domain.album.dto.request.AlbumDeleteRequest; import kr.kro.photoliner.domain.album.dto.request.AlbumItemCreateRequest; import kr.kro.photoliner.domain.album.dto.request.AlbumItemDeleteRequest; +import kr.kro.photoliner.domain.album.dto.request.AlbumPhotoMarkersRequest; import kr.kro.photoliner.domain.album.dto.request.AlbumTitleUpdateRequest; import kr.kro.photoliner.domain.album.dto.response.AlbumCreateResponse; import kr.kro.photoliner.domain.album.dto.response.AlbumPhotoItemsResponse; +import kr.kro.photoliner.domain.album.dto.response.AlbumPhotoMarkersResponse; import kr.kro.photoliner.domain.album.dto.response.AlbumsResponse; import kr.kro.photoliner.domain.album.model.Album; -import kr.kro.photoliner.domain.album.model.view.AlbumPhotoView; import kr.kro.photoliner.domain.album.repository.AlbumPhotoRepository; import kr.kro.photoliner.domain.album.repository.AlbumRepository; import kr.kro.photoliner.domain.user.model.User; @@ -17,6 +20,8 @@ import kr.kro.photoliner.global.code.ApiResponseCode; import kr.kro.photoliner.global.exception.CustomException; import lombok.RequiredArgsConstructor; +import org.locationtech.jts.geom.GeometryFactory; +import org.locationtech.jts.geom.Point; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; @@ -29,6 +34,7 @@ public class AlbumService { private final UserRepository userRepository; private final AlbumRepository albumRepository; private final AlbumPhotoRepository albumPhotoRepository; + private final GeometryFactory geometryFactory; @Transactional public AlbumCreateResponse createAlbum(AlbumCreateRequest request) { @@ -50,8 +56,8 @@ public AlbumsResponse getAlbums(Long userId, Pageable pageable) { @Transactional(readOnly = true) public AlbumPhotoItemsResponse getAlbumPhotoItems(Long albumId, Pageable pageable) { - Page albumPhotoViews = albumPhotoRepository.findByAlbumId(albumId, pageable); - return AlbumPhotoItemsResponse.from(albumPhotoViews); + Page albumPhotoItems = albumPhotoRepository.findByAlbumId(albumId, pageable); + return AlbumPhotoItemsResponse.from(albumPhotoItems); } @Transactional @@ -79,4 +85,14 @@ public void deleteAlbumItems(Long albumId, AlbumItemDeleteRequest request) { .orElseThrow(() -> CustomException.of(ApiResponseCode.NOT_FOUND_ALBUM, "album id: " + albumId)); album.removePhotos(request.ids()); } + + @Transactional(readOnly = true) + public AlbumPhotoMarkersResponse getAlbumPhotoMarkers(Long albumId, AlbumPhotoMarkersRequest request) { + Point sw = geometryFactory.createPoint(request.getSouthWestCoordinate()); + Point ne = geometryFactory.createPoint(request.getNorthEastCoordinate()); + + AlbumPhotoItems albumPhotoItems = albumPhotoRepository.getByAlbumIdInBox(albumId, sw, ne); + + return AlbumPhotoMarkersResponse.from(albumPhotoItems); + } } diff --git a/src/main/java/kr/kro/photoliner/domain/photo/controller/PhotoController.java b/src/main/java/kr/kro/photoliner/domain/photo/controller/PhotoController.java index 34d0cb0..14fb26f 100644 --- a/src/main/java/kr/kro/photoliner/domain/photo/controller/PhotoController.java +++ b/src/main/java/kr/kro/photoliner/domain/photo/controller/PhotoController.java @@ -2,11 +2,11 @@ import jakarta.validation.Valid; import java.util.List; -import kr.kro.photoliner.domain.photo.dto.DeletePhotosRequest; -import kr.kro.photoliner.domain.photo.dto.request.MapMarkersRequest; +import kr.kro.photoliner.domain.photo.dto.request.DeletePhotosRequest; import kr.kro.photoliner.domain.photo.dto.request.PhotoCapturedDateUpdateRequest; import kr.kro.photoliner.domain.photo.dto.request.PhotoLocationUpdateRequest; -import kr.kro.photoliner.domain.photo.dto.response.MapMarkersResponse; +import kr.kro.photoliner.domain.photo.dto.request.PhotoMarkersRequest; +import kr.kro.photoliner.domain.photo.dto.response.PhotoMarkersResponse; import kr.kro.photoliner.domain.photo.dto.response.PhotoUploadResponse; import kr.kro.photoliner.domain.photo.dto.response.PhotosResponse; import kr.kro.photoliner.domain.photo.service.PhotoService; @@ -47,8 +47,8 @@ public ResponseEntity getPhotos( } @GetMapping("/markers") - public ResponseEntity getMarkersInViewport(@Valid MapMarkersRequest request) { - return ResponseEntity.ok(photoService.getMarkersInViewport(request)); + public ResponseEntity getPhotoMarkers(@Valid PhotoMarkersRequest request) { + return ResponseEntity.ok(photoService.getPhotoMarkers(request)); } @PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE) diff --git a/src/main/java/kr/kro/photoliner/domain/photo/dto/DeletePhotosRequest.java b/src/main/java/kr/kro/photoliner/domain/photo/dto/request/DeletePhotosRequest.java similarity index 63% rename from src/main/java/kr/kro/photoliner/domain/photo/dto/DeletePhotosRequest.java rename to src/main/java/kr/kro/photoliner/domain/photo/dto/request/DeletePhotosRequest.java index 85458ff..b32318f 100644 --- a/src/main/java/kr/kro/photoliner/domain/photo/dto/DeletePhotosRequest.java +++ b/src/main/java/kr/kro/photoliner/domain/photo/dto/request/DeletePhotosRequest.java @@ -1,4 +1,4 @@ -package kr.kro.photoliner.domain.photo.dto; +package kr.kro.photoliner.domain.photo.dto.request; import java.util.List; diff --git a/src/main/java/kr/kro/photoliner/domain/photo/dto/request/MapMarkersRequest.java b/src/main/java/kr/kro/photoliner/domain/photo/dto/request/PhotoMarkersRequest.java similarity index 89% rename from src/main/java/kr/kro/photoliner/domain/photo/dto/request/MapMarkersRequest.java rename to src/main/java/kr/kro/photoliner/domain/photo/dto/request/PhotoMarkersRequest.java index 0e5deac..8dab443 100644 --- a/src/main/java/kr/kro/photoliner/domain/photo/dto/request/MapMarkersRequest.java +++ b/src/main/java/kr/kro/photoliner/domain/photo/dto/request/PhotoMarkersRequest.java @@ -5,13 +5,10 @@ import jakarta.validation.constraints.NotNull; import org.locationtech.jts.geom.Coordinate; -public record MapMarkersRequest( +public record PhotoMarkersRequest( @NotNull @Min(0) Long userId, - @NotNull @Min(0) - Long albumId, - @Min(0) @Max(90) double swLat, diff --git a/src/main/java/kr/kro/photoliner/domain/photo/dto/response/MapMarkersResponse.java b/src/main/java/kr/kro/photoliner/domain/photo/dto/response/MapMarkersResponse.java deleted file mode 100644 index 6c23ace..0000000 --- a/src/main/java/kr/kro/photoliner/domain/photo/dto/response/MapMarkersResponse.java +++ /dev/null @@ -1,91 +0,0 @@ -package kr.kro.photoliner.domain.photo.dto.response; - -import java.time.LocalDateTime; -import java.util.List; -import kr.kro.photoliner.domain.album.model.view.AlbumPhotoView; - -public record MapMarkersResponse( - InnerPhotoMarkers innerPhotoMarkers, - InnerPoiMarkers innerPoiMarkers -) { - - public static MapMarkersResponse of(List photosIncludedAlbum, - List photosExcludedAlbum) { - return new MapMarkersResponse( - InnerPhotoMarkers.from(photosIncludedAlbum), - InnerPoiMarkers.from(photosExcludedAlbum) - ); - } - - public record InnerPhotoMarkers( - Integer count, - List photoMarkers - ) { - - public static InnerPhotoMarkers from(List photos) { - return new InnerPhotoMarkers( - photos.size(), - photos.stream() - .map(InnerPhotoMarker::from) - .toList() - ); - } - - public record InnerPhotoMarker( - Long id, - LocalDateTime capturedDt, - String filePath, - String thumbnailPath, - Double lat, - Double lng - ) { - - public static InnerPhotoMarker from(AlbumPhotoView photo) { - return new InnerPhotoMarker( - photo.getId(), - photo.getCapturedDt(), - photo.getFilePath(), - photo.getThumbnailPath(), - photo.getLongitude(), - photo.getLatitude() - ); - } - } - } - - public record InnerPoiMarkers( - Integer count, - List markers - ) { - - public static InnerPoiMarkers from(List photos) { - return new InnerPoiMarkers( - photos.size(), - photos.stream() - .map(InnerPoiMarker::from) - .toList() - ); - } - - public record InnerPoiMarker( - Long id, - LocalDateTime capturedDt, - String filePath, - String thumbnailPath, - Double lat, - Double lng - ) { - - public static InnerPoiMarker from(AlbumPhotoView photo) { - return new InnerPoiMarker( - photo.getId(), - photo.getCapturedDt(), - photo.getFilePath(), - photo.getThumbnailPath(), - photo.getLongitude(), - photo.getLatitude() - ); - } - } - } -} diff --git a/src/main/java/kr/kro/photoliner/domain/photo/dto/response/PhotoMarkersResponse.java b/src/main/java/kr/kro/photoliner/domain/photo/dto/response/PhotoMarkersResponse.java new file mode 100644 index 0000000..60ad44d --- /dev/null +++ b/src/main/java/kr/kro/photoliner/domain/photo/dto/response/PhotoMarkersResponse.java @@ -0,0 +1,42 @@ +package kr.kro.photoliner.domain.photo.dto.response; + +import java.time.LocalDateTime; +import java.util.List; +import kr.kro.photoliner.domain.photo.model.Photo; +import kr.kro.photoliner.domain.photo.model.Photos; + +public record PhotoMarkersResponse( + Integer count, + List photoMarkers +) { + + public static PhotoMarkersResponse from(Photos albumPhotoItems) { + return new PhotoMarkersResponse( + albumPhotoItems.count(), + albumPhotoItems.photos().stream() + .map(InnerPhotoMarker::from) + .toList() + ); + } + + public record InnerPhotoMarker( + Long id, + String filePath, + String thumbnailPath, + LocalDateTime capturedDt, + Double lat, + Double lng + ) { + + public static InnerPhotoMarker from(Photo photo) { + return new InnerPhotoMarker( + photo.getId(), + photo.getFilePath(), + photo.getThumbnailPath(), + photo.getCapturedDt(), + photo.getLongitude(), + photo.getLatitude() + ); + } + } +} diff --git a/src/main/java/kr/kro/photoliner/domain/photo/repository/PhotoRepository.java b/src/main/java/kr/kro/photoliner/domain/photo/repository/PhotoRepository.java index c7123c9..0d0c62c 100644 --- a/src/main/java/kr/kro/photoliner/domain/photo/repository/PhotoRepository.java +++ b/src/main/java/kr/kro/photoliner/domain/photo/repository/PhotoRepository.java @@ -1,10 +1,14 @@ package kr.kro.photoliner.domain.photo.repository; +import java.util.List; import java.util.Optional; import kr.kro.photoliner.domain.photo.model.Photo; +import kr.kro.photoliner.domain.photo.model.Photos; +import org.locationtech.jts.geom.Point; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; public interface PhotoRepository extends JpaRepository { @@ -13,6 +17,23 @@ Page findByUserId( Pageable pageable ); + @Query(""" + select p + from Photo p + left outer join PhotoItem pi on p.id = pi.photoId + where p.user.id = :userId + and function('st_x', p.location) between function('st_x', :sw) and function('st_x', :ne) + and function('st_y', p.location) between function('st_y', :sw) and function('st_y', :ne) + order by p.capturedDt + """) + List findByUserIdInBox(Long userId, Point sw, Point ne); + + default Photos getByUserIdInBox(Long userId, Point sw, Point ne) { + return new Photos( + findByUserIdInBox(userId, sw, ne) + ); + } + Photo save(Photo photo); Optional findById(Long photoId); diff --git a/src/main/java/kr/kro/photoliner/domain/photo/service/PhotoService.java b/src/main/java/kr/kro/photoliner/domain/photo/service/PhotoService.java index 07021e1..380951c 100644 --- a/src/main/java/kr/kro/photoliner/domain/photo/service/PhotoService.java +++ b/src/main/java/kr/kro/photoliner/domain/photo/service/PhotoService.java @@ -1,16 +1,16 @@ package kr.kro.photoliner.domain.photo.service; import java.util.List; -import kr.kro.photoliner.domain.album.model.view.AlbumPhotoViews; import kr.kro.photoliner.domain.album.repository.AlbumPhotoRepository; -import kr.kro.photoliner.domain.photo.dto.DeletePhotosRequest; -import kr.kro.photoliner.domain.photo.dto.request.MapMarkersRequest; +import kr.kro.photoliner.domain.photo.dto.request.DeletePhotosRequest; import kr.kro.photoliner.domain.photo.dto.request.PhotoCapturedDateUpdateRequest; import kr.kro.photoliner.domain.photo.dto.request.PhotoLocationUpdateRequest; -import kr.kro.photoliner.domain.photo.dto.response.MapMarkersResponse; +import kr.kro.photoliner.domain.photo.dto.request.PhotoMarkersRequest; +import kr.kro.photoliner.domain.photo.dto.response.PhotoMarkersResponse; import kr.kro.photoliner.domain.photo.dto.response.PhotosResponse; import kr.kro.photoliner.domain.photo.infra.FileStorage; import kr.kro.photoliner.domain.photo.model.Photo; +import kr.kro.photoliner.domain.photo.model.Photos; import kr.kro.photoliner.domain.photo.repository.PhotoRepository; import kr.kro.photoliner.global.code.ApiResponseCode; import kr.kro.photoliner.global.exception.CustomException; @@ -37,16 +37,13 @@ public PhotosResponse getPhotosByIds(Long userId, Pageable pageable) { } @Transactional(readOnly = true) - public MapMarkersResponse getMarkersInViewport(MapMarkersRequest request) { + public PhotoMarkersResponse getPhotoMarkers(PhotoMarkersRequest request) { Point sw = geometryFactory.createPoint(request.getSouthWestCoordinate()); Point ne = geometryFactory.createPoint(request.getNorthEastCoordinate()); - AlbumPhotoViews albumPhotoViews = albumPhotoRepository.getByUserIdInBox(request.userId(), sw, ne); + Photos photos = photoRepository.getByUserIdInBox(request.userId(), sw, ne); - return MapMarkersResponse.of( - albumPhotoViews.filterIncludedInAlbum(request.albumId()), - albumPhotoViews.filterExcludedFromAlbum(request.albumId()) - ); + return PhotoMarkersResponse.from(photos); } @Transactional From 208624b0fa9305148b58f5f8504e29302fdd1f6d Mon Sep 17 00:00:00 2001 From: chanrhan Date: Sat, 22 Nov 2025 22:11:10 +0900 Subject: [PATCH 2/5] =?UTF-8?q?chore:=20drop=20view=20=EB=A7=88=EC=9D=B4?= =?UTF-8?q?=EA=B7=B8=EB=A0=88=EC=9D=B4=EC=85=98=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/album/repository/AlbumPhotoRepository.java | 2 +- src/main/resources/db/migration/V8__drop_album_photos_view.sql | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 src/main/resources/db/migration/V8__drop_album_photos_view.sql diff --git a/src/main/java/kr/kro/photoliner/domain/album/repository/AlbumPhotoRepository.java b/src/main/java/kr/kro/photoliner/domain/album/repository/AlbumPhotoRepository.java index 4936acb..fd181e8 100644 --- a/src/main/java/kr/kro/photoliner/domain/album/repository/AlbumPhotoRepository.java +++ b/src/main/java/kr/kro/photoliner/domain/album/repository/AlbumPhotoRepository.java @@ -38,7 +38,7 @@ public interface AlbumPhotoRepository extends JpaRepository { p.location ) from PhotoItem pi - left outer join Photo p on p.id = pi.photoId + inner join Photo p on p.id = pi.photoId where pi.album.id = :albumId and function('st_x', p.location) between function('st_x', :sw) and function('st_x', :ne) and function('st_y', p.location) between function('st_y', :sw) and function('st_y', :ne) diff --git a/src/main/resources/db/migration/V8__drop_album_photos_view.sql b/src/main/resources/db/migration/V8__drop_album_photos_view.sql new file mode 100644 index 0000000..f9d6115 --- /dev/null +++ b/src/main/resources/db/migration/V8__drop_album_photos_view.sql @@ -0,0 +1 @@ +drop view if exists vw_album_photos From 13677586d507117f456b6558ed61f92d4f30de77 Mon Sep 17 00:00:00 2001 From: chanrhan Date: Sat, 22 Nov 2025 22:18:05 +0900 Subject: [PATCH 3/5] =?UTF-8?q?fix:=20pageable=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kro/photoliner/domain/album/controller/AlbumController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/kr/kro/photoliner/domain/album/controller/AlbumController.java b/src/main/java/kr/kro/photoliner/domain/album/controller/AlbumController.java index 6439e17..ede4bce 100644 --- a/src/main/java/kr/kro/photoliner/domain/album/controller/AlbumController.java +++ b/src/main/java/kr/kro/photoliner/domain/album/controller/AlbumController.java @@ -71,7 +71,7 @@ public ResponseEntity deletePhoto( @GetMapping("/{albumId}/photos") public ResponseEntity getAlbumItems( @PathVariable Long albumId, - @PageableDefault(sort = "capturedDt", direction = Sort.Direction.DESC) Pageable pageable + @PageableDefault Pageable pageable ) { return ResponseEntity.ok(albumService.getAlbumPhotoItems(albumId, pageable)); } From f4d14cfb6b18e97dfd0b5702326a319272029ef7 Mon Sep 17 00:00:00 2001 From: chanrhan Date: Sat, 22 Nov 2025 22:41:04 +0900 Subject: [PATCH 4/5] =?UTF-8?q?fix:=20get=20api=EC=97=90=20requestbody=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kro/photoliner/domain/album/controller/AlbumController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/kr/kro/photoliner/domain/album/controller/AlbumController.java b/src/main/java/kr/kro/photoliner/domain/album/controller/AlbumController.java index ede4bce..12acd42 100644 --- a/src/main/java/kr/kro/photoliner/domain/album/controller/AlbumController.java +++ b/src/main/java/kr/kro/photoliner/domain/album/controller/AlbumController.java @@ -97,7 +97,7 @@ public ResponseEntity deleteAlbumItems( @GetMapping("/{albumId}/markers") public ResponseEntity getAlbumPhotoMarkers( @PathVariable Long albumId, - @RequestBody @Valid AlbumPhotoMarkersRequest request + @Valid AlbumPhotoMarkersRequest request ) { return ResponseEntity.ok(albumService.getAlbumPhotoMarkers(albumId, request)); } From 2cb2ab807c9673060c8f0e2708b24206865fd711 Mon Sep 17 00:00:00 2001 From: chanrhan Date: Sat, 22 Nov 2025 22:45:15 +0900 Subject: [PATCH 5/5] =?UTF-8?q?fix:=20=EC=9C=84=EB=8F=84/=EA=B2=BD?= =?UTF-8?q?=EB=8F=84=20=EB=B0=98=EB=8C=80=EB=A1=9C=20=EC=B6=9C=EB=A0=A5?= =?UTF-8?q?=ED=95=98=EA=B3=A0=20=EC=9E=88=EB=8D=98=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kr/kro/photoliner/domain/album/dto/AlbumPhotoItem.java | 4 ++-- .../domain/photo/dto/response/PhotoMarkersResponse.java | 4 ++-- src/main/java/kr/kro/photoliner/domain/photo/model/Photo.java | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/kr/kro/photoliner/domain/album/dto/AlbumPhotoItem.java b/src/main/java/kr/kro/photoliner/domain/album/dto/AlbumPhotoItem.java index 6b6036a..8daff21 100644 --- a/src/main/java/kr/kro/photoliner/domain/album/dto/AlbumPhotoItem.java +++ b/src/main/java/kr/kro/photoliner/domain/album/dto/AlbumPhotoItem.java @@ -18,13 +18,13 @@ public Double getLatitude() { if (Objects.isNull(location)) { return null; } - return location.getX(); + return location.getY(); } public Double getLongitude() { if (Objects.isNull(location)) { return null; } - return location.getY(); + return location.getX(); } } diff --git a/src/main/java/kr/kro/photoliner/domain/photo/dto/response/PhotoMarkersResponse.java b/src/main/java/kr/kro/photoliner/domain/photo/dto/response/PhotoMarkersResponse.java index 60ad44d..99acd7a 100644 --- a/src/main/java/kr/kro/photoliner/domain/photo/dto/response/PhotoMarkersResponse.java +++ b/src/main/java/kr/kro/photoliner/domain/photo/dto/response/PhotoMarkersResponse.java @@ -34,8 +34,8 @@ public static InnerPhotoMarker from(Photo photo) { photo.getFilePath(), photo.getThumbnailPath(), photo.getCapturedDt(), - photo.getLongitude(), - photo.getLatitude() + photo.getLatitude(), + photo.getLongitude() ); } } diff --git a/src/main/java/kr/kro/photoliner/domain/photo/model/Photo.java b/src/main/java/kr/kro/photoliner/domain/photo/model/Photo.java index 8ba6830..a7ba947 100644 --- a/src/main/java/kr/kro/photoliner/domain/photo/model/Photo.java +++ b/src/main/java/kr/kro/photoliner/domain/photo/model/Photo.java @@ -67,13 +67,13 @@ public Double getLatitude() { if (Objects.isNull(location)) { return null; } - return location.getX(); + return location.getY(); } public Double getLongitude() { if (Objects.isNull(location)) { return null; } - return location.getY(); + return location.getX(); } }