tokens, String topic) throws FirebaseMessagingException;
+}
diff --git a/src/main/java/com/kustacks/kuring/common/dto/NoticeMessageDto.java b/src/main/java/com/kustacks/kuring/message/application/port/out/dto/NoticeMessageDto.java
similarity index 97%
rename from src/main/java/com/kustacks/kuring/common/dto/NoticeMessageDto.java
rename to src/main/java/com/kustacks/kuring/message/application/port/out/dto/NoticeMessageDto.java
index 89668245..dec19e26 100644
--- a/src/main/java/com/kustacks/kuring/common/dto/NoticeMessageDto.java
+++ b/src/main/java/com/kustacks/kuring/message/application/port/out/dto/NoticeMessageDto.java
@@ -1,4 +1,4 @@
-package com.kustacks.kuring.common.dto;
+package com.kustacks.kuring.message.application.port.out.dto;
import com.kustacks.kuring.notice.domain.DepartmentNotice;
import com.kustacks.kuring.notice.domain.Notice;
diff --git a/src/main/java/com/kustacks/kuring/message/firebase/FirebaseService.java b/src/main/java/com/kustacks/kuring/message/application/service/FirebaseNotificationService.java
similarity index 59%
rename from src/main/java/com/kustacks/kuring/message/firebase/FirebaseService.java
rename to src/main/java/com/kustacks/kuring/message/application/service/FirebaseNotificationService.java
index 4bf79493..df6cb18a 100644
--- a/src/main/java/com/kustacks/kuring/message/firebase/FirebaseService.java
+++ b/src/main/java/com/kustacks/kuring/message/application/service/FirebaseNotificationService.java
@@ -1,107 +1,68 @@
-package com.kustacks.kuring.message.firebase;
+package com.kustacks.kuring.message.application.service;
import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.firebase.messaging.*;
-import com.kustacks.kuring.admin.common.dto.AdminNotificationDto;
-import com.kustacks.kuring.common.dto.NoticeMessageDto;
+import com.google.firebase.messaging.FirebaseMessagingException;
+import com.google.firebase.messaging.Message;
+import com.google.firebase.messaging.Notification;
+import com.kustacks.kuring.common.annotation.UseCase;
import com.kustacks.kuring.common.exception.InternalLogicException;
import com.kustacks.kuring.common.exception.code.ErrorCode;
-import com.kustacks.kuring.message.firebase.exception.FirebaseInvalidTokenException;
-import com.kustacks.kuring.message.firebase.exception.FirebaseMessageSendException;
-import com.kustacks.kuring.message.firebase.exception.FirebaseSubscribeException;
-import com.kustacks.kuring.message.firebase.exception.FirebaseUnSubscribeException;
+import com.kustacks.kuring.common.properties.ServerProperties;
+import com.kustacks.kuring.message.application.port.in.FirebaseWithAdminUseCase;
+import com.kustacks.kuring.message.application.port.in.dto.AdminNotificationCommand;
+import com.kustacks.kuring.message.application.port.in.dto.AdminTestNotificationCommand;
+import com.kustacks.kuring.message.application.port.out.FirebaseMessagingPort;
+import com.kustacks.kuring.message.application.port.out.dto.NoticeMessageDto;
+import com.kustacks.kuring.message.application.service.exception.FirebaseMessageSendException;
import com.kustacks.kuring.notice.domain.Notice;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
-import java.util.function.Function;
-import java.util.stream.Collectors;
+import java.util.function.UnaryOperator;
+
+import static com.kustacks.kuring.message.application.service.FirebaseSubscribeService.ALL_DEVICE_SUBSCRIBED_TOPIC;
@Slf4j
-@Service
+@UseCase
@RequiredArgsConstructor
-public class FirebaseService {
+public class FirebaseNotificationService implements FirebaseWithAdminUseCase {
private static final String NOTIFICATION_TITLE = "새로운 공지가 왔어요!";
- public static final String ALL_DEVICE_SUBSCRIBED_TOPIC = "allDevice";
- private final FirebaseMessaging firebaseMessaging;
- private final ObjectMapper objectMapper;
+ private final FirebaseMessagingPort firebaseMessagingPort;
private final ServerProperties serverProperties;
+ private final ObjectMapper objectMapper;
- public void validationToken(String token) throws FirebaseInvalidTokenException {
- try {
- Message message = Message.builder().setToken(token).build();
-
- firebaseMessaging.send(message);
- } catch (FirebaseMessagingException exception) {
- throw new FirebaseInvalidTokenException();
- }
- }
-
- public void subscribe(String token, String topic) throws FirebaseSubscribeException {
- try {
- TopicManagementResponse response = firebaseMessaging
- .subscribeToTopic(List.of(token), serverProperties.ifDevThenAddSuffix(topic));
-
- if (response.getFailureCount() > 0) {
- throw new FirebaseSubscribeException();
- }
- } catch (FirebaseMessagingException | FirebaseSubscribeException exception) {
- throw new FirebaseSubscribeException();
- }
- }
-
- public void unsubscribe(String token, String topic) throws FirebaseUnSubscribeException {
- try {
- TopicManagementResponse response = firebaseMessaging
- .unsubscribeFromTopic(List.of(token), serverProperties.ifDevThenAddSuffix(topic));
+ @Override
+ public void sendTestNotificationByAdmin(AdminTestNotificationCommand command) {
+ NoticeMessageDto messageDto = NoticeMessageDto.builder()
+ .articleId(command.articleId())
+ .postedDate(command.postedDate())
+ .category(command.categoryName())
+ .subject(command.subject())
+ .categoryKorName(command.korName())
+ .baseUrl(command.url())
+ .build();
- if (response.getFailureCount() > 0) {
- throw new FirebaseUnSubscribeException();
- }
- } catch (FirebaseMessagingException | FirebaseUnSubscribeException exception) {
- throw new FirebaseUnSubscribeException();
- }
- }
-
- /**
- * Firebase message에는 두 가지 paylaad가 존재한다.
- * 1. notification
- * 2. data
- *
- * notification을 Message로 만들어 보내면 여기서 설정한 title, body가 직접 앱 noti로 뜬다.
- * data로 Message를 만들어 보내면 이것을 앱 클라이언트(Andriod)가 받아서, 가공한 뒤 푸쉬 알람으로 만들 수 있다.
- *
- * 따라서 여기선 putData를 사용하여 보내고, 클라이언트가 푸쉬 알람을 만들어 띄운다.
- *
- * @param messageDto
- * @throws FirebaseMessageSendException
- */
- public void sendNotification(NoticeMessageDto messageDto) throws FirebaseMessageSendException {
- sendBaseNotification(messageDto, serverProperties::ifDevThenAddSuffix);
- }
-
- public void sendTestNotification(NoticeMessageDto messageDto) throws FirebaseMessageSendException {
sendBaseNotification(messageDto, serverProperties::addDevSuffix);
}
- public void sendNotificationByAdmin(AdminNotificationDto messageDto) {
+ @Override
+ public void sendNotificationByAdmin(AdminNotificationCommand command) {
try {
Message newMessage = Message.builder()
.setNotification(Notification
.builder()
- .setTitle(messageDto.getTitle())
- .setBody(messageDto.getBody())
+ .setTitle(command.title())
+ .setBody(command.body())
.build())
- .putAllData(objectMapper.convertValue(messageDto, Map.class))
+ .putAllData(objectMapper.convertValue(command, Map.class))
.setTopic(serverProperties.ifDevThenAddSuffix(ALL_DEVICE_SUBSCRIBED_TOPIC))
.build();
- firebaseMessaging.send(newMessage);
+ firebaseMessagingPort.send(newMessage);
} catch (FirebaseMessagingException exception) {
throw new FirebaseMessageSendException();
}
@@ -126,7 +87,24 @@ public void sendNotificationList(List extends Notice> noticeList) {
}
}
- private void sendBaseNotification(NoticeMessageDto messageDto, Function suffixUtil) throws FirebaseMessageSendException {
+ /**
+ * Firebase message에는 두 가지 paylaad가 존재한다.
+ * 1. notification
+ * 2. data
+ *
+ * notification을 Message로 만들어 보내면 여기서 설정한 title, body가 직접 앱 noti로 뜬다.
+ * data로 Message를 만들어 보내면 이것을 앱 클라이언트(Andriod)가 받아서, 가공한 뒤 푸쉬 알람으로 만들 수 있다.
+ *
+ * 따라서 여기선 putData를 사용하여 보내고, 클라이언트가 푸쉬 알람을 만들어 띄운다.
+ *
+ * @param messageDto
+ * @throws FirebaseMessageSendException
+ */
+ private void sendNotification(NoticeMessageDto messageDto) throws FirebaseMessageSendException {
+ sendBaseNotification(messageDto, serverProperties::ifDevThenAddSuffix);
+ }
+
+ private void sendBaseNotification(NoticeMessageDto messageDto, UnaryOperator suffixUtil) throws FirebaseMessageSendException {
try {
Message newMessage = Message.builder()
.setNotification(Notification
@@ -138,7 +116,7 @@ private void sendBaseNotification(NoticeMessageDto messageDto, Function 0) {
+ throw new FirebaseSubscribeException();
+ }
+ } catch (FirebaseMessagingException | FirebaseSubscribeException exception) {
+ throw new FirebaseSubscribeException();
+ }
+ }
+
+ @Override
+ public void unsubscribe(UserUnsubscribeCommand command) throws FirebaseUnSubscribeException {
+ try {
+ TopicManagementResponse response = firebaseSubscribePort
+ .unsubscribeFromTopic(List.of(command.token()), serverProperties.ifDevThenAddSuffix(command.topic()));
+
+ if (response.getFailureCount() > 0) {
+ throw new FirebaseUnSubscribeException();
+ }
+ } catch (FirebaseMessagingException | FirebaseUnSubscribeException exception) {
+ throw new FirebaseUnSubscribeException();
+ }
+ }
+}
diff --git a/src/main/java/com/kustacks/kuring/message/firebase/exception/FirebaseBusinessException.java b/src/main/java/com/kustacks/kuring/message/application/service/exception/FirebaseBusinessException.java
similarity index 82%
rename from src/main/java/com/kustacks/kuring/message/firebase/exception/FirebaseBusinessException.java
rename to src/main/java/com/kustacks/kuring/message/application/service/exception/FirebaseBusinessException.java
index fa623cc7..9748bb7e 100644
--- a/src/main/java/com/kustacks/kuring/message/firebase/exception/FirebaseBusinessException.java
+++ b/src/main/java/com/kustacks/kuring/message/application/service/exception/FirebaseBusinessException.java
@@ -1,4 +1,4 @@
-package com.kustacks.kuring.message.firebase.exception;
+package com.kustacks.kuring.message.application.service.exception;
import com.kustacks.kuring.common.exception.BusinessException;
import com.kustacks.kuring.common.exception.code.ErrorCode;
diff --git a/src/main/java/com/kustacks/kuring/message/firebase/exception/FirebaseInvalidTokenException.java b/src/main/java/com/kustacks/kuring/message/application/service/exception/FirebaseInvalidTokenException.java
similarity index 78%
rename from src/main/java/com/kustacks/kuring/message/firebase/exception/FirebaseInvalidTokenException.java
rename to src/main/java/com/kustacks/kuring/message/application/service/exception/FirebaseInvalidTokenException.java
index b50d79e1..29946da3 100644
--- a/src/main/java/com/kustacks/kuring/message/firebase/exception/FirebaseInvalidTokenException.java
+++ b/src/main/java/com/kustacks/kuring/message/application/service/exception/FirebaseInvalidTokenException.java
@@ -1,4 +1,4 @@
-package com.kustacks.kuring.message.firebase.exception;
+package com.kustacks.kuring.message.application.service.exception;
import com.kustacks.kuring.common.exception.code.ErrorCode;
diff --git a/src/main/java/com/kustacks/kuring/message/firebase/exception/FirebaseMessageSendException.java b/src/main/java/com/kustacks/kuring/message/application/service/exception/FirebaseMessageSendException.java
similarity index 77%
rename from src/main/java/com/kustacks/kuring/message/firebase/exception/FirebaseMessageSendException.java
rename to src/main/java/com/kustacks/kuring/message/application/service/exception/FirebaseMessageSendException.java
index 6af9fe76..32ff5718 100644
--- a/src/main/java/com/kustacks/kuring/message/firebase/exception/FirebaseMessageSendException.java
+++ b/src/main/java/com/kustacks/kuring/message/application/service/exception/FirebaseMessageSendException.java
@@ -1,4 +1,4 @@
-package com.kustacks.kuring.message.firebase.exception;
+package com.kustacks.kuring.message.application.service.exception;
import com.kustacks.kuring.common.exception.code.ErrorCode;
diff --git a/src/main/java/com/kustacks/kuring/message/firebase/exception/FirebaseSubscribeException.java b/src/main/java/com/kustacks/kuring/message/application/service/exception/FirebaseSubscribeException.java
similarity index 77%
rename from src/main/java/com/kustacks/kuring/message/firebase/exception/FirebaseSubscribeException.java
rename to src/main/java/com/kustacks/kuring/message/application/service/exception/FirebaseSubscribeException.java
index b12ff83c..4ecccc8f 100644
--- a/src/main/java/com/kustacks/kuring/message/firebase/exception/FirebaseSubscribeException.java
+++ b/src/main/java/com/kustacks/kuring/message/application/service/exception/FirebaseSubscribeException.java
@@ -1,4 +1,4 @@
-package com.kustacks.kuring.message.firebase.exception;
+package com.kustacks.kuring.message.application.service.exception;
import com.kustacks.kuring.common.exception.code.ErrorCode;
diff --git a/src/main/java/com/kustacks/kuring/message/firebase/exception/FirebaseUnSubscribeException.java b/src/main/java/com/kustacks/kuring/message/application/service/exception/FirebaseUnSubscribeException.java
similarity index 78%
rename from src/main/java/com/kustacks/kuring/message/firebase/exception/FirebaseUnSubscribeException.java
rename to src/main/java/com/kustacks/kuring/message/application/service/exception/FirebaseUnSubscribeException.java
index 88450b4e..885865ad 100644
--- a/src/main/java/com/kustacks/kuring/message/firebase/exception/FirebaseUnSubscribeException.java
+++ b/src/main/java/com/kustacks/kuring/message/application/service/exception/FirebaseUnSubscribeException.java
@@ -1,4 +1,4 @@
-package com.kustacks.kuring.message.firebase.exception;
+package com.kustacks.kuring.message.application.service.exception;
import com.kustacks.kuring.common.exception.code.ErrorCode;
diff --git a/src/main/java/com/kustacks/kuring/notice/adapter/in/web/NoticeQueryApiV2.java b/src/main/java/com/kustacks/kuring/notice/adapter/in/web/NoticeQueryApiV2.java
new file mode 100644
index 00000000..a00f0223
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/notice/adapter/in/web/NoticeQueryApiV2.java
@@ -0,0 +1,86 @@
+package com.kustacks.kuring.notice.adapter.in.web;
+
+import static com.kustacks.kuring.common.dto.ResponseCodeAndMessages.CATEGORY_SEARCH_SUCCESS;
+import static com.kustacks.kuring.common.dto.ResponseCodeAndMessages.DEPARTMENTS_SEARCH_SUCCESS;
+import static com.kustacks.kuring.common.dto.ResponseCodeAndMessages.NOTICE_SEARCH_SUCCESS;
+
+import com.kustacks.kuring.common.annotation.RestWebAdapter;
+import com.kustacks.kuring.common.dto.BaseResponse;
+import com.kustacks.kuring.notice.adapter.in.web.dto.NoticeCategoryNameResponse;
+import com.kustacks.kuring.notice.adapter.in.web.dto.NoticeContentSearchResponse;
+import com.kustacks.kuring.notice.adapter.in.web.dto.NoticeDepartmentNameResponse;
+import com.kustacks.kuring.notice.adapter.in.web.dto.NoticeRangeLookupResponse;
+import com.kustacks.kuring.notice.application.port.in.NoticeQueryUseCase;
+import com.kustacks.kuring.notice.application.port.in.dto.NoticeContentSearchResult;
+import com.kustacks.kuring.notice.application.port.in.dto.NoticeRangeLookupCommand;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import java.util.List;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotBlank;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@Tag(name = "Notice-Query", description = "공지 정보 조회")
+@Validated
+@RequiredArgsConstructor
+@RestWebAdapter(path = "/api/v2/notices")
+public class NoticeQueryApiV2 {
+
+ private final NoticeQueryUseCase noticeQueryUseCase;
+
+ @Operation(summary = "공지 조회", description = "일반 공지 조회와 학과별 공지 조회를 지원합니다")
+ @GetMapping
+ public ResponseEntity>> getNotices(
+ @Parameter(description = "공지 타입") @RequestParam(name = "type") String type,
+ @Parameter(description = "학과는 hostPrefix 로 전달") @RequestParam(name = "department", required = false) String department,
+ @Parameter(description = "중요도") @RequestParam(name = "important", defaultValue = "false") Boolean important,
+ @Parameter(description = "페이지") @RequestParam(name = "page") @Min(0) int page,
+ @Parameter(description = "단일 페이지의 사이즈, 1 ~ 30까지 허용") @RequestParam(name = "size") @Min(1) @Max(30) int size
+ ) {
+ NoticeRangeLookupCommand command = new NoticeRangeLookupCommand(type, department, important, page, size);
+ List searchResults = noticeQueryUseCase.getNotices(command)
+ .stream()
+ .map(NoticeRangeLookupResponse::from)
+ .toList();
+
+ return ResponseEntity.ok().body(new BaseResponse<>(NOTICE_SEARCH_SUCCESS, searchResults));
+ }
+
+ @Operation(summary = "키워드 공지 조회", description = "일반 공지 조회와 학과별 공지 검색을 지원하며, 2글자 이상의 키워드를 입력하길 권장합니다")
+ @GetMapping("/search")
+ public ResponseEntity> searchNotice(
+ @NotBlank @RequestParam String content
+ ) {
+ List response = noticeQueryUseCase.findAllNoticeByContent(content);
+ NoticeContentSearchResponse noticeContentSearchResponse = new NoticeContentSearchResponse(response);
+ return ResponseEntity.ok().body(new BaseResponse<>(NOTICE_SEARCH_SUCCESS, noticeContentSearchResponse));
+ }
+
+ @Operation(summary = "일반 공지 카테고리", description = "서버가 지원하는 일반공지 카테고리 목록을 조회합니다")
+ @GetMapping("/categories")
+ public ResponseEntity>> getSupportedCategories() {
+ List categoryNames = noticeQueryUseCase.lookupSupportedCategories()
+ .stream()
+ .map(NoticeCategoryNameResponse::from)
+ .toList();
+
+ return ResponseEntity.ok().body(new BaseResponse<>(CATEGORY_SEARCH_SUCCESS, categoryNames));
+ }
+
+ @Operation(summary = "학과별 공지 카테고리", description = "서버가 지원하는 학과별 공지 카테고리 목록을 조회합니다")
+ @GetMapping("/departments")
+ public ResponseEntity>> getSupportedDepartments() {
+ List departmentNames = noticeQueryUseCase.lookupSupportedDepartments()
+ .stream()
+ .map(NoticeDepartmentNameResponse::from)
+ .toList();
+
+ return ResponseEntity.ok().body(new BaseResponse<>(DEPARTMENTS_SEARCH_SUCCESS, departmentNames));
+ }
+}
diff --git a/src/main/java/com/kustacks/kuring/notice/adapter/in/web/dto/NoticeCategoryNameResponse.java b/src/main/java/com/kustacks/kuring/notice/adapter/in/web/dto/NoticeCategoryNameResponse.java
new file mode 100644
index 00000000..9b244f19
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/notice/adapter/in/web/dto/NoticeCategoryNameResponse.java
@@ -0,0 +1,17 @@
+package com.kustacks.kuring.notice.adapter.in.web.dto;
+
+import com.kustacks.kuring.notice.application.port.in.dto.NoticeCategoryNameResult;
+
+public record NoticeCategoryNameResponse(
+ String name,
+ String hostPrefix,
+ String korName
+) {
+ public static NoticeCategoryNameResponse from(NoticeCategoryNameResult result) {
+ return new NoticeCategoryNameResponse(
+ result.name(),
+ result.hostPrefix(),
+ result.korName()
+ );
+ }
+}
diff --git a/src/main/java/com/kustacks/kuring/notice/adapter/in/web/dto/NoticeContentSearchResponse.java b/src/main/java/com/kustacks/kuring/notice/adapter/in/web/dto/NoticeContentSearchResponse.java
new file mode 100644
index 00000000..6556b6c4
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/notice/adapter/in/web/dto/NoticeContentSearchResponse.java
@@ -0,0 +1,10 @@
+package com.kustacks.kuring.notice.adapter.in.web.dto;
+
+import com.kustacks.kuring.notice.application.port.in.dto.NoticeContentSearchResult;
+
+import java.util.List;
+
+public record NoticeContentSearchResponse(
+ List noticeList
+) {
+}
diff --git a/src/main/java/com/kustacks/kuring/notice/adapter/in/web/dto/NoticeDepartmentNameResponse.java b/src/main/java/com/kustacks/kuring/notice/adapter/in/web/dto/NoticeDepartmentNameResponse.java
new file mode 100644
index 00000000..05cd4e6d
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/notice/adapter/in/web/dto/NoticeDepartmentNameResponse.java
@@ -0,0 +1,17 @@
+package com.kustacks.kuring.notice.adapter.in.web.dto;
+
+import com.kustacks.kuring.notice.application.port.in.dto.NoticeDepartmentNameResult;
+
+public record NoticeDepartmentNameResponse(
+ String name,
+ String hostPrefix,
+ String korName
+) {
+ public static NoticeDepartmentNameResponse from(NoticeDepartmentNameResult result) {
+ return new NoticeDepartmentNameResponse(
+ result.name(),
+ result.hostPrefix(),
+ result.korName()
+ );
+ }
+}
diff --git a/src/main/java/com/kustacks/kuring/notice/adapter/in/web/dto/NoticeRangeLookupResponse.java b/src/main/java/com/kustacks/kuring/notice/adapter/in/web/dto/NoticeRangeLookupResponse.java
new file mode 100644
index 00000000..6fa80737
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/notice/adapter/in/web/dto/NoticeRangeLookupResponse.java
@@ -0,0 +1,23 @@
+package com.kustacks.kuring.notice.adapter.in.web.dto;
+
+import com.kustacks.kuring.notice.application.port.in.dto.NoticeRangeLookupResult;
+
+public record NoticeRangeLookupResponse(
+ String articleId,
+ String postedDate,
+ String url,
+ String subject,
+ String category,
+ Boolean important
+){
+ public static NoticeRangeLookupResponse from(NoticeRangeLookupResult result) {
+ return new NoticeRangeLookupResponse(
+ result.articleId(),
+ result.postedDate(),
+ result.url(),
+ result.subject(),
+ result.category(),
+ result.important()
+ );
+ }
+}
diff --git a/src/main/java/com/kustacks/kuring/notice/domain/NoticeJdbcRepository.java b/src/main/java/com/kustacks/kuring/notice/adapter/out/persistence/NoticeJdbcRepository.java
similarity index 92%
rename from src/main/java/com/kustacks/kuring/notice/domain/NoticeJdbcRepository.java
rename to src/main/java/com/kustacks/kuring/notice/adapter/out/persistence/NoticeJdbcRepository.java
index 3430dadb..229c5e44 100644
--- a/src/main/java/com/kustacks/kuring/notice/domain/NoticeJdbcRepository.java
+++ b/src/main/java/com/kustacks/kuring/notice/adapter/out/persistence/NoticeJdbcRepository.java
@@ -1,5 +1,8 @@
-package com.kustacks.kuring.notice.domain;
+package com.kustacks.kuring.notice.adapter.out.persistence;
+import com.kustacks.kuring.notice.domain.DepartmentName;
+import com.kustacks.kuring.notice.domain.DepartmentNotice;
+import com.kustacks.kuring.notice.domain.Notice;
import lombok.RequiredArgsConstructor;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
@@ -12,7 +15,7 @@
@Repository
@RequiredArgsConstructor
-public class NoticeJdbcRepository {
+class NoticeJdbcRepository {
private final JdbcTemplate jdbcTemplate;
diff --git a/src/main/java/com/kustacks/kuring/notice/adapter/out/persistence/NoticePersistenceAdapter.java b/src/main/java/com/kustacks/kuring/notice/adapter/out/persistence/NoticePersistenceAdapter.java
new file mode 100644
index 00000000..281105b9
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/notice/adapter/out/persistence/NoticePersistenceAdapter.java
@@ -0,0 +1,89 @@
+package com.kustacks.kuring.notice.adapter.out.persistence;
+
+import com.kustacks.kuring.common.annotation.PersistenceAdapter;
+import com.kustacks.kuring.notice.application.port.out.NoticeCommandPort;
+import com.kustacks.kuring.notice.application.port.out.NoticeQueryPort;
+import com.kustacks.kuring.notice.application.port.out.dto.NoticeDto;
+import com.kustacks.kuring.notice.application.port.out.dto.NoticeSearchDto;
+import com.kustacks.kuring.notice.domain.CategoryName;
+import com.kustacks.kuring.notice.domain.DepartmentName;
+import com.kustacks.kuring.notice.domain.DepartmentNotice;
+import com.kustacks.kuring.notice.domain.Notice;
+import com.kustacks.kuring.user.application.port.out.dto.BookmarkDto;
+import lombok.RequiredArgsConstructor;
+import org.springframework.data.domain.Pageable;
+
+import java.util.List;
+
+@PersistenceAdapter
+@RequiredArgsConstructor
+public class NoticePersistenceAdapter implements NoticeCommandPort, NoticeQueryPort {
+
+ private final NoticeRepository noticeRepository;
+ private final NoticeJdbcRepository noticeJdbcRepository;
+
+ @Override
+ public void saveAllCategoryNotices(List notices) {
+ this.noticeJdbcRepository.saveAllCategoryNotices(notices);
+ }
+
+ @Override
+ public void saveAllDepartmentNotices(List departmentNotices) {
+ this.noticeJdbcRepository.saveAllDepartmentNotices(departmentNotices);
+ }
+
+ @Override
+ public void deleteAllByIdsAndCategory(CategoryName categoryName, List articleIds) {
+ this.noticeRepository.deleteAllByIdsAndCategory(categoryName, articleIds);
+ }
+
+ @Override
+ public void deleteAllByIdsAndDepartment(DepartmentName departmentName, List articleIds) {
+ this.noticeRepository.deleteAllByIdsAndDepartment(departmentName, articleIds);
+ }
+
+ @Override
+ public List findNoticesByCategoryWithOffset(CategoryName categoryName, Pageable pageable) {
+ return this.noticeRepository.findNoticesByCategoryWithOffset(categoryName, pageable);
+ }
+
+ @Override
+ public List findAllByKeywords(List containedNames) {
+ return this.noticeRepository.findAllByKeywords(containedNames);
+ }
+
+ @Override
+ public List findNormalArticleIdsByCategory(CategoryName categoryName) {
+ return this.noticeRepository.findNormalArticleIdsByCategory(categoryName);
+ }
+
+ @Override
+ public List findImportantNoticesByDepartment(DepartmentName departmentName) {
+ return this.noticeRepository.findImportantNoticesByDepartment(departmentName);
+ }
+
+ @Override
+ public List findNormalNoticesByDepartmentWithOffset(DepartmentName departmentName, Pageable pageable) {
+ return this.noticeRepository.findNormalNoticesByDepartmentWithOffset(departmentName, pageable);
+ }
+
+ @Override
+ public List findImportantArticleIdsByDepartment(DepartmentName departmentNameEnum) {
+ return this.noticeRepository.findImportantArticleIdsByDepartment(departmentNameEnum);
+ }
+
+ @Override
+ public List findNormalArticleIdsByDepartment(DepartmentName departmentNameEnum) {
+ return this.noticeRepository.findNormalArticleIdsByDepartment(departmentNameEnum);
+ }
+
+ @Override
+ public List findAllByBookmarkIds(List ids) {
+ return this.noticeRepository.findAllByBookmarkIds(ids);
+ }
+
+ @Override
+ public Long count() {
+ return this.noticeRepository.count();
+ }
+}
diff --git a/src/main/java/com/kustacks/kuring/notice/domain/NoticeQueryRepository.java b/src/main/java/com/kustacks/kuring/notice/adapter/out/persistence/NoticeQueryRepository.java
similarity index 69%
rename from src/main/java/com/kustacks/kuring/notice/domain/NoticeQueryRepository.java
rename to src/main/java/com/kustacks/kuring/notice/adapter/out/persistence/NoticeQueryRepository.java
index 11b0dc31..1f7be949 100644
--- a/src/main/java/com/kustacks/kuring/notice/domain/NoticeQueryRepository.java
+++ b/src/main/java/com/kustacks/kuring/notice/adapter/out/persistence/NoticeQueryRepository.java
@@ -1,13 +1,15 @@
-package com.kustacks.kuring.notice.domain;
+package com.kustacks.kuring.notice.adapter.out.persistence;
-import com.kustacks.kuring.notice.common.dto.NoticeDto;
-import com.kustacks.kuring.notice.common.dto.NoticeSearchDto;
-import com.kustacks.kuring.user.common.dto.BookmarkDto;
+import com.kustacks.kuring.notice.application.port.out.dto.NoticeDto;
+import com.kustacks.kuring.notice.application.port.out.dto.NoticeSearchDto;
+import com.kustacks.kuring.notice.domain.CategoryName;
+import com.kustacks.kuring.notice.domain.DepartmentName;
+import com.kustacks.kuring.user.application.port.out.dto.BookmarkDto;
import org.springframework.data.domain.Pageable;
import java.util.List;
-public interface NoticeQueryRepository {
+interface NoticeQueryRepository {
List findNoticesByCategoryWithOffset(CategoryName categoryName, Pageable pageable);
diff --git a/src/main/java/com/kustacks/kuring/notice/domain/NoticeQueryRepositoryImpl.java b/src/main/java/com/kustacks/kuring/notice/adapter/out/persistence/NoticeQueryRepositoryImpl.java
similarity index 91%
rename from src/main/java/com/kustacks/kuring/notice/domain/NoticeQueryRepositoryImpl.java
rename to src/main/java/com/kustacks/kuring/notice/adapter/out/persistence/NoticeQueryRepositoryImpl.java
index c3754d52..511341c0 100644
--- a/src/main/java/com/kustacks/kuring/notice/domain/NoticeQueryRepositoryImpl.java
+++ b/src/main/java/com/kustacks/kuring/notice/adapter/out/persistence/NoticeQueryRepositoryImpl.java
@@ -1,11 +1,13 @@
-package com.kustacks.kuring.notice.domain;
-
-import com.kustacks.kuring.notice.common.dto.NoticeDto;
-import com.kustacks.kuring.notice.common.dto.NoticeSearchDto;
-import com.kustacks.kuring.notice.common.dto.QNoticeDto;
-import com.kustacks.kuring.notice.common.dto.QNoticeSearchDto;
-import com.kustacks.kuring.user.common.dto.BookmarkDto;
-import com.kustacks.kuring.user.common.dto.QBookmarkDto;
+package com.kustacks.kuring.notice.adapter.out.persistence;
+
+import com.kustacks.kuring.notice.application.port.out.dto.NoticeDto;
+import com.kustacks.kuring.notice.application.port.out.dto.NoticeSearchDto;
+import com.kustacks.kuring.notice.application.port.out.dto.QNoticeDto;
+import com.kustacks.kuring.notice.application.port.out.dto.QNoticeSearchDto;
+import com.kustacks.kuring.notice.domain.CategoryName;
+import com.kustacks.kuring.notice.domain.DepartmentName;
+import com.kustacks.kuring.user.application.port.out.dto.BookmarkDto;
+import com.kustacks.kuring.user.application.port.out.dto.QBookmarkDto;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.dsl.Expressions;
import com.querydsl.core.types.dsl.NumberTemplate;
@@ -20,7 +22,7 @@
import static com.kustacks.kuring.notice.domain.QNotice.notice;
@RequiredArgsConstructor
-public class NoticeQueryRepositoryImpl implements NoticeQueryRepository {
+class NoticeQueryRepositoryImpl implements NoticeQueryRepository {
private final JPAQueryFactory queryFactory;
diff --git a/src/main/java/com/kustacks/kuring/notice/adapter/out/persistence/NoticeRepository.java b/src/main/java/com/kustacks/kuring/notice/adapter/out/persistence/NoticeRepository.java
new file mode 100644
index 00000000..0d912191
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/notice/adapter/out/persistence/NoticeRepository.java
@@ -0,0 +1,7 @@
+package com.kustacks.kuring.notice.adapter.out.persistence;
+
+import com.kustacks.kuring.notice.domain.Notice;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+interface NoticeRepository extends JpaRepository, NoticeQueryRepository {
+}
diff --git a/src/main/java/com/kustacks/kuring/notice/application/port/in/NoticeQueryUseCase.java b/src/main/java/com/kustacks/kuring/notice/application/port/in/NoticeQueryUseCase.java
new file mode 100644
index 00000000..45df89aa
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/notice/application/port/in/NoticeQueryUseCase.java
@@ -0,0 +1,12 @@
+package com.kustacks.kuring.notice.application.port.in;
+
+import com.kustacks.kuring.notice.application.port.in.dto.*;
+
+import java.util.List;
+
+public interface NoticeQueryUseCase {
+ List getNotices(NoticeRangeLookupCommand command);
+ List findAllNoticeByContent(String content);
+ List lookupSupportedCategories();
+ List lookupSupportedDepartments();
+}
diff --git a/src/main/java/com/kustacks/kuring/notice/application/port/in/dto/NoticeCategoryNameResult.java b/src/main/java/com/kustacks/kuring/notice/application/port/in/dto/NoticeCategoryNameResult.java
new file mode 100644
index 00000000..9ac18f73
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/notice/application/port/in/dto/NoticeCategoryNameResult.java
@@ -0,0 +1,13 @@
+package com.kustacks.kuring.notice.application.port.in.dto;
+
+import com.kustacks.kuring.notice.domain.CategoryName;
+
+public record NoticeCategoryNameResult(
+ String name,
+ String hostPrefix,
+ String korName
+) {
+ public static NoticeCategoryNameResult from(CategoryName name) {
+ return new NoticeCategoryNameResult(name.getName(), name.getShortName(), name.getKorName());
+ }
+}
diff --git a/src/main/java/com/kustacks/kuring/notice/application/port/in/dto/NoticeContentSearchResult.java b/src/main/java/com/kustacks/kuring/notice/application/port/in/dto/NoticeContentSearchResult.java
new file mode 100644
index 00000000..98cb86d6
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/notice/application/port/in/dto/NoticeContentSearchResult.java
@@ -0,0 +1,10 @@
+package com.kustacks.kuring.notice.application.port.in.dto;
+
+public record NoticeContentSearchResult(
+ String articleId,
+ String postedDate,
+ String subject,
+ String category,
+ String baseUrl
+) {
+}
diff --git a/src/main/java/com/kustacks/kuring/notice/application/port/in/dto/NoticeDepartmentNameResult.java b/src/main/java/com/kustacks/kuring/notice/application/port/in/dto/NoticeDepartmentNameResult.java
new file mode 100644
index 00000000..9dbc7bcd
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/notice/application/port/in/dto/NoticeDepartmentNameResult.java
@@ -0,0 +1,13 @@
+package com.kustacks.kuring.notice.application.port.in.dto;
+
+import com.kustacks.kuring.notice.domain.DepartmentName;
+
+public record NoticeDepartmentNameResult(
+ String name,
+ String hostPrefix,
+ String korName
+) {
+ public static NoticeDepartmentNameResult from(DepartmentName name) {
+ return new NoticeDepartmentNameResult(name.getName(), name.getHostPrefix(), name.getKorName());
+ }
+}
diff --git a/src/main/java/com/kustacks/kuring/notice/application/port/in/dto/NoticeRangeLookupCommand.java b/src/main/java/com/kustacks/kuring/notice/application/port/in/dto/NoticeRangeLookupCommand.java
new file mode 100644
index 00000000..8f804020
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/notice/application/port/in/dto/NoticeRangeLookupCommand.java
@@ -0,0 +1,13 @@
+package com.kustacks.kuring.notice.application.port.in.dto;
+
+public record NoticeRangeLookupCommand(
+ String type,
+ String department,
+ Boolean important,
+ int page,
+ int size
+) {
+ public boolean isImportant() {
+ return this.important;
+ }
+}
diff --git a/src/main/java/com/kustacks/kuring/notice/application/port/in/dto/NoticeRangeLookupResult.java b/src/main/java/com/kustacks/kuring/notice/application/port/in/dto/NoticeRangeLookupResult.java
new file mode 100644
index 00000000..8a43c71a
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/notice/application/port/in/dto/NoticeRangeLookupResult.java
@@ -0,0 +1,11 @@
+package com.kustacks.kuring.notice.application.port.in.dto;
+
+public record NoticeRangeLookupResult(
+ String articleId,
+ String postedDate,
+ String url,
+ String subject,
+ String category,
+ Boolean important
+){
+}
diff --git a/src/main/java/com/kustacks/kuring/notice/application/port/out/NoticeCommandPort.java b/src/main/java/com/kustacks/kuring/notice/application/port/out/NoticeCommandPort.java
new file mode 100644
index 00000000..df836350
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/notice/application/port/out/NoticeCommandPort.java
@@ -0,0 +1,16 @@
+package com.kustacks.kuring.notice.application.port.out;
+
+import com.kustacks.kuring.notice.domain.CategoryName;
+import com.kustacks.kuring.notice.domain.DepartmentName;
+import com.kustacks.kuring.notice.domain.DepartmentNotice;
+import com.kustacks.kuring.notice.domain.Notice;
+
+import java.util.List;
+
+public interface NoticeCommandPort {
+
+ void saveAllCategoryNotices(List notices);
+ void saveAllDepartmentNotices(List departmentNotices);
+ void deleteAllByIdsAndCategory(CategoryName categoryName, List articleIds);
+ void deleteAllByIdsAndDepartment(DepartmentName departmentName, List articleIds);
+}
diff --git a/src/main/java/com/kustacks/kuring/notice/application/port/out/NoticeQueryPort.java b/src/main/java/com/kustacks/kuring/notice/application/port/out/NoticeQueryPort.java
new file mode 100644
index 00000000..925393f5
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/notice/application/port/out/NoticeQueryPort.java
@@ -0,0 +1,31 @@
+package com.kustacks.kuring.notice.application.port.out;
+
+import com.kustacks.kuring.notice.application.port.out.dto.NoticeDto;
+import com.kustacks.kuring.notice.application.port.out.dto.NoticeSearchDto;
+import com.kustacks.kuring.notice.domain.CategoryName;
+import com.kustacks.kuring.notice.domain.DepartmentName;
+import com.kustacks.kuring.user.application.port.out.dto.BookmarkDto;
+import org.springframework.data.domain.Pageable;
+
+import java.util.List;
+
+public interface NoticeQueryPort {
+
+ List findNoticesByCategoryWithOffset(CategoryName categoryName, Pageable pageable);
+
+ List findAllByKeywords(List containedNames);
+
+ List findNormalArticleIdsByCategory(CategoryName categoryName);
+
+ List findImportantNoticesByDepartment(DepartmentName departmentName);
+
+ List findNormalNoticesByDepartmentWithOffset(DepartmentName departmentName, Pageable pageable);
+
+ List findImportantArticleIdsByDepartment(DepartmentName departmentNameEnum);
+
+ List findNormalArticleIdsByDepartment(DepartmentName departmentNameEnum);
+
+ List findAllByBookmarkIds(List ids);
+
+ Long count();
+}
diff --git a/src/main/java/com/kustacks/kuring/notice/common/dto/NoticeDto.java b/src/main/java/com/kustacks/kuring/notice/application/port/out/dto/NoticeDto.java
similarity index 95%
rename from src/main/java/com/kustacks/kuring/notice/common/dto/NoticeDto.java
rename to src/main/java/com/kustacks/kuring/notice/application/port/out/dto/NoticeDto.java
index f85b8591..28fd5a39 100644
--- a/src/main/java/com/kustacks/kuring/notice/common/dto/NoticeDto.java
+++ b/src/main/java/com/kustacks/kuring/notice/application/port/out/dto/NoticeDto.java
@@ -1,4 +1,4 @@
-package com.kustacks.kuring.notice.common.dto;
+package com.kustacks.kuring.notice.application.port.out.dto;
import com.querydsl.core.annotations.QueryProjection;
import lombok.AccessLevel;
diff --git a/src/main/java/com/kustacks/kuring/notice/common/dto/NoticeSearchDto.java b/src/main/java/com/kustacks/kuring/notice/application/port/out/dto/NoticeSearchDto.java
similarity index 94%
rename from src/main/java/com/kustacks/kuring/notice/common/dto/NoticeSearchDto.java
rename to src/main/java/com/kustacks/kuring/notice/application/port/out/dto/NoticeSearchDto.java
index cdb8ff2f..d986752a 100644
--- a/src/main/java/com/kustacks/kuring/notice/common/dto/NoticeSearchDto.java
+++ b/src/main/java/com/kustacks/kuring/notice/application/port/out/dto/NoticeSearchDto.java
@@ -1,4 +1,4 @@
-package com.kustacks.kuring.notice.common.dto;
+package com.kustacks.kuring.notice.application.port.out.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.querydsl.core.annotations.QueryProjection;
diff --git a/src/main/java/com/kustacks/kuring/notice/application/service/NoticeQueryService.java b/src/main/java/com/kustacks/kuring/notice/application/service/NoticeQueryService.java
new file mode 100644
index 00000000..a6544415
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/notice/application/service/NoticeQueryService.java
@@ -0,0 +1,163 @@
+package com.kustacks.kuring.notice.application.service;
+
+import com.kustacks.kuring.common.annotation.UseCase;
+import com.kustacks.kuring.common.exception.InternalLogicException;
+import com.kustacks.kuring.common.exception.NotFoundException;
+import com.kustacks.kuring.common.exception.code.ErrorCode;
+import com.kustacks.kuring.notice.application.port.in.NoticeQueryUseCase;
+import com.kustacks.kuring.notice.application.port.in.dto.*;
+import com.kustacks.kuring.notice.application.port.out.NoticeQueryPort;
+import com.kustacks.kuring.notice.application.port.out.dto.NoticeDto;
+import com.kustacks.kuring.notice.domain.CategoryName;
+import com.kustacks.kuring.notice.domain.DepartmentName;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static com.kustacks.kuring.notice.domain.CategoryName.DEPARTMENT;
+
+@UseCase
+@Transactional(readOnly = true)
+public class NoticeQueryService implements NoticeQueryUseCase {
+
+ private static final String SPACE_REGEX = "[\\s+]";
+ private final NoticeQueryPort noticeQueryPort;
+ private final List supportedCategoryNameList;
+ private final List supportedDepartmentNameList;
+
+ public NoticeQueryService(NoticeQueryPort noticeQueryPort) {
+ this.noticeQueryPort = noticeQueryPort;
+ this.supportedCategoryNameList = Arrays.asList(CategoryName.values());
+ this.supportedDepartmentNameList = Arrays.asList(DepartmentName.values());
+ }
+
+ @Override
+ public List getNotices(NoticeRangeLookupCommand command) {
+ if (isDepartmentSearchRequest(command.type(), command.department())) {
+ return getDepartmentNoticeRangeLookup(command);
+ }
+
+ return getNoticeRangeLookup(command);
+ }
+
+ @Override
+ public List findAllNoticeByContent(String content) {
+ String[] splitedKeywords = splitBySpace(content);
+
+ List keywords = noticeCategoryNameConvertEnglish(splitedKeywords);
+
+ return noticeQueryPort.findAllByKeywords(keywords)
+ .stream()
+ .map(dto -> new NoticeContentSearchResult(
+ dto.getArticleId(),
+ dto.getPostedDate(),
+ dto.getSubject(),
+ dto.getCategoryName(),
+ dto.getBaseUrl()
+ ))
+ .toList();
+ }
+
+ @Override
+ public List lookupSupportedCategories() {
+ return supportedCategoryNameList.stream()
+ .map(NoticeCategoryNameResult::from)
+ .toList();
+ }
+
+ @Override
+ public List lookupSupportedDepartments() {
+ return convertDepartmentNameDtos(supportedDepartmentNameList);
+ }
+
+ private List getNoticeRangeLookup(NoticeRangeLookupCommand command) {
+ String categoryName = convertShortNameIntoLongName(command.type());
+ if (isDepartment(categoryName)) {
+ throw new InternalLogicException(ErrorCode.API_INVALID_PARAM);
+ }
+
+ return noticeQueryPort
+ .findNoticesByCategoryWithOffset(
+ CategoryName.fromStringName(categoryName),
+ PageRequest.of(command.page(), command.size())
+ ).stream()
+ .map(NoticeQueryService::convertPortResult)
+ .toList();
+ }
+
+ private List getDepartmentNoticeRangeLookup(NoticeRangeLookupCommand command) {
+ DepartmentName departmentName = DepartmentName.fromHostPrefix(command.department());
+
+ if (command.isImportant()) {
+ return noticeQueryPort
+ .findImportantNoticesByDepartment(departmentName)
+ .stream()
+ .map(NoticeQueryService::convertPortResult)
+ .toList();
+ }
+
+ return noticeQueryPort
+ .findNormalNoticesByDepartmentWithOffset(
+ departmentName,
+ PageRequest.of(command.page(), command.size())
+ ).stream()
+ .map(NoticeQueryService::convertPortResult)
+ .toList();
+ }
+
+ private List convertDepartmentNameDtos(List departmentNames) {
+ return departmentNames.stream()
+ .filter(dn -> !dn.equals(DepartmentName.BIO_SCIENCE))
+ .filter(dn -> !dn.equals(DepartmentName.COMM_DESIGN))
+ .map(NoticeDepartmentNameResult::from)
+ .toList();
+ }
+
+ private boolean isDepartmentSearchRequest(String type, String department) {
+ return type.equals("dep") && !department.isEmpty();
+ }
+
+ private boolean isDepartment(String categoryName) {
+ return DEPARTMENT.isSameName(categoryName);
+ }
+
+ private String[] splitBySpace(String content) {
+ return content.trim().split(SPACE_REGEX);
+ }
+
+ private List noticeCategoryNameConvertEnglish(String[] splitedKeywords) {
+ return Arrays.stream(splitedKeywords)
+ .map(this::convertEnglish)
+ .toList();
+ }
+
+ private String convertEnglish(String keyword) {
+ for (CategoryName categoryName : supportedCategoryNameList) {
+ if (categoryName.isSameKorName(keyword)) {
+ return categoryName.getName();
+ }
+ }
+ return keyword;
+ }
+
+ private String convertShortNameIntoLongName(String typeShortName) {
+ return supportedCategoryNameList.stream()
+ .filter(categoryName -> categoryName.isSameShortName(typeShortName))
+ .findFirst()
+ .map(CategoryName::getName)
+ .orElseThrow(() -> new NotFoundException(ErrorCode.API_NOTICE_NOT_EXIST_CATEGORY));
+ }
+
+ public static NoticeRangeLookupResult convertPortResult(NoticeDto dto) {
+ return new NoticeRangeLookupResult(
+ dto.getArticleId(),
+ dto.getPostedDate(),
+ dto.getUrl(),
+ dto.getSubject(),
+ dto.getCategory(),
+ dto.getImportant()
+ );
+ }
+}
diff --git a/src/main/java/com/kustacks/kuring/notice/business/NoticeService.java b/src/main/java/com/kustacks/kuring/notice/business/NoticeService.java
deleted file mode 100644
index 59095dd7..00000000
--- a/src/main/java/com/kustacks/kuring/notice/business/NoticeService.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package com.kustacks.kuring.notice.business;
-
-import com.kustacks.kuring.common.exception.InternalLogicException;
-import com.kustacks.kuring.common.exception.NotFoundException;
-import com.kustacks.kuring.common.exception.code.ErrorCode;
-import com.kustacks.kuring.notice.common.dto.NoticeDto;
-import com.kustacks.kuring.notice.common.dto.NoticeSearchDto;
-import com.kustacks.kuring.notice.domain.CategoryName;
-import com.kustacks.kuring.notice.domain.DepartmentName;
-import com.kustacks.kuring.notice.domain.NoticeRepository;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.data.domain.PageRequest;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.util.Arrays;
-import java.util.List;
-
-@Service
-@Transactional(readOnly = true)
-public class NoticeService {
-
- private final NoticeRepository noticeRepository;
- private final CategoryName[] supportedCategoryNameList;
- private final DepartmentName[] supportedDepartmentNameList;
- private final String SPACE_REGEX = "[\\s+]";
-
- @Value("${notice.normal-base-url}")
- private String normalBaseUrl;
-
- @Value("${notice.library-base-url}")
- private String libraryBaseUrl;
-
- public NoticeService(NoticeRepository noticeRepository) {
- this.noticeRepository = noticeRepository;
- this.supportedCategoryNameList = CategoryName.values();
- this.supportedDepartmentNameList = DepartmentName.values();
- }
-
- public List lookupSupportedDepartments() {
- return List.of(supportedDepartmentNameList);
- }
-
- public List getNotices(String type, String department, Boolean important, int page, int size) {
- if (isDepartmentSearchRequest(type, department)) {
- DepartmentName departmentName = DepartmentName.fromHostPrefix(department);
-
- if (Boolean.TRUE.equals(important)) {
- return noticeRepository.findImportantNoticesByDepartment(departmentName);
- } else {
- return noticeRepository.findNormalNoticesByDepartmentWithOffset(departmentName, PageRequest.of(page, size));
- }
- }
-
- String categoryName = convertShortNameIntoLongName(type);
- if (isDepartment(categoryName)) {
- throw new InternalLogicException(ErrorCode.API_INVALID_PARAM);
- }
-
- return noticeRepository.findNoticesByCategoryWithOffset(CategoryName.fromStringName(categoryName), PageRequest.of(page, size));
- }
-
- public List findAllNoticeByContent(String content) {
- String[] splitedKeywords = splitBySpace(content);
-
- List keywords = noticeCategoryNameConvertEnglish(splitedKeywords);
-
- return noticeRepository.findAllByKeywords(keywords);
- }
-
- private boolean isDepartmentSearchRequest(String type, String department) {
- return type.equals("dep") && !department.isEmpty();
- }
-
- private boolean isDepartment(String categoryName) {
- return CategoryName.DEPARTMENT.isSameName(categoryName);
- }
-
- private String[] splitBySpace(String content) {
- return content.trim().split(SPACE_REGEX);
- }
-
- private List noticeCategoryNameConvertEnglish(String[] splitedKeywords) {
- return Arrays.stream(splitedKeywords)
- .map(this::convertEnglish)
- .toList();
- }
-
- private String convertEnglish(String keyword) {
- for (CategoryName categoryName : supportedCategoryNameList) {
- if (categoryName.isSameKorName(keyword)) {
- return categoryName.getName();
- }
- }
- return keyword;
- }
-
- private String convertShortNameIntoLongName(String typeShortName) {
- return Arrays.stream(supportedCategoryNameList)
- .filter(categoryName -> categoryName.isSameShortName(typeShortName))
- .findFirst()
- .map(CategoryName::getName)
- .orElseThrow(() -> new NotFoundException(ErrorCode.API_NOTICE_NOT_EXIST_CATEGORY));
- }
-
- private String convertBaseUrl(String categoryName) {
- return CategoryName.LIBRARY.isSameName(categoryName) ? libraryBaseUrl : normalBaseUrl;
- }
-}
diff --git a/src/main/java/com/kustacks/kuring/notice/common/OffsetBasedPageRequest.java b/src/main/java/com/kustacks/kuring/notice/common/OffsetBasedPageRequest.java
deleted file mode 100644
index 790e2f7f..00000000
--- a/src/main/java/com/kustacks/kuring/notice/common/OffsetBasedPageRequest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package com.kustacks.kuring.notice.common;
-
-import org.springframework.data.domain.Pageable;
-import org.springframework.data.domain.Sort;
-
-public class OffsetBasedPageRequest implements Pageable {
- private int limit;
- private int offset;
-
- public OffsetBasedPageRequest(int offset, int limit) {
- if (offset < 0) {
- throw new IllegalArgumentException("Offset must not be less than zero!");
- }
-
- if (limit < 1) {
- throw new IllegalArgumentException("Limit must not be less than zero!");
- }
-
- this.offset = offset;
- this.limit = limit;
- }
-
- @Override
- public int getPageNumber() {
- return 0;
- }
-
- @Override
- public int getPageSize() {
- return this.limit;
- }
-
- @Override
- public long getOffset() {
- return this.offset;
- }
-
- @Override
- public Sort getSort() {
- return null;
- }
-
- @Override
- public Pageable next() {
- return null;
- }
-
- @Override
- public Pageable previousOrFirst() {
- return this;
- }
-
- @Override
- public Pageable first() {
- return this;
- }
-
- @Override
- public Pageable withPage(int pageNumber) {
- return null;
- }
-
- @Override
- public boolean hasPrevious() {
- return false;
- }
-}
diff --git a/src/main/java/com/kustacks/kuring/notice/common/dto/CategoryNameDto.java b/src/main/java/com/kustacks/kuring/notice/common/dto/CategoryNameDto.java
deleted file mode 100644
index 2d7caccf..00000000
--- a/src/main/java/com/kustacks/kuring/notice/common/dto/CategoryNameDto.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.kustacks.kuring.notice.common.dto;
-
-import com.kustacks.kuring.notice.domain.CategoryName;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-
-@Getter
-@NoArgsConstructor
-public class CategoryNameDto {
-
- private String name;
- private String hostPrefix;
- private String korName;
-
- public CategoryNameDto(String name, String hostPrefix, String korName) {
- this.name = name;
- this.hostPrefix = hostPrefix;
- this.korName = korName;
- }
-
- public static CategoryNameDto from(CategoryName name) {
- return new CategoryNameDto(name.getName(), name.getShortName(), name.getKorName());
- }
-}
diff --git a/src/main/java/com/kustacks/kuring/notice/common/dto/DepartmentNameDto.java b/src/main/java/com/kustacks/kuring/notice/common/dto/DepartmentNameDto.java
deleted file mode 100644
index d0e912c5..00000000
--- a/src/main/java/com/kustacks/kuring/notice/common/dto/DepartmentNameDto.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.kustacks.kuring.notice.common.dto;
-
-import com.kustacks.kuring.notice.domain.DepartmentName;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-
-@Getter
-@NoArgsConstructor
-public class DepartmentNameDto {
-
- private String name;
- private String hostPrefix;
- private String korName;
-
- private DepartmentNameDto(String name, String hostPrefix, String korName) {
- this.name = name;
- this.hostPrefix = hostPrefix;
- this.korName = korName;
- }
-
- public static DepartmentNameDto from(DepartmentName name) {
- return new DepartmentNameDto(name.getName(), name.getHostPrefix(), name.getKorName());
- }
-}
diff --git a/src/main/java/com/kustacks/kuring/notice/common/dto/NoticeListResponse.java b/src/main/java/com/kustacks/kuring/notice/common/dto/NoticeListResponse.java
deleted file mode 100644
index 2fb92261..00000000
--- a/src/main/java/com/kustacks/kuring/notice/common/dto/NoticeListResponse.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.kustacks.kuring.notice.common.dto;
-
-import com.kustacks.kuring.common.dto.ResponseDto;
-import lombok.AccessLevel;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-
-import java.util.List;
-
-@Getter
-@NoArgsConstructor(access = AccessLevel.PROTECTED)
-public class NoticeListResponse extends ResponseDto {
-
- private String baseUrl;
-
- private List noticeList;
-
- public NoticeListResponse(String baseUrl, List noticeList) {
- super(true, "성공", 200);
- this.baseUrl = baseUrl;
- this.noticeList = noticeList;
- }
-}
diff --git a/src/main/java/com/kustacks/kuring/notice/common/dto/NoticeLookupResponse.java b/src/main/java/com/kustacks/kuring/notice/common/dto/NoticeLookupResponse.java
deleted file mode 100644
index b73f9620..00000000
--- a/src/main/java/com/kustacks/kuring/notice/common/dto/NoticeLookupResponse.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.kustacks.kuring.notice.common.dto;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-
-import java.util.List;
-
-@Getter
-@NoArgsConstructor
-@AllArgsConstructor
-public class NoticeLookupResponse {
-
- private List noticeList;
-}
diff --git a/src/main/java/com/kustacks/kuring/notice/domain/NoticeRepository.java b/src/main/java/com/kustacks/kuring/notice/domain/NoticeRepository.java
deleted file mode 100644
index a15d69ca..00000000
--- a/src/main/java/com/kustacks/kuring/notice/domain/NoticeRepository.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.kustacks.kuring.notice.domain;
-
-import org.springframework.data.jpa.repository.JpaRepository;
-
-public interface NoticeRepository extends JpaRepository, NoticeQueryRepository {
-}
diff --git a/src/main/java/com/kustacks/kuring/notice/facade/NoticeQueryFacade.java b/src/main/java/com/kustacks/kuring/notice/facade/NoticeQueryFacade.java
deleted file mode 100644
index 6f4617d2..00000000
--- a/src/main/java/com/kustacks/kuring/notice/facade/NoticeQueryFacade.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.kustacks.kuring.notice.facade;
-
-import com.kustacks.kuring.notice.business.NoticeService;
-import com.kustacks.kuring.notice.common.dto.*;
-import com.kustacks.kuring.notice.domain.CategoryName;
-import com.kustacks.kuring.notice.domain.DepartmentName;
-import lombok.RequiredArgsConstructor;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.util.List;
-import java.util.stream.Stream;
-
-@Service
-@Transactional(readOnly = true)
-@RequiredArgsConstructor
-public class NoticeQueryFacade {
-
- private final NoticeService noticeService;
-
- public List getNotices(String type, String department, Boolean important, int page, int size) {
- return noticeService.getNotices(type, department, important, page, size);
- }
-
- public NoticeLookupResponse searchNoticeByContent(String content) {
- List noticeDtoList = noticeService.findAllNoticeByContent(content);
- return new NoticeLookupResponse(noticeDtoList);
- }
-
- public List getSupportedCategories() {
- return Stream.of(CategoryName.values())
- .map(CategoryNameDto::from)
- .toList();
- }
-
- public List getSupportedDepartments() {
- List departmentNames = noticeService.lookupSupportedDepartments();
- return convertDepartmentNameDtos(departmentNames);
- }
-
- private List convertDepartmentNameDtos(List departmentNames) {
- return departmentNames.stream()
- .filter(dn -> !dn.equals(DepartmentName.BIO_SCIENCE))
- .filter(dn -> !dn.equals(DepartmentName.COMM_DESIGN))
- .map(DepartmentNameDto::from)
- .toList();
- }
-}
diff --git a/src/main/java/com/kustacks/kuring/notice/presentation/NoticeQueryApiV2.java b/src/main/java/com/kustacks/kuring/notice/presentation/NoticeQueryApiV2.java
deleted file mode 100644
index 6a3626ec..00000000
--- a/src/main/java/com/kustacks/kuring/notice/presentation/NoticeQueryApiV2.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.kustacks.kuring.notice.presentation;
-
-import com.kustacks.kuring.common.dto.BaseResponse;
-import com.kustacks.kuring.notice.common.dto.CategoryNameDto;
-import com.kustacks.kuring.notice.common.dto.DepartmentNameDto;
-import com.kustacks.kuring.notice.common.dto.NoticeDto;
-import com.kustacks.kuring.notice.common.dto.NoticeLookupResponse;
-import com.kustacks.kuring.notice.facade.NoticeQueryFacade;
-import lombok.RequiredArgsConstructor;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
-import org.springframework.validation.annotation.Validated;
-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 javax.validation.constraints.Max;
-import javax.validation.constraints.Min;
-import javax.validation.constraints.NotBlank;
-import java.util.List;
-
-import static com.kustacks.kuring.common.dto.ResponseCodeAndMessages.CATEGORY_SEARCH_SUCCESS;
-import static com.kustacks.kuring.common.dto.ResponseCodeAndMessages.DEPARTMENTS_SEARCH_SUCCESS;
-import static com.kustacks.kuring.common.dto.ResponseCodeAndMessages.NOTICE_SEARCH_SUCCESS;
-
-@Validated
-@RestController
-@RequiredArgsConstructor
-@RequestMapping(value = "/api/v2/notices", produces = MediaType.APPLICATION_JSON_VALUE)
-public class NoticeQueryApiV2 {
-
- private final NoticeQueryFacade noticeQueryFacade;
-
- @GetMapping
- public ResponseEntity>> getNotices(
- @RequestParam(name = "type") String type,
- @RequestParam(name = "department", required = false) String department,
- @RequestParam(name = "important", required = false) Boolean important,
- @RequestParam(name = "page") @Min(0) int page,
- @RequestParam(name = "size") @Min(1) @Max(30) int size) {
- List searchResults = noticeQueryFacade.getNotices(type, department, important, page, size);
- return ResponseEntity.ok().body(new BaseResponse<>(NOTICE_SEARCH_SUCCESS, searchResults));
- }
-
- @GetMapping("/search")
- public ResponseEntity> searchNotice(@NotBlank @RequestParam String content) {
- NoticeLookupResponse response = noticeQueryFacade.searchNoticeByContent(content);
- return ResponseEntity.ok().body(new BaseResponse<>(NOTICE_SEARCH_SUCCESS, response));
- }
-
- @GetMapping("/categories")
- public ResponseEntity>> getSupportedCategories() {
- List categoryNames = noticeQueryFacade.getSupportedCategories();
- return ResponseEntity.ok().body(new BaseResponse<>(CATEGORY_SEARCH_SUCCESS, categoryNames));
- }
-
- @GetMapping("/departments")
- public ResponseEntity>> getSupportedDepartments() {
- List departmentNames = noticeQueryFacade.getSupportedDepartments();
- return ResponseEntity.ok().body(new BaseResponse<>(DEPARTMENTS_SEARCH_SUCCESS, departmentNames));
- }
-}
diff --git a/src/main/java/com/kustacks/kuring/staff/adapter/in/web/StaffQueryApiV2.java b/src/main/java/com/kustacks/kuring/staff/adapter/in/web/StaffQueryApiV2.java
new file mode 100644
index 00000000..ef838391
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/staff/adapter/in/web/StaffQueryApiV2.java
@@ -0,0 +1,39 @@
+package com.kustacks.kuring.staff.adapter.in.web;
+
+import static com.kustacks.kuring.common.dto.ResponseCodeAndMessages.STAFF_SEARCH_SUCCESS;
+
+import com.kustacks.kuring.common.annotation.RestWebAdapter;
+import com.kustacks.kuring.common.dto.BaseResponse;
+import com.kustacks.kuring.staff.adapter.in.web.dto.StaffSearchListResponse;
+import com.kustacks.kuring.staff.adapter.in.web.dto.StaffSearchResponse;
+import com.kustacks.kuring.staff.application.port.in.StaffQueryUseCase;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import java.util.List;
+import javax.validation.constraints.NotBlank;
+import lombok.RequiredArgsConstructor;
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@Tag(name = "Staff-Query", description = "교직원 정보 조회")
+@Validated
+@RequiredArgsConstructor
+@RestWebAdapter(path = "/api/v2/staffs")
+public class StaffQueryApiV2 {
+
+ private final StaffQueryUseCase staffQueryUseCase;
+
+ @Operation(summary = "교직원 검색", description = "교직원 이름을 통하여 검색합니다")
+ @GetMapping("/search")
+ public ResponseEntity> searchStaff(@NotBlank @RequestParam String content) {
+ List staffSearchResults = staffQueryUseCase.findAllStaffByContent(content)
+ .stream()
+ .map(StaffSearchResponse::from)
+ .toList();
+
+ StaffSearchListResponse response = new StaffSearchListResponse(staffSearchResults);
+ return ResponseEntity.ok().body(new BaseResponse<>(STAFF_SEARCH_SUCCESS, response));
+ }
+}
diff --git a/src/main/java/com/kustacks/kuring/staff/adapter/in/web/dto/StaffSearchListResponse.java b/src/main/java/com/kustacks/kuring/staff/adapter/in/web/dto/StaffSearchListResponse.java
new file mode 100644
index 00000000..48e38e28
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/staff/adapter/in/web/dto/StaffSearchListResponse.java
@@ -0,0 +1,8 @@
+package com.kustacks.kuring.staff.adapter.in.web.dto;
+
+import java.util.List;
+
+public record StaffSearchListResponse(
+ List staffList
+) {
+}
diff --git a/src/main/java/com/kustacks/kuring/staff/adapter/in/web/dto/StaffSearchResponse.java b/src/main/java/com/kustacks/kuring/staff/adapter/in/web/dto/StaffSearchResponse.java
new file mode 100644
index 00000000..930aded1
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/staff/adapter/in/web/dto/StaffSearchResponse.java
@@ -0,0 +1,26 @@
+package com.kustacks.kuring.staff.adapter.in.web.dto;
+
+import com.kustacks.kuring.staff.application.port.in.dto.StaffSearchResult;
+
+public record StaffSearchResponse(
+ String name,
+ String major,
+ String lab,
+ String phone,
+ String email,
+ String deptName,
+ String collegeName
+) {
+
+ public static StaffSearchResponse from(StaffSearchResult result) {
+ return new StaffSearchResponse(
+ result.name(),
+ result.major(),
+ result.lab(),
+ result.phone(),
+ result.email(),
+ result.deptName(),
+ result.collegeName()
+ );
+ }
+}
diff --git a/src/main/java/com/kustacks/kuring/staff/adapter/out/persistence/StaffPersistenceAdapter.java b/src/main/java/com/kustacks/kuring/staff/adapter/out/persistence/StaffPersistenceAdapter.java
new file mode 100644
index 00000000..0edfbc8f
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/staff/adapter/out/persistence/StaffPersistenceAdapter.java
@@ -0,0 +1,20 @@
+package com.kustacks.kuring.staff.adapter.out.persistence;
+
+import com.kustacks.kuring.common.annotation.PersistenceAdapter;
+import com.kustacks.kuring.staff.application.port.out.StaffQueryPort;
+import com.kustacks.kuring.staff.application.port.out.dto.StaffSearchDto;
+import lombok.RequiredArgsConstructor;
+
+import java.util.List;
+
+@PersistenceAdapter
+@RequiredArgsConstructor
+public class StaffPersistenceAdapter implements StaffQueryPort {
+
+ private final StaffRepository staffRepository;
+
+ @Override
+ public List findAllByKeywords(List keywords) {
+ return this.staffRepository.findAllByKeywords(keywords);
+ }
+}
diff --git a/src/main/java/com/kustacks/kuring/staff/domain/StaffQueryRepository.java b/src/main/java/com/kustacks/kuring/staff/adapter/out/persistence/StaffQueryRepository.java
similarity index 50%
rename from src/main/java/com/kustacks/kuring/staff/domain/StaffQueryRepository.java
rename to src/main/java/com/kustacks/kuring/staff/adapter/out/persistence/StaffQueryRepository.java
index 447f8d45..a4098c72 100644
--- a/src/main/java/com/kustacks/kuring/staff/domain/StaffQueryRepository.java
+++ b/src/main/java/com/kustacks/kuring/staff/adapter/out/persistence/StaffQueryRepository.java
@@ -1,6 +1,6 @@
-package com.kustacks.kuring.staff.domain;
+package com.kustacks.kuring.staff.adapter.out.persistence;
-import com.kustacks.kuring.staff.common.dto.StaffSearchDto;
+import com.kustacks.kuring.staff.application.port.out.dto.StaffSearchDto;
import java.util.List;
diff --git a/src/main/java/com/kustacks/kuring/staff/domain/StaffQueryRepositoryImpl.java b/src/main/java/com/kustacks/kuring/staff/adapter/out/persistence/StaffQueryRepositoryImpl.java
similarity index 89%
rename from src/main/java/com/kustacks/kuring/staff/domain/StaffQueryRepositoryImpl.java
rename to src/main/java/com/kustacks/kuring/staff/adapter/out/persistence/StaffQueryRepositoryImpl.java
index 7a8271d9..04b0e821 100644
--- a/src/main/java/com/kustacks/kuring/staff/domain/StaffQueryRepositoryImpl.java
+++ b/src/main/java/com/kustacks/kuring/staff/adapter/out/persistence/StaffQueryRepositoryImpl.java
@@ -1,7 +1,7 @@
-package com.kustacks.kuring.staff.domain;
+package com.kustacks.kuring.staff.adapter.out.persistence;
-import com.kustacks.kuring.staff.common.dto.QStaffSearchDto;
-import com.kustacks.kuring.staff.common.dto.StaffSearchDto;
+import com.kustacks.kuring.staff.application.port.out.dto.QStaffSearchDto;
+import com.kustacks.kuring.staff.application.port.out.dto.StaffSearchDto;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
diff --git a/src/main/java/com/kustacks/kuring/staff/domain/StaffRepository.java b/src/main/java/com/kustacks/kuring/staff/adapter/out/persistence/StaffRepository.java
similarity index 71%
rename from src/main/java/com/kustacks/kuring/staff/domain/StaffRepository.java
rename to src/main/java/com/kustacks/kuring/staff/adapter/out/persistence/StaffRepository.java
index 0fc85e56..1db6ca84 100644
--- a/src/main/java/com/kustacks/kuring/staff/domain/StaffRepository.java
+++ b/src/main/java/com/kustacks/kuring/staff/adapter/out/persistence/StaffRepository.java
@@ -1,16 +1,13 @@
-package com.kustacks.kuring.staff.domain;
+package com.kustacks.kuring.staff.adapter.out.persistence;
+import com.kustacks.kuring.staff.domain.Staff;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.stream.Collectors;
public interface StaffRepository extends JpaRepository, StaffQueryRepository {
- default Map findAllMap() {
- return findAll().stream().collect(Collectors.toMap(Staff::getEmail, v -> v));
- }
default Map findByDeptContainingMap(List deptNames) {
@@ -29,6 +26,4 @@ default Map findByDeptContainingMap(List deptNames) {
}
List findByDeptContaining(String deptName);
-
- List findByNameContainingOrDeptContainingOrCollegeContaining(String name, String dept, String college);
}
diff --git a/src/main/java/com/kustacks/kuring/staff/application/port/in/StaffQueryUseCase.java b/src/main/java/com/kustacks/kuring/staff/application/port/in/StaffQueryUseCase.java
new file mode 100644
index 00000000..e669acea
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/staff/application/port/in/StaffQueryUseCase.java
@@ -0,0 +1,9 @@
+package com.kustacks.kuring.staff.application.port.in;
+
+import com.kustacks.kuring.staff.application.port.in.dto.StaffSearchResult;
+
+import java.util.List;
+
+public interface StaffQueryUseCase {
+ List findAllStaffByContent(String content);
+}
diff --git a/src/main/java/com/kustacks/kuring/staff/application/port/in/dto/StaffSearchResult.java b/src/main/java/com/kustacks/kuring/staff/application/port/in/dto/StaffSearchResult.java
new file mode 100644
index 00000000..4d831e16
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/staff/application/port/in/dto/StaffSearchResult.java
@@ -0,0 +1,12 @@
+package com.kustacks.kuring.staff.application.port.in.dto;
+
+public record StaffSearchResult(
+ String name,
+ String major,
+ String lab,
+ String phone,
+ String email,
+ String deptName,
+ String collegeName
+) {
+}
diff --git a/src/main/java/com/kustacks/kuring/staff/application/port/out/StaffQueryPort.java b/src/main/java/com/kustacks/kuring/staff/application/port/out/StaffQueryPort.java
new file mode 100644
index 00000000..fae29c59
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/staff/application/port/out/StaffQueryPort.java
@@ -0,0 +1,9 @@
+package com.kustacks.kuring.staff.application.port.out;
+
+import com.kustacks.kuring.staff.application.port.out.dto.StaffSearchDto;
+
+import java.util.List;
+
+public interface StaffQueryPort {
+ List findAllByKeywords(List keywords);
+}
diff --git a/src/main/java/com/kustacks/kuring/staff/common/dto/StaffSearchDto.java b/src/main/java/com/kustacks/kuring/staff/application/port/out/dto/StaffSearchDto.java
similarity index 92%
rename from src/main/java/com/kustacks/kuring/staff/common/dto/StaffSearchDto.java
rename to src/main/java/com/kustacks/kuring/staff/application/port/out/dto/StaffSearchDto.java
index fef6df3b..7460673f 100644
--- a/src/main/java/com/kustacks/kuring/staff/common/dto/StaffSearchDto.java
+++ b/src/main/java/com/kustacks/kuring/staff/application/port/out/dto/StaffSearchDto.java
@@ -1,4 +1,4 @@
-package com.kustacks.kuring.staff.common.dto;
+package com.kustacks.kuring.staff.application.port.out.dto;
import com.querydsl.core.annotations.QueryProjection;
import lombok.AccessLevel;
diff --git a/src/main/java/com/kustacks/kuring/staff/application/service/StaffQueryService.java b/src/main/java/com/kustacks/kuring/staff/application/service/StaffQueryService.java
new file mode 100644
index 00000000..ec39bb7a
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/staff/application/service/StaffQueryService.java
@@ -0,0 +1,37 @@
+package com.kustacks.kuring.staff.application.service;
+
+import com.kustacks.kuring.staff.application.port.in.StaffQueryUseCase;
+import com.kustacks.kuring.staff.application.port.in.dto.StaffSearchResult;
+import com.kustacks.kuring.staff.application.port.out.StaffQueryPort;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.Arrays;
+import java.util.List;
+
+@Service
+@RequiredArgsConstructor
+public class StaffQueryService implements StaffQueryUseCase {
+
+ private static final String SPACE_REGEX = "[\\s+]";
+ private final StaffQueryPort staffQueryPort;
+
+ public List findAllStaffByContent(String content) {
+ List splitedKeywords = Arrays.asList(splitBySpace(content));
+ return staffQueryPort.findAllByKeywords(splitedKeywords)
+ .stream()
+ .map(dto -> new StaffSearchResult(
+ dto.getName(),
+ dto.getMajor(),
+ dto.getLab(),
+ dto.getPhone(),
+ dto.getEmail(),
+ dto.getDeptName(),
+ dto.getCollegeName()
+ )).toList();
+ }
+
+ private String[] splitBySpace(String content) {
+ return content.trim().split(SPACE_REGEX);
+ }
+}
diff --git a/src/main/java/com/kustacks/kuring/staff/business/StaffService.java b/src/main/java/com/kustacks/kuring/staff/business/StaffService.java
deleted file mode 100644
index 8394dce4..00000000
--- a/src/main/java/com/kustacks/kuring/staff/business/StaffService.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.kustacks.kuring.staff.business;
-
-import com.kustacks.kuring.staff.common.dto.StaffSearchDto;
-import com.kustacks.kuring.staff.domain.Staff;
-import com.kustacks.kuring.staff.domain.StaffRepository;
-import org.springframework.stereotype.Service;
-
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-
-@Service
-public class StaffService {
-
- private final String SPACE_REGEX = "[\\s+]";
-
- private final StaffRepository staffRepository;
-
- public StaffService(StaffRepository staffRepository) {
- this.staffRepository = staffRepository;
- }
-
-
- public List handleSearchRequest(String keywords) {
-
- keywords = keywords.trim();
- String[] splitedKeywords = keywords.split("[\\s+]");
-
- return getStaffsByNameOrDeptOrCollege(splitedKeywords);
- }
-
- public List findAllStaffByContent(String content) {
- List splitedKeywords = Arrays.asList(splitBySpace(content));
-
- return staffRepository.findAllByKeywords(splitedKeywords);
- }
-
- private List getStaffsByNameOrDeptOrCollege(String[] keywords) {
-
- List staffs = staffRepository.findByNameContainingOrDeptContainingOrCollegeContaining(keywords[0], keywords[0], keywords[0]);
- Iterator iterator = staffs.iterator();
-
- for(int i=1; i staffList;
-}
diff --git a/src/main/java/com/kustacks/kuring/staff/presentation/StaffQueryApiV2.java b/src/main/java/com/kustacks/kuring/staff/presentation/StaffQueryApiV2.java
deleted file mode 100644
index 77d3293f..00000000
--- a/src/main/java/com/kustacks/kuring/staff/presentation/StaffQueryApiV2.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.kustacks.kuring.staff.presentation;
-
-import com.kustacks.kuring.common.dto.BaseResponse;
-import com.kustacks.kuring.staff.business.StaffService;
-import com.kustacks.kuring.staff.common.dto.StaffLookupResponse;
-import com.kustacks.kuring.staff.common.dto.StaffSearchDto;
-import lombok.RequiredArgsConstructor;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
-import org.springframework.validation.annotation.Validated;
-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 javax.validation.constraints.NotBlank;
-import java.util.List;
-
-import static com.kustacks.kuring.common.dto.ResponseCodeAndMessages.STAFF_SEARCH_SUCCESS;
-
-@Validated
-@RestController
-@RequiredArgsConstructor
-@RequestMapping(value = "/api/v2", produces = MediaType.APPLICATION_JSON_VALUE)
-public class StaffQueryApiV2 {
-
- private final StaffService staffService;
-
- @GetMapping("/staffs/search")
- public ResponseEntity> searchStaff(@NotBlank @RequestParam String content) {
- List staffDtoList = staffService.findAllStaffByContent(content);
- StaffLookupResponse response = new StaffLookupResponse(staffDtoList);
- return ResponseEntity.ok().body(new BaseResponse<>(STAFF_SEARCH_SUCCESS, response));
- }
-}
diff --git a/src/main/java/com/kustacks/kuring/user/adapter/in/web/UserCommandApiV2.java b/src/main/java/com/kustacks/kuring/user/adapter/in/web/UserCommandApiV2.java
new file mode 100644
index 00000000..febff789
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/user/adapter/in/web/UserCommandApiV2.java
@@ -0,0 +1,86 @@
+package com.kustacks.kuring.user.adapter.in.web;
+
+import static com.kustacks.kuring.common.dto.ResponseCodeAndMessages.BOOKMAKR_SAVE_SUCCESS;
+import static com.kustacks.kuring.common.dto.ResponseCodeAndMessages.CATEGORY_SUBSCRIBE_SUCCESS;
+import static com.kustacks.kuring.common.dto.ResponseCodeAndMessages.DEPARTMENTS_SUBSCRIBE_SUCCESS;
+import static com.kustacks.kuring.common.dto.ResponseCodeAndMessages.FEEDBACK_SAVE_SUCCESS;
+
+import com.kustacks.kuring.common.annotation.RestWebAdapter;
+import com.kustacks.kuring.common.dto.BaseResponse;
+import com.kustacks.kuring.user.adapter.in.web.dto.UserBookmarkRequest;
+import com.kustacks.kuring.user.adapter.in.web.dto.UserCategoriesSubscribeRequest;
+import com.kustacks.kuring.user.adapter.in.web.dto.UserDepartmentsSubscribeRequest;
+import com.kustacks.kuring.user.adapter.in.web.dto.UserFeedbackRequest;
+import com.kustacks.kuring.user.application.port.in.UserCommandUseCase;
+import com.kustacks.kuring.user.application.port.in.dto.UserBookmarkCommand;
+import com.kustacks.kuring.user.application.port.in.dto.UserCategoriesSubscribeCommand;
+import com.kustacks.kuring.user.application.port.in.dto.UserDepartmentsSubscribeCommand;
+import com.kustacks.kuring.user.application.port.in.dto.UserFeedbackCommand;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.security.SecurityRequirement;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import javax.validation.Valid;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestHeader;
+
+@Tag(name = "User-Command", description = "사용자가 주체가 되는 정보 수정")
+@Slf4j
+@Validated
+@RequiredArgsConstructor
+@RestWebAdapter(path = "/api/v2/users")
+class UserCommandApiV2 {
+
+ private static final String USER_TOKEN_HEADER_KEY = "User-Token";
+
+ private final UserCommandUseCase userCommandUseCase;
+
+ @Operation(summary = "사용자 카테고리 수정", description = "사용자가 구독한 카테고리 목록을 추가, 삭제 합니다")
+ @SecurityRequirement(name = "User-Token")
+ @PostMapping(value = "/subscriptions/categories", consumes = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity> editUserSubscribeCategories(
+ @Valid @RequestBody UserCategoriesSubscribeRequest request,
+ @RequestHeader(USER_TOKEN_HEADER_KEY) String id
+ ) {
+ userCommandUseCase.editSubscribeCategories(new UserCategoriesSubscribeCommand(id, request.categories()));
+ return ResponseEntity.ok().body(new BaseResponse<>(CATEGORY_SUBSCRIBE_SUCCESS, null));
+ }
+
+ @Operation(summary = "사용자 학과 수정", description = "사용자가 구독한 학과 목록을 추가, 삭제 합니다")
+ @SecurityRequirement(name = "User-Token")
+ @PostMapping(value = "/subscriptions/departments", consumes = MediaType.APPLICATION_JSON_VALUE)
+ public ResponseEntity> editUserSubscribeDepartments(
+ @Valid @RequestBody UserDepartmentsSubscribeRequest request,
+ @RequestHeader(USER_TOKEN_HEADER_KEY) String id
+ ) {
+ userCommandUseCase.editSubscribeDepartments(new UserDepartmentsSubscribeCommand(id, request.departments()));
+ return ResponseEntity.ok().body(new BaseResponse<>(DEPARTMENTS_SUBSCRIBE_SUCCESS, null));
+ }
+
+ @Operation(summary = "사용자 피드백 작성", description = "사용자가 피드백을 작성하여 저장합니다")
+ @SecurityRequirement(name = "User-Token")
+ @PostMapping("/feedbacks")
+ public ResponseEntity> saveFeedback(
+ @Valid @RequestBody UserFeedbackRequest request,
+ @RequestHeader(USER_TOKEN_HEADER_KEY) String id
+ ) {
+ userCommandUseCase.saveFeedback(new UserFeedbackCommand(id, request.content()));
+ return ResponseEntity.ok().body(new BaseResponse<>(FEEDBACK_SAVE_SUCCESS, null));
+ }
+
+ @Operation(summary = "사용자 북마크 작성", description = "사용자가 원하는 공지를 북마크 하여 저장합니다")
+ @SecurityRequirement(name = "User-Token")
+ @PostMapping("/bookmarks")
+ public ResponseEntity> saveBookmark(
+ @Valid @RequestBody UserBookmarkRequest request,
+ @RequestHeader(USER_TOKEN_HEADER_KEY) String id
+ ) {
+ userCommandUseCase.saveBookmark(new UserBookmarkCommand(id, request.articleId()));
+ return ResponseEntity.ok().body(new BaseResponse<>(BOOKMAKR_SAVE_SUCCESS, null));
+ }
+}
diff --git a/src/main/java/com/kustacks/kuring/user/adapter/in/web/UserQueryApiV2.java b/src/main/java/com/kustacks/kuring/user/adapter/in/web/UserQueryApiV2.java
new file mode 100644
index 00000000..e7993daf
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/user/adapter/in/web/UserQueryApiV2.java
@@ -0,0 +1,76 @@
+package com.kustacks.kuring.user.adapter.in.web;
+
+import static com.kustacks.kuring.common.dto.ResponseCodeAndMessages.BOOKMARK_LOOKUP_SUCCESS;
+import static com.kustacks.kuring.common.dto.ResponseCodeAndMessages.CATEGORY_USER_SUBSCRIBES_LOOKUP_SUCCESS;
+import static com.kustacks.kuring.common.dto.ResponseCodeAndMessages.DEPARTMENTS_USER_SUBSCRIBES_LOOKUP_SUCCESS;
+
+import com.kustacks.kuring.common.annotation.RestWebAdapter;
+import com.kustacks.kuring.common.dto.BaseResponse;
+import com.kustacks.kuring.user.adapter.in.web.dto.UserBookmarkResponse;
+import com.kustacks.kuring.user.adapter.in.web.dto.UserCategoryNameResponse;
+import com.kustacks.kuring.user.adapter.in.web.dto.UserDepartmentNameResponse;
+import com.kustacks.kuring.user.application.port.in.UserQueryUseCase;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.security.SecurityRequirement;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import java.util.List;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.ResponseEntity;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestHeader;
+
+@Tag(name = "User-Query", description = "사용자가 주체가 되는 정보 조회")
+@Slf4j
+@Validated
+@RequiredArgsConstructor
+@RestWebAdapter(path = "/api/v2/users")
+class UserQueryApiV2 {
+
+ private static final String USER_TOKEN_HEADER_KEY = "User-Token";
+
+ private final UserQueryUseCase userQueryUseCase;
+
+ @Operation(summary = "사용자 카테고리 조회", description = "사용자가 구독한 카테고리 목록을 조회합니다")
+ @SecurityRequirement(name = "User-Token")
+ @GetMapping("/subscriptions/categories")
+ public ResponseEntity>> lookupUserSubscribeCategories(
+ @RequestHeader(USER_TOKEN_HEADER_KEY) String userToken
+ ) {
+ List responses = userQueryUseCase.lookupSubscribeCategories(userToken)
+ .stream()
+ .map(UserCategoryNameResponse::from)
+ .toList();
+
+ return ResponseEntity.ok().body(new BaseResponse<>(CATEGORY_USER_SUBSCRIBES_LOOKUP_SUCCESS, responses));
+ }
+
+ @Operation(summary = "사용자 학과 조회", description = "사용자가 구독한 학과의 목록을 조회합니다")
+ @SecurityRequirement(name = "User-Token")
+ @GetMapping("/subscriptions/departments")
+ public ResponseEntity>> lookupUserSubscribeDepartments(
+ @RequestHeader(USER_TOKEN_HEADER_KEY) String userToken
+ ) {
+ List responses = userQueryUseCase.lookupSubscribeDepartments(userToken)
+ .stream()
+ .map(UserDepartmentNameResponse::from)
+ .toList();
+
+ return ResponseEntity.ok().body(new BaseResponse<>(DEPARTMENTS_USER_SUBSCRIBES_LOOKUP_SUCCESS, responses));
+ }
+
+ @Operation(summary = "사용자 북마크 조회", description = "사용자가 북마크한 공지의 목록을 조회합니다")
+ @SecurityRequirement(name = "User-Token")
+ @GetMapping("/bookmarks")
+ public ResponseEntity>> lookupUserBookmarks(
+ @RequestHeader(USER_TOKEN_HEADER_KEY) String userToken
+ ) {
+ List responses = userQueryUseCase.lookupUserBookmarkedNotices(userToken)
+ .stream()
+ .map(UserBookmarkResponse::from)
+ .toList();
+
+ return ResponseEntity.ok().body(new BaseResponse<>(BOOKMARK_LOOKUP_SUCCESS, responses));
+ }
+}
diff --git a/src/main/java/com/kustacks/kuring/user/adapter/in/web/dto/UserBookmarkRequest.java b/src/main/java/com/kustacks/kuring/user/adapter/in/web/dto/UserBookmarkRequest.java
new file mode 100644
index 00000000..e8cdc56c
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/user/adapter/in/web/dto/UserBookmarkRequest.java
@@ -0,0 +1,8 @@
+package com.kustacks.kuring.user.adapter.in.web.dto;
+
+import javax.validation.constraints.NotBlank;
+
+public record UserBookmarkRequest(
+ @NotBlank String articleId
+) {
+}
diff --git a/src/main/java/com/kustacks/kuring/user/adapter/in/web/dto/UserBookmarkResponse.java b/src/main/java/com/kustacks/kuring/user/adapter/in/web/dto/UserBookmarkResponse.java
new file mode 100644
index 00000000..bebfde56
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/user/adapter/in/web/dto/UserBookmarkResponse.java
@@ -0,0 +1,22 @@
+package com.kustacks.kuring.user.adapter.in.web.dto;
+
+import com.kustacks.kuring.user.application.port.in.dto.UserBookmarkResult;
+
+public record UserBookmarkResponse(
+ String articleId,
+ String postedDate,
+ String subject,
+ String category,
+ String baseUrl
+) {
+
+ public static UserBookmarkResponse from(UserBookmarkResult result) {
+ return new UserBookmarkResponse(
+ result.articleId(),
+ result.postedDate(),
+ result.subject(),
+ result.category(),
+ result.baseUrl()
+ );
+ }
+}
diff --git a/src/main/java/com/kustacks/kuring/user/adapter/in/web/dto/UserCategoriesSubscribeRequest.java b/src/main/java/com/kustacks/kuring/user/adapter/in/web/dto/UserCategoriesSubscribeRequest.java
new file mode 100644
index 00000000..e6e211fb
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/user/adapter/in/web/dto/UserCategoriesSubscribeRequest.java
@@ -0,0 +1,9 @@
+package com.kustacks.kuring.user.adapter.in.web.dto;
+
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+public record UserCategoriesSubscribeRequest(
+ @NotNull List categories
+) {
+}
diff --git a/src/main/java/com/kustacks/kuring/user/adapter/in/web/dto/UserCategoryNameResponse.java b/src/main/java/com/kustacks/kuring/user/adapter/in/web/dto/UserCategoryNameResponse.java
new file mode 100644
index 00000000..15c4aa95
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/user/adapter/in/web/dto/UserCategoryNameResponse.java
@@ -0,0 +1,13 @@
+package com.kustacks.kuring.user.adapter.in.web.dto;
+
+import com.kustacks.kuring.user.application.port.in.dto.UserCategoryNameResult;
+
+public record UserCategoryNameResponse(
+ String name,
+ String hostPrefix,
+ String korName
+) {
+ public static UserCategoryNameResponse from(UserCategoryNameResult name) {
+ return new UserCategoryNameResponse(name.name(), name.hostPrefix(), name.korName());
+ }
+}
diff --git a/src/main/java/com/kustacks/kuring/user/adapter/in/web/dto/UserDepartmentNameResponse.java b/src/main/java/com/kustacks/kuring/user/adapter/in/web/dto/UserDepartmentNameResponse.java
new file mode 100644
index 00000000..66b228f0
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/user/adapter/in/web/dto/UserDepartmentNameResponse.java
@@ -0,0 +1,13 @@
+package com.kustacks.kuring.user.adapter.in.web.dto;
+
+import com.kustacks.kuring.user.application.port.in.dto.UserDepartmentNameResult;
+
+public record UserDepartmentNameResponse(
+ String name,
+ String hostPrefix,
+ String korName
+) {
+ public static UserDepartmentNameResponse from(UserDepartmentNameResult name) {
+ return new UserDepartmentNameResponse(name.name(), name.hostPrefix(), name.korName());
+ }
+}
diff --git a/src/main/java/com/kustacks/kuring/user/adapter/in/web/dto/UserDepartmentsSubscribeRequest.java b/src/main/java/com/kustacks/kuring/user/adapter/in/web/dto/UserDepartmentsSubscribeRequest.java
new file mode 100644
index 00000000..ebf6ae53
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/user/adapter/in/web/dto/UserDepartmentsSubscribeRequest.java
@@ -0,0 +1,10 @@
+package com.kustacks.kuring.user.adapter.in.web.dto;
+
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+
+public record UserDepartmentsSubscribeRequest(
+ @NotNull List departments
+) {
+}
diff --git a/src/main/java/com/kustacks/kuring/user/adapter/in/web/dto/UserFeedbackRequest.java b/src/main/java/com/kustacks/kuring/user/adapter/in/web/dto/UserFeedbackRequest.java
new file mode 100644
index 00000000..52cf16e6
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/user/adapter/in/web/dto/UserFeedbackRequest.java
@@ -0,0 +1,9 @@
+package com.kustacks.kuring.user.adapter.in.web.dto;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+
+public record UserFeedbackRequest(
+ @NotBlank @Size(min = 5, max = 256) String content
+) {
+}
diff --git a/src/main/java/com/kustacks/kuring/user/adapter/out/event/UserFirebaseMessageAdapter.java b/src/main/java/com/kustacks/kuring/user/adapter/out/event/UserFirebaseMessageAdapter.java
new file mode 100644
index 00000000..ba8b2195
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/user/adapter/out/event/UserFirebaseMessageAdapter.java
@@ -0,0 +1,25 @@
+package com.kustacks.kuring.user.adapter.out.event;
+
+import com.kustacks.kuring.common.domain.Events;
+import com.kustacks.kuring.message.adapter.in.event.dto.UserSubscribeEvent;
+import com.kustacks.kuring.message.adapter.in.event.dto.UserUnsubscribeEvent;
+import com.kustacks.kuring.message.application.service.exception.FirebaseSubscribeException;
+import com.kustacks.kuring.message.application.service.exception.FirebaseUnSubscribeException;
+import com.kustacks.kuring.user.application.port.out.UserEventPort;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Component;
+
+@Component
+@RequiredArgsConstructor
+public class UserFirebaseMessageAdapter implements UserEventPort {
+
+ @Override
+ public void subscribeEvent(String token, String topic) throws FirebaseSubscribeException {
+ Events.raise(new UserSubscribeEvent(token, topic));
+ }
+
+ @Override
+ public void unsubscribeEvent(String token, String topic) throws FirebaseUnSubscribeException {
+ Events.raise(new UserUnsubscribeEvent(token, topic));
+ }
+}
diff --git a/src/main/java/com/kustacks/kuring/user/adapter/out/persistence/UserPersistenceAdapter.java b/src/main/java/com/kustacks/kuring/user/adapter/out/persistence/UserPersistenceAdapter.java
new file mode 100644
index 00000000..b9d85669
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/user/adapter/out/persistence/UserPersistenceAdapter.java
@@ -0,0 +1,50 @@
+package com.kustacks.kuring.user.adapter.out.persistence;
+
+import com.kustacks.kuring.user.application.port.out.dto.FeedbackDto;
+import com.kustacks.kuring.admin.application.port.out.AdminUserFeedbackPort;
+import com.kustacks.kuring.common.annotation.PersistenceAdapter;
+import com.kustacks.kuring.user.application.port.out.UserCommandPort;
+import com.kustacks.kuring.user.application.port.out.UserQueryPort;
+import com.kustacks.kuring.user.domain.User;
+import lombok.RequiredArgsConstructor;
+import org.springframework.data.domain.Pageable;
+
+import java.util.List;
+import java.util.Optional;
+
+@PersistenceAdapter
+@RequiredArgsConstructor
+public class UserPersistenceAdapter implements UserCommandPort, UserQueryPort, AdminUserFeedbackPort {
+
+ private final UserRepository userRepository;
+
+ @Override
+ public List findAllFeedbackByPageRequest(Pageable pageable) {
+ return userRepository.findAllFeedbackByPageRequest(pageable);
+ }
+
+ @Override
+ public List findAllToken() {
+ return userRepository.findAllToken();
+ }
+
+ @Override
+ public Optional findByToken(String token) {
+ return userRepository.findByToken(token);
+ }
+
+ @Override
+ public List findAll() {
+ return userRepository.findAll();
+ }
+
+ @Override
+ public User save(User user) {
+ return userRepository.save(user);
+ }
+
+ @Override
+ public void delete(User user) {
+ userRepository.delete(user);
+ }
+}
diff --git a/src/main/java/com/kustacks/kuring/user/adapter/out/persistence/UserQueryRepository.java b/src/main/java/com/kustacks/kuring/user/adapter/out/persistence/UserQueryRepository.java
new file mode 100644
index 00000000..8c450fea
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/user/adapter/out/persistence/UserQueryRepository.java
@@ -0,0 +1,11 @@
+package com.kustacks.kuring.user.adapter.out.persistence;
+
+import com.kustacks.kuring.user.application.port.out.dto.FeedbackDto;
+import org.springframework.data.domain.Pageable;
+
+import java.util.List;
+
+interface UserQueryRepository {
+
+ List findAllFeedbackByPageRequest(Pageable pageable);
+}
diff --git a/src/main/java/com/kustacks/kuring/user/domain/UserQueryRepositoryImpl.java b/src/main/java/com/kustacks/kuring/user/adapter/out/persistence/UserQueryRepositoryImpl.java
similarity index 73%
rename from src/main/java/com/kustacks/kuring/user/domain/UserQueryRepositoryImpl.java
rename to src/main/java/com/kustacks/kuring/user/adapter/out/persistence/UserQueryRepositoryImpl.java
index 2a69c011..23761b23 100644
--- a/src/main/java/com/kustacks/kuring/user/domain/UserQueryRepositoryImpl.java
+++ b/src/main/java/com/kustacks/kuring/user/adapter/out/persistence/UserQueryRepositoryImpl.java
@@ -1,7 +1,7 @@
-package com.kustacks.kuring.user.domain;
+package com.kustacks.kuring.user.adapter.out.persistence;
-import com.kustacks.kuring.admin.common.dto.FeedbackDto;
-import com.kustacks.kuring.admin.common.dto.QFeedbackDto;
+import com.kustacks.kuring.user.application.port.out.dto.FeedbackDto;
+import com.kustacks.kuring.user.application.port.out.dto.QFeedbackDto;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
@@ -11,7 +11,7 @@
import static com.kustacks.kuring.user.domain.QFeedback.feedback;
@RequiredArgsConstructor
-public class UserQueryRepositoryImpl implements UserQueryRepository {
+class UserQueryRepositoryImpl implements UserQueryRepository {
private final JPAQueryFactory queryFactory;
diff --git a/src/main/java/com/kustacks/kuring/user/domain/UserRepository.java b/src/main/java/com/kustacks/kuring/user/adapter/out/persistence/UserRepository.java
similarity index 61%
rename from src/main/java/com/kustacks/kuring/user/domain/UserRepository.java
rename to src/main/java/com/kustacks/kuring/user/adapter/out/persistence/UserRepository.java
index f3c04123..72df8984 100644
--- a/src/main/java/com/kustacks/kuring/user/domain/UserRepository.java
+++ b/src/main/java/com/kustacks/kuring/user/adapter/out/persistence/UserRepository.java
@@ -1,12 +1,13 @@
-package com.kustacks.kuring.user.domain;
+package com.kustacks.kuring.user.adapter.out.persistence;
+import com.kustacks.kuring.user.domain.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
import java.util.Optional;
-public interface UserRepository extends JpaRepository, UserQueryRepository {
+interface UserRepository extends JpaRepository, UserQueryRepository {
Optional findByToken(String token);
@Query("SELECT u.token FROM User u")
diff --git a/src/main/java/com/kustacks/kuring/user/application/port/in/UserCommandUseCase.java b/src/main/java/com/kustacks/kuring/user/application/port/in/UserCommandUseCase.java
new file mode 100644
index 00000000..686d6427
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/user/application/port/in/UserCommandUseCase.java
@@ -0,0 +1,13 @@
+package com.kustacks.kuring.user.application.port.in;
+
+import com.kustacks.kuring.user.application.port.in.dto.UserBookmarkCommand;
+import com.kustacks.kuring.user.application.port.in.dto.UserFeedbackCommand;
+import com.kustacks.kuring.user.application.port.in.dto.UserCategoriesSubscribeCommand;
+import com.kustacks.kuring.user.application.port.in.dto.UserDepartmentsSubscribeCommand;
+
+public interface UserCommandUseCase {
+ void editSubscribeCategories(UserCategoriesSubscribeCommand command);
+ void editSubscribeDepartments(UserDepartmentsSubscribeCommand command);
+ void saveFeedback(UserFeedbackCommand command);
+ void saveBookmark(UserBookmarkCommand command);
+}
diff --git a/src/main/java/com/kustacks/kuring/user/application/port/in/UserQueryUseCase.java b/src/main/java/com/kustacks/kuring/user/application/port/in/UserQueryUseCase.java
new file mode 100644
index 00000000..338e951e
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/user/application/port/in/UserQueryUseCase.java
@@ -0,0 +1,13 @@
+package com.kustacks.kuring.user.application.port.in;
+
+import com.kustacks.kuring.user.application.port.in.dto.UserBookmarkResult;
+import com.kustacks.kuring.user.application.port.in.dto.UserCategoryNameResult;
+import com.kustacks.kuring.user.application.port.in.dto.UserDepartmentNameResult;
+
+import java.util.List;
+
+public interface UserQueryUseCase {
+ List lookupSubscribeCategories(String userToken);
+ List lookupSubscribeDepartments(String userToken);
+ List lookupUserBookmarkedNotices(String userToken);
+}
diff --git a/src/main/java/com/kustacks/kuring/user/application/port/in/dto/AdminFeedbacksResult.java b/src/main/java/com/kustacks/kuring/user/application/port/in/dto/AdminFeedbacksResult.java
new file mode 100644
index 00000000..27979bb6
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/user/application/port/in/dto/AdminFeedbacksResult.java
@@ -0,0 +1,10 @@
+package com.kustacks.kuring.user.application.port.in.dto;
+
+import java.time.LocalDateTime;
+
+public record AdminFeedbacksResult(
+ String contents,
+ Long userId,
+ LocalDateTime createdAt
+) {
+}
diff --git a/src/main/java/com/kustacks/kuring/user/application/port/in/dto/UserBookmarkCommand.java b/src/main/java/com/kustacks/kuring/user/application/port/in/dto/UserBookmarkCommand.java
new file mode 100644
index 00000000..dd514a7a
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/user/application/port/in/dto/UserBookmarkCommand.java
@@ -0,0 +1,7 @@
+package com.kustacks.kuring.user.application.port.in.dto;
+
+public record UserBookmarkCommand(
+ String userToken,
+ String articleId
+) {
+}
diff --git a/src/main/java/com/kustacks/kuring/user/application/port/in/dto/UserBookmarkResult.java b/src/main/java/com/kustacks/kuring/user/application/port/in/dto/UserBookmarkResult.java
new file mode 100644
index 00000000..422d9e03
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/user/application/port/in/dto/UserBookmarkResult.java
@@ -0,0 +1,10 @@
+package com.kustacks.kuring.user.application.port.in.dto;
+
+public record UserBookmarkResult(
+ String articleId,
+ String postedDate,
+ String subject,
+ String category,
+ String baseUrl
+) {
+}
diff --git a/src/main/java/com/kustacks/kuring/user/application/port/in/dto/UserCategoriesSubscribeCommand.java b/src/main/java/com/kustacks/kuring/user/application/port/in/dto/UserCategoriesSubscribeCommand.java
new file mode 100644
index 00000000..eb55f5a2
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/user/application/port/in/dto/UserCategoriesSubscribeCommand.java
@@ -0,0 +1,9 @@
+package com.kustacks.kuring.user.application.port.in.dto;
+
+import java.util.List;
+
+public record UserCategoriesSubscribeCommand(
+ String userToken,
+ List categories
+) {
+}
diff --git a/src/main/java/com/kustacks/kuring/user/application/port/in/dto/UserCategoryNameResult.java b/src/main/java/com/kustacks/kuring/user/application/port/in/dto/UserCategoryNameResult.java
new file mode 100644
index 00000000..50d8e737
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/user/application/port/in/dto/UserCategoryNameResult.java
@@ -0,0 +1,13 @@
+package com.kustacks.kuring.user.application.port.in.dto;
+
+import com.kustacks.kuring.notice.domain.CategoryName;
+
+public record UserCategoryNameResult(
+ String name,
+ String hostPrefix,
+ String korName
+) {
+ public static UserCategoryNameResult from(CategoryName name) {
+ return new UserCategoryNameResult(name.getName(), name.getShortName(), name.getKorName());
+ }
+}
diff --git a/src/main/java/com/kustacks/kuring/user/application/port/in/dto/UserDepartmentNameResult.java b/src/main/java/com/kustacks/kuring/user/application/port/in/dto/UserDepartmentNameResult.java
new file mode 100644
index 00000000..ec8cf45b
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/user/application/port/in/dto/UserDepartmentNameResult.java
@@ -0,0 +1,13 @@
+package com.kustacks.kuring.user.application.port.in.dto;
+
+import com.kustacks.kuring.notice.domain.DepartmentName;
+
+public record UserDepartmentNameResult(
+ String name,
+ String hostPrefix,
+ String korName
+) {
+ public static UserDepartmentNameResult from(DepartmentName name) {
+ return new UserDepartmentNameResult(name.getName(), name.getHostPrefix(), name.getKorName());
+ }
+}
diff --git a/src/main/java/com/kustacks/kuring/user/application/port/in/dto/UserDepartmentsSubscribeCommand.java b/src/main/java/com/kustacks/kuring/user/application/port/in/dto/UserDepartmentsSubscribeCommand.java
new file mode 100644
index 00000000..34ec8a71
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/user/application/port/in/dto/UserDepartmentsSubscribeCommand.java
@@ -0,0 +1,10 @@
+package com.kustacks.kuring.user.application.port.in.dto;
+
+import java.util.List;
+
+
+public record UserDepartmentsSubscribeCommand(
+ String userToken,
+ List departments
+) {
+}
diff --git a/src/main/java/com/kustacks/kuring/user/application/port/in/dto/UserFeedbackCommand.java b/src/main/java/com/kustacks/kuring/user/application/port/in/dto/UserFeedbackCommand.java
new file mode 100644
index 00000000..0bab3b0c
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/user/application/port/in/dto/UserFeedbackCommand.java
@@ -0,0 +1,7 @@
+package com.kustacks.kuring.user.application.port.in.dto;
+
+public record UserFeedbackCommand(
+ String userToken,
+ String content
+) {
+}
diff --git a/src/main/java/com/kustacks/kuring/user/application/port/in/dto/UserSubscribeCompareResult.java b/src/main/java/com/kustacks/kuring/user/application/port/in/dto/UserSubscribeCompareResult.java
new file mode 100644
index 00000000..6087b9b5
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/user/application/port/in/dto/UserSubscribeCompareResult.java
@@ -0,0 +1,9 @@
+package com.kustacks.kuring.user.application.port.in.dto;
+
+import java.util.List;
+
+public record UserSubscribeCompareResult(
+ List savedNameList,
+ List deletedNameList
+) {
+}
diff --git a/src/main/java/com/kustacks/kuring/user/application/port/out/UserCommandPort.java b/src/main/java/com/kustacks/kuring/user/application/port/out/UserCommandPort.java
new file mode 100644
index 00000000..8a24f4f4
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/user/application/port/out/UserCommandPort.java
@@ -0,0 +1,8 @@
+package com.kustacks.kuring.user.application.port.out;
+
+import com.kustacks.kuring.user.domain.User;
+
+public interface UserCommandPort {
+ User save(User user);
+ void delete(User user);
+}
diff --git a/src/main/java/com/kustacks/kuring/user/application/port/out/UserEventPort.java b/src/main/java/com/kustacks/kuring/user/application/port/out/UserEventPort.java
new file mode 100644
index 00000000..e7dc56f5
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/user/application/port/out/UserEventPort.java
@@ -0,0 +1,11 @@
+package com.kustacks.kuring.user.application.port.out;
+
+import com.kustacks.kuring.message.application.service.exception.FirebaseSubscribeException;
+import com.kustacks.kuring.message.application.service.exception.FirebaseUnSubscribeException;
+
+public interface UserEventPort {
+
+ void subscribeEvent(String token, String topic) throws FirebaseSubscribeException;
+
+ void unsubscribeEvent(String token, String topic) throws FirebaseUnSubscribeException;
+}
diff --git a/src/main/java/com/kustacks/kuring/user/application/port/out/UserQueryPort.java b/src/main/java/com/kustacks/kuring/user/application/port/out/UserQueryPort.java
new file mode 100644
index 00000000..36502d43
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/user/application/port/out/UserQueryPort.java
@@ -0,0 +1,12 @@
+package com.kustacks.kuring.user.application.port.out;
+
+import com.kustacks.kuring.user.domain.User;
+
+import java.util.List;
+import java.util.Optional;
+
+public interface UserQueryPort {
+
+ Optional findByToken(String token);
+ List findAll();
+}
diff --git a/src/main/java/com/kustacks/kuring/user/common/dto/BookmarkDto.java b/src/main/java/com/kustacks/kuring/user/application/port/out/dto/BookmarkDto.java
similarity index 92%
rename from src/main/java/com/kustacks/kuring/user/common/dto/BookmarkDto.java
rename to src/main/java/com/kustacks/kuring/user/application/port/out/dto/BookmarkDto.java
index b8fdb95a..1347b585 100644
--- a/src/main/java/com/kustacks/kuring/user/common/dto/BookmarkDto.java
+++ b/src/main/java/com/kustacks/kuring/user/application/port/out/dto/BookmarkDto.java
@@ -1,4 +1,4 @@
-package com.kustacks.kuring.user.common.dto;
+package com.kustacks.kuring.user.application.port.out.dto;
import com.querydsl.core.annotations.QueryProjection;
import lombok.AccessLevel;
diff --git a/src/main/java/com/kustacks/kuring/admin/common/dto/FeedbackDto.java b/src/main/java/com/kustacks/kuring/user/application/port/out/dto/FeedbackDto.java
similarity index 90%
rename from src/main/java/com/kustacks/kuring/admin/common/dto/FeedbackDto.java
rename to src/main/java/com/kustacks/kuring/user/application/port/out/dto/FeedbackDto.java
index 623030f8..0e13b046 100644
--- a/src/main/java/com/kustacks/kuring/admin/common/dto/FeedbackDto.java
+++ b/src/main/java/com/kustacks/kuring/user/application/port/out/dto/FeedbackDto.java
@@ -1,4 +1,4 @@
-package com.kustacks.kuring.admin.common.dto;
+package com.kustacks.kuring.user.application.port.out.dto;
import com.querydsl.core.annotations.QueryProjection;
import lombok.AccessLevel;
diff --git a/src/main/java/com/kustacks/kuring/user/application/service/UserCommandService.java b/src/main/java/com/kustacks/kuring/user/application/service/UserCommandService.java
new file mode 100644
index 00000000..e7805aa6
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/user/application/service/UserCommandService.java
@@ -0,0 +1,203 @@
+package com.kustacks.kuring.user.application.service;
+
+import com.kustacks.kuring.common.annotation.UseCase;
+import com.kustacks.kuring.common.exception.NotFoundException;
+import com.kustacks.kuring.common.exception.code.ErrorCode;
+import com.kustacks.kuring.common.properties.ServerProperties;
+import com.kustacks.kuring.message.application.service.exception.FirebaseSubscribeException;
+import com.kustacks.kuring.message.application.service.exception.FirebaseUnSubscribeException;
+import com.kustacks.kuring.notice.domain.CategoryName;
+import com.kustacks.kuring.notice.domain.DepartmentName;
+import com.kustacks.kuring.user.application.port.in.UserCommandUseCase;
+import com.kustacks.kuring.user.application.port.in.dto.*;
+import com.kustacks.kuring.user.application.port.out.UserCommandPort;
+import com.kustacks.kuring.user.application.port.out.UserEventPort;
+import com.kustacks.kuring.user.application.port.out.UserQueryPort;
+import com.kustacks.kuring.user.domain.User;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Optional;
+
+import static com.kustacks.kuring.message.application.service.FirebaseSubscribeService.ALL_DEVICE_SUBSCRIBED_TOPIC;
+
+@Slf4j
+@UseCase
+@Transactional
+@RequiredArgsConstructor
+class UserCommandService implements UserCommandUseCase {
+
+ private final UserCommandPort userCommandPort;
+ private final UserQueryPort userQueryPort;
+ private final UserEventPort userEventPort;
+ private final ServerProperties serverProperties;
+
+ @Override
+ public void editSubscribeCategories(UserCategoriesSubscribeCommand command) {
+ UserSubscribeCompareResult compareResults =
+ this.editSubscribeCategoryList(command.userToken(), command.categories());
+
+ editUserCategoryList(
+ command.userToken(),
+ compareResults.savedNameList(),
+ compareResults.deletedNameList()
+ );
+ }
+
+ @Override
+ public void editSubscribeDepartments(UserDepartmentsSubscribeCommand command) {
+ UserSubscribeCompareResult compareResults
+ = this.editSubscribeDepartmentList(command.userToken(), command.departments());
+
+ editDepartmentNameList(
+ command.userToken(),
+ compareResults.savedNameList(),
+ compareResults.deletedNameList()
+ );
+ }
+
+ @Override
+ public void saveFeedback(UserFeedbackCommand command) {
+ User findUser = findUserByToken(command.userToken());
+ findUser.addFeedback(command.content());
+ }
+
+ @Override
+ public void saveBookmark(UserBookmarkCommand command) {
+ User user = findUserByToken(command.userToken());
+ user.addBookmark(command.articleId());
+ }
+
+ private UserSubscribeCompareResult editSubscribeCategoryList(
+ String userToken,
+ List newCategoryStringNames
+ ) {
+ User user = findUserByToken(userToken);
+
+ List newCategoryNames = convertToEnumList(newCategoryStringNames);
+
+ List savedCategoryNames = user.filteringNewCategoryName(newCategoryNames);
+ List deletedCategoryNames = user.filteringOldCategoryName(newCategoryNames);
+
+ return new UserSubscribeCompareResult<>(savedCategoryNames, deletedCategoryNames);
+ }
+
+ private void editUserCategoryList(
+ String userToken,
+ List savedCategoryNames,
+ List deletedCategoryNames
+ ) throws FirebaseSubscribeException, FirebaseUnSubscribeException {
+ subscribeUserCategory(userToken, savedCategoryNames);
+ unsubscribeUserCategory(userToken, deletedCategoryNames);
+ }
+
+ private UserSubscribeCompareResult editSubscribeDepartmentList(
+ String userToken,
+ List departments
+ ) {
+ User user = findUserByToken(userToken);
+
+ List newDepartmentNames = convertHostPrefixToEnum(departments);
+
+ List savedDepartmentNames = user.filteringNewDepartmentName(newDepartmentNames);
+ List deletedDepartmentNames = user.filteringOldDepartmentName(newDepartmentNames);
+ return new UserSubscribeCompareResult<>(savedDepartmentNames, deletedDepartmentNames);
+ }
+
+ private void subscribeUserCategory(
+ String token,
+ List newCategoryNames
+ ) throws FirebaseSubscribeException {
+ for (CategoryName newCategoryName : newCategoryNames) {
+ userEventPort.subscribeEvent(token, newCategoryName.getName());
+ this.subscribeCategory(token, newCategoryName);
+ log.debug("구독 성공 = {}", newCategoryName.getName());
+ }
+ }
+
+ private void unsubscribeUserCategory(
+ String token,
+ List removeCategoryNames
+ ) throws FirebaseUnSubscribeException {
+ for (CategoryName removeCategoryName : removeCategoryNames) {
+ userEventPort.unsubscribeEvent(token, removeCategoryName.getName());
+ this.unsubscribeCategory(token, removeCategoryName);
+ log.debug("구독 취소 = {}", removeCategoryName.getName());
+ }
+ }
+
+ private void editDepartmentNameList(
+ String userToken,
+ List savedDepartmentNames,
+ List deletedDepartmentNames
+ ) throws FirebaseSubscribeException, FirebaseUnSubscribeException {
+ subscribeDepartment(userToken, savedDepartmentNames);
+ unsubscribeDepartment(userToken, deletedDepartmentNames);
+ }
+
+ private void subscribeCategory(String userToken, CategoryName categoryName) {
+ User user = findUserByToken(userToken);
+ user.subscribeCategory(categoryName);
+ }
+
+ private void unsubscribeCategory(String userToken, CategoryName categoryName) {
+ User user = findUserByToken(userToken);
+ user.unsubscribeCategory(categoryName);
+ }
+
+ private void subscribeDepartment(
+ String userToken,
+ List newDepartmentNames
+ ) {
+ for (DepartmentName newDepartmentName : newDepartmentNames) {
+ userEventPort.subscribeEvent(userToken, newDepartmentName.getName());
+ this.subscribeDepartment(userToken, newDepartmentName);
+ log.debug("구독 성공 = {}", newDepartmentName.getName());
+ }
+ }
+
+ private void unsubscribeDepartment(
+ String userToken,
+ List removeDepartmentNames
+ ) {
+ for (DepartmentName removeDepartmentName : removeDepartmentNames) {
+ userEventPort.unsubscribeEvent(userToken, removeDepartmentName.getName());
+ this.unsubscribeDepartment(userToken, removeDepartmentName);
+ log.debug("구독 취소 = {}", removeDepartmentName.getName());
+ }
+ }
+
+ private void subscribeDepartment(String userToken, DepartmentName newDepartmentName) {
+ User user = findUserByToken(userToken);
+ user.subscribeDepartment(newDepartmentName);
+ }
+
+ private void unsubscribeDepartment(String userToken, DepartmentName removeDepartmentName) {
+ User user = findUserByToken(userToken);
+ user.unsubscribeDepartment(removeDepartmentName);
+ }
+
+ private User findUserByToken(String token) {
+ Optional optionalUser = userQueryPort.findByToken(token);
+ if (optionalUser.isEmpty()) {
+ optionalUser = Optional.of(userCommandPort.save(new User(token)));
+ userEventPort.subscribeEvent(token, serverProperties.ifDevThenAddSuffix(ALL_DEVICE_SUBSCRIBED_TOPIC));
+ }
+
+ return optionalUser.orElseThrow(() -> new NotFoundException(ErrorCode.USER_NOT_FOUND));
+ }
+
+ private List convertToEnumList(List categories) {
+ return categories.stream()
+ .map(CategoryName::fromStringName)
+ .toList();
+ }
+
+ private List convertHostPrefixToEnum(List departments) {
+ return departments.stream()
+ .map(DepartmentName::fromHostPrefix)
+ .toList();
+ }
+}
diff --git a/src/main/java/com/kustacks/kuring/user/application/service/UserQueryService.java b/src/main/java/com/kustacks/kuring/user/application/service/UserQueryService.java
new file mode 100644
index 00000000..ea9faf8b
--- /dev/null
+++ b/src/main/java/com/kustacks/kuring/user/application/service/UserQueryService.java
@@ -0,0 +1,88 @@
+package com.kustacks.kuring.user.application.service;
+
+import com.kustacks.kuring.common.annotation.UseCase;
+import com.kustacks.kuring.common.exception.NotFoundException;
+import com.kustacks.kuring.common.exception.code.ErrorCode;
+import com.kustacks.kuring.common.properties.ServerProperties;
+import com.kustacks.kuring.notice.application.port.out.NoticeQueryPort;
+import com.kustacks.kuring.notice.domain.CategoryName;
+import com.kustacks.kuring.notice.domain.DepartmentName;
+import com.kustacks.kuring.user.application.port.in.UserQueryUseCase;
+import com.kustacks.kuring.user.application.port.in.dto.UserBookmarkResult;
+import com.kustacks.kuring.user.application.port.in.dto.UserCategoryNameResult;
+import com.kustacks.kuring.user.application.port.in.dto.UserDepartmentNameResult;
+import com.kustacks.kuring.user.application.port.out.UserCommandPort;
+import com.kustacks.kuring.user.application.port.out.UserEventPort;
+import com.kustacks.kuring.user.application.port.out.UserQueryPort;
+import com.kustacks.kuring.user.domain.User;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Optional;
+
+import static com.kustacks.kuring.message.application.service.FirebaseSubscribeService.ALL_DEVICE_SUBSCRIBED_TOPIC;
+
+@Slf4j
+@UseCase
+@Transactional(readOnly = true)
+@RequiredArgsConstructor
+class UserQueryService implements UserQueryUseCase {
+
+ private final UserCommandPort userCommandPort;
+ private final UserQueryPort userQueryPort;
+ private final NoticeQueryPort noticeQueryPort;
+ private final UserEventPort userEventPort;
+ private final ServerProperties serverProperties;
+
+ @Override
+ public List lookupSubscribeCategories(String userToken) {
+ User findUser = findUserByToken(userToken);
+ return convertCategoryNameDtoList(findUser.getSubscribedCategoryList());
+ }
+
+ @Override
+ public List lookupSubscribeDepartments(String userToken) {
+ User findUser = findUserByToken(userToken);
+ return convertDepartmentDtoList(findUser.getSubscribedDepartmentList());
+ }
+
+ @Override
+ public List lookupUserBookmarkedNotices(String userToken) {
+ User user = findUserByToken(userToken);
+ List bookmarkIds = user.lookupAllBookmarkIds();
+
+ return noticeQueryPort.findAllByBookmarkIds(bookmarkIds)
+ .stream()
+ .map(dto -> new UserBookmarkResult(
+ dto.getArticleId(),
+ dto.getPostedDate(),
+ dto.getSubject(),
+ dto.getCategory(),
+ dto.getBaseUrl())
+ ).toList();
+ }
+
+ private User findUserByToken(String token) {
+ Optional optionalUser = userQueryPort.findByToken(token);
+ if (optionalUser.isEmpty()) {
+ optionalUser = Optional.of(userCommandPort.save(new User(token)));
+ userEventPort.subscribeEvent(token, serverProperties.ifDevThenAddSuffix(ALL_DEVICE_SUBSCRIBED_TOPIC));
+ }
+
+ return optionalUser.orElseThrow(() -> new NotFoundException(ErrorCode.USER_NOT_FOUND));
+ }
+
+ private List convertCategoryNameDtoList(List categoryNamesList) {
+ return categoryNamesList.stream()
+ .map(UserCategoryNameResult::from)
+ .toList();
+ }
+
+ private List convertDepartmentDtoList(List departmentNames) {
+ return departmentNames.stream()
+ .map(UserDepartmentNameResult::from)
+ .toList();
+ }
+}
diff --git a/src/main/java/com/kustacks/kuring/user/business/UserService.java b/src/main/java/com/kustacks/kuring/user/business/UserService.java
deleted file mode 100644
index 9d0e1601..00000000
--- a/src/main/java/com/kustacks/kuring/user/business/UserService.java
+++ /dev/null
@@ -1,135 +0,0 @@
-package com.kustacks.kuring.user.business;
-
-import com.kustacks.kuring.admin.common.dto.FeedbackDto;
-import com.kustacks.kuring.common.exception.NotFoundException;
-import com.kustacks.kuring.common.exception.code.ErrorCode;
-import com.kustacks.kuring.message.firebase.FirebaseService;
-import com.kustacks.kuring.message.firebase.ServerProperties;
-import com.kustacks.kuring.notice.domain.CategoryName;
-import com.kustacks.kuring.notice.domain.DepartmentName;
-import com.kustacks.kuring.notice.domain.NoticeRepository;
-import com.kustacks.kuring.user.common.dto.BookmarkDto;
-import com.kustacks.kuring.user.common.dto.SubscribeCompareResultDto;
-import com.kustacks.kuring.user.domain.User;
-import com.kustacks.kuring.user.domain.UserRepository;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.data.domain.PageRequest;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.util.List;
-import java.util.Optional;
-
-import static com.kustacks.kuring.message.firebase.FirebaseService.ALL_DEVICE_SUBSCRIBED_TOPIC;
-
-@Slf4j
-@Service
-@Transactional
-@RequiredArgsConstructor
-public class UserService {
-
- private final UserRepository userRepository;
- private final NoticeRepository noticeRepository;
- private final FirebaseService firebaseService;
- private final ServerProperties serverProperties;
-
- @Transactional(readOnly = true)
- public List lookupSubscribeDepartmentList(String id) {
- User findUser = findUserByToken(id);
- return findUser.getSubscribedDepartmentList();
- }
-
- @Transactional(readOnly = true)
- public List lookUpUserCategories(String token) {
- User findUser = findUserByToken(token);
- return findUser.getSubscribedCategoryList();
- }
-
- @Transactional(readOnly = true)
- public List lookupFeedbacks(int page, int size) {
- PageRequest pageRequest = PageRequest.of(page, size);
- return userRepository.findAllFeedbackByPageRequest(pageRequest);
- }
-
- @Transactional(readOnly = true)
- public List lookupUserBookmarkedNotices(String userToken) {
- User user = findUserByToken(userToken);
- List bookmarkIds = user.lookupAllBookmarkIds();
- return noticeRepository.findAllByBookmarkIds(bookmarkIds);
- }
-
- public void saveFeedback(String token, String content) {
- User findUser = findUserByToken(token);
- findUser.addFeedback(content);
- }
-
- public SubscribeCompareResultDto editSubscribeCategoryList(
- String userToken, List newCategoryStringNames) {
- User user = findUserByToken(userToken);
-
- List newCategoryNames = convertToEnumList(newCategoryStringNames);
-
- List savedCategoryNames = user.filteringNewCategoryName(newCategoryNames);
- List deletedCategoryNames = user.filteringOldCategoryName(newCategoryNames);
-
- return new SubscribeCompareResultDto<>(savedCategoryNames, deletedCategoryNames);
- }
-
- public void subscribeCategory(String userToken, CategoryName categoryName) {
- User user = findUserByToken(userToken);
- user.subscribeCategory(categoryName);
- }
-
- public void unsubscribeCategory(String userToken, CategoryName categoryName) {
- User user = findUserByToken(userToken);
- user.unsubscribeCategory(categoryName);
- }
-
- public SubscribeCompareResultDto editSubscribeDepartmentList(String userToken, List departments) {
- User user = findUserByToken(userToken);
-
- List newDepartmentNames = convertHostPrefixToEnum(departments);
-
- List savedDepartmentNames = user.filteringNewDepartmentName(newDepartmentNames);
- List deletedDepartmentNames = user.filteringOldDepartmentName(newDepartmentNames);
- return new SubscribeCompareResultDto<>(savedDepartmentNames, deletedDepartmentNames);
- }
-
- public void subscribeDepartment(String userToken, DepartmentName newDepartmentName) {
- User user = findUserByToken(userToken);
- user.subscribeDepartment(newDepartmentName);
- }
-
- public void unsubscribeDepartment(String userToken, DepartmentName removeDepartmentName) {
- User user = findUserByToken(userToken);
- user.unsubscribeDepartment(removeDepartmentName);
- }
-
- public void saveBookmark(String userToken, String articleId) {
- User user = findUserByToken(userToken);
- user.addBookmark(articleId);
- }
-
- private User findUserByToken(String token) {
- Optional optionalUser = userRepository.findByToken(token);
- if (optionalUser.isEmpty()) {
- optionalUser = Optional.of(userRepository.save(new User(token)));
- firebaseService.subscribe(token, serverProperties.ifDevThenAddSuffix(ALL_DEVICE_SUBSCRIBED_TOPIC));
- }
-
- return optionalUser.orElseThrow(() -> new NotFoundException(ErrorCode.USER_NOT_FOUND));
- }
-
- private List convertToEnumList(List categories) {
- return categories.stream()
- .map(CategoryName::fromStringName)
- .toList();
- }
-
- private List convertHostPrefixToEnum(List departments) {
- return departments.stream()
- .map(DepartmentName::fromHostPrefix)
- .toList();
- }
-}
diff --git a/src/main/java/com/kustacks/kuring/user/common/dto/SaveBookmarkRequest.java b/src/main/java/com/kustacks/kuring/user/common/dto/SaveBookmarkRequest.java
deleted file mode 100644
index e6cdfe50..00000000
--- a/src/main/java/com/kustacks/kuring/user/common/dto/SaveBookmarkRequest.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.kustacks.kuring.user.common.dto;
-
-import lombok.AccessLevel;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-
-import javax.validation.constraints.NotBlank;
-
-@Getter
-@AllArgsConstructor
-@NoArgsConstructor(access = AccessLevel.PROTECTED)
-public class SaveBookmarkRequest {
-
- @NotBlank
- private String articleId;
-}
diff --git a/src/main/java/com/kustacks/kuring/user/common/dto/SaveFeedbackRequest.java b/src/main/java/com/kustacks/kuring/user/common/dto/SaveFeedbackRequest.java
deleted file mode 100644
index a37efe76..00000000
--- a/src/main/java/com/kustacks/kuring/user/common/dto/SaveFeedbackRequest.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.kustacks.kuring.user.common.dto;
-
-import lombok.AccessLevel;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.Size;
-
-@Getter
-@AllArgsConstructor
-@NoArgsConstructor(access = AccessLevel.PROTECTED)
-public class SaveFeedbackRequest {
-
- @NotBlank
- @Size(min = 5, max = 256)
- private String content;
-}
diff --git a/src/main/java/com/kustacks/kuring/user/common/dto/SaveFeedbackResponse.java b/src/main/java/com/kustacks/kuring/user/common/dto/SaveFeedbackResponse.java
deleted file mode 100644
index b61db4c0..00000000
--- a/src/main/java/com/kustacks/kuring/user/common/dto/SaveFeedbackResponse.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.kustacks.kuring.user.common.dto;
-
-import com.kustacks.kuring.common.dto.ResponseDto;
-import lombok.Getter;
-
-@Getter
-public class SaveFeedbackResponse extends ResponseDto {
-
- public SaveFeedbackResponse() {
- super(true, "성공", 201);
- }
-}
diff --git a/src/main/java/com/kustacks/kuring/user/common/dto/SubscribeCategoriesRequest.java b/src/main/java/com/kustacks/kuring/user/common/dto/SubscribeCategoriesRequest.java
deleted file mode 100644
index ec25e72a..00000000
--- a/src/main/java/com/kustacks/kuring/user/common/dto/SubscribeCategoriesRequest.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.kustacks.kuring.user.common.dto;
-
-import lombok.AccessLevel;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-
-import javax.validation.constraints.NotNull;
-import java.util.List;
-
-@Getter
-@AllArgsConstructor
-@NoArgsConstructor(access = AccessLevel.PROTECTED)
-public class SubscribeCategoriesRequest {
-
- @NotNull
- private List categories;
-}
diff --git a/src/main/java/com/kustacks/kuring/user/common/dto/SubscribeCompareResultDto.java b/src/main/java/com/kustacks/kuring/user/common/dto/SubscribeCompareResultDto.java
deleted file mode 100644
index a976dc26..00000000
--- a/src/main/java/com/kustacks/kuring/user/common/dto/SubscribeCompareResultDto.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.kustacks.kuring.user.common.dto;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-import java.util.List;
-
-@Getter
-@AllArgsConstructor
-public class SubscribeCompareResultDto {
-
- private List savedNameList;
- private List deletedNameList;
-}
diff --git a/src/main/java/com/kustacks/kuring/user/common/dto/SubscribeDepartmentsRequest.java b/src/main/java/com/kustacks/kuring/user/common/dto/SubscribeDepartmentsRequest.java
deleted file mode 100644
index 964c4114..00000000
--- a/src/main/java/com/kustacks/kuring/user/common/dto/SubscribeDepartmentsRequest.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.kustacks.kuring.user.common.dto;
-
-import lombok.AccessLevel;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-
-import javax.validation.constraints.NotNull;
-import java.util.List;
-
-
-@Getter
-@AllArgsConstructor
-@NoArgsConstructor(access = AccessLevel.PROTECTED)
-public class SubscribeDepartmentsRequest {
-
- @NotNull
- private List departments;
-}
diff --git a/src/main/java/com/kustacks/kuring/user/domain/UserQueryRepository.java b/src/main/java/com/kustacks/kuring/user/domain/UserQueryRepository.java
deleted file mode 100644
index 5a493589..00000000
--- a/src/main/java/com/kustacks/kuring/user/domain/UserQueryRepository.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.kustacks.kuring.user.domain;
-
-import com.kustacks.kuring.admin.common.dto.FeedbackDto;
-import org.springframework.data.domain.Pageable;
-
-import java.util.List;
-
-public interface UserQueryRepository {
-
- List findAllFeedbackByPageRequest(Pageable pageable);
-}
diff --git a/src/main/java/com/kustacks/kuring/user/facade/UserCommandFacade.java b/src/main/java/com/kustacks/kuring/user/facade/UserCommandFacade.java
deleted file mode 100644
index 72377368..00000000
--- a/src/main/java/com/kustacks/kuring/user/facade/UserCommandFacade.java
+++ /dev/null
@@ -1,115 +0,0 @@
-package com.kustacks.kuring.user.facade;
-
-import com.kustacks.kuring.message.firebase.FirebaseService;
-import com.kustacks.kuring.message.firebase.exception.FirebaseSubscribeException;
-import com.kustacks.kuring.message.firebase.exception.FirebaseUnSubscribeException;
-import com.kustacks.kuring.notice.domain.CategoryName;
-import com.kustacks.kuring.notice.domain.DepartmentName;
-import com.kustacks.kuring.user.business.UserService;
-import com.kustacks.kuring.user.common.dto.SubscribeCompareResultDto;
-import com.kustacks.kuring.worker.event.Events;
-import com.kustacks.kuring.worker.event.SubscribedRollbackEvent;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
-
-import javax.transaction.Transactional;
-import java.util.List;
-
-@Slf4j
-@Service
-@Transactional
-@RequiredArgsConstructor
-public class UserCommandFacade {
-
- private final UserService userService;
- private final FirebaseService firebaseService;
-
- public void editSubscribeCategories(String userToken, List newCategoryNames) {
- firebaseService.validationToken(userToken);
- SubscribeCompareResultDto compareResults = userService.editSubscribeCategoryList(userToken, newCategoryNames);
- editUserCategoryList(userToken, compareResults.getSavedNameList(), compareResults.getDeletedNameList());
- }
-
- public void editSubscribeDepartments(String userToken, List departments) {
- firebaseService.validationToken(userToken);
- SubscribeCompareResultDto compareResults = userService.editSubscribeDepartmentList(userToken, departments);
- editDepartmentNameList(userToken, compareResults.getSavedNameList(), compareResults.getDeletedNameList());
- }
-
- public void saveFeedback(String userToken, String feedback) {
- firebaseService.validationToken(userToken);
- userService.saveFeedback(userToken, feedback);
- }
-
- public void saveBookmark(String userToken, String articleId) {
- firebaseService.validationToken(userToken);
- userService.saveBookmark(userToken, articleId);
- }
-
- private void editUserCategoryList(
- String userToken, List savedCategoryNames, List deletedCategoryNames)
- throws FirebaseSubscribeException, FirebaseUnSubscribeException
- {
- SubscribedRollbackEvent subscribedRollbackEvent = new SubscribedRollbackEvent(userToken);
- Events.raise(subscribedRollbackEvent);
-
- subscribeUserCategory(userToken, savedCategoryNames, subscribedRollbackEvent);
- unsubscribeUserCategory(userToken, deletedCategoryNames, subscribedRollbackEvent);
- }
-
- private void subscribeUserCategory(
- String token,
- List newCategoryNames,
- SubscribedRollbackEvent subscribedRollbackEvent) throws FirebaseSubscribeException
- {
- for (CategoryName newCategoryName : newCategoryNames) {
- firebaseService.subscribe(token, newCategoryName.getName());
- userService.subscribeCategory(token, newCategoryName);
- subscribedRollbackEvent.addNewCategoryName(newCategoryName.getName());
- log.info("구독 성공 = {}", newCategoryName.getName());
- }
- }
-
- private void unsubscribeUserCategory(
- String token,
- List removeCategoryNames,
- SubscribedRollbackEvent subscribedRollbackEvent) throws FirebaseUnSubscribeException
- {
- for (CategoryName removeCategoryName : removeCategoryNames) {
- firebaseService.unsubscribe(token, removeCategoryName.getName());
- userService.unsubscribeCategory(token, removeCategoryName);
- subscribedRollbackEvent.deleteNewCategoryName(removeCategoryName.getName());
- log.info("구독 취소 = {}", removeCategoryName.getName());
- }
- }
-
- private void editDepartmentNameList(
- String userToken, List savedDepartmentNames, List deletedDepartmentNames)
- throws FirebaseSubscribeException, FirebaseUnSubscribeException
- {
- SubscribedRollbackEvent subscribedRollbackEvent = new SubscribedRollbackEvent(userToken);
- Events.raise(subscribedRollbackEvent);
-
- subscribeDepartment(userToken, savedDepartmentNames, subscribedRollbackEvent);
- unsubscribeDepartment(userToken, deletedDepartmentNames, subscribedRollbackEvent);
- }
-
- private void subscribeDepartment(String userToken, List newDepartmentNames, SubscribedRollbackEvent subscribedRollbackEvent) {
- for (DepartmentName newDepartmentName : newDepartmentNames) {
- firebaseService.subscribe(userToken, newDepartmentName.getName());
- userService.subscribeDepartment(userToken, newDepartmentName);
- subscribedRollbackEvent.addNewCategoryName(newDepartmentName.getName());
- log.info("구독 성공 = {}", newDepartmentName.getName());
- }
- }
-
- private void unsubscribeDepartment(String userToken, List removeDepartmentNames, SubscribedRollbackEvent subscribedRollbackEvent) {
- for (DepartmentName removeDepartmentName : removeDepartmentNames) {
- firebaseService.unsubscribe(userToken, removeDepartmentName.getName());
- userService.unsubscribeDepartment(userToken, removeDepartmentName);
- subscribedRollbackEvent.deleteNewCategoryName(removeDepartmentName.getName());
- log.info("구독 취소 = {}", removeDepartmentName.getName());
- }
- }
-}
diff --git a/src/main/java/com/kustacks/kuring/user/facade/UserQueryFacade.java b/src/main/java/com/kustacks/kuring/user/facade/UserQueryFacade.java
deleted file mode 100644
index 60089a0d..00000000
--- a/src/main/java/com/kustacks/kuring/user/facade/UserQueryFacade.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.kustacks.kuring.user.facade;
-
-import com.kustacks.kuring.admin.common.dto.FeedbackDto;
-import com.kustacks.kuring.message.firebase.FirebaseService;
-import com.kustacks.kuring.notice.common.dto.CategoryNameDto;
-import com.kustacks.kuring.notice.common.dto.DepartmentNameDto;
-import com.kustacks.kuring.notice.domain.CategoryName;
-import com.kustacks.kuring.notice.domain.DepartmentName;
-import com.kustacks.kuring.user.business.UserService;
-import com.kustacks.kuring.user.common.dto.BookmarkDto;
-import lombok.RequiredArgsConstructor;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.util.List;
-
-@Service
-@Transactional(readOnly = true)
-@RequiredArgsConstructor
-public class UserQueryFacade {
-
- private final UserService userService;
- private final FirebaseService firebaseService;
-
- public List lookupSubscribeCategories(String userToken) {
- firebaseService.validationToken(userToken);
- return convertCategoryNameDtoList(userService.lookUpUserCategories(userToken));
- }
-
- public List lookupSubscribeDepartments(String userToken) {
- firebaseService.validationToken(userToken);
- return convertDepartmentDtoList(userService.lookupSubscribeDepartmentList(userToken));
- }
-
- public List lookupFeedbacks(int page, int size) {
- return userService.lookupFeedbacks(page, size);
- }
-
- public List lookupUserBookmarkedNotices(String userToken) {
- return userService.lookupUserBookmarkedNotices(userToken);
- }
-
- private List convertCategoryNameDtoList(List categoryNamesList) {
- return categoryNamesList.stream()
- .map(CategoryNameDto::from)
- .toList();
- }
-
- private List convertDepartmentDtoList(List