From 1d37836ee198f9976d0c79200073bca60a9e2353 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=82=98=EB=AF=B8?= Date: Mon, 3 Aug 2026 15:17:27 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=EC=BD=94=EC=8A=A4=EB=B0=9C?= =?UTF-8?q?=EA=B2=AC=20=ED=83=AD=20=EC=83=81=EB=8B=A8=20=EB=B0=B0=EB=84=88?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=20API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Banner 엔티티/Repository/Service/Controller 추가, GET /api/banner로 활성 배너를 sortOrder 순으로 반환. Android 연동은 후속 작업. --- .../banner/controller/BannerController.java | 26 +++++++++++++ .../banner/dto/response/BannerResponse.java | 19 +++++++++ .../dto/response/GetBannerResponseDto.java | 19 +++++++++ .../runnect/server/banner/entity/Banner.java | 39 +++++++++++++++++++ .../banner/repository/BannerRepository.java | 11 ++++++ .../server/banner/service/BannerService.java | 30 ++++++++++++++ .../server/common/constant/SuccessStatus.java | 1 + 7 files changed, 145 insertions(+) create mode 100644 src/main/java/org/runnect/server/banner/controller/BannerController.java create mode 100644 src/main/java/org/runnect/server/banner/dto/response/BannerResponse.java create mode 100644 src/main/java/org/runnect/server/banner/dto/response/GetBannerResponseDto.java create mode 100644 src/main/java/org/runnect/server/banner/entity/Banner.java create mode 100644 src/main/java/org/runnect/server/banner/repository/BannerRepository.java create mode 100644 src/main/java/org/runnect/server/banner/service/BannerService.java diff --git a/src/main/java/org/runnect/server/banner/controller/BannerController.java b/src/main/java/org/runnect/server/banner/controller/BannerController.java new file mode 100644 index 0000000..b745fbc --- /dev/null +++ b/src/main/java/org/runnect/server/banner/controller/BannerController.java @@ -0,0 +1,26 @@ +package org.runnect.server.banner.controller; + +import lombok.RequiredArgsConstructor; +import org.runnect.server.banner.dto.response.GetBannerResponseDto; +import org.runnect.server.banner.service.BannerService; +import org.runnect.server.common.constant.SuccessStatus; +import org.runnect.server.common.dto.ApiResponseDto; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/banner") +public class BannerController { + + private final BannerService bannerService; + + @GetMapping + @ResponseStatus(HttpStatus.OK) + public ApiResponseDto getBanners() { + return ApiResponseDto.success(SuccessStatus.GET_BANNER_SUCCESS, bannerService.getBanners()); + } +} diff --git a/src/main/java/org/runnect/server/banner/dto/response/BannerResponse.java b/src/main/java/org/runnect/server/banner/dto/response/BannerResponse.java new file mode 100644 index 0000000..eab85ff --- /dev/null +++ b/src/main/java/org/runnect/server/banner/dto/response/BannerResponse.java @@ -0,0 +1,19 @@ +package org.runnect.server.banner.dto.response; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PRIVATE) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class BannerResponse { + private Integer index; + private String imageUrl; + private String linkUrl; + + public static BannerResponse of(Integer index, String imageUrl, String linkUrl) { + return new BannerResponse(index, imageUrl, linkUrl); + } +} diff --git a/src/main/java/org/runnect/server/banner/dto/response/GetBannerResponseDto.java b/src/main/java/org/runnect/server/banner/dto/response/GetBannerResponseDto.java new file mode 100644 index 0000000..b9657f9 --- /dev/null +++ b/src/main/java/org/runnect/server/banner/dto/response/GetBannerResponseDto.java @@ -0,0 +1,19 @@ +package org.runnect.server.banner.dto.response; + +import java.util.List; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PRIVATE) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class GetBannerResponseDto { + private List banners; + + public static GetBannerResponseDto of(List banners) { + return new GetBannerResponseDto(banners); + } +} diff --git a/src/main/java/org/runnect/server/banner/entity/Banner.java b/src/main/java/org/runnect/server/banner/entity/Banner.java new file mode 100644 index 0000000..4f229c4 --- /dev/null +++ b/src/main/java/org/runnect/server/banner/entity/Banner.java @@ -0,0 +1,39 @@ +package org.runnect.server.banner.entity; + +import javax.persistence.*; + +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.runnect.server.common.entity.AuditingTimeEntity; + +@Getter +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Banner extends AuditingTimeEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false) + private String imageUrl; + + @Column(nullable = false) + private String linkUrl; + + @Column(nullable = false) + private Integer sortOrder; + + @Column(nullable = false) + private Boolean isActive; + + @Builder + public Banner(String imageUrl, String linkUrl, Integer sortOrder) { + this.imageUrl = imageUrl; + this.linkUrl = linkUrl; + this.sortOrder = sortOrder; + this.isActive = true; + } +} diff --git a/src/main/java/org/runnect/server/banner/repository/BannerRepository.java b/src/main/java/org/runnect/server/banner/repository/BannerRepository.java new file mode 100644 index 0000000..ef1d0da --- /dev/null +++ b/src/main/java/org/runnect/server/banner/repository/BannerRepository.java @@ -0,0 +1,11 @@ +package org.runnect.server.banner.repository; + +import java.util.List; + +import org.runnect.server.banner.entity.Banner; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface BannerRepository extends JpaRepository { + + List findByIsActiveTrueOrderBySortOrderAsc(); +} diff --git a/src/main/java/org/runnect/server/banner/service/BannerService.java b/src/main/java/org/runnect/server/banner/service/BannerService.java new file mode 100644 index 0000000..e3b9451 --- /dev/null +++ b/src/main/java/org/runnect/server/banner/service/BannerService.java @@ -0,0 +1,30 @@ +package org.runnect.server.banner.service; + +import java.util.ArrayList; +import java.util.List; + +import lombok.RequiredArgsConstructor; +import org.runnect.server.banner.dto.response.BannerResponse; +import org.runnect.server.banner.dto.response.GetBannerResponseDto; +import org.runnect.server.banner.entity.Banner; +import org.runnect.server.banner.repository.BannerRepository; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class BannerService { + + private final BannerRepository bannerRepository; + + public GetBannerResponseDto getBanners() { + List banners = bannerRepository.findByIsActiveTrueOrderBySortOrderAsc(); + + List bannerResponses = new ArrayList<>(); + for (int index = 0; index < banners.size(); index++) { + Banner banner = banners.get(index); + bannerResponses.add(BannerResponse.of(index, banner.getImageUrl(), banner.getLinkUrl())); + } + + return GetBannerResponseDto.of(bannerResponses); + } +} diff --git a/src/main/java/org/runnect/server/common/constant/SuccessStatus.java b/src/main/java/org/runnect/server/common/constant/SuccessStatus.java index b374589..e6bb3a9 100644 --- a/src/main/java/org/runnect/server/common/constant/SuccessStatus.java +++ b/src/main/java/org/runnect/server/common/constant/SuccessStatus.java @@ -31,6 +31,7 @@ public enum SuccessStatus { GET_HEALTH_DATA_SUCCESS(HttpStatus.OK, "건강 데이터 조회 성공"), GET_HEALTH_SUMMARY_SUCCESS(HttpStatus.OK, "건강 통계 조회 성공"), + GET_BANNER_SUCCESS(HttpStatus.OK, "배너 조회 성공"), UPDATE_RECORD_SUCCESS(HttpStatus.OK, "활동 기록 수정 성공"), From ea96a51572a8628e3f63f8eb041461d11e78f76d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=82=98=EB=AF=B8?= Date: Mon, 3 Aug 2026 15:29:06 +0900 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20=EB=B0=B0=EB=84=88=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=8B=9C=20sortOrder=20=EB=8F=99=EB=A5=A0=20?= =?UTF-8?q?=EC=BC=80=EC=9D=B4=EC=8A=A4=EC=97=90=20id=EB=A5=BC=20=EB=B3=B4?= =?UTF-8?q?=EC=A1=B0=20=EC=A0=95=EB=A0=AC=ED=82=A4=EB=A1=9C=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 sortOrder에 유니크 제약이 없어 값이 같은 배너가 있으면 정렬 순서가 요청마다 달라질 수 있어, id ASC를 보조 키로 붙여 결정론적으로 정렬되도록 함. --- .../org/runnect/server/banner/repository/BannerRepository.java | 2 +- .../java/org/runnect/server/banner/service/BannerService.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/runnect/server/banner/repository/BannerRepository.java b/src/main/java/org/runnect/server/banner/repository/BannerRepository.java index ef1d0da..87a49b9 100644 --- a/src/main/java/org/runnect/server/banner/repository/BannerRepository.java +++ b/src/main/java/org/runnect/server/banner/repository/BannerRepository.java @@ -7,5 +7,5 @@ public interface BannerRepository extends JpaRepository { - List findByIsActiveTrueOrderBySortOrderAsc(); + List findByIsActiveTrueOrderBySortOrderAscIdAsc(); } diff --git a/src/main/java/org/runnect/server/banner/service/BannerService.java b/src/main/java/org/runnect/server/banner/service/BannerService.java index e3b9451..17b5454 100644 --- a/src/main/java/org/runnect/server/banner/service/BannerService.java +++ b/src/main/java/org/runnect/server/banner/service/BannerService.java @@ -17,7 +17,7 @@ public class BannerService { private final BannerRepository bannerRepository; public GetBannerResponseDto getBanners() { - List banners = bannerRepository.findByIsActiveTrueOrderBySortOrderAsc(); + List banners = bannerRepository.findByIsActiveTrueOrderBySortOrderAscIdAsc(); List bannerResponses = new ArrayList<>(); for (int index = 0; index < banners.size(); index++) {