diff --git a/build.gradle b/build.gradle
index ed442ea..a011a6a 100644
--- a/build.gradle
+++ b/build.gradle
@@ -3,6 +3,7 @@ plugins {
id 'org.springframework.boot' version '3.5.7'
id 'io.spring.dependency-management' version '1.1.7'
id 'com.diffplug.spotless' version '6.25.0'
+ id 'checkstyle'
}
group = 'opensource'
@@ -66,26 +67,28 @@ tasks.named('test') {
useJUnitPlatform()
}
-apply plugin: 'checkstyle'
+tasks.register("checkstyle") {
+ dependsOn("checkstyleMain", "checkstyleTest")
+}
checkstyle {
- toolVersion = '10.12.0'
- configFile = file('config/checkstyle/google_checks.xml')
+ toolVersion = "10.12.0"
+
+ configFile = file("${rootDir}/config/checkstyle/google_checks.xml")
}
-tasks.withType(Checkstyle) {
+tasks.withType(Checkstyle).configureEach {
reports {
xml.required.set(true)
html.required.set(true)
}
}
-// Spotless 적용
-apply plugin: 'com.diffplug.spotless'
-
spotless {
java {
- googleJavaFormat()
+ eclipse().configFile file("${rootDir}/config/checkstyle/checkstyle_eclipse_format.xml")
target 'src/**/*.java'
+ trimTrailingWhitespace()
+ endWithNewline()
}
}
\ No newline at end of file
diff --git a/config/checkstyle/checkstyle_eclipse_format.xml b/config/checkstyle/checkstyle_eclipse_format.xml
new file mode 100644
index 0000000..b13dbcb
--- /dev/null
+++ b/config/checkstyle/checkstyle_eclipse_format.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/config/checkstyle/google_checks.xml b/config/checkstyle/google_checks.xml
index 6eff7fe..1013d86 100644
--- a/config/checkstyle/google_checks.xml
+++ b/config/checkstyle/google_checks.xml
@@ -1,10 +1,46 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
\ No newline at end of file
+
diff --git a/src/main/java/opensource/bravest/BravestApplication.java b/src/main/java/opensource/bravest/BravestApplication.java
index 144da2e..15912ca 100644
--- a/src/main/java/opensource/bravest/BravestApplication.java
+++ b/src/main/java/opensource/bravest/BravestApplication.java
@@ -6,7 +6,7 @@
@SpringBootApplication
public class BravestApplication {
- public static void main(String[] args) {
- SpringApplication.run(BravestApplication.class, args);
- }
+ public static void main(String[] args) {
+ SpringApplication.run(BravestApplication.class, args);
+ }
}
diff --git a/src/main/java/opensource/bravest/domain/chatList/controller/ChatListController.java b/src/main/java/opensource/bravest/domain/chatList/controller/ChatListController.java
index 38810d3..8c51ad4 100644
--- a/src/main/java/opensource/bravest/domain/chatList/controller/ChatListController.java
+++ b/src/main/java/opensource/bravest/domain/chatList/controller/ChatListController.java
@@ -23,37 +23,36 @@
@RequiredArgsConstructor
public class ChatListController {
- private final ChatListService chatListService;
-
- @PostMapping
- public ApiResponse createChatList(
- @Valid @RequestBody ChatListCreateRequest request) {
- ChatListResponse response = chatListService.createChatList(request);
- return ApiResponse.onSuccess(response);
- }
-
- @GetMapping("/room/{roomId}")
- public ApiResponse> getChatListsByRoomId(@PathVariable Long roomId) {
- List response = chatListService.getChatListsByRoomId(roomId);
- return ApiResponse.onSuccess(response);
- }
-
- @GetMapping("/{id}")
- public ApiResponse getChatListById(@PathVariable Long id) {
- ChatListResponse response = chatListService.getChatListById(id);
- return ApiResponse.onSuccess(response);
- }
-
- @PutMapping("/{id}")
- public ApiResponse updateChatList(
- @PathVariable Long id, @Valid @RequestBody ChatListUpdateRequest request) {
- ChatListResponse response = chatListService.updateChatList(id, request);
- return ApiResponse.onSuccess(response);
- }
-
- @DeleteMapping("/{id}")
- public ApiResponse deleteChatList(@PathVariable Long id) {
- chatListService.deleteChatList(id);
- return ApiResponse.onSuccess(null);
- }
+ private final ChatListService chatListService;
+
+ @PostMapping
+ public ApiResponse createChatList(@Valid @RequestBody ChatListCreateRequest request) {
+ ChatListResponse response = chatListService.createChatList(request);
+ return ApiResponse.onSuccess(response);
+ }
+
+ @GetMapping("/room/{roomId}")
+ public ApiResponse> getChatListsByRoomId(@PathVariable Long roomId) {
+ List response = chatListService.getChatListsByRoomId(roomId);
+ return ApiResponse.onSuccess(response);
+ }
+
+ @GetMapping("/{id}")
+ public ApiResponse getChatListById(@PathVariable Long id) {
+ ChatListResponse response = chatListService.getChatListById(id);
+ return ApiResponse.onSuccess(response);
+ }
+
+ @PutMapping("/{id}")
+ public ApiResponse updateChatList(@PathVariable Long id,
+ @Valid @RequestBody ChatListUpdateRequest request) {
+ ChatListResponse response = chatListService.updateChatList(id, request);
+ return ApiResponse.onSuccess(response);
+ }
+
+ @DeleteMapping("/{id}")
+ public ApiResponse deleteChatList(@PathVariable Long id) {
+ chatListService.deleteChatList(id);
+ return ApiResponse.onSuccess(null);
+ }
}
diff --git a/src/main/java/opensource/bravest/domain/chatList/dto/ChatListDto.java b/src/main/java/opensource/bravest/domain/chatList/dto/ChatListDto.java
index 77baf7d..ff012ac 100644
--- a/src/main/java/opensource/bravest/domain/chatList/dto/ChatListDto.java
+++ b/src/main/java/opensource/bravest/domain/chatList/dto/ChatListDto.java
@@ -8,44 +8,40 @@
public class ChatListDto {
- // 1. 아이디어 생성 요청 DTO (Create Request)
- @Getter
- @Setter
- public static class ChatListCreateRequest {
-
- private Long roomId;
-
- private String content;
-
- private Long registeredBy;
- }
-
- // 2. 아이디어 수정 요청 DTO (Update Request)
- @Getter
- @Setter
- public static class ChatListUpdateRequest {
-
- // 아이디어 내용 수정만 가정
- private String content;
- }
-
- @Getter
- @Builder
- public static class ChatListResponse {
- private Long id;
- private Long roomId;
- private String content;
- private Long registeredBy;
- private LocalDateTime createdAt;
-
- public static ChatListResponse fromEntity(ChatList chatList) {
- return ChatListResponse.builder()
- .id(chatList.getId())
- .roomId(chatList.getRoomId())
- .content(chatList.getContent())
- .registeredBy(chatList.getRegisteredBy().getId())
- .createdAt(chatList.getCreatedAt())
- .build();
+ // 1. 아이디어 생성 요청 DTO (Create Request)
+ @Getter
+ @Setter
+ public static class ChatListCreateRequest {
+
+ private Long roomId;
+
+ private String content;
+
+ private Long registeredBy;
+ }
+
+ // 2. 아이디어 수정 요청 DTO (Update Request)
+ @Getter
+ @Setter
+ public static class ChatListUpdateRequest {
+
+ // 아이디어 내용 수정만 가정
+ private String content;
+ }
+
+ @Getter
+ @Builder
+ public static class ChatListResponse {
+ private Long id;
+ private Long roomId;
+ private String content;
+ private Long registeredBy;
+ private LocalDateTime createdAt;
+
+ public static ChatListResponse fromEntity(ChatList chatList) {
+ return ChatListResponse.builder().id(chatList.getId()).roomId(chatList.getRoomId())
+ .content(chatList.getContent()).registeredBy(chatList.getRegisteredBy().getId())
+ .createdAt(chatList.getCreatedAt()).build();
+ }
}
- }
}
diff --git a/src/main/java/opensource/bravest/domain/chatList/entity/ChatList.java b/src/main/java/opensource/bravest/domain/chatList/entity/ChatList.java
index 63cb45a..d4a93d8 100644
--- a/src/main/java/opensource/bravest/domain/chatList/entity/ChatList.java
+++ b/src/main/java/opensource/bravest/domain/chatList/entity/ChatList.java
@@ -25,40 +25,41 @@
@Table(name = "chat_list")
public class ChatList {
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long id;
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
- @ManyToOne(fetch = FetchType.LAZY)
- @JoinColumn(name = "room_id", nullable = false)
- private AnonymousRoom room;
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "room_id", nullable = false)
+ private AnonymousRoom room;
- @NotNull
- @Column(length = 255)
- private String content;
+ @NotNull
+ @Column(length = 255)
+ private String content;
- @ManyToOne(fetch = FetchType.LAZY)
- @JoinColumn(name = "profile_id", nullable = false)
- private AnonymousProfile registeredBy;
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "profile_id", nullable = false)
+ private AnonymousProfile registeredBy;
- @CreationTimestamp private LocalDateTime createdAt;
+ @CreationTimestamp
+ private LocalDateTime createdAt;
- @Builder
- public ChatList(AnonymousRoom room, String content, AnonymousProfile registeredBy) {
- this.room = room;
- this.content = content;
- this.registeredBy = registeredBy;
- }
+ @Builder
+ public ChatList(AnonymousRoom room, String content, AnonymousProfile registeredBy) {
+ this.room = room;
+ this.content = content;
+ this.registeredBy = registeredBy;
+ }
- public void updateContent(String content) {
- this.content = content;
- }
+ public void updateContent(String content) {
+ this.content = content;
+ }
- public Long getRoomId() {
- return this.room.getId();
- }
+ public Long getRoomId() {
+ return this.room.getId();
+ }
- public Long getProfileId() {
- return this.registeredBy.getId();
- }
+ public Long getProfileId() {
+ return this.registeredBy.getId();
+ }
}
diff --git a/src/main/java/opensource/bravest/domain/chatList/repository/ChatListRepository.java b/src/main/java/opensource/bravest/domain/chatList/repository/ChatListRepository.java
index b90efd1..b005041 100644
--- a/src/main/java/opensource/bravest/domain/chatList/repository/ChatListRepository.java
+++ b/src/main/java/opensource/bravest/domain/chatList/repository/ChatListRepository.java
@@ -7,6 +7,6 @@
public interface ChatListRepository extends JpaRepository {
- @Query("SELECT c FROM ChatList c WHERE c.room.id = :roomId ORDER BY c.createdAt DESC")
- List findAllByRoomId(Long roomId);
+ @Query("SELECT c FROM ChatList c WHERE c.room.id = :roomId ORDER BY c.createdAt DESC")
+ List findAllByRoomId(Long roomId);
}
diff --git a/src/main/java/opensource/bravest/domain/chatList/service/ChatListService.java b/src/main/java/opensource/bravest/domain/chatList/service/ChatListService.java
index e375a13..4443986 100644
--- a/src/main/java/opensource/bravest/domain/chatList/service/ChatListService.java
+++ b/src/main/java/opensource/bravest/domain/chatList/service/ChatListService.java
@@ -25,55 +25,48 @@
@Transactional(readOnly = true)
public class ChatListService {
- private final ChatListRepository chatListRepository;
- private final AnonymousRoomRepository anonymousRoomRepository;
- private final AnonymousProfileRepository anonymousProfileRepository;
+ private final ChatListRepository chatListRepository;
+ private final AnonymousRoomRepository anonymousRoomRepository;
+ private final AnonymousProfileRepository anonymousProfileRepository;
- @Transactional
- public ChatListResponse createChatList(ChatListCreateRequest request) {
- AnonymousRoom room =
- anonymousRoomRepository
- .findById(request.getRoomId())
- .orElseThrow(() -> new CustomException(_CHATROOM_NOT_FOUND));
+ @Transactional
+ public ChatListResponse createChatList(ChatListCreateRequest request) {
+ AnonymousRoom room = anonymousRoomRepository.findById(request.getRoomId())
+ .orElseThrow(() -> new CustomException(_CHATROOM_NOT_FOUND));
- AnonymousProfile profile =
- anonymousProfileRepository
- .findById(request.getRegisteredBy())
- .orElseThrow(() -> new CustomException(_USER_NOT_FOUND));
+ AnonymousProfile profile = anonymousProfileRepository.findById(request.getRegisteredBy())
+ .orElseThrow(() -> new CustomException(_USER_NOT_FOUND));
- ChatList chatList =
- ChatList.builder().room(room).registeredBy(profile).content(request.getContent()).build();
+ ChatList chatList = ChatList.builder().room(room).registeredBy(profile).content(request.getContent()).build();
- ChatList savedList = chatListRepository.save(chatList);
- return ChatListResponse.fromEntity(savedList);
- }
+ ChatList savedList = chatListRepository.save(chatList);
+ return ChatListResponse.fromEntity(savedList);
+ }
- public List getChatListsByRoomId(Long roomId) {
- List chatLists = chatListRepository.findAllByRoomId(roomId);
- return chatLists.stream().map(ChatListResponse::fromEntity).collect(Collectors.toList());
- }
+ public List getChatListsByRoomId(Long roomId) {
+ List chatLists = chatListRepository.findAllByRoomId(roomId);
+ return chatLists.stream().map(ChatListResponse::fromEntity).collect(Collectors.toList());
+ }
- public ChatListResponse getChatListById(Long id) {
- ChatList chatList =
- chatListRepository.findById(id).orElseThrow(() -> new CustomException(_CHATLIST_NOT_FOUND));
- return ChatListResponse.fromEntity(chatList);
- }
+ public ChatListResponse getChatListById(Long id) {
+ ChatList chatList = chatListRepository.findById(id).orElseThrow(() -> new CustomException(_CHATLIST_NOT_FOUND));
+ return ChatListResponse.fromEntity(chatList);
+ }
- @Transactional
- public ChatListResponse updateChatList(Long id, ChatListUpdateRequest request) {
- ChatList chatList =
- chatListRepository.findById(id).orElseThrow(() -> new CustomException(_CHATLIST_NOT_FOUND));
+ @Transactional
+ public ChatListResponse updateChatList(Long id, ChatListUpdateRequest request) {
+ ChatList chatList = chatListRepository.findById(id).orElseThrow(() -> new CustomException(_CHATLIST_NOT_FOUND));
- chatList.updateContent(request.getContent());
+ chatList.updateContent(request.getContent());
- return ChatListResponse.fromEntity(chatList);
- }
+ return ChatListResponse.fromEntity(chatList);
+ }
- @Transactional
- public void deleteChatList(Long id) {
- if (!chatListRepository.existsById(id)) {
- throw new CustomException(_CHATLIST_NOT_FOUND);
+ @Transactional
+ public void deleteChatList(Long id) {
+ if (!chatListRepository.existsById(id)) {
+ throw new CustomException(_CHATLIST_NOT_FOUND);
+ }
+ chatListRepository.deleteById(id);
}
- chatListRepository.deleteById(id);
- }
}
diff --git a/src/main/java/opensource/bravest/domain/message/controller/ChatMessageController.java b/src/main/java/opensource/bravest/domain/message/controller/ChatMessageController.java
index 609e347..a80df92 100644
--- a/src/main/java/opensource/bravest/domain/message/controller/ChatMessageController.java
+++ b/src/main/java/opensource/bravest/domain/message/controller/ChatMessageController.java
@@ -17,17 +17,17 @@
@Controller
@RequiredArgsConstructor
public class ChatMessageController {
- private final ChatMessageService chatMessageService;
- private final SimpMessagingTemplate messagingTemplate;
+ private final ChatMessageService chatMessageService;
+ private final SimpMessagingTemplate messagingTemplate;
- @MessageMapping("/send")
- @SendTo("/subs/chat-rooms")
- public void receiveMessage(MessageRequest request, Principal principal) {
- Long id = Long.parseLong(principal.getName());
- MessageResponse response = chatMessageService.send(request, id);
+ @MessageMapping("/send")
+ @SendTo("/subs/chat-rooms")
+ public void receiveMessage(MessageRequest request, Principal principal) {
+ Long id = Long.parseLong(principal.getName());
+ MessageResponse response = chatMessageService.send(request, id);
- // 특정 채팅방 구독자들에게 메시지 전송
- messagingTemplate.convertAndSend(
- "/subs/chat-rooms/" + request.getChatRoomId(), ApiResponse.onSuccess(response));
- }
+ // 특정 채팅방 구독자들에게 메시지 전송
+ messagingTemplate.convertAndSend("/subs/chat-rooms/" + request.getChatRoomId(),
+ ApiResponse.onSuccess(response));
+ }
}
diff --git a/src/main/java/opensource/bravest/domain/message/dto/MessageDto.java b/src/main/java/opensource/bravest/domain/message/dto/MessageDto.java
index 72b32c5..f44edbb 100644
--- a/src/main/java/opensource/bravest/domain/message/dto/MessageDto.java
+++ b/src/main/java/opensource/bravest/domain/message/dto/MessageDto.java
@@ -7,36 +7,34 @@
public class MessageDto {
- @Getter
- public static class SendMessageRequest {
- private String content;
- }
+ @Getter
+ public static class SendMessageRequest {
+ private String content;
+ }
- @Getter
- @RequiredArgsConstructor
- public static class MessageResponse {
- private final String senderName; // 익명 닉네임
- private final String content;
- private final LocalDateTime createdAt;
+ @Getter
+ @RequiredArgsConstructor
+ public static class MessageResponse {
+ private final String senderName; // 익명 닉네임
+ private final String content;
+ private final LocalDateTime createdAt;
- public static MessageResponse from(ChatMessage chatMessage) {
- return new MessageResponse(
- chatMessage.getSender().getAnonymousName(),
- chatMessage.getContent(),
- chatMessage.getCreatedAt());
+ public static MessageResponse from(ChatMessage chatMessage) {
+ return new MessageResponse(chatMessage.getSender().getAnonymousName(), chatMessage.getContent(),
+ chatMessage.getCreatedAt());
+ }
}
- }
- @Getter
- @RequiredArgsConstructor
- public static class MessageRequest {
- private final Long chatRoomId;
- private final String content;
- }
+ @Getter
+ @RequiredArgsConstructor
+ public static class MessageRequest {
+ private final Long chatRoomId;
+ private final String content;
+ }
- @Getter
- @RequiredArgsConstructor
- public static class ChatReadRequest {
- private final Long chatRoomId;
- }
+ @Getter
+ @RequiredArgsConstructor
+ public static class ChatReadRequest {
+ private final Long chatRoomId;
+ }
}
diff --git a/src/main/java/opensource/bravest/domain/message/entity/ChatMessage.java b/src/main/java/opensource/bravest/domain/message/entity/ChatMessage.java
index 2ab7d59..2544637 100644
--- a/src/main/java/opensource/bravest/domain/message/entity/ChatMessage.java
+++ b/src/main/java/opensource/bravest/domain/message/entity/ChatMessage.java
@@ -13,22 +13,22 @@
@Builder
public class ChatMessage {
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long id;
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
- // 어느 방의 메시지인지
- @ManyToOne(fetch = FetchType.LAZY)
- @JoinColumn(name = "room_id", nullable = false)
- private AnonymousRoom room;
+ // 어느 방의 메시지인지
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "room_id", nullable = false)
+ private AnonymousRoom room;
- // 누가 보냈는지 (익명 프로필 기준)
- @ManyToOne(fetch = FetchType.LAZY)
- @JoinColumn(name = "anonymous_profile_id", nullable = false)
- private AnonymousProfile sender;
+ // 누가 보냈는지 (익명 프로필 기준)
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "anonymous_profile_id", nullable = false)
+ private AnonymousProfile sender;
- @Column(nullable = false, length = 1000)
- private String content;
+ @Column(nullable = false, length = 1000)
+ private String content;
- private LocalDateTime createdAt;
+ private LocalDateTime createdAt;
}
diff --git a/src/main/java/opensource/bravest/domain/message/repository/ChatMessageRepository.java b/src/main/java/opensource/bravest/domain/message/repository/ChatMessageRepository.java
index eaae205..4621641 100644
--- a/src/main/java/opensource/bravest/domain/message/repository/ChatMessageRepository.java
+++ b/src/main/java/opensource/bravest/domain/message/repository/ChatMessageRepository.java
@@ -7,6 +7,6 @@
public interface ChatMessageRepository extends JpaRepository {
- // 방 기준으로 최근 메시지 목록
- List findByRoomOrderByCreatedAtAsc(AnonymousRoom room);
+ // 방 기준으로 최근 메시지 목록
+ List findByRoomOrderByCreatedAtAsc(AnonymousRoom room);
}
diff --git a/src/main/java/opensource/bravest/domain/message/service/ChatMessageService.java b/src/main/java/opensource/bravest/domain/message/service/ChatMessageService.java
index 57808a6..a5a64de 100644
--- a/src/main/java/opensource/bravest/domain/message/service/ChatMessageService.java
+++ b/src/main/java/opensource/bravest/domain/message/service/ChatMessageService.java
@@ -21,40 +21,35 @@
@RequiredArgsConstructor
public class ChatMessageService {
- private final AnonymousProfileRepository memberRepository;
- private final AnonymousRoomRepository chatRoomRepository;
- private final ChatMessageRepository chatMessageRepository;
-
- // 메시지 전송
- public MessageResponse send(MessageRequest request, Long id) {
- AnonymousProfile sender =
- memberRepository.findById(id).orElseThrow(() -> new CustomException(_USER_NOT_FOUND));
-
- AnonymousRoom chatRoom =
- chatRoomRepository
- .findById(request.getChatRoomId())
- .orElseThrow(() -> new CustomException(_CHATROOM_NOT_FOUND));
-
- ChatMessage chatMessage =
- ChatMessage.builder().room(chatRoom).sender(sender).content(request.getContent()).build();
-
- chatMessageRepository.save(chatMessage);
-
- return MessageResponse.from(chatMessage);
- }
-
- @Transactional
- public void readMessages(Long chatRoomId, Long memberId) {
- AnonymousRoom chatRoom =
- chatRoomRepository
- .findById(chatRoomId)
- .orElseThrow(() -> new CustomException(_CHATROOM_NOT_FOUND));
-
- // if (!Objects.equals(chatRoom.getMember1().getId(), memberId) &&
- // !Objects.equals(chatRoom.getMember2().getId(),
- // memberId)) {
- // throw new BaseException(ChatExceptionType.CHAT_ROOM_ACCESS_DENIED);
- // }
- // messageReceiptRepository.bulkUpdateStatusToRead(chatRoomId, memberId);
- }
+ private final AnonymousProfileRepository memberRepository;
+ private final AnonymousRoomRepository chatRoomRepository;
+ private final ChatMessageRepository chatMessageRepository;
+
+ // 메시지 전송
+ public MessageResponse send(MessageRequest request, Long id) {
+ AnonymousProfile sender = memberRepository.findById(id).orElseThrow(() -> new CustomException(_USER_NOT_FOUND));
+
+ AnonymousRoom chatRoom = chatRoomRepository.findById(request.getChatRoomId())
+ .orElseThrow(() -> new CustomException(_CHATROOM_NOT_FOUND));
+
+ ChatMessage chatMessage = ChatMessage.builder().room(chatRoom).sender(sender).content(request.getContent())
+ .build();
+
+ chatMessageRepository.save(chatMessage);
+
+ return MessageResponse.from(chatMessage);
+ }
+
+ @Transactional
+ public void readMessages(Long chatRoomId, Long memberId) {
+ AnonymousRoom chatRoom = chatRoomRepository.findById(chatRoomId)
+ .orElseThrow(() -> new CustomException(_CHATROOM_NOT_FOUND));
+
+ // if (!Objects.equals(chatRoom.getMember1().getId(), memberId) &&
+ // !Objects.equals(chatRoom.getMember2().getId(),
+ // memberId)) {
+ // throw new BaseException(ChatExceptionType.CHAT_ROOM_ACCESS_DENIED);
+ // }
+ // messageReceiptRepository.bulkUpdateStatusToRead(chatRoomId, memberId);
+ }
}
diff --git a/src/main/java/opensource/bravest/domain/profile/controller/AnonymousProfileController.java b/src/main/java/opensource/bravest/domain/profile/controller/AnonymousProfileController.java
index 6b2923f..02dcb41 100644
--- a/src/main/java/opensource/bravest/domain/profile/controller/AnonymousProfileController.java
+++ b/src/main/java/opensource/bravest/domain/profile/controller/AnonymousProfileController.java
@@ -15,21 +15,21 @@
@RequestMapping("/anonymous-profiles")
public class AnonymousProfileController {
- private final AnonymousProfileService anonymousProfileService;
+ private final AnonymousProfileService anonymousProfileService;
- @Operation(summary = "익명 프로필 생성", description = "특정 채팅방에 대한 새로운 익명 프로필을 생성합니다.")
- @PostMapping("/rooms/{roomId}")
- public ApiResponse createAnonymousProfile(
- @PathVariable Long roomId, @RequestBody CreateAnonymousProfileRequest request) {
- AnonymousProfile profile = anonymousProfileService.createAnonymousProfile(roomId, request);
- AnonymousProfileResponse response = AnonymousProfileResponse.from(profile);
- return ApiResponse.of(SuccessStatus._CREATED, SuccessStatus._CREATED.getMessage(), response);
- }
+ @Operation(summary = "익명 프로필 생성", description = "특정 채팅방에 대한 새로운 익명 프로필을 생성합니다.")
+ @PostMapping("/rooms/{roomId}")
+ public ApiResponse createAnonymousProfile(@PathVariable Long roomId,
+ @RequestBody CreateAnonymousProfileRequest request) {
+ AnonymousProfile profile = anonymousProfileService.createAnonymousProfile(roomId, request);
+ AnonymousProfileResponse response = AnonymousProfileResponse.from(profile);
+ return ApiResponse.of(SuccessStatus._CREATED, SuccessStatus._CREATED.getMessage(), response);
+ }
- @DeleteMapping("/{profileId}")
- @Operation(summary = "익명 프로필 삭제", description = "ID로 특정 익명 프로필을 삭제합니다.")
- public ApiResponse> deleteAnonymousProfile(@PathVariable Long profileId) {
- anonymousProfileService.deleteAnonymousProfile(profileId);
- return ApiResponse.of(SuccessStatus._OK, SuccessStatus._OK.getMessage(), null);
- }
+ @DeleteMapping("/{profileId}")
+ @Operation(summary = "익명 프로필 삭제", description = "ID로 특정 익명 프로필을 삭제합니다.")
+ public ApiResponse> deleteAnonymousProfile(@PathVariable Long profileId) {
+ anonymousProfileService.deleteAnonymousProfile(profileId);
+ return ApiResponse.of(SuccessStatus._OK, SuccessStatus._OK.getMessage(), null);
+ }
}
diff --git a/src/main/java/opensource/bravest/domain/profile/dto/AnonymousProfileResponse.java b/src/main/java/opensource/bravest/domain/profile/dto/AnonymousProfileResponse.java
index 95165ea..de5ba8c 100644
--- a/src/main/java/opensource/bravest/domain/profile/dto/AnonymousProfileResponse.java
+++ b/src/main/java/opensource/bravest/domain/profile/dto/AnonymousProfileResponse.java
@@ -7,17 +7,14 @@
@Getter
@Builder
public class AnonymousProfileResponse {
- private Long id;
- private Long roomId;
- private String nickname;
+ private Long id;
+ private Long roomId;
+ private String nickname;
- // 필요한 필드만
+ // 필요한 필드만
- public static AnonymousProfileResponse from(AnonymousProfile profile) {
- return AnonymousProfileResponse.builder()
- .id(profile.getId())
- .roomId(profile.getRoom().getId())
- .nickname(profile.getAnonymousName())
- .build();
- }
+ public static AnonymousProfileResponse from(AnonymousProfile profile) {
+ return AnonymousProfileResponse.builder().id(profile.getId()).roomId(profile.getRoom().getId())
+ .nickname(profile.getAnonymousName()).build();
+ }
}
diff --git a/src/main/java/opensource/bravest/domain/profile/dto/CreateAnonymousProfileRequest.java b/src/main/java/opensource/bravest/domain/profile/dto/CreateAnonymousProfileRequest.java
index 9c43be9..4b06c9e 100644
--- a/src/main/java/opensource/bravest/domain/profile/dto/CreateAnonymousProfileRequest.java
+++ b/src/main/java/opensource/bravest/domain/profile/dto/CreateAnonymousProfileRequest.java
@@ -6,6 +6,6 @@
@Getter
@NoArgsConstructor
public class CreateAnonymousProfileRequest {
- private Long realUserId;
- private String anonymousName;
+ private Long realUserId;
+ private String anonymousName;
}
diff --git a/src/main/java/opensource/bravest/domain/profile/entity/AnonymousProfile.java b/src/main/java/opensource/bravest/domain/profile/entity/AnonymousProfile.java
index fe773e5..1c95fdd 100644
--- a/src/main/java/opensource/bravest/domain/profile/entity/AnonymousProfile.java
+++ b/src/main/java/opensource/bravest/domain/profile/entity/AnonymousProfile.java
@@ -11,20 +11,20 @@
@Builder
public class AnonymousProfile {
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long id;
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
- // 어떤 방에 속한 익명 프로필인지
- @ManyToOne(fetch = FetchType.LAZY)
- @JoinColumn(name = "room_id", nullable = false)
- private AnonymousRoom room;
+ // 어떤 방에 속한 익명 프로필인지
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "room_id", nullable = false)
+ private AnonymousRoom room;
- // 실제 유저 PK (User 테이블 없다면 JWT의 userId 기준으로)
- @Column(nullable = false)
- private Long realUserId;
+ // 실제 유저 PK (User 테이블 없다면 JWT의 userId 기준으로)
+ @Column(nullable = false)
+ private Long realUserId;
- // 방 안에서 보여줄 익명 닉네임 (예: BlueTiger12)
- @Column(nullable = false, length = 50)
- private String anonymousName;
+ // 방 안에서 보여줄 익명 닉네임 (예: BlueTiger12)
+ @Column(nullable = false, length = 50)
+ private String anonymousName;
}
diff --git a/src/main/java/opensource/bravest/domain/profile/repository/AnonymousProfileRepository.java b/src/main/java/opensource/bravest/domain/profile/repository/AnonymousProfileRepository.java
index 88bbdbe..103c514 100644
--- a/src/main/java/opensource/bravest/domain/profile/repository/AnonymousProfileRepository.java
+++ b/src/main/java/opensource/bravest/domain/profile/repository/AnonymousProfileRepository.java
@@ -7,6 +7,6 @@
public interface AnonymousProfileRepository extends JpaRepository {
- // 같은 방 + 같은 실제 유저라면 익명 프로필 하나만 사용
- Optional findByRoomAndRealUserId(AnonymousRoom room, Long realUserId);
+ // 같은 방 + 같은 실제 유저라면 익명 프로필 하나만 사용
+ Optional findByRoomAndRealUserId(AnonymousRoom room, Long realUserId);
}
diff --git a/src/main/java/opensource/bravest/domain/profile/service/AnonymousProfileService.java b/src/main/java/opensource/bravest/domain/profile/service/AnonymousProfileService.java
index 0217c7d..6547577 100644
--- a/src/main/java/opensource/bravest/domain/profile/service/AnonymousProfileService.java
+++ b/src/main/java/opensource/bravest/domain/profile/service/AnonymousProfileService.java
@@ -15,39 +15,32 @@
@Transactional(readOnly = true)
public class AnonymousProfileService {
- private final AnonymousProfileRepository anonymousProfileRepository;
- private final AnonymousRoomRepository anonymousRoomRepository;
-
- @Transactional
- public AnonymousProfile createAnonymousProfile(
- Long roomId, CreateAnonymousProfileRequest request) {
- AnonymousRoom room =
- anonymousRoomRepository
- .findById(roomId)
- .orElseThrow(() -> new RuntimeException("방을 찾을 수 없음.뿡"));
-
- // 중복 프로필 체크
- Optional existingProfile =
- anonymousProfileRepository.findByRoomAndRealUserId(room, request.getRealUserId());
- if (existingProfile.isPresent()) {
- throw new RuntimeException("이미 방에 존재하는 유저임. 다른걸로 접속하셈.");
- }
+ private final AnonymousProfileRepository anonymousProfileRepository;
+ private final AnonymousRoomRepository anonymousRoomRepository;
+
+ @Transactional
+ public AnonymousProfile createAnonymousProfile(Long roomId, CreateAnonymousProfileRequest request) {
+ AnonymousRoom room = anonymousRoomRepository.findById(roomId)
+ .orElseThrow(() -> new RuntimeException("방을 찾을 수 없음.뿡"));
- AnonymousProfile newProfile =
- AnonymousProfile.builder()
- .room(room)
- .realUserId(request.getRealUserId())
- .anonymousName(request.getAnonymousName())
- .build();
+ // 중복 프로필 체크
+ Optional existingProfile = anonymousProfileRepository.findByRoomAndRealUserId(room,
+ request.getRealUserId());
+ if (existingProfile.isPresent()) {
+ throw new RuntimeException("이미 방에 존재하는 유저임. 다른걸로 접속하셈.");
+ }
- return anonymousProfileRepository.save(newProfile);
- }
+ AnonymousProfile newProfile = AnonymousProfile.builder().room(room).realUserId(request.getRealUserId())
+ .anonymousName(request.getAnonymousName()).build();
+
+ return anonymousProfileRepository.save(newProfile);
+ }
- @Transactional
- public void deleteAnonymousProfile(Long profileId) {
- if (!anonymousProfileRepository.existsById(profileId)) {
- throw new RuntimeException("없는 사용자임. 너~ 누구야!");
+ @Transactional
+ public void deleteAnonymousProfile(Long profileId) {
+ if (!anonymousProfileRepository.existsById(profileId)) {
+ throw new RuntimeException("없는 사용자임. 너~ 누구야!");
+ }
+ anonymousProfileRepository.deleteById(profileId);
}
- anonymousProfileRepository.deleteById(profileId);
- }
}
diff --git a/src/main/java/opensource/bravest/domain/room/controller/RoomController.java b/src/main/java/opensource/bravest/domain/room/controller/RoomController.java
index 3a12474..d0faf85 100644
--- a/src/main/java/opensource/bravest/domain/room/controller/RoomController.java
+++ b/src/main/java/opensource/bravest/domain/room/controller/RoomController.java
@@ -14,81 +14,56 @@
@RequestMapping("/rooms")
public class RoomController {
- private final RoomService roomService;
+ private final RoomService roomService;
- @PostMapping
- @Operation(summary = "채팅방 생성", description = "새로운 채팅방을 생성합니다.")
- public ApiResponse createRoom(
- @RequestBody RoomDto.CreateRoomRequest request) {
- AnonymousRoom room = roomService.createRoom(request);
- return ApiResponse.of(
- SuccessStatus._CREATED,
- SuccessStatus._CREATED.getMessage(),
- RoomDto.RoomResponse.builder()
- .id(room.getId())
- .roomCode(room.getRoomCode())
- .title(room.getTitle())
- .createdAt(room.getCreatedAt())
- .build());
- }
+ @PostMapping
+ @Operation(summary = "채팅방 생성", description = "새로운 채팅방을 생성합니다.")
+ public ApiResponse createRoom(@RequestBody RoomDto.CreateRoomRequest request) {
+ AnonymousRoom room = roomService.createRoom(request);
+ return ApiResponse.of(SuccessStatus._CREATED, SuccessStatus._CREATED.getMessage(),
+ RoomDto.RoomResponse.builder().id(room.getId()).roomCode(room.getRoomCode())
+ .title(room.getTitle()).createdAt(room.getCreatedAt()).build());
+ }
- @GetMapping("/{roomId}")
- @Operation(summary = "채팅방 조회", description = "ID로 특정 채팅방의 정보를 조회합니다.")
- public ApiResponse getRoom(@PathVariable Long roomId) {
- AnonymousRoom room = roomService.getRoom(roomId);
- return ApiResponse.of(
- SuccessStatus._OK,
- SuccessStatus._OK.getMessage(),
- RoomDto.RoomResponse.builder()
- .id(room.getId())
- .roomCode(room.getRoomCode())
- .title(room.getTitle())
- .createdAt(room.getCreatedAt())
- .build());
- }
+ @GetMapping("/{roomId}")
+ @Operation(summary = "채팅방 조회", description = "ID로 특정 채팅방의 정보를 조회합니다.")
+ public ApiResponse getRoom(@PathVariable Long roomId) {
+ AnonymousRoom room = roomService.getRoom(roomId);
+ return ApiResponse.of(SuccessStatus._OK, SuccessStatus._OK.getMessage(),
+ RoomDto.RoomResponse.builder().id(room.getId()).roomCode(room.getRoomCode())
+ .title(room.getTitle()).createdAt(room.getCreatedAt()).build());
+ }
- @PutMapping("/{roomId}")
- @Operation(summary = "채팅방 정보 수정", description = "ID로 특정 채팅방의 정보를 수정합니다.")
- public ApiResponse updateRoom(
- @PathVariable Long roomId, @RequestBody RoomDto.UpdateRoomRequest request) {
- AnonymousRoom room = roomService.updateRoom(roomId, request);
- return ApiResponse.of(
- SuccessStatus._OK,
- SuccessStatus._OK.getMessage(),
- RoomDto.RoomResponse.builder()
- .id(room.getId())
- .roomCode(room.getRoomCode())
- .title(room.getTitle())
- .createdAt(room.getCreatedAt())
- .build());
- }
+ @PutMapping("/{roomId}")
+ @Operation(summary = "채팅방 정보 수정", description = "ID로 특정 채팅방의 정보를 수정합니다.")
+ public ApiResponse updateRoom(@PathVariable Long roomId,
+ @RequestBody RoomDto.UpdateRoomRequest request) {
+ AnonymousRoom room = roomService.updateRoom(roomId, request);
+ return ApiResponse.of(SuccessStatus._OK, SuccessStatus._OK.getMessage(),
+ RoomDto.RoomResponse.builder().id(room.getId()).roomCode(room.getRoomCode())
+ .title(room.getTitle()).createdAt(room.getCreatedAt()).build());
+ }
- @DeleteMapping("/{roomId}")
- @Operation(summary = "채팅방 삭제", description = "ID로 특정 채팅방을 삭제합니다.")
- public ApiResponse> deleteRoom(@PathVariable Long roomId) {
- roomService.deleteRoom(roomId);
- return ApiResponse.of(SuccessStatus._OK, SuccessStatus._OK.getMessage(), null);
- }
+ @DeleteMapping("/{roomId}")
+ @Operation(summary = "채팅방 삭제", description = "ID로 특정 채팅방을 삭제합니다.")
+ public ApiResponse> deleteRoom(@PathVariable Long roomId) {
+ roomService.deleteRoom(roomId);
+ return ApiResponse.of(SuccessStatus._OK, SuccessStatus._OK.getMessage(), null);
+ }
- @GetMapping("/{roomId}/invite-code")
- @Operation(summary = "초대 코드 조회", description = "ID로 특정 채팅방의 초대 코드를 조회합니다.")
- public ApiResponse getInviteCode(@PathVariable Long roomId) {
- String inviteCode = roomService.getInviteCode(roomId);
- return ApiResponse.of(SuccessStatus._OK, SuccessStatus._OK.getMessage(), inviteCode);
- }
+ @GetMapping("/{roomId}/invite-code")
+ @Operation(summary = "초대 코드 조회", description = "ID로 특정 채팅방의 초대 코드를 조회합니다.")
+ public ApiResponse getInviteCode(@PathVariable Long roomId) {
+ String inviteCode = roomService.getInviteCode(roomId);
+ return ApiResponse.of(SuccessStatus._OK, SuccessStatus._OK.getMessage(), inviteCode);
+ }
- @PostMapping("/join")
- @Operation(summary = "초대 코드로 채팅방 참여", description = "초대 코드를 사용하여 특정 채팅방에 참여합니다.")
- public ApiResponse joinRoom(@RequestBody RoomDto.JoinRoomRequest request) {
- AnonymousRoom room = roomService.joinRoom(request.getRoomCode());
- return ApiResponse.of(
- SuccessStatus._OK,
- SuccessStatus._OK.getMessage(),
- RoomDto.RoomResponse.builder()
- .id(room.getId())
- .roomCode(room.getRoomCode())
- .title(room.getTitle())
- .createdAt(room.getCreatedAt())
- .build());
- }
+ @PostMapping("/join")
+ @Operation(summary = "초대 코드로 채팅방 참여", description = "초대 코드를 사용하여 특정 채팅방에 참여합니다.")
+ public ApiResponse joinRoom(@RequestBody RoomDto.JoinRoomRequest request) {
+ AnonymousRoom room = roomService.joinRoom(request.getRoomCode());
+ return ApiResponse.of(SuccessStatus._OK, SuccessStatus._OK.getMessage(),
+ RoomDto.RoomResponse.builder().id(room.getId()).roomCode(room.getRoomCode())
+ .title(room.getTitle()).createdAt(room.getCreatedAt()).build());
+ }
}
diff --git a/src/main/java/opensource/bravest/domain/room/dto/RoomDto.java b/src/main/java/opensource/bravest/domain/room/dto/RoomDto.java
index 8655c0c..e0e02dc 100644
--- a/src/main/java/opensource/bravest/domain/room/dto/RoomDto.java
+++ b/src/main/java/opensource/bravest/domain/room/dto/RoomDto.java
@@ -8,32 +8,32 @@
public class RoomDto {
- @Getter
- @NoArgsConstructor
- public static class CreateRoomRequest {
- private String title;
- }
+ @Getter
+ @NoArgsConstructor
+ public static class CreateRoomRequest {
+ private String title;
+ }
- @Getter
- @NoArgsConstructor
- public static class UpdateRoomRequest {
- private String title;
- }
+ @Getter
+ @NoArgsConstructor
+ public static class UpdateRoomRequest {
+ private String title;
+ }
- @Getter
- @Builder
- @NoArgsConstructor
- @AllArgsConstructor
- public static class RoomResponse {
- private Long id;
- private String roomCode;
- private String title;
- private LocalDateTime createdAt;
- }
+ @Getter
+ @Builder
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class RoomResponse {
+ private Long id;
+ private String roomCode;
+ private String title;
+ private LocalDateTime createdAt;
+ }
- @Getter
- @NoArgsConstructor
- public static class JoinRoomRequest {
- private String roomCode;
- }
+ @Getter
+ @NoArgsConstructor
+ public static class JoinRoomRequest {
+ private String roomCode;
+ }
}
diff --git a/src/main/java/opensource/bravest/domain/room/entity/AnonymousRoom.java b/src/main/java/opensource/bravest/domain/room/entity/AnonymousRoom.java
index 3be35e9..ce9b74e 100644
--- a/src/main/java/opensource/bravest/domain/room/entity/AnonymousRoom.java
+++ b/src/main/java/opensource/bravest/domain/room/entity/AnonymousRoom.java
@@ -14,25 +14,25 @@
@Builder
public class AnonymousRoom {
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long id;
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
- // 친구들에게 공유하는 코드 (예: ABC123)
- @Column(nullable = false, unique = true, length = 20)
- private String roomCode;
+ // 친구들에게 공유하는 코드 (예: ABC123)
+ @Column(nullable = false, unique = true, length = 20)
+ private String roomCode;
- // 방 제목 (선택)
- @Column(nullable = false, length = 100)
- private String title;
+ // 방 제목 (선택)
+ @Column(nullable = false, length = 100)
+ private String title;
- @OneToMany(mappedBy = "room", cascade = CascadeType.ALL, orphanRemoval = true)
- @Builder.Default
- private List profiles = new ArrayList<>();
+ @OneToMany(mappedBy = "room", cascade = CascadeType.ALL, orphanRemoval = true)
+ @Builder.Default
+ private List profiles = new ArrayList<>();
- private LocalDateTime createdAt;
+ private LocalDateTime createdAt;
- public void updateTitle(String title) {
- this.title = title;
- }
+ public void updateTitle(String title) {
+ this.title = title;
+ }
}
diff --git a/src/main/java/opensource/bravest/domain/room/repository/AnonymousRoomRepository.java b/src/main/java/opensource/bravest/domain/room/repository/AnonymousRoomRepository.java
index a900571..d58c838 100644
--- a/src/main/java/opensource/bravest/domain/room/repository/AnonymousRoomRepository.java
+++ b/src/main/java/opensource/bravest/domain/room/repository/AnonymousRoomRepository.java
@@ -6,7 +6,7 @@
public interface AnonymousRoomRepository extends JpaRepository {
- Optional findByRoomCode(String roomCode);
+ Optional findByRoomCode(String roomCode);
- boolean existsByRoomCode(String roomCode);
+ boolean existsByRoomCode(String roomCode);
}
diff --git a/src/main/java/opensource/bravest/domain/room/service/RoomService.java b/src/main/java/opensource/bravest/domain/room/service/RoomService.java
index 21d1c2c..5ea299b 100644
--- a/src/main/java/opensource/bravest/domain/room/service/RoomService.java
+++ b/src/main/java/opensource/bravest/domain/room/service/RoomService.java
@@ -14,57 +14,50 @@
@Transactional(readOnly = true)
public class RoomService {
- private final AnonymousRoomRepository anonymousRoomRepository;
-
- @Transactional
- public AnonymousRoom createRoom(RoomDto.CreateRoomRequest request) {
- String roomCode = generateUniqueRoomCode();
- AnonymousRoom room =
- AnonymousRoom.builder()
- .title(request.getTitle())
- .roomCode(roomCode)
- .createdAt(LocalDateTime.now())
- .build();
- return anonymousRoomRepository.save(room);
- }
+ private final AnonymousRoomRepository anonymousRoomRepository;
+
+ @Transactional
+ public AnonymousRoom createRoom(RoomDto.CreateRoomRequest request) {
+ String roomCode = generateUniqueRoomCode();
+ AnonymousRoom room = AnonymousRoom.builder().title(request.getTitle()).roomCode(roomCode)
+ .createdAt(LocalDateTime.now()).build();
+ return anonymousRoomRepository.save(room);
+ }
- public AnonymousRoom getRoom(Long roomId) {
- return anonymousRoomRepository
- .findById(roomId)
- .orElseThrow(() -> new RuntimeException("Room not found"));
- }
+ public AnonymousRoom getRoom(Long roomId) {
+ return anonymousRoomRepository.findById(roomId).orElseThrow(() -> new RuntimeException("Room not found"));
+ }
- @Transactional
- public AnonymousRoom updateRoom(Long roomId, RoomDto.UpdateRoomRequest request) {
- AnonymousRoom room = getRoom(roomId);
- room.updateTitle(request.getTitle());
- return room;
- }
+ @Transactional
+ public AnonymousRoom updateRoom(Long roomId, RoomDto.UpdateRoomRequest request) {
+ AnonymousRoom room = getRoom(roomId);
+ room.updateTitle(request.getTitle());
+ return room;
+ }
- @Transactional
- public void deleteRoom(Long roomId) {
- if (!anonymousRoomRepository.existsById(roomId)) {
- throw new RuntimeException("Room not found");
+ @Transactional
+ public void deleteRoom(Long roomId) {
+ if (!anonymousRoomRepository.existsById(roomId)) {
+ throw new RuntimeException("Room not found");
+ }
+ anonymousRoomRepository.deleteById(roomId);
}
- anonymousRoomRepository.deleteById(roomId);
- }
- public String getInviteCode(Long roomId) {
- AnonymousRoom room = getRoom(roomId);
- return room.getRoomCode();
- }
+ public String getInviteCode(Long roomId) {
+ AnonymousRoom room = getRoom(roomId);
+ return room.getRoomCode();
+ }
- public AnonymousRoom joinRoom(String roomCode) {
- return anonymousRoomRepository
- .findByRoomCode(roomCode)
- .orElseThrow(() -> new RuntimeException("Room not found with code: " + roomCode));
- }
+ public AnonymousRoom joinRoom(String roomCode) {
+ return anonymousRoomRepository.findByRoomCode(roomCode)
+ .orElseThrow(() -> new RuntimeException("Room not found with code: " + roomCode));
+ }
- private String generateUniqueRoomCode() {
- String roomCode;
- do {
- roomCode = UUID.randomUUID().toString().substring(0, 6).toUpperCase();
- } while (anonymousRoomRepository.existsByRoomCode(roomCode));
- return roomCode;
- }
+ private String generateUniqueRoomCode() {
+ String roomCode;
+ do {
+ roomCode = UUID.randomUUID().toString().substring(0, 6).toUpperCase();
+ } while (anonymousRoomRepository.existsByRoomCode(roomCode));
+ return roomCode;
+ }
}
diff --git a/src/main/java/opensource/bravest/domain/vote/controller/VoteController.java b/src/main/java/opensource/bravest/domain/vote/controller/VoteController.java
index e46aca8..bf40633 100644
--- a/src/main/java/opensource/bravest/domain/vote/controller/VoteController.java
+++ b/src/main/java/opensource/bravest/domain/vote/controller/VoteController.java
@@ -14,51 +14,49 @@
@RequestMapping("/votes")
public class VoteController {
- private final VoteService voteService;
-
- @PostMapping
- @Operation(summary = "투표 생성", description = "새로운 투표를 생성합니다.")
- public ApiResponse createVote(
- @RequestBody VoteDto.CreateVoteRequest request) {
- Vote vote = voteService.createVote(request);
- // The response DTO needs to be built manually
- VoteDto.VoteResponse responseDto = voteService.getVoteResult(vote.getId());
- return ApiResponse.of(SuccessStatus._CREATED, SuccessStatus._CREATED.getMessage(), responseDto);
- }
-
- @GetMapping("/{voteId}")
- @Operation(summary = "투표 조회", description = "ID로 특정 투표의 정보를 조회합니다.")
- public ApiResponse getVote(@PathVariable Long voteId) {
- VoteDto.VoteResponse responseDto = voteService.getVoteResult(voteId);
- return ApiResponse.of(SuccessStatus._OK, SuccessStatus._OK.getMessage(), responseDto);
- }
-
- @PostMapping("/{voteId}/cast")
- @Operation(summary = "투표 참여", description = "특정 투표 항목에 투표합니다.")
- public ApiResponse> castVote(
- @PathVariable Long voteId, @RequestBody VoteDto.CastVoteRequest request) {
- voteService.castVote(voteId, request);
- return ApiResponse.of(SuccessStatus._OK, SuccessStatus._OK.getMessage(), null);
- }
-
- @PostMapping("/{voteId}/end")
- @Operation(summary = "투표 종료", description = "특정 투표를 종료합니다.")
- public ApiResponse> endVote(@PathVariable Long voteId) {
- voteService.endVote(voteId);
- return ApiResponse.of(SuccessStatus._OK, SuccessStatus._OK.getMessage(), null);
- }
-
- @GetMapping("/{voteId}/result")
- @Operation(summary = "투표 결과 조회", description = "종료된 투표의 결과를 조회합니다.")
- public ApiResponse getVoteResult(@PathVariable Long voteId) {
- VoteDto.VoteResponse responseDto = voteService.getVoteResult(voteId);
- return ApiResponse.of(SuccessStatus._OK, SuccessStatus._OK.getMessage(), responseDto);
- }
-
- @DeleteMapping("/{voteId}")
- @Operation(summary = "투표 삭제", description = "ID로 특정 투표를 삭제합니다.")
- public ApiResponse> deleteVote(@PathVariable Long voteId) {
- voteService.deleteVote(voteId);
- return ApiResponse.of(SuccessStatus._OK, SuccessStatus._OK.getMessage(), null);
- }
+ private final VoteService voteService;
+
+ @PostMapping
+ @Operation(summary = "투표 생성", description = "새로운 투표를 생성합니다.")
+ public ApiResponse createVote(@RequestBody VoteDto.CreateVoteRequest request) {
+ Vote vote = voteService.createVote(request);
+ // The response DTO needs to be built manually
+ VoteDto.VoteResponse responseDto = voteService.getVoteResult(vote.getId());
+ return ApiResponse.of(SuccessStatus._CREATED, SuccessStatus._CREATED.getMessage(), responseDto);
+ }
+
+ @GetMapping("/{voteId}")
+ @Operation(summary = "투표 조회", description = "ID로 특정 투표의 정보를 조회합니다.")
+ public ApiResponse getVote(@PathVariable Long voteId) {
+ VoteDto.VoteResponse responseDto = voteService.getVoteResult(voteId);
+ return ApiResponse.of(SuccessStatus._OK, SuccessStatus._OK.getMessage(), responseDto);
+ }
+
+ @PostMapping("/{voteId}/cast")
+ @Operation(summary = "투표 참여", description = "특정 투표 항목에 투표합니다.")
+ public ApiResponse> castVote(@PathVariable Long voteId, @RequestBody VoteDto.CastVoteRequest request) {
+ voteService.castVote(voteId, request);
+ return ApiResponse.of(SuccessStatus._OK, SuccessStatus._OK.getMessage(), null);
+ }
+
+ @PostMapping("/{voteId}/end")
+ @Operation(summary = "투표 종료", description = "특정 투표를 종료합니다.")
+ public ApiResponse> endVote(@PathVariable Long voteId) {
+ voteService.endVote(voteId);
+ return ApiResponse.of(SuccessStatus._OK, SuccessStatus._OK.getMessage(), null);
+ }
+
+ @GetMapping("/{voteId}/result")
+ @Operation(summary = "투표 결과 조회", description = "종료된 투표의 결과를 조회합니다.")
+ public ApiResponse getVoteResult(@PathVariable Long voteId) {
+ VoteDto.VoteResponse responseDto = voteService.getVoteResult(voteId);
+ return ApiResponse.of(SuccessStatus._OK, SuccessStatus._OK.getMessage(), responseDto);
+ }
+
+ @DeleteMapping("/{voteId}")
+ @Operation(summary = "투표 삭제", description = "ID로 특정 투표를 삭제합니다.")
+ public ApiResponse> deleteVote(@PathVariable Long voteId) {
+ voteService.deleteVote(voteId);
+ return ApiResponse.of(SuccessStatus._OK, SuccessStatus._OK.getMessage(), null);
+ }
}
diff --git a/src/main/java/opensource/bravest/domain/vote/dto/VoteDto.java b/src/main/java/opensource/bravest/domain/vote/dto/VoteDto.java
index 83cd3dd..7c31382 100644
--- a/src/main/java/opensource/bravest/domain/vote/dto/VoteDto.java
+++ b/src/main/java/opensource/bravest/domain/vote/dto/VoteDto.java
@@ -8,35 +8,35 @@
public class VoteDto {
- @Getter
- @NoArgsConstructor
- public static class CreateVoteRequest {
- private Long roomId;
- private List messages;
- }
+ @Getter
+ @NoArgsConstructor
+ public static class CreateVoteRequest {
+ private Long roomId;
+ private List messages;
+ }
- @Getter
- @NoArgsConstructor
- public static class CastVoteRequest {
- private Long voteOptionId;
- private Long anonymousProfileId;
- }
+ @Getter
+ @NoArgsConstructor
+ public static class CastVoteRequest {
+ private Long voteOptionId;
+ private Long anonymousProfileId;
+ }
- @Getter
- @Builder
- public static class VoteResponse {
- private Long id;
- private String title;
- private boolean isActive;
- private LocalDateTime createdAt;
- private List options;
- }
+ @Getter
+ @Builder
+ public static class VoteResponse {
+ private Long id;
+ private String title;
+ private boolean isActive;
+ private LocalDateTime createdAt;
+ private List options;
+ }
- @Getter
- @Builder
- public static class VoteOptionResponse {
- private Long id;
- private String messageContent;
- private int voteCount;
- }
+ @Getter
+ @Builder
+ public static class VoteOptionResponse {
+ private Long id;
+ private String messageContent;
+ private int voteCount;
+ }
}
diff --git a/src/main/java/opensource/bravest/domain/vote/entity/UserVote.java b/src/main/java/opensource/bravest/domain/vote/entity/UserVote.java
index f88a73b..21c4b9e 100644
--- a/src/main/java/opensource/bravest/domain/vote/entity/UserVote.java
+++ b/src/main/java/opensource/bravest/domain/vote/entity/UserVote.java
@@ -11,19 +11,19 @@
@Builder
public class UserVote {
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long id;
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
- @ManyToOne(fetch = FetchType.LAZY)
- @JoinColumn(name = "vote_id", nullable = false)
- private Vote vote;
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "vote_id", nullable = false)
+ private Vote vote;
- @ManyToOne(fetch = FetchType.LAZY)
- @JoinColumn(name = "vote_option_id", nullable = false)
- private VoteOption voteOption;
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "vote_option_id", nullable = false)
+ private VoteOption voteOption;
- @ManyToOne(fetch = FetchType.LAZY)
- @JoinColumn(name = "anonymous_profile_id", nullable = false)
- private AnonymousProfile voter;
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "anonymous_profile_id", nullable = false)
+ private AnonymousProfile voter;
}
diff --git a/src/main/java/opensource/bravest/domain/vote/entity/Vote.java b/src/main/java/opensource/bravest/domain/vote/entity/Vote.java
index 3f2df78..cb115db 100644
--- a/src/main/java/opensource/bravest/domain/vote/entity/Vote.java
+++ b/src/main/java/opensource/bravest/domain/vote/entity/Vote.java
@@ -14,26 +14,26 @@
@Builder
public class Vote {
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long id;
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
- @ManyToOne(fetch = FetchType.LAZY)
- @JoinColumn(name = "room_id", nullable = false)
- private AnonymousRoom room;
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "room_id", nullable = false)
+ private AnonymousRoom room;
- @Column(nullable = false, length = 100)
- private String title;
+ @Column(nullable = false, length = 100)
+ private String title;
- @Builder.Default
- @OneToMany(mappedBy = "vote", cascade = CascadeType.ALL, orphanRemoval = true)
- private List options = new ArrayList<>();
+ @Builder.Default
+ @OneToMany(mappedBy = "vote", cascade = CascadeType.ALL, orphanRemoval = true)
+ private List options = new ArrayList<>();
- private boolean isActive;
+ private boolean isActive;
- private LocalDateTime createdAt;
+ private LocalDateTime createdAt;
- public void endVote() {
- this.isActive = false;
- }
+ public void endVote() {
+ this.isActive = false;
+ }
}
diff --git a/src/main/java/opensource/bravest/domain/vote/entity/VoteOption.java b/src/main/java/opensource/bravest/domain/vote/entity/VoteOption.java
index 70f03c7..50a9ea0 100644
--- a/src/main/java/opensource/bravest/domain/vote/entity/VoteOption.java
+++ b/src/main/java/opensource/bravest/domain/vote/entity/VoteOption.java
@@ -10,21 +10,21 @@
@Builder
public class VoteOption {
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long id;
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
- @ManyToOne(fetch = FetchType.LAZY)
- @JoinColumn(name = "vote_id", nullable = false)
- private Vote vote;
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "vote_id", nullable = false)
+ private Vote vote;
- @Column(name = "message_content", nullable = false)
- private String messageContent;
+ @Column(name = "message_content", nullable = false)
+ private String messageContent;
- @Column(nullable = false)
- private int voteCount;
+ @Column(nullable = false)
+ private int voteCount;
- public void incrementVoteCount() {
- this.voteCount++;
- }
+ public void incrementVoteCount() {
+ this.voteCount++;
+ }
}
diff --git a/src/main/java/opensource/bravest/domain/vote/repository/UserVoteRepository.java b/src/main/java/opensource/bravest/domain/vote/repository/UserVoteRepository.java
index 7fe9954..9ead3ee 100644
--- a/src/main/java/opensource/bravest/domain/vote/repository/UserVoteRepository.java
+++ b/src/main/java/opensource/bravest/domain/vote/repository/UserVoteRepository.java
@@ -7,5 +7,5 @@
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserVoteRepository extends JpaRepository {
- Optional findByVoteAndVoter(Vote vote, AnonymousProfile voter);
+ Optional findByVoteAndVoter(Vote vote, AnonymousProfile voter);
}
diff --git a/src/main/java/opensource/bravest/domain/vote/service/VoteService.java b/src/main/java/opensource/bravest/domain/vote/service/VoteService.java
index 39224b9..0a05107 100644
--- a/src/main/java/opensource/bravest/domain/vote/service/VoteService.java
+++ b/src/main/java/opensource/bravest/domain/vote/service/VoteService.java
@@ -22,107 +22,80 @@
@Transactional(readOnly = true)
public class VoteService {
- private final VoteRepository voteRepository;
- private final UserVoteRepository userVoteRepository;
- private final AnonymousRoomRepository anonymousRoomRepository;
- private final AnonymousProfileRepository anonymousProfileRepository;
-
- @Transactional
- public Vote createVote(VoteDto.CreateVoteRequest request) {
- AnonymousRoom room =
- anonymousRoomRepository
- .findById(request.getRoomId())
- .orElseThrow(() -> new RuntimeException("Room not found"));
-
- Vote vote =
- Vote.builder()
- .room(room)
- .title(room.getTitle())
- .isActive(true)
- .createdAt(LocalDateTime.now())
- .build();
-
- List options =
- request.getMessages().stream()
- .map(
- message ->
- VoteOption.builder().vote(vote).messageContent(message).voteCount(0).build())
- .collect(Collectors.toList());
-
- vote.getOptions().addAll(options);
-
- return voteRepository.save(vote);
- }
-
- @Transactional
- public void castVote(Long voteId, VoteDto.CastVoteRequest request) {
- Vote vote =
- voteRepository.findById(voteId).orElseThrow(() -> new RuntimeException("Vote not found"));
- if (!vote.isActive()) {
- throw new RuntimeException("Vote is not active");
- }
+ private final VoteRepository voteRepository;
+ private final UserVoteRepository userVoteRepository;
+ private final AnonymousRoomRepository anonymousRoomRepository;
+ private final AnonymousProfileRepository anonymousProfileRepository;
+
+ @Transactional
+ public Vote createVote(VoteDto.CreateVoteRequest request) {
+ AnonymousRoom room = anonymousRoomRepository.findById(request.getRoomId())
+ .orElseThrow(() -> new RuntimeException("Room not found"));
+
+ Vote vote = Vote.builder().room(room).title(room.getTitle()).isActive(true).createdAt(LocalDateTime.now())
+ .build();
+
+ List options = request.getMessages().stream()
+ .map(message -> VoteOption.builder().vote(vote).messageContent(message).voteCount(0).build())
+ .collect(Collectors.toList());
- AnonymousProfile voter =
- anonymousProfileRepository
- .findById(request.getAnonymousProfileId())
- .orElseThrow(() -> new RuntimeException("AnonymousProfile not found"));
+ vote.getOptions().addAll(options);
- if (userVoteRepository.findByVoteAndVoter(vote, voter).isPresent()) {
- throw new RuntimeException("User has already voted");
+ return voteRepository.save(vote);
}
- VoteOption voteOption =
- vote.getOptions().stream()
- .filter(option -> option.getId().equals(request.getVoteOptionId()))
- .findFirst()
- .orElseThrow(() -> new RuntimeException("VoteOption not found"));
+ @Transactional
+ public void castVote(Long voteId, VoteDto.CastVoteRequest request) {
+ Vote vote = voteRepository.findById(voteId).orElseThrow(() -> new RuntimeException("Vote not found"));
+ if (!vote.isActive()) {
+ throw new RuntimeException("Vote is not active");
+ }
- voteOption.incrementVoteCount();
+ AnonymousProfile voter = anonymousProfileRepository.findById(request.getAnonymousProfileId())
+ .orElseThrow(() -> new RuntimeException("AnonymousProfile not found"));
- UserVote userVote = UserVote.builder().vote(vote).voteOption(voteOption).voter(voter).build();
- userVoteRepository.save(userVote);
- }
+ if (userVoteRepository.findByVoteAndVoter(vote, voter).isPresent()) {
+ throw new RuntimeException("User has already voted");
+ }
- @Transactional
- public void endVote(Long voteId) {
- Vote vote =
- voteRepository.findById(voteId).orElseThrow(() -> new RuntimeException("Vote not found"));
- vote.endVote();
- }
+ VoteOption voteOption = vote.getOptions().stream()
+ .filter(option -> option.getId().equals(request.getVoteOptionId())).findFirst()
+ .orElseThrow(() -> new RuntimeException("VoteOption not found"));
+
+ voteOption.incrementVoteCount();
+
+ UserVote userVote = UserVote.builder().vote(vote).voteOption(voteOption).voter(voter).build();
+ userVoteRepository.save(userVote);
+ }
- public VoteDto.VoteResponse getVoteResult(Long voteId) {
- Vote vote =
- voteRepository.findById(voteId).orElseThrow(() -> new RuntimeException("Vote not found"));
+ @Transactional
+ public void endVote(Long voteId) {
+ Vote vote = voteRepository.findById(voteId).orElseThrow(() -> new RuntimeException("Vote not found"));
+ vote.endVote();
+ }
+
+ public VoteDto.VoteResponse getVoteResult(Long voteId) {
+ Vote vote = voteRepository.findById(voteId).orElseThrow(() -> new RuntimeException("Vote not found"));
+
+ return buildVoteResponse(vote);
+ }
+
+ @Transactional
+ public void deleteVote(Long voteId) {
+ if (!voteRepository.existsById(voteId)) {
+ throw new RuntimeException("Vote not found");
+ }
+ voteRepository.deleteById(voteId);
+ }
- return buildVoteResponse(vote);
- }
+ private VoteDto.VoteResponse buildVoteResponse(Vote vote) {
+ List optionResponses = vote.getOptions().stream()
+ .map(option -> VoteDto.VoteOptionResponse.builder().id(option.getId())
+ .messageContent(option.getMessageContent()).voteCount(option.getVoteCount())
+ .build())
+ .collect(Collectors.toList());
- @Transactional
- public void deleteVote(Long voteId) {
- if (!voteRepository.existsById(voteId)) {
- throw new RuntimeException("Vote not found");
+ return VoteDto.VoteResponse.builder().id(vote.getId()).title(vote.getTitle()).isActive(vote.isActive())
+ .createdAt(vote.getCreatedAt()).options(optionResponses).build();
}
- voteRepository.deleteById(voteId);
- }
-
- private VoteDto.VoteResponse buildVoteResponse(Vote vote) {
- List optionResponses =
- vote.getOptions().stream()
- .map(
- option ->
- VoteDto.VoteOptionResponse.builder()
- .id(option.getId())
- .messageContent(option.getMessageContent())
- .voteCount(option.getVoteCount())
- .build())
- .collect(Collectors.toList());
-
- return VoteDto.VoteResponse.builder()
- .id(vote.getId())
- .title(vote.getTitle())
- .isActive(vote.isActive())
- .createdAt(vote.getCreatedAt())
- .options(optionResponses)
- .build();
- }
}
diff --git a/src/main/java/opensource/bravest/global/apiPayload/ApiResponse.java b/src/main/java/opensource/bravest/global/apiPayload/ApiResponse.java
index b577884..859bbaa 100644
--- a/src/main/java/opensource/bravest/global/apiPayload/ApiResponse.java
+++ b/src/main/java/opensource/bravest/global/apiPayload/ApiResponse.java
@@ -14,31 +14,30 @@
@AllArgsConstructor
@JsonPropertyOrder({"isSuccess", "code", "message", "data"})
public class ApiResponse {
- @JsonProperty("isSuccess")
- private final boolean isSuccess;
+ @JsonProperty("isSuccess")
+ private final boolean isSuccess;
- private final String code;
- private final String message;
+ private final String code;
+ private final String message;
- @JsonInclude(JsonInclude.Include.NON_NULL)
- private T data;
+ @JsonInclude(JsonInclude.Include.NON_NULL)
+ private T data;
- public static ApiResponse onSuccess(T data) {
- return new ApiResponse<>(
- true, SuccessStatus._OK.getCode(), SuccessStatus._OK.getMessage(), data);
- }
+ public static ApiResponse onSuccess(T data) {
+ return new ApiResponse<>(true, SuccessStatus._OK.getCode(), SuccessStatus._OK.getMessage(), data);
+ }
- public static ApiResponse of(BaseCode code, String message, T data) {
- return new ApiResponse<>(
- true, code.getReasonHttpStatus().getCode(), code.getReasonHttpStatus().getMessage(), data);
- }
+ public static ApiResponse of(BaseCode code, String message, T data) {
+ return new ApiResponse<>(true, code.getReasonHttpStatus().getCode(), code.getReasonHttpStatus().getMessage(),
+ data);
+ }
- public static ApiResponse onFailure(BaseErrorCode errorCode, T data) {
- ErrorReasonDto reason = errorCode.getReasonHttpStatus();
- return new ApiResponse<>(reason.getIsSuccess(), reason.getCode(), reason.getMessage(), data);
- }
+ public static ApiResponse onFailure(BaseErrorCode errorCode, T data) {
+ ErrorReasonDto reason = errorCode.getReasonHttpStatus();
+ return new ApiResponse<>(reason.getIsSuccess(), reason.getCode(), reason.getMessage(), data);
+ }
- public static ApiResponse onFailure(String code, String message, T data) {
- return new ApiResponse<>(false, code, message, data);
- }
+ public static ApiResponse onFailure(String code, String message, T data) {
+ return new ApiResponse<>(false, code, message, data);
+ }
}
diff --git a/src/main/java/opensource/bravest/global/apiPayload/code/BaseCode.java b/src/main/java/opensource/bravest/global/apiPayload/code/BaseCode.java
index 00f3dd4..81444ee 100644
--- a/src/main/java/opensource/bravest/global/apiPayload/code/BaseCode.java
+++ b/src/main/java/opensource/bravest/global/apiPayload/code/BaseCode.java
@@ -1,7 +1,7 @@
package opensource.bravest.global.apiPayload.code;
public interface BaseCode {
- ReasonDto getReason();
+ ReasonDto getReason();
- ReasonDto getReasonHttpStatus();
+ ReasonDto getReasonHttpStatus();
}
diff --git a/src/main/java/opensource/bravest/global/apiPayload/code/BaseErrorCode.java b/src/main/java/opensource/bravest/global/apiPayload/code/BaseErrorCode.java
index 6f514a7..6607ad0 100644
--- a/src/main/java/opensource/bravest/global/apiPayload/code/BaseErrorCode.java
+++ b/src/main/java/opensource/bravest/global/apiPayload/code/BaseErrorCode.java
@@ -1,7 +1,7 @@
package opensource.bravest.global.apiPayload.code;
public interface BaseErrorCode {
- ErrorReasonDto getReason();
+ ErrorReasonDto getReason();
- ErrorReasonDto getReasonHttpStatus();
+ ErrorReasonDto getReasonHttpStatus();
}
diff --git a/src/main/java/opensource/bravest/global/apiPayload/code/ErrorReasonDto.java b/src/main/java/opensource/bravest/global/apiPayload/code/ErrorReasonDto.java
index bda7a57..2172a3c 100644
--- a/src/main/java/opensource/bravest/global/apiPayload/code/ErrorReasonDto.java
+++ b/src/main/java/opensource/bravest/global/apiPayload/code/ErrorReasonDto.java
@@ -7,8 +7,8 @@
@Getter
@Builder
public class ErrorReasonDto {
- private HttpStatus httpStatus;
- private final Boolean isSuccess;
- private final String message;
- private final String code;
+ private HttpStatus httpStatus;
+ private final Boolean isSuccess;
+ private final String message;
+ private final String code;
}
diff --git a/src/main/java/opensource/bravest/global/apiPayload/code/ReasonDto.java b/src/main/java/opensource/bravest/global/apiPayload/code/ReasonDto.java
index df56f57..e8ba0a0 100644
--- a/src/main/java/opensource/bravest/global/apiPayload/code/ReasonDto.java
+++ b/src/main/java/opensource/bravest/global/apiPayload/code/ReasonDto.java
@@ -7,8 +7,8 @@
@Getter
@Builder
public class ReasonDto {
- private HttpStatus httpStatus;
- private final Boolean isSuccess;
- private final String code;
- private final String message;
+ private HttpStatus httpStatus;
+ private final Boolean isSuccess;
+ private final String code;
+ private final String message;
}
diff --git a/src/main/java/opensource/bravest/global/apiPayload/code/status/ErrorStatus.java b/src/main/java/opensource/bravest/global/apiPayload/code/status/ErrorStatus.java
index b0ae3d4..3b7b59e 100644
--- a/src/main/java/opensource/bravest/global/apiPayload/code/status/ErrorStatus.java
+++ b/src/main/java/opensource/bravest/global/apiPayload/code/status/ErrorStatus.java
@@ -9,33 +9,33 @@
@Getter
@AllArgsConstructor
public enum ErrorStatus implements BaseErrorCode {
- _INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "COMMON500", "서버 에러, 관리자에게 문의 바랍니다."),
- _BAD_REQUEST(HttpStatus.BAD_REQUEST, "COMMON400", "잘못된 요청입니다."),
- _UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "COMMON401", "인증이 필요합니다."),
- _FORBIDDEN(HttpStatus.FORBIDDEN, "COMMON403", "금지된 요청입니다."),
- _NOT_FOUND(HttpStatus.NOT_FOUND, "COMMON404", "요청한 리소스를 찾을 수 없습니다."),
- _FAMILY_NOT_FOUND(HttpStatus.NOT_FOUND, "FAMILY404", "유효하지 않은 초대 코드입니다."),
- _USER_NOT_FOUND(HttpStatus.NOT_FOUND, "USER404", "사용자를 찾을 수 없습니다."),
- _CHATROOM_NOT_FOUND(HttpStatus.NOT_FOUND, "USER404", "채팅방을 찾을 수 없습니다."),
- _CHATLIST_NOT_FOUND(HttpStatus.NOT_FOUND, "USER404", "리스트를 찾을 수 없습니다."),
- ;
+ _INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "COMMON500", "서버 에러, 관리자에게 문의 바랍니다."), _BAD_REQUEST(
+ HttpStatus.BAD_REQUEST, "COMMON400",
+ "잘못된 요청입니다."), _UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "COMMON401", "인증이 필요합니다."), _FORBIDDEN(
+ HttpStatus.FORBIDDEN, "COMMON403",
+ "금지된 요청입니다."), _NOT_FOUND(HttpStatus.NOT_FOUND, "COMMON404",
+ "요청한 리소스를 찾을 수 없습니다."), _FAMILY_NOT_FOUND(HttpStatus.NOT_FOUND,
+ "FAMILY404", "유효하지 않은 초대 코드입니다."), _USER_NOT_FOUND(
+ HttpStatus.NOT_FOUND, "USER404",
+ "사용자를 찾을 수 없습니다."), _CHATROOM_NOT_FOUND(
+ HttpStatus.NOT_FOUND,
+ "USER404",
+ "채팅방을 찾을 수 없습니다."), _CHATLIST_NOT_FOUND(
+ HttpStatus.NOT_FOUND,
+ "USER404",
+ "리스트를 찾을 수 없습니다."),;
- private final HttpStatus httpStatus;
- private final String code;
- private final String message;
+ private final HttpStatus httpStatus;
+ private final String code;
+ private final String message;
- @Override
- public ErrorReasonDto getReason() {
- return ErrorReasonDto.builder().isSuccess(false).message(message).code(code).build();
- }
+ @Override
+ public ErrorReasonDto getReason() {
+ return ErrorReasonDto.builder().isSuccess(false).message(message).code(code).build();
+ }
- @Override
- public ErrorReasonDto getReasonHttpStatus() {
- return ErrorReasonDto.builder()
- .httpStatus(httpStatus)
- .isSuccess(false)
- .code(code)
- .message(message)
- .build();
- }
+ @Override
+ public ErrorReasonDto getReasonHttpStatus() {
+ return ErrorReasonDto.builder().httpStatus(httpStatus).isSuccess(false).code(code).message(message).build();
+ }
}
diff --git a/src/main/java/opensource/bravest/global/apiPayload/code/status/SuccessStatus.java b/src/main/java/opensource/bravest/global/apiPayload/code/status/SuccessStatus.java
index 7845515..25d02ed 100644
--- a/src/main/java/opensource/bravest/global/apiPayload/code/status/SuccessStatus.java
+++ b/src/main/java/opensource/bravest/global/apiPayload/code/status/SuccessStatus.java
@@ -9,25 +9,18 @@
@Getter
@AllArgsConstructor
public enum SuccessStatus implements BaseCode {
- _OK(HttpStatus.OK, "COMMON2000", "성공입니다."),
- _CREATED(HttpStatus.CREATED, "COMMON201", "생성되었습니다."),
- ;
- private final HttpStatus httpStatus;
- private final String code;
- private final String message;
+ _OK(HttpStatus.OK, "COMMON2000", "성공입니다."), _CREATED(HttpStatus.CREATED, "COMMON201", "생성되었습니다."),;
+ private final HttpStatus httpStatus;
+ private final String code;
+ private final String message;
- @Override
- public ReasonDto getReason() {
- return ReasonDto.builder().isSuccess(true).message(message).code(code).build();
- }
+ @Override
+ public ReasonDto getReason() {
+ return ReasonDto.builder().isSuccess(true).message(message).code(code).build();
+ }
- @Override
- public ReasonDto getReasonHttpStatus() {
- return ReasonDto.builder()
- .httpStatus(httpStatus)
- .isSuccess(true)
- .code(code)
- .message(message)
- .build();
- }
+ @Override
+ public ReasonDto getReasonHttpStatus() {
+ return ReasonDto.builder().httpStatus(httpStatus).isSuccess(true).code(code).message(message).build();
+ }
}
diff --git a/src/main/java/opensource/bravest/global/config/OpenApiConfig.java b/src/main/java/opensource/bravest/global/config/OpenApiConfig.java
index 25c4cff..c791d78 100644
--- a/src/main/java/opensource/bravest/global/config/OpenApiConfig.java
+++ b/src/main/java/opensource/bravest/global/config/OpenApiConfig.java
@@ -13,29 +13,19 @@
@Configuration
public class OpenApiConfig {
- private static final String SECURITY_SCHEME_NAME = "bearerAuth";
+ private static final String SECURITY_SCHEME_NAME = "bearerAuth";
- @Bean
- public OpenAPI baseOpenAPI() {
- return new OpenAPI()
- // 1) 전역으로 "이 API는 이 인증 방식을 쓴다" 선언
- .addSecurityItem(new SecurityRequirement().addList(SECURITY_SCHEME_NAME))
- // 2) JWT Bearer 스키마 정의
- .components(
- new Components()
- .addSecuritySchemes(
- SECURITY_SCHEME_NAME,
- new SecurityScheme()
- .name(SECURITY_SCHEME_NAME)
- .type(SecurityScheme.Type.HTTP)
- .scheme("bearer")
- .bearerFormat("JWT")))
- .info(
- new Info()
- .title("openSource Bravest API")
- .description("openSource Bravest 백엔드 API 문서")
- .version("v1.0.0")
- .license(new License().name("MIT")))
- .externalDocs(new ExternalDocumentation().description("README"));
- }
+ @Bean
+ public OpenAPI baseOpenAPI() {
+ return new OpenAPI()
+ // 1) 전역으로 "이 API는 이 인증 방식을 쓴다" 선언
+ .addSecurityItem(new SecurityRequirement().addList(SECURITY_SCHEME_NAME))
+ // 2) JWT Bearer 스키마 정의
+ .components(new Components().addSecuritySchemes(SECURITY_SCHEME_NAME,
+ new SecurityScheme().name(SECURITY_SCHEME_NAME).type(SecurityScheme.Type.HTTP)
+ .scheme("bearer").bearerFormat("JWT")))
+ .info(new Info().title("openSource Bravest API").description("openSource Bravest 백엔드 API 문서")
+ .version("v1.0.0").license(new License().name("MIT")))
+ .externalDocs(new ExternalDocumentation().description("README"));
+ }
}
diff --git a/src/main/java/opensource/bravest/global/config/SecurityConfig.java b/src/main/java/opensource/bravest/global/config/SecurityConfig.java
index 35abcef..e087085 100644
--- a/src/main/java/opensource/bravest/global/config/SecurityConfig.java
+++ b/src/main/java/opensource/bravest/global/config/SecurityConfig.java
@@ -25,126 +25,93 @@
@RequiredArgsConstructor
public class SecurityConfig {
- private final JwtTokenProvider jwtTokenProvider;
-
- // Swagger
- private static final String[] SWAGGER = {"/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html"};
-
- // 로그인/토큰 교환/리다이렉트/헬스체크 등 공개 경로
- private static final String[] PUBLIC = {
- "/",
- "/actuator/health",
- "/api/auth/**", // 카카오 코드 교환 API 등
- "/oauth2/**",
- "/login/**",
- "/login/oauth2/**",
- "/api/test/auth/**",
- "/rooms/**",
- "/chatlists/**",
- "/anonymous-profiles/**",
- "/votes/**",
- "/ws-connect/**",
- "/chat-test",
- "/pub/**",
- "/sub/**"
- };
-
- // 정적 리소스
- private static final String[] STATIC = {
- "/favicon.ico", "/assets/**", "/css/**", "/js/**", "/images/**"
- };
-
- @Bean
- public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
- // Jwt 필터에서 건너뛸(스킵) 경로 패턴 통합
- List skip = new ArrayList<>();
- addAll(skip, SWAGGER);
- addAll(skip, PUBLIC);
- addAll(skip, STATIC);
-
- JwtAuthenticationFilter jwtFilter = new JwtAuthenticationFilter(jwtTokenProvider, skip);
-
- http
- // REST API 기본 세팅
- .csrf(csrf -> csrf.disable())
- .cors(Customizer.withDefaults())
- .sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
- .httpBasic(basic -> basic.disable())
- .formLogin(form -> form.disable())
- .logout(lo -> lo.disable())
- .requestCache(cache -> cache.disable())
-
- // 권한 규칙
- .authorizeHttpRequests(
- auth ->
- auth.requestMatchers(HttpMethod.OPTIONS, "/**")
- .permitAll() // CORS preflight 허용
- .requestMatchers(SWAGGER)
- .permitAll()
- .requestMatchers(PUBLIC)
- .permitAll()
- .requestMatchers(STATIC)
- .permitAll()
- .anyRequest()
- .authenticated())
-
- // 인증/인가 실패 공통 응답(JSON) - ApiResponse 형식
- .exceptionHandling(
- ex ->
- ex.authenticationEntryPoint(
- (req, res, ex1) -> {
- ErrorStatus errorStatus = ErrorStatus._UNAUTHORIZED;
- res.setStatus(errorStatus.getReasonHttpStatus().getHttpStatus().value());
- res.setContentType("application/json;charset=UTF-8");
- try (PrintWriter w = res.getWriter()) {
- w.write(
- String.format(
- "{\"isSuccess\":false,\"code\":\"%s\",\"message\":\"%s\",\"data\":null}",
- errorStatus.getCode(), errorStatus.getMessage()));
- }
- })
- .accessDeniedHandler(
- (req, res, ex2) -> {
- ErrorStatus errorStatus = ErrorStatus._FORBIDDEN;
- res.setStatus(errorStatus.getReasonHttpStatus().getHttpStatus().value());
- res.setContentType("application/json;charset=UTF-8");
- try (PrintWriter w = res.getWriter()) {
- w.write(
- String.format(
- "{\"isSuccess\":false,\"code\":\"%s\",\"message\":\"%s\",\"data\":null}",
- errorStatus.getCode(), errorStatus.getMessage()));
- }
+ private final JwtTokenProvider jwtTokenProvider;
+
+ // Swagger
+ private static final String[] SWAGGER = {"/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html"};
+
+ // 로그인/토큰 교환/리다이렉트/헬스체크 등 공개 경로
+ private static final String[] PUBLIC = {"/", "/actuator/health", "/api/auth/**", // 카카오 코드 교환 API 등
+ "/oauth2/**", "/login/**", "/login/oauth2/**", "/api/test/auth/**", "/rooms/**", "/chatlists/**",
+ "/anonymous-profiles/**", "/votes/**", "/ws-connect/**", "/chat-test", "/pub/**", "/sub/**"};
+
+ // 정적 리소스
+ private static final String[] STATIC = {"/favicon.ico", "/assets/**", "/css/**", "/js/**", "/images/**"};
+
+ @Bean
+ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
+ // Jwt 필터에서 건너뛸(스킵) 경로 패턴 통합
+ List skip = new ArrayList<>();
+ addAll(skip, SWAGGER);
+ addAll(skip, PUBLIC);
+ addAll(skip, STATIC);
+
+ JwtAuthenticationFilter jwtFilter = new JwtAuthenticationFilter(jwtTokenProvider, skip);
+
+ http
+ // REST API 기본 세팅
+ .csrf(csrf -> csrf.disable()).cors(Customizer.withDefaults())
+ .sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
+ .httpBasic(basic -> basic.disable()).formLogin(form -> form.disable())
+ .logout(lo -> lo.disable()).requestCache(cache -> cache.disable())
+
+ // 권한 규칙
+ .authorizeHttpRequests(auth -> auth.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() // CORS
+ // preflight
+ // 허용
+ .requestMatchers(SWAGGER).permitAll().requestMatchers(PUBLIC).permitAll()
+ .requestMatchers(STATIC).permitAll().anyRequest().authenticated())
+
+ // 인증/인가 실패 공통 응답(JSON) - ApiResponse 형식
+ .exceptionHandling(ex -> ex.authenticationEntryPoint((req, res, ex1) -> {
+ ErrorStatus errorStatus = ErrorStatus._UNAUTHORIZED;
+ res.setStatus(errorStatus.getReasonHttpStatus().getHttpStatus().value());
+ res.setContentType("application/json;charset=UTF-8");
+ try (PrintWriter w = res.getWriter()) {
+ w.write(String.format(
+ "{\"isSuccess\":false,\"code\":\"%s\",\"message\":\"%s\",\"data\":null}",
+ errorStatus.getCode(), errorStatus.getMessage()));
+ }
+ }).accessDeniedHandler((req, res, ex2) -> {
+ ErrorStatus errorStatus = ErrorStatus._FORBIDDEN;
+ res.setStatus(errorStatus.getReasonHttpStatus().getHttpStatus().value());
+ res.setContentType("application/json;charset=UTF-8");
+ try (PrintWriter w = res.getWriter()) {
+ w.write(String.format(
+ "{\"isSuccess\":false,\"code\":\"%s\",\"message\":\"%s\",\"data\":null}",
+ errorStatus.getCode(), errorStatus.getMessage()));
+ }
}))
- // JWT 필터 등록(UsernamePasswordAuthenticationFilter 앞)
- .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
-
- return http.build();
- }
-
- private static void addAll(List target, String[] arr) {
- for (String s : arr) target.add(s);
- }
-
- // CORS (개발용: 필요 시 도메인 고정/축소)
- @Bean
- public CorsConfigurationSource corsConfigurationSource() {
- CorsConfiguration c = new CorsConfiguration();
- c.setAllowedOrigins(
- List.of("http://localhost:3000", "http://127.0.0.1:3000", "http://localhost:5173"));
- c.setAllowedMethods(List.of("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
- c.setAllowedHeaders(List.of("*"));
- c.setExposedHeaders(List.of("Authorization", "Location"));
- c.setAllowCredentials(true);
- c.setMaxAge(3600L);
-
- UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
- source.registerCorsConfiguration("/**", c);
- return source;
- }
-
- @Bean
- public PasswordEncoder passwordEncoder() {
- return new BCryptPasswordEncoder();
- }
+ // JWT 필터 등록(UsernamePasswordAuthenticationFilter 앞)
+ .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
+
+ return http.build();
+ }
+
+ private static void addAll(List target, String[] arr) {
+ for (String s : arr)
+ target.add(s);
+ }
+
+ // CORS (개발용: 필요 시 도메인 고정/축소)
+ @Bean
+ public CorsConfigurationSource corsConfigurationSource() {
+ CorsConfiguration c = new CorsConfiguration();
+ c.setAllowedOrigins(List.of("http://localhost:3000", "http://127.0.0.1:3000", "http://localhost:5173"));
+ c.setAllowedMethods(List.of("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
+ c.setAllowedHeaders(List.of("*"));
+ c.setExposedHeaders(List.of("Authorization", "Location"));
+ c.setAllowCredentials(true);
+ c.setMaxAge(3600L);
+
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", c);
+ return source;
+ }
+
+ @Bean
+ public PasswordEncoder passwordEncoder() {
+ return new BCryptPasswordEncoder();
+ }
}
diff --git a/src/main/java/opensource/bravest/global/config/ValkeyConfig.java b/src/main/java/opensource/bravest/global/config/ValkeyConfig.java
index be6c578..2be6ffa 100644
--- a/src/main/java/opensource/bravest/global/config/ValkeyConfig.java
+++ b/src/main/java/opensource/bravest/global/config/ValkeyConfig.java
@@ -8,8 +8,8 @@
@Configuration
public class ValkeyConfig {
- @Bean
- public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory connectionFactory) {
- return new StringRedisTemplate(connectionFactory);
- }
+ @Bean
+ public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory connectionFactory) {
+ return new StringRedisTemplate(connectionFactory);
+ }
}
diff --git a/src/main/java/opensource/bravest/global/config/WebSocketConfig.java b/src/main/java/opensource/bravest/global/config/WebSocketConfig.java
index 177db70..449d017 100644
--- a/src/main/java/opensource/bravest/global/config/WebSocketConfig.java
+++ b/src/main/java/opensource/bravest/global/config/WebSocketConfig.java
@@ -14,21 +14,21 @@
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
- private final StompHandler stompHandler;
+ private final StompHandler stompHandler;
- @Override
- public void registerStompEndpoints(StompEndpointRegistry registry) {
- registry.addEndpoint("/ws-connect").setAllowedOriginPatterns("*").withSockJS();
- }
+ @Override
+ public void registerStompEndpoints(StompEndpointRegistry registry) {
+ registry.addEndpoint("/ws-connect").setAllowedOriginPatterns("*").withSockJS();
+ }
- @Override
- public void configureMessageBroker(MessageBrokerRegistry registry) {
- registry.enableSimpleBroker("/subs");
- registry.setApplicationDestinationPrefixes("/pubs");
- }
+ @Override
+ public void configureMessageBroker(MessageBrokerRegistry registry) {
+ registry.enableSimpleBroker("/subs");
+ registry.setApplicationDestinationPrefixes("/pubs");
+ }
- @Override
- public void configureClientInboundChannel(ChannelRegistration registration) {
- registration.interceptors(stompHandler);
- }
+ @Override
+ public void configureClientInboundChannel(ChannelRegistration registration) {
+ registration.interceptors(stompHandler);
+ }
}
diff --git a/src/main/java/opensource/bravest/global/exception/CustomException.java b/src/main/java/opensource/bravest/global/exception/CustomException.java
index 3fb913e..1b8ab2e 100644
--- a/src/main/java/opensource/bravest/global/exception/CustomException.java
+++ b/src/main/java/opensource/bravest/global/exception/CustomException.java
@@ -7,10 +7,10 @@
@Getter
public class CustomException extends RuntimeException {
- private final BaseErrorCode errorCode;
+ private final BaseErrorCode errorCode;
- public CustomException(BaseErrorCode errorCode) {
- super(errorCode.getReason().getMessage());
- this.errorCode = errorCode;
- }
+ public CustomException(BaseErrorCode errorCode) {
+ super(errorCode.getReason().getMessage());
+ this.errorCode = errorCode;
+ }
}
diff --git a/src/main/java/opensource/bravest/global/exception/GlobalExceptionHandler.java b/src/main/java/opensource/bravest/global/exception/GlobalExceptionHandler.java
index 6faa479..be2b96b 100644
--- a/src/main/java/opensource/bravest/global/exception/GlobalExceptionHandler.java
+++ b/src/main/java/opensource/bravest/global/exception/GlobalExceptionHandler.java
@@ -11,46 +11,42 @@
@RestControllerAdvice
public class GlobalExceptionHandler {
- @ExceptionHandler(CustomException.class)
- public ResponseEntity> handleCustomException(CustomException e) {
- log.warn("CustomException: {}", e.getMessage());
- return ResponseEntity.status(e.getErrorCode().getReasonHttpStatus().getHttpStatus())
- .body(ApiResponse.onFailure(e.getErrorCode(), null));
- }
-
- @ExceptionHandler(RuntimeException.class)
- public ResponseEntity> handleRuntimeException(RuntimeException e) {
- String message = e.getMessage();
-
- // 메시지에 따라 적절한 에러 코드 결정
- if (message != null) {
- if (message.contains("유효하지 않은 초대 코드") || message.contains("가족을 찾을 수 없습니다")) {
- log.warn("Family not found: {}", message);
- return ResponseEntity.status(
- ErrorStatus._FAMILY_NOT_FOUND.getReasonHttpStatus().getHttpStatus())
- .body(ApiResponse.onFailure(ErrorStatus._FAMILY_NOT_FOUND, null));
- }
-
- if (message.contains("사용자를 찾을 수 없습니다")) {
- log.warn("User not found: {}", message);
- return ResponseEntity.status(
- ErrorStatus._USER_NOT_FOUND.getReasonHttpStatus().getHttpStatus())
- .body(ApiResponse.onFailure(ErrorStatus._USER_NOT_FOUND, null));
- }
+ @ExceptionHandler(CustomException.class)
+ public ResponseEntity> handleCustomException(CustomException e) {
+ log.warn("CustomException: {}", e.getMessage());
+ return ResponseEntity.status(e.getErrorCode().getReasonHttpStatus().getHttpStatus())
+ .body(ApiResponse.onFailure(e.getErrorCode(), null));
}
- // 기본값: 500 Internal Server Error
- log.error("RuntimeException: ", e);
- return ResponseEntity.status(
- ErrorStatus._INTERNAL_SERVER_ERROR.getReasonHttpStatus().getHttpStatus())
- .body(ApiResponse.onFailure(ErrorStatus._INTERNAL_SERVER_ERROR, null));
- }
-
- @ExceptionHandler(Exception.class)
- public ResponseEntity> handleException(Exception e) {
- log.error("Unexpected exception: ", e);
- return ResponseEntity.status(
- ErrorStatus._INTERNAL_SERVER_ERROR.getReasonHttpStatus().getHttpStatus())
- .body(ApiResponse.onFailure(ErrorStatus._INTERNAL_SERVER_ERROR, null));
- }
+ @ExceptionHandler(RuntimeException.class)
+ public ResponseEntity> handleRuntimeException(RuntimeException e) {
+ String message = e.getMessage();
+
+ // 메시지에 따라 적절한 에러 코드 결정
+ if (message != null) {
+ if (message.contains("유효하지 않은 초대 코드") || message.contains("가족을 찾을 수 없습니다")) {
+ log.warn("Family not found: {}", message);
+ return ResponseEntity.status(ErrorStatus._FAMILY_NOT_FOUND.getReasonHttpStatus().getHttpStatus())
+ .body(ApiResponse.onFailure(ErrorStatus._FAMILY_NOT_FOUND, null));
+ }
+
+ if (message.contains("사용자를 찾을 수 없습니다")) {
+ log.warn("User not found: {}", message);
+ return ResponseEntity.status(ErrorStatus._USER_NOT_FOUND.getReasonHttpStatus().getHttpStatus())
+ .body(ApiResponse.onFailure(ErrorStatus._USER_NOT_FOUND, null));
+ }
+ }
+
+ // 기본값: 500 Internal Server Error
+ log.error("RuntimeException: ", e);
+ return ResponseEntity.status(ErrorStatus._INTERNAL_SERVER_ERROR.getReasonHttpStatus().getHttpStatus())
+ .body(ApiResponse.onFailure(ErrorStatus._INTERNAL_SERVER_ERROR, null));
+ }
+
+ @ExceptionHandler(Exception.class)
+ public ResponseEntity> handleException(Exception e) {
+ log.error("Unexpected exception: ", e);
+ return ResponseEntity.status(ErrorStatus._INTERNAL_SERVER_ERROR.getReasonHttpStatus().getHttpStatus())
+ .body(ApiResponse.onFailure(ErrorStatus._INTERNAL_SERVER_ERROR, null));
+ }
}
diff --git a/src/main/java/opensource/bravest/global/handler/StompHandler.java b/src/main/java/opensource/bravest/global/handler/StompHandler.java
index d7ec8d8..ff026ed 100644
--- a/src/main/java/opensource/bravest/global/handler/StompHandler.java
+++ b/src/main/java/opensource/bravest/global/handler/StompHandler.java
@@ -23,136 +23,120 @@
@RequiredArgsConstructor
public class StompHandler implements ChannelInterceptor {
- private final AnonymousProfileRepository anonymousProfileRepository;
- private final StringRedisTemplate redisTemplate;
+ private final AnonymousProfileRepository anonymousProfileRepository;
+ private final StringRedisTemplate redisTemplate;
- private static final String USER_SUB_KEY_PREFIX = "ws:subs:user:"; // + anonymousId
- private static final String METRIC_TOTAL_SUB = "ws:metrics:sub:total";
- private static final String METRIC_DUP_SUB = "ws:metrics:sub:duplicate";
+ private static final String USER_SUB_KEY_PREFIX = "ws:subs:user:"; // + anonymousId
+ private static final String METRIC_TOTAL_SUB = "ws:metrics:sub:total";
+ private static final String METRIC_DUP_SUB = "ws:metrics:sub:duplicate";
- @Override
- public Message> preSend(Message> message, MessageChannel channel) {
- StompHeaderAccessor accessor =
- MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
+ @Override
+ public Message> preSend(Message> message, MessageChannel channel) {
+ StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
- if (accessor == null) {
- return message;
- }
+ if (accessor == null) {
+ return message;
+ }
+
+ StompCommand command = accessor.getCommand();
- StompCommand command = accessor.getCommand();
-
- // 1) CONNECT: anonymousId를 Principal로 설정
- if (StompCommand.CONNECT.equals(command)) {
- String anonymousId = accessor.getFirstNativeHeader("anonymousId");
- if (anonymousId == null || anonymousId.isBlank()) {
- log.warn("STOMP CONNECT: anonymousId missing");
- throw new IllegalArgumentException("anonymousId header is required");
- }
-
- anonymousProfileRepository
- .findById(Long.valueOf(anonymousId))
- .ifPresentOrElse(
- member -> {
- Authentication auth =
- new UsernamePasswordAuthenticationToken(
- anonymousId, null, List.of(new SimpleGrantedAuthority("ROLE_ANONYMOUS")));
+ // 1) CONNECT: anonymousId를 Principal로 설정
+ if (StompCommand.CONNECT.equals(command)) {
+ String anonymousId = accessor.getFirstNativeHeader("anonymousId");
+ if (anonymousId == null || anonymousId.isBlank()) {
+ log.warn("STOMP CONNECT: anonymousId missing");
+ throw new IllegalArgumentException("anonymousId header is required");
+ }
+
+ anonymousProfileRepository.findById(Long.valueOf(anonymousId)).ifPresentOrElse(member -> {
+ Authentication auth = new UsernamePasswordAuthenticationToken(anonymousId, null,
+ List.of(new SimpleGrantedAuthority("ROLE_ANONYMOUS")));
SecurityContextHolder.getContext().setAuthentication(auth);
accessor.setUser(auth);
log.info("STOMP CONNECT: anonymousId={} principal set", anonymousId);
- },
- () -> {
+ }, () -> {
log.warn("STOMP CONNECT: invalid anonymousId={}", anonymousId);
throw new IllegalArgumentException("Invalid anonymousId");
- });
- }
-
- // 2) SUBSCRIBE: Redis를 사용해 anonymousId 기준 중복 구독 방지 + 메트릭 기록
- if (StompCommand.SUBSCRIBE.equals(command)) {
- Principal user = accessor.getUser();
- if (user == null) {
- Authentication auth = SecurityContextHolder.getContext().getAuthentication();
- if (auth != null) {
- accessor.setUser(auth);
- user = auth;
+ });
}
- }
-
- String destination = accessor.getDestination();
-
- if (user != null && destination != null) {
- String anonymousId = user.getName();
- String key = USER_SUB_KEY_PREFIX + anonymousId;
-
- log.info(
- "[SUBSCRIBE] handling: anonymousId={}, destination={}, key={}",
- anonymousId,
- destination,
- key);
- try {
- Long total = redisTemplate.opsForValue().increment(METRIC_TOTAL_SUB);
- Long added = redisTemplate.opsForSet().add(key, destination);
- redisTemplate.expire(key, java.time.Duration.ofHours(1));
-
- log.info("[SUBSCRIBE] redis result: total={}, added={}", total, added);
-
- if (added != null && added == 0L) {
- Long dup = redisTemplate.opsForValue().increment(METRIC_DUP_SUB);
- log.warn(
- "[SUBSCRIBE] duplicate detected: anonymousId={}, dest={}, dupCount={}",
- anonymousId,
- destination,
- dup);
- return null;
- }
-
- log.info("[SUBSCRIBE] stored in Redis: key={}, member={}", key, destination);
-
- } catch (Exception e) {
- log.error("Redis error while handling SUBSCRIBE", e);
+ // 2) SUBSCRIBE: Redis를 사용해 anonymousId 기준 중복 구독 방지 + 메트릭 기록
+ if (StompCommand.SUBSCRIBE.equals(command)) {
+ Principal user = accessor.getUser();
+ if (user == null) {
+ Authentication auth = SecurityContextHolder.getContext().getAuthentication();
+ if (auth != null) {
+ accessor.setUser(auth);
+ user = auth;
+ }
+ }
+
+ String destination = accessor.getDestination();
+
+ if (user != null && destination != null) {
+ String anonymousId = user.getName();
+ String key = USER_SUB_KEY_PREFIX + anonymousId;
+
+ log.info("[SUBSCRIBE] handling: anonymousId={}, destination={}, key={}", anonymousId, destination, key);
+
+ try {
+ Long total = redisTemplate.opsForValue().increment(METRIC_TOTAL_SUB);
+ Long added = redisTemplate.opsForSet().add(key, destination);
+ redisTemplate.expire(key, java.time.Duration.ofHours(1));
+
+ log.info("[SUBSCRIBE] redis result: total={}, added={}", total, added);
+
+ if (added != null && added == 0L) {
+ Long dup = redisTemplate.opsForValue().increment(METRIC_DUP_SUB);
+ log.warn("[SUBSCRIBE] duplicate detected: anonymousId={}, dest={}, dupCount={}", anonymousId,
+ destination, dup);
+ return null;
+ }
+
+ log.info("[SUBSCRIBE] stored in Redis: key={}, member={}", key, destination);
+
+ } catch (Exception e) {
+ log.error("Redis error while handling SUBSCRIBE", e);
+ }
+ } else {
+ log.warn("[SUBSCRIBE] skipped: user or destination is null (user={}, dest={})", user, destination);
+ }
}
- } else {
- log.warn(
- "[SUBSCRIBE] skipped: user or destination is null (user={}, dest={})",
- user,
- destination);
- }
- }
- // 3) SEND: Principal 비어 있으면 SecurityContext에서 복구
- if (StompCommand.SEND.equals(command)) {
- Principal user = accessor.getUser();
- if (user == null) {
- Authentication auth = SecurityContextHolder.getContext().getAuthentication();
- if (auth != null) {
- accessor.setUser(auth);
+ // 3) SEND: Principal 비어 있으면 SecurityContext에서 복구
+ if (StompCommand.SEND.equals(command)) {
+ Principal user = accessor.getUser();
+ if (user == null) {
+ Authentication auth = SecurityContextHolder.getContext().getAuthentication();
+ if (auth != null) {
+ accessor.setUser(auth);
+ }
+ }
}
- }
- }
- // 4) DISCONNECT: 유저별 구독 키를 정리할지 여부 (옵션)
- // - 전체 방 전체 유저 수가 크지 않다면 TTL만으로도 충분.
- if (StompCommand.DISCONNECT.equals(command)) {
- Principal user = accessor.getUser();
- if (user == null) {
- Authentication auth = SecurityContextHolder.getContext().getAuthentication();
- if (auth != null) {
- user = auth;
- }
- }
- if (user != null) {
- String anonymousId = user.getName();
- String key = USER_SUB_KEY_PREFIX + anonymousId;
- try {
- // 완전히 정리하고 싶으면 delete
- redisTemplate.delete(key);
- log.info("DISCONNECT: cleared subscriptions for anonymousId={}", anonymousId);
- } catch (Exception e) {
- log.error("Redis error while handling DISCONNECT", e);
+ // 4) DISCONNECT: 유저별 구독 키를 정리할지 여부 (옵션)
+ // - 전체 방 전체 유저 수가 크지 않다면 TTL만으로도 충분.
+ if (StompCommand.DISCONNECT.equals(command)) {
+ Principal user = accessor.getUser();
+ if (user == null) {
+ Authentication auth = SecurityContextHolder.getContext().getAuthentication();
+ if (auth != null) {
+ user = auth;
+ }
+ }
+ if (user != null) {
+ String anonymousId = user.getName();
+ String key = USER_SUB_KEY_PREFIX + anonymousId;
+ try {
+ // 완전히 정리하고 싶으면 delete
+ redisTemplate.delete(key);
+ log.info("DISCONNECT: cleared subscriptions for anonymousId={}", anonymousId);
+ } catch (Exception e) {
+ log.error("Redis error while handling DISCONNECT", e);
+ }
+ }
}
- }
- }
- return message;
- }
+ return message;
+ }
}
diff --git a/src/main/java/opensource/bravest/global/security/jwt/JwtAuthenticationFilter.java b/src/main/java/opensource/bravest/global/security/jwt/JwtAuthenticationFilter.java
index 34ccece..89e00b7 100644
--- a/src/main/java/opensource/bravest/global/security/jwt/JwtAuthenticationFilter.java
+++ b/src/main/java/opensource/bravest/global/security/jwt/JwtAuthenticationFilter.java
@@ -16,56 +16,56 @@
import org.springframework.web.filter.OncePerRequestFilter;
/**
- * JWT가 필요한 보호 경로에만 동작하도록 만든 필터. - 화이트리스트(permitAll) 경로와 OPTIONS 프리플라이트는 필터를 건너뜀. - 토큰이 유효하면
- * SecurityContext 설정, 아니면 체인 진행 (401은 EntryPoint가 처리)
+ * JWT가 필요한 보호 경로에만 동작하도록 만든 필터. - 화이트리스트(permitAll) 경로와 OPTIONS 프리플라이트는 필터를 건너뜀. - 토큰이 유효하면 SecurityContext 설정, 아니면 체인
+ * 진행 (401은 EntryPoint가 처리)
*/
public class JwtAuthenticationFilter extends OncePerRequestFilter {
- private final JwtTokenProvider jwtTokenProvider;
- private final List skipPatterns; // 필터를 스킵할 경로 패턴들(ant style)
- private final AntPathMatcher matcher = new AntPathMatcher();
+ private final JwtTokenProvider jwtTokenProvider;
+ private final List skipPatterns; // 필터를 스킵할 경로 패턴들(ant style)
+ private final AntPathMatcher matcher = new AntPathMatcher();
- public JwtAuthenticationFilter(JwtTokenProvider provider, Collection skipPatterns) {
- this.jwtTokenProvider = provider;
- this.skipPatterns = skipPatterns == null ? List.of() : List.copyOf(skipPatterns);
- }
+ public JwtAuthenticationFilter(JwtTokenProvider provider, Collection skipPatterns) {
+ this.jwtTokenProvider = provider;
+ this.skipPatterns = skipPatterns == null ? List.of() : List.copyOf(skipPatterns);
+ }
- @Override
- protected boolean shouldNotFilter(HttpServletRequest request) {
- // 1) CORS preflight는 항상 스킵
- if ("OPTIONS".equalsIgnoreCase(request.getMethod())) return true;
+ @Override
+ protected boolean shouldNotFilter(HttpServletRequest request) {
+ // 1) CORS preflight는 항상 스킵
+ if ("OPTIONS".equalsIgnoreCase(request.getMethod()))
+ return true;
- // 2) 화이트리스트 패턴은 스킵
- String path = request.getServletPath();
- for (String p : skipPatterns) {
- if (matcher.match(p, path)) return true;
+ // 2) 화이트리스트 패턴은 스킵
+ String path = request.getServletPath();
+ for (String p : skipPatterns) {
+ if (matcher.match(p, path))
+ return true;
+ }
+ return false;
}
- return false;
- }
- @Override
- protected void doFilterInternal(
- HttpServletRequest request, HttpServletResponse response, FilterChain chain)
- throws ServletException, IOException {
+ @Override
+ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
+ throws ServletException, IOException {
- String header = request.getHeader(HttpHeaders.AUTHORIZATION);
+ String header = request.getHeader(HttpHeaders.AUTHORIZATION);
- if (header != null && header.startsWith("Bearer ")) {
- String token = header.substring(7);
- try {
- Claims claims = jwtTokenProvider.parseClaims(token);
- String subject = claims.getSubject();
- if (subject != null && SecurityContextHolder.getContext().getAuthentication() == null) {
- // 필요 시 roles/authorities를 claims에서 꺼내서 넣어도 됨
- var auth =
- new UsernamePasswordAuthenticationToken(subject, null, Collections.emptyList());
- SecurityContextHolder.getContext().setAuthentication(auth);
+ if (header != null && header.startsWith("Bearer ")) {
+ String token = header.substring(7);
+ try {
+ Claims claims = jwtTokenProvider.parseClaims(token);
+ String subject = claims.getSubject();
+ if (subject != null && SecurityContextHolder.getContext().getAuthentication() == null) {
+ // 필요 시 roles/authorities를 claims에서 꺼내서 넣어도 됨
+ var auth = new UsernamePasswordAuthenticationToken(subject, null, Collections.emptyList());
+ SecurityContextHolder.getContext().setAuthentication(auth);
+ }
+ } catch (Exception ignored) {
+ // 유효하지 않으면 그냥 통과 -> 최종적으로 EntryPoint가 401 응답 처리
+ }
}
- } catch (Exception ignored) {
- // 유효하지 않으면 그냥 통과 -> 최종적으로 EntryPoint가 401 응답 처리
- }
- }
- chain.doFilter(request, response);
- }
+ chain.doFilter(request, response);
+ }
}
diff --git a/src/main/java/opensource/bravest/global/security/jwt/JwtTokenProvider.java b/src/main/java/opensource/bravest/global/security/jwt/JwtTokenProvider.java
index f5a8f66..6640e7a 100644
--- a/src/main/java/opensource/bravest/global/security/jwt/JwtTokenProvider.java
+++ b/src/main/java/opensource/bravest/global/security/jwt/JwtTokenProvider.java
@@ -16,78 +16,64 @@
@Component
public class JwtTokenProvider {
- @Value("${jwt.secret}")
- private String secret;
+ @Value("${jwt.secret}")
+ private String secret;
- @Value("${jwt.access-token-validity-seconds}")
- private long accessValidity;
+ @Value("${jwt.access-token-validity-seconds}")
+ private long accessValidity;
- @Value("${jwt.refresh-token-validity-seconds}")
- private long refreshValidity;
+ @Value("${jwt.refresh-token-validity-seconds}")
+ private long refreshValidity;
- private SecretKey key;
+ private SecretKey key;
- @PostConstruct
- void init() {
- if (secret == null || secret.isBlank()) {
- throw new IllegalStateException(
- "jwt.secret is not configured. Check your application.yml / env.");
- }
+ @PostConstruct
+ void init() {
+ if (secret == null || secret.isBlank()) {
+ throw new IllegalStateException("jwt.secret is not configured. Check your application.yml / env.");
+ }
- byte[] keyBytes;
- try {
- // secret이 Base64면 여기서 정상 디코딩
- keyBytes = Decoders.BASE64.decode(secret);
- } catch (IllegalArgumentException e) {
- // Base64 아니면 그냥 문자열 바이트로 사용
- keyBytes = secret.getBytes(StandardCharsets.UTF_8);
- }
+ byte[] keyBytes;
+ try {
+ // secret이 Base64면 여기서 정상 디코딩
+ keyBytes = Decoders.BASE64.decode(secret);
+ } catch (IllegalArgumentException e) {
+ // Base64 아니면 그냥 문자열 바이트로 사용
+ keyBytes = secret.getBytes(StandardCharsets.UTF_8);
+ }
- this.key = Keys.hmacShaKeyFor(keyBytes);
- }
+ this.key = Keys.hmacShaKeyFor(keyBytes);
+ }
- public String createAccessToken(String subject, Map claims) {
- Instant now = Instant.now();
- return Jwts.builder()
- .subject(subject)
- .claims(claims)
- .issuedAt(Date.from(now))
- .expiration(Date.from(now.plusSeconds(accessValidity)))
- .signWith(key)
- .compact();
- }
+ public String createAccessToken(String subject, Map claims) {
+ Instant now = Instant.now();
+ return Jwts.builder().subject(subject).claims(claims).issuedAt(Date.from(now))
+ .expiration(Date.from(now.plusSeconds(accessValidity))).signWith(key).compact();
+ }
- public String createRefreshToken(String subject) {
- Instant now = Instant.now();
- return Jwts.builder()
- .subject(subject)
- .issuedAt(Date.from(now))
- .expiration(Date.from(now.plusSeconds(refreshValidity)))
- .signWith(key)
- .compact();
- }
+ public String createRefreshToken(String subject) {
+ Instant now = Instant.now();
+ return Jwts.builder().subject(subject).issuedAt(Date.from(now))
+ .expiration(Date.from(now.plusSeconds(refreshValidity))).signWith(key).compact();
+ }
- public Long getIdFromToken(String token) {
- Claims claims =
- Jwts.parser()
- .verifyWith(key) // init()에서 만든 key 재사용
- .build()
- .parseSignedClaims(token)
- .getPayload();
+ public Long getIdFromToken(String token) {
+ Claims claims = Jwts.parser().verifyWith(key) // init()에서 만든 key 재사용
+ .build().parseSignedClaims(token).getPayload();
- return claims.get("id", Long.class);
- }
+ return claims.get("id", Long.class);
+ }
- public boolean validateToken(String token) {
- try {
- Jwts.parser().verifyWith(key).build().parseSignedClaims(token);
- return true;
- } catch (Exception e) {
- return false;
+ public boolean validateToken(String token) {
+ try {
+ Jwts.parser().verifyWith(key).build().parseSignedClaims(token);
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
}
- }
- public Claims parseClaims(String token) {
- return Jwts.parser().verifyWith(key).build().parseSignedClaims(token).getPayload();
- }
+ public Claims parseClaims(String token) {
+ return Jwts.parser().verifyWith(key).build().parseSignedClaims(token).getPayload();
+ }
}
diff --git a/src/test/java/opensource/bravest/BravestApplicationTests.java b/src/test/java/opensource/bravest/BravestApplicationTests.java
index bde485a..ca77007 100644
--- a/src/test/java/opensource/bravest/BravestApplicationTests.java
+++ b/src/test/java/opensource/bravest/BravestApplicationTests.java
@@ -6,6 +6,6 @@
@SpringBootTest
class BravestApplicationTests {
- @Test
- void contextLoads() {}
+ @Test
+ void contextLoads() {}
}