From 5ab9d1fb923dc91b82e011557fe8d3406685cc22 Mon Sep 17 00:00:00 2001 From: pywoo Date: Sun, 13 Jul 2025 22:14:12 +0900 Subject: [PATCH 1/2] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor:=20NoticeCate?= =?UTF-8?q?gory=20Enum=20=EA=B4=80=EB=A0=A8=20=EC=BB=A8=EB=B2=84=ED=84=B0?= =?UTF-8?q?=20=EB=B0=8F=20@JsonCreator=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../query/NoticeQueryController.java | 21 ++++---- .../converter/NoticeCategoryConverter.java | 17 +++++++ .../notice/converter/NoticeConverter.java | 50 +------------------ .../notice/dto/request/NoticeRequestDTO.java | 23 ++------- .../dto/response/NoticeResponseDTO.java | 1 - .../notice/entity/enums/NoticeCategory.java | 20 +++++++- .../service/query/NoticeQueryService.java | 11 ++-- .../service/query/NoticeQueryServiceImpl.java | 22 ++++---- .../withtimebe/global/config/WebConfig.java | 7 +++ .../global/error/code/NoticeErrorCode.java | 2 + 10 files changed, 78 insertions(+), 96 deletions(-) create mode 100644 src/main/java/org/withtime/be/withtimebe/domain/notice/converter/NoticeCategoryConverter.java diff --git a/src/main/java/org/withtime/be/withtimebe/domain/notice/controller/query/NoticeQueryController.java b/src/main/java/org/withtime/be/withtimebe/domain/notice/controller/query/NoticeQueryController.java index 423660f..98bce95 100644 --- a/src/main/java/org/withtime/be/withtimebe/domain/notice/controller/query/NoticeQueryController.java +++ b/src/main/java/org/withtime/be/withtimebe/domain/notice/controller/query/NoticeQueryController.java @@ -15,6 +15,7 @@ import org.withtime.be.withtimebe.domain.notice.dto.request.NoticeRequestDTO; import org.withtime.be.withtimebe.domain.notice.dto.response.NoticeResponseDTO; import org.withtime.be.withtimebe.domain.notice.entity.Notice; +import org.withtime.be.withtimebe.domain.notice.entity.enums.NoticeCategory; import org.withtime.be.withtimebe.domain.notice.service.query.NoticeQueryService; import org.withtime.be.withtimebe.global.annotation.SwaggerPageable; import org.withtime.be.withtimebe.global.security.annotation.AuthenticatedMember; @@ -46,10 +47,9 @@ public class NoticeQueryController { @GetMapping("/notices") public DefaultResponse findNoticeList( @PageableDefault(page = 0, size = 10) Pageable pageable, - @RequestParam String noticeCategory + @RequestParam NoticeCategory noticeCategory ) { - NoticeRequestDTO.FindNoticeList request = NoticeConverter.toFindNoticeList(pageable, noticeCategory); - Page result = noticeQueryService.findNoticeList(request); + Page result = noticeQueryService.findNoticeList(pageable, noticeCategory); NoticeResponseDTO.NoticeList response = NoticeConverter.toNoticeList(result); return DefaultResponse.ok(response); } @@ -69,10 +69,9 @@ public DefaultResponse findNoticeList( public DefaultResponse findNoticeListByKeyword( @PageableDefault(page = 0, size = 10) Pageable pageable, @RequestParam String keyword, - @RequestParam String noticeCategory + @RequestParam NoticeCategory noticeCategory ) { - NoticeRequestDTO.FindNoticeListByKeyword request = NoticeConverter.toFindNoticeListByKeyword(pageable, keyword, noticeCategory); - Page result = noticeQueryService.findNoticeListByKeyword(request); + Page result = noticeQueryService.findNoticeListByKeyword(pageable, keyword, noticeCategory); NoticeResponseDTO.NoticeList response = NoticeConverter.toNoticeList(result); return DefaultResponse.ok(response); } @@ -96,9 +95,8 @@ public DefaultResponse findNoticeDetail( @PathVariable("noticeId") Long noticeId, @AuthenticatedMember Member member ) { - NoticeRequestDTO.FindNoticeDetail request = NoticeConverter.toFindNoticeDetail(noticeId, member); - Notice result = noticeQueryService.findNoticeDetail(request); - NoticeResponseDTO.NoticeDetail response = NoticeConverter.toNoticeDetail(result, member); + Notice result = noticeQueryService.findNoticeDetail(noticeId, member); + NoticeResponseDTO.NoticeDetail response = NoticeConverter.toNoticeDetail(result); return DefaultResponse.ok(response); } @@ -120,10 +118,9 @@ public DefaultResponse findNoticeDetail( @GetMapping("/admin/notices/trash") public DefaultResponse findTrashNoticeList( @PageableDefault(page = 0, size = 10) Pageable pageable, - @RequestParam String noticeCategory + @RequestParam NoticeCategory noticeCategory ) { - NoticeRequestDTO.FindNoticeList request = NoticeConverter.toFindNoticeList(pageable, noticeCategory); - Page result = noticeQueryService.findTrashNoticeList(request); + Page result = noticeQueryService.findTrashNoticeList(pageable, noticeCategory); NoticeResponseDTO.NoticeList response = NoticeConverter.toNoticeList(result); return DefaultResponse.ok(response); } diff --git a/src/main/java/org/withtime/be/withtimebe/domain/notice/converter/NoticeCategoryConverter.java b/src/main/java/org/withtime/be/withtimebe/domain/notice/converter/NoticeCategoryConverter.java new file mode 100644 index 0000000..5d083ca --- /dev/null +++ b/src/main/java/org/withtime/be/withtimebe/domain/notice/converter/NoticeCategoryConverter.java @@ -0,0 +1,17 @@ +package org.withtime.be.withtimebe.domain.notice.converter; + +import org.springframework.core.convert.converter.Converter; +import org.springframework.util.StringUtils; +import org.withtime.be.withtimebe.domain.notice.entity.enums.NoticeCategory; +import org.withtime.be.withtimebe.global.error.code.NoticeErrorCode; +import org.withtime.be.withtimebe.global.error.exception.NoticeException; + +public class NoticeCategoryConverter implements Converter { + + @Override + public NoticeCategory convert(String source) { + if(!StringUtils.hasText(source)) throw new NoticeException(NoticeErrorCode.NOTICE_CATEGORY_EMPTY); + return NoticeCategory.findNoticeCategory(source); + } +} + diff --git a/src/main/java/org/withtime/be/withtimebe/domain/notice/converter/NoticeConverter.java b/src/main/java/org/withtime/be/withtimebe/domain/notice/converter/NoticeConverter.java index 5d7276c..54a5d23 100644 --- a/src/main/java/org/withtime/be/withtimebe/domain/notice/converter/NoticeConverter.java +++ b/src/main/java/org/withtime/be/withtimebe/domain/notice/converter/NoticeConverter.java @@ -15,50 +15,6 @@ public class NoticeConverter { - // Request DTO : 전체 조회 (Controller -> Service) - public static NoticeRequestDTO.FindNoticeList toFindNoticeList(Pageable pageable, String type) { - - NoticeCategory noticeCategory; - - try { - noticeCategory = NoticeCategory.valueOf(type); - } catch (IllegalArgumentException e) { - throw new NoticeException(NoticeErrorCode.NOTICE_CATEGORY_NOT_FOUND); - } - - return NoticeRequestDTO.FindNoticeList.builder() - .pageable(pageable) - .noticeCategory(noticeCategory) - .build(); - } - - // Request DTO : 검색어 전체 조회 (Controller -> Service) - public static NoticeRequestDTO.FindNoticeListByKeyword toFindNoticeListByKeyword(Pageable pageable, String keyword, String type) { - - NoticeCategory noticeCategory; - - try { - noticeCategory = NoticeCategory.valueOf(type); - } catch (IllegalArgumentException e) { - throw new NoticeException(NoticeErrorCode.NOTICE_CATEGORY_NOT_FOUND); - } - - return NoticeRequestDTO.FindNoticeListByKeyword.builder() - .pageable(pageable) - .keyword(keyword) - .noticeCategory(noticeCategory) - .build(); - } - - // Request : 상세 조회 요청 (Controller -> Service) DTO - public static NoticeRequestDTO.FindNoticeDetail toFindNoticeDetail(Long noticeId, Member member) { - - return NoticeRequestDTO.FindNoticeDetail.builder() - .noticeId(noticeId) - .member(member) - .build(); - } - // Response DTO : NoticeResponseDTO.NoticeList public static NoticeResponseDTO.NoticeList toNoticeList(Page noticePage) { @@ -87,16 +43,13 @@ public static NoticeResponseDTO.Notice toNotice(Notice notice) { } // Response : NoticeDetail(DTO)로 변환 - public static NoticeResponseDTO.NoticeDetail toNoticeDetail(Notice notice, Member member) { - - boolean hasAdminAuth = member != null && member.getRole().equals(Role.ADMIN); + public static NoticeResponseDTO.NoticeDetail toNoticeDetail(Notice notice) { return NoticeResponseDTO.NoticeDetail.builder() .noticeId(notice.getId()) .title(notice.getTitle()) .content(notice.getContent()) .isPinned(notice.getIsPinned()) - .hasAdminAuth(hasAdminAuth) .createdAt(notice.getCreatedAt()) .build(); } @@ -108,6 +61,7 @@ public static Notice toNoticeEntity(NoticeRequestDTO.CreateNotice request, Membe .title(request.title()) .content(request.content()) .isPinned(request.isPinned()) + .noticeCategory(request.noticeCategory()) .build(); } } diff --git a/src/main/java/org/withtime/be/withtimebe/domain/notice/dto/request/NoticeRequestDTO.java b/src/main/java/org/withtime/be/withtimebe/domain/notice/dto/request/NoticeRequestDTO.java index b6e28b5..f3aceaa 100644 --- a/src/main/java/org/withtime/be/withtimebe/domain/notice/dto/request/NoticeRequestDTO.java +++ b/src/main/java/org/withtime/be/withtimebe/domain/notice/dto/request/NoticeRequestDTO.java @@ -10,32 +10,15 @@ public record NoticeRequestDTO() { - @Builder - public record FindNoticeList( - Pageable pageable, // 게시글 식별자 값 - NoticeCategory noticeCategory // 게시글 유형 - ) {} - - @Builder - public record FindNoticeListByKeyword( - Pageable pageable, // 게시글 식별자 값 - String keyword, // 검색 키워드 - NoticeCategory noticeCategory // 게시글 유형 - ) {} - - @Builder - public record FindNoticeDetail( - Long noticeId, - Member member - ) {} - public record CreateNotice( @NotBlank(message = "제목을 입력해주세요") String title, @NotBlank(message = "내용을 입력해주세요") String content, @NotNull(message = "상단 고정 여부를 결정해주세요") - Boolean isPinned + Boolean isPinned, + @NotNull(message = "공지사항 유형을 입력해주세요") + NoticeCategory noticeCategory ) {} public record UpdateNotice ( diff --git a/src/main/java/org/withtime/be/withtimebe/domain/notice/dto/response/NoticeResponseDTO.java b/src/main/java/org/withtime/be/withtimebe/domain/notice/dto/response/NoticeResponseDTO.java index e4fc557..1c8de43 100644 --- a/src/main/java/org/withtime/be/withtimebe/domain/notice/dto/response/NoticeResponseDTO.java +++ b/src/main/java/org/withtime/be/withtimebe/domain/notice/dto/response/NoticeResponseDTO.java @@ -30,7 +30,6 @@ public record NoticeDetail( String title, // 게시글 제목 String content, // 게시글 내용 Boolean isPinned, // 고정 여부 - Boolean hasAdminAuth, // 어드민 여부 LocalDateTime createdAt // 생성 날짜 ) {} } diff --git a/src/main/java/org/withtime/be/withtimebe/domain/notice/entity/enums/NoticeCategory.java b/src/main/java/org/withtime/be/withtimebe/domain/notice/entity/enums/NoticeCategory.java index a05920f..cc740e2 100644 --- a/src/main/java/org/withtime/be/withtimebe/domain/notice/entity/enums/NoticeCategory.java +++ b/src/main/java/org/withtime/be/withtimebe/domain/notice/entity/enums/NoticeCategory.java @@ -1,6 +1,24 @@ package org.withtime.be.withtimebe.domain.notice.entity.enums; +import java.util.Arrays; + +import org.withtime.be.withtimebe.global.error.code.NoticeErrorCode; +import org.withtime.be.withtimebe.global.error.exception.NoticeException; + +import com.fasterxml.jackson.annotation.JsonCreator; + public enum NoticeCategory { SERVICE, - SYSTEM + SYSTEM; + + // @RequestBody + @JsonCreator + public static NoticeCategory findNoticeCategory(String label) { + return Arrays.stream(values()) + .filter(type -> type.name().equalsIgnoreCase(label)) + .findAny() + .orElseThrow( + () -> new NoticeException(NoticeErrorCode.NOTICE_CATEGORY_NOT_FOUND) + ); + } } diff --git a/src/main/java/org/withtime/be/withtimebe/domain/notice/service/query/NoticeQueryService.java b/src/main/java/org/withtime/be/withtimebe/domain/notice/service/query/NoticeQueryService.java index bc6bd86..3b0a933 100644 --- a/src/main/java/org/withtime/be/withtimebe/domain/notice/service/query/NoticeQueryService.java +++ b/src/main/java/org/withtime/be/withtimebe/domain/notice/service/query/NoticeQueryService.java @@ -1,12 +1,15 @@ package org.withtime.be.withtimebe.domain.notice.service.query; import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.withtime.be.withtimebe.domain.member.entity.Member; import org.withtime.be.withtimebe.domain.notice.dto.request.NoticeRequestDTO; import org.withtime.be.withtimebe.domain.notice.entity.Notice; +import org.withtime.be.withtimebe.domain.notice.entity.enums.NoticeCategory; public interface NoticeQueryService { - Page findNoticeList(NoticeRequestDTO.FindNoticeList request); - Page findNoticeListByKeyword(NoticeRequestDTO.FindNoticeListByKeyword request); - Page findTrashNoticeList(NoticeRequestDTO.FindNoticeList request); - Notice findNoticeDetail(NoticeRequestDTO.FindNoticeDetail request); + Page findNoticeList(Pageable pageable, NoticeCategory noticeCategory); + Page findNoticeListByKeyword(Pageable pageable, String keyword, NoticeCategory noticeCategory); + Page findTrashNoticeList(Pageable pageable, NoticeCategory noticeCategory); + Notice findNoticeDetail(Long noticeId, Member member); } diff --git a/src/main/java/org/withtime/be/withtimebe/domain/notice/service/query/NoticeQueryServiceImpl.java b/src/main/java/org/withtime/be/withtimebe/domain/notice/service/query/NoticeQueryServiceImpl.java index 4846417..0baac4a 100644 --- a/src/main/java/org/withtime/be/withtimebe/domain/notice/service/query/NoticeQueryServiceImpl.java +++ b/src/main/java/org/withtime/be/withtimebe/domain/notice/service/query/NoticeQueryServiceImpl.java @@ -1,12 +1,15 @@ package org.withtime.be.withtimebe.domain.notice.service.query; import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.withtime.be.withtimebe.domain.member.entity.Member; import org.withtime.be.withtimebe.domain.member.entity.enums.Role; +import org.withtime.be.withtimebe.domain.member.repository.MemberRepository; import org.withtime.be.withtimebe.domain.notice.dto.request.NoticeRequestDTO; import org.withtime.be.withtimebe.domain.notice.entity.Notice; +import org.withtime.be.withtimebe.domain.notice.entity.enums.NoticeCategory; import org.withtime.be.withtimebe.domain.notice.repository.NoticeRepository; import org.withtime.be.withtimebe.global.error.code.AuthErrorCode; import org.withtime.be.withtimebe.global.error.code.NoticeErrorCode; @@ -23,32 +26,31 @@ public class NoticeQueryServiceImpl implements NoticeQueryService { private final NoticeRepository noticeRepository; @Override - public Page findNoticeList(NoticeRequestDTO.FindNoticeList request) { + public Page findNoticeList(Pageable pageable, NoticeCategory noticeCategory) { return noticeRepository.findNoticeListByNoticeCategory( - request.noticeCategory(), request.pageable()); + noticeCategory, pageable); } @Override - public Page findNoticeListByKeyword(NoticeRequestDTO.FindNoticeListByKeyword request) { + public Page findNoticeListByKeyword(Pageable pageable, String keyword, NoticeCategory noticeCategory) { return noticeRepository.findNoticeListByNoticeCategoryAndKeyword( - request.noticeCategory(), request.keyword(), request.pageable()); + noticeCategory, keyword, pageable); } @Override - public Page findTrashNoticeList(NoticeRequestDTO.FindNoticeList request) { + public Page findTrashNoticeList(Pageable pageable, NoticeCategory noticeCategory) { return noticeRepository.findTrashNoticeListByNoticeCategory( - request.noticeCategory(), request.pageable() + noticeCategory, pageable ); } @Override - public Notice findNoticeDetail(NoticeRequestDTO.FindNoticeDetail request) { + public Notice findNoticeDetail(Long noticeId, Member member) { - Notice notice = noticeRepository.findNoticeById(request.noticeId()) + Notice notice = noticeRepository.findNoticeById(noticeId) .orElseThrow(() -> new NoticeException(NoticeErrorCode.NOTICE_NOT_FOUND)); - Member member = request.member(); - // 삭제된 게시글을 USER가 보려는 경우 처리 + // 삭제된 게시글을 'USER'가 보려는 경우 처리 if(notice.getDeletedAt() != null) { if(member == null || !member.getRole().equals(Role.ADMIN)) throw new AuthException(NoticeErrorCode.DELETED_NOTICE_FORBIDDEN_ACCESS); diff --git a/src/main/java/org/withtime/be/withtimebe/global/config/WebConfig.java b/src/main/java/org/withtime/be/withtimebe/global/config/WebConfig.java index 05eb654..5f571ff 100644 --- a/src/main/java/org/withtime/be/withtimebe/global/config/WebConfig.java +++ b/src/main/java/org/withtime/be/withtimebe/global/config/WebConfig.java @@ -2,8 +2,10 @@ import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Configuration; +import org.springframework.format.FormatterRegistry; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.withtime.be.withtimebe.domain.notice.converter.NoticeCategoryConverter; import org.withtime.be.withtimebe.global.security.annotation.resolver.AuthenticatedMemberResolver; import java.util.List; @@ -18,4 +20,9 @@ public class WebConfig implements WebMvcConfigurer { public void addArgumentResolvers(List resolvers) { resolvers.add(authenticatedMemberResolver); } + + @Override + public void addFormatters(FormatterRegistry registry) { + registry.addConverter(new NoticeCategoryConverter()); + } } diff --git a/src/main/java/org/withtime/be/withtimebe/global/error/code/NoticeErrorCode.java b/src/main/java/org/withtime/be/withtimebe/global/error/code/NoticeErrorCode.java index 6c6389f..32d18ba 100644 --- a/src/main/java/org/withtime/be/withtimebe/global/error/code/NoticeErrorCode.java +++ b/src/main/java/org/withtime/be/withtimebe/global/error/code/NoticeErrorCode.java @@ -10,6 +10,8 @@ @AllArgsConstructor public enum NoticeErrorCode implements BaseErrorCode { + NOTICE_CATEGORY_EMPTY(HttpStatus.BAD_REQUEST, "NOTICE400_1", "공지사항 유형을 입력해주세요."), + DELETED_NOTICE_FORBIDDEN_ACCESS(HttpStatus.FORBIDDEN, "NOTICE403_1", "삭제된 공지사항을 열람할 Admin 권한이 없습니다."), NOTICE_CATEGORY_NOT_FOUND(HttpStatus.NOT_FOUND, "NOTICE404_1", "해당하는 공지사항 유형을 찾을 수 없습니다."), From 3f2f5e51dd8e05b2b24695830139b014e4461a29 Mon Sep 17 00:00:00 2001 From: pywoo Date: Sun, 13 Jul 2025 22:16:38 +0900 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=90=9B=20fix:=20=EB=B3=80=EC=88=98?= =?UTF-8?q?=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../withtimebe/domain/notice/entity/enums/NoticeCategory.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/withtime/be/withtimebe/domain/notice/entity/enums/NoticeCategory.java b/src/main/java/org/withtime/be/withtimebe/domain/notice/entity/enums/NoticeCategory.java index cc740e2..c12f003 100644 --- a/src/main/java/org/withtime/be/withtimebe/domain/notice/entity/enums/NoticeCategory.java +++ b/src/main/java/org/withtime/be/withtimebe/domain/notice/entity/enums/NoticeCategory.java @@ -13,9 +13,9 @@ public enum NoticeCategory { // @RequestBody @JsonCreator - public static NoticeCategory findNoticeCategory(String label) { + public static NoticeCategory findNoticeCategory(String name) { return Arrays.stream(values()) - .filter(type -> type.name().equalsIgnoreCase(label)) + .filter(type -> type.name().equalsIgnoreCase(name)) .findAny() .orElseThrow( () -> new NoticeException(NoticeErrorCode.NOTICE_CATEGORY_NOT_FOUND)