From fd72c03d73225e8e7a9197f87350ef538f7371b6 Mon Sep 17 00:00:00 2001 From: chaechae Date: Thu, 17 Jul 2025 10:52:08 +0900 Subject: [PATCH 1/8] =?UTF-8?q?style:=20=EC=BF=BC=EB=A6=AC=20=ED=86=B5?= =?UTF-8?q?=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dao/ParticipantRepository.java | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/oronaminc/join/participant/dao/ParticipantRepository.java b/src/main/java/com/oronaminc/join/participant/dao/ParticipantRepository.java index 2b86ccc..6f200f8 100644 --- a/src/main/java/com/oronaminc/join/participant/dao/ParticipantRepository.java +++ b/src/main/java/com/oronaminc/join/participant/dao/ParticipantRepository.java @@ -15,11 +15,11 @@ public interface ParticipantRepository extends JpaRepository { - @Query( - "SELECT COUNT(p) > 0 " + - "FROM Participant p " + - "WHERE p.room.id = :roomId AND p.member.id = :memberId" - ) + @Query(""" + select COUNT(p) > 0 + from Participant p + where p.room.id = :roomId and p.member.id = :memberId + """) boolean existsByRoomIdAndMemberId(@Param("roomId") Long roomId, @Param("memberId") Long memberId); Optional findByRoomIdAndParticipantType(Long roomId, ParticipantType participantType); @@ -30,7 +30,7 @@ public interface ParticipantRepository extends JpaRepository from Participant p where p.member.id = :memberId group by p.participantType - """) + """) List countByMemberIdGroupByParticipantType(Long memberId); @Query(""" @@ -38,7 +38,7 @@ public interface ParticipantRepository extends JpaRepository from Participant p join fetch p.room where p.member.id = :memberId - """) + """) Page findByMemberId(Long memberId, Pageable pageable); @Query(""" @@ -46,7 +46,7 @@ public interface ParticipantRepository extends JpaRepository from Participant p join fetch p.room where p.member.id = :memberId and p.participantType = :pType - """) + """) Page findByMemberIdAndParticipantType(Long memberId, ParticipantType pType, Pageable pageable); @@ -55,30 +55,30 @@ Page findByMemberIdAndParticipantType(Long memberId, ParticipantTyp from Participant p join fetch p.room where p.member.id = :memberId and p.participantType != :pType - """) + """) Page findByMemberIdAndParticipantTypeNot(Long memberId, ParticipantType pType, Pageable pageable); Optional findByRoomIdAndMemberId( @Param("roomId") Long roomId, @Param("memberId") Long memberId ); @Query(""" - SELECT CASE WHEN COUNT(p) > 0 THEN true ELSE false END - FROM Participant p - WHERE p.room.id = :roomId - AND p.member.id = :memberId - AND (p.participantType = com.oronaminc.join.participant.domain.ParticipantType.PRESENTER - OR p.participantType = com.oronaminc.join.participant.domain.ParticipantType.TEAM) + select case when COUNT(p) > 0 then true else false end + from Participant p + where p.room.id = :roomId + and p.member.id = :memberId + and (p.participantType = com.oronaminc.join.participant.domain.ParticipantType.PRESENTER + or p.participantType = com.oronaminc.join.participant.domain.ParticipantType.TEAM) """) boolean existsPresenterOrTeamByMemberId(@Param("roomId") Long roomId, @Param("memberId") Long memberId); void deleteByRoomId(Long roomId); @Query(value = """ - SELECT COUNT(*) - FROM participant - WHERE room_id = :roomId - AND exited_at IS NOT NULL - AND TIMESTAMPDIFF(SECOND, created_at, exited_at) >= 30 + select COUNT(*) + from participant + where room_id = :roomId + and exited_at is not null + and TIMESTAMPDIFF(SECOND, created_at, exited_at) >= 30 """, nativeQuery = true) Long countParticipantsStayedOver30Seconds(@Param("roomId") Long roomId); } \ No newline at end of file From 984bec6c0ea8e0c3dadbae2035e9942e48ce7d2b Mon Sep 17 00:00:00 2001 From: chaechae Date: Thu, 17 Jul 2025 11:20:53 +0900 Subject: [PATCH 2/8] =?UTF-8?q?refactor:=20eventType=20enum=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../oronaminc/join/answer/dto/AnswerCreateResponse.java | 3 ++- .../oronaminc/join/answer/dto/AnswerDeleteResponse.java | 3 ++- .../oronaminc/join/answer/dto/AnswerUpdateResponse.java | 3 ++- .../com/oronaminc/join/answer/mapper/AnswerMapper.java | 5 +++-- .../java/com/oronaminc/join/emoji/dto/EmojiResponse.java | 3 ++- .../com/oronaminc/join/emoji/service/EmojiService.java | 5 +++-- .../join/question/dto/QuestionCreateResponse.java | 3 ++- .../join/question/dto/QuestionDeleteResponse.java | 3 ++- .../join/question/dto/QuestionUpdateResponse.java | 3 ++- .../oronaminc/join/question/service/QuestionService.java | 3 --- .../com/oronaminc/join/question/util/QuestionMapper.java | 7 ++++--- .../com/oronaminc/join/websocket/common/EventType.java | 5 +++++ 12 files changed, 29 insertions(+), 17 deletions(-) create mode 100644 src/main/java/com/oronaminc/join/websocket/common/EventType.java diff --git a/src/main/java/com/oronaminc/join/answer/dto/AnswerCreateResponse.java b/src/main/java/com/oronaminc/join/answer/dto/AnswerCreateResponse.java index 391426d..c0defbb 100644 --- a/src/main/java/com/oronaminc/join/answer/dto/AnswerCreateResponse.java +++ b/src/main/java/com/oronaminc/join/answer/dto/AnswerCreateResponse.java @@ -1,6 +1,7 @@ package com.oronaminc.join.answer.dto; import com.oronaminc.join.global.dto.WriterDto; +import com.oronaminc.join.websocket.common.EventType; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Size; @@ -14,7 +15,7 @@ public record AnswerCreateResponse( @Schema(description = "답변이 생성될 질문 ID") Long questionId, @Schema(description = "답변 생성/삭제/수정 상태", example = "CREATE") - String event, + EventType event, @Schema(description = "답변 ID", example = "11") Long answerId, @Schema(description = "답변 내용", example = "답변입니다.") diff --git a/src/main/java/com/oronaminc/join/answer/dto/AnswerDeleteResponse.java b/src/main/java/com/oronaminc/join/answer/dto/AnswerDeleteResponse.java index d8f4f64..36b5c9b 100644 --- a/src/main/java/com/oronaminc/join/answer/dto/AnswerDeleteResponse.java +++ b/src/main/java/com/oronaminc/join/answer/dto/AnswerDeleteResponse.java @@ -1,12 +1,13 @@ package com.oronaminc.join.answer.dto; +import com.oronaminc.join.websocket.common.EventType; import io.swagger.v3.oas.annotations.media.Schema; @Schema(description = "답변 삭제 응답 DTO") public record AnswerDeleteResponse( Long answerId, @Schema(description = "삭제 이벤트", example = "DELETE") - String event + EventType event ) { } diff --git a/src/main/java/com/oronaminc/join/answer/dto/AnswerUpdateResponse.java b/src/main/java/com/oronaminc/join/answer/dto/AnswerUpdateResponse.java index 3248b78..11f3835 100644 --- a/src/main/java/com/oronaminc/join/answer/dto/AnswerUpdateResponse.java +++ b/src/main/java/com/oronaminc/join/answer/dto/AnswerUpdateResponse.java @@ -1,5 +1,6 @@ package com.oronaminc.join.answer.dto; +import com.oronaminc.join.websocket.common.EventType; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; @@ -8,7 +9,7 @@ public record AnswerUpdateResponse( Long answerId, @Schema(description = "수정 이벤트", example = "UPDATE") - String event, + EventType event, @Schema(description = "수정된 내용", example = "수정된 답변입니다.") String content diff --git a/src/main/java/com/oronaminc/join/answer/mapper/AnswerMapper.java b/src/main/java/com/oronaminc/join/answer/mapper/AnswerMapper.java index 95dace3..0d27485 100644 --- a/src/main/java/com/oronaminc/join/answer/mapper/AnswerMapper.java +++ b/src/main/java/com/oronaminc/join/answer/mapper/AnswerMapper.java @@ -8,6 +8,7 @@ import com.oronaminc.join.global.dto.WriterDto; import com.oronaminc.join.member.domain.Member; import com.oronaminc.join.question.domain.Question; +import com.oronaminc.join.websocket.common.EventType; import lombok.AccessLevel; import lombok.NoArgsConstructor; @@ -17,7 +18,7 @@ public class AnswerMapper { public static AnswerCreateResponse toAnswerCreateResponse(Answer answer) { return AnswerCreateResponse.builder() .questionId(answer.getQuestion().getId()) - .event("CREATE") + .event(EventType.CREATE) .answerId(answer.getId()) .content(answer.getContent()) .emojiCount(0) @@ -51,7 +52,7 @@ public static Answer toEntity(Question question, Member member, AnswerRequest re public static AnswerUpdateResponse toAnswerUpdateResponse(Answer answer) { return AnswerUpdateResponse.builder() .answerId(answer.getId()) - .event("UPDATE") + .event(EventType.UPDATE) .content(answer.getContent()) .build(); } diff --git a/src/main/java/com/oronaminc/join/emoji/dto/EmojiResponse.java b/src/main/java/com/oronaminc/join/emoji/dto/EmojiResponse.java index eda6d68..99fc8a5 100644 --- a/src/main/java/com/oronaminc/join/emoji/dto/EmojiResponse.java +++ b/src/main/java/com/oronaminc/join/emoji/dto/EmojiResponse.java @@ -1,12 +1,13 @@ package com.oronaminc.join.emoji.dto; import com.oronaminc.join.emoji.domain.TargetType; +import com.oronaminc.join.websocket.common.EventType; import io.swagger.v3.oas.annotations.media.Schema; @Schema(description = "발표방/질문/답변 공감 생성/삭제 응답 DTO") public record EmojiResponse( @Schema(description = "이벤트 타입 (CREATE, DELETE)", example = "CREATE") - String event, + EventType event, @Schema(description = "공감 대상 타입 (ROOM, QUESTION, ANSWER)", example = "ROOM") TargetType targetType, @Schema(description = "공감 대상 ID", example = "1") diff --git a/src/main/java/com/oronaminc/join/emoji/service/EmojiService.java b/src/main/java/com/oronaminc/join/emoji/service/EmojiService.java index 8bdc68b..4b20cae 100644 --- a/src/main/java/com/oronaminc/join/emoji/service/EmojiService.java +++ b/src/main/java/com/oronaminc/join/emoji/service/EmojiService.java @@ -11,6 +11,7 @@ import com.oronaminc.join.member.service.MemberReader; import com.oronaminc.join.question.service.QuestionReader; import com.oronaminc.join.room.service.RoomReader; +import com.oronaminc.join.websocket.common.EventType; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -46,7 +47,7 @@ public EmojiResponse createEmoji(Long memberId, EmojiRequest emojiRequest) { emojiCount = incrementEmojiCount(targetType, targetId); - return new EmojiResponse("CREATE", targetType, targetId, emojiCount); + return new EmojiResponse(EventType.CREATE, targetType, targetId, emojiCount); } @@ -62,7 +63,7 @@ public EmojiResponse deleteEmoji(Long memberId, EmojiRequest emojiRequest) { ); emojiCount = decrementEmojiCount(targetType, targetId); - return new EmojiResponse("DELETE", targetType, targetId, emojiCount); + return new EmojiResponse(EventType.DELETE, targetType, targetId, emojiCount); } diff --git a/src/main/java/com/oronaminc/join/question/dto/QuestionCreateResponse.java b/src/main/java/com/oronaminc/join/question/dto/QuestionCreateResponse.java index 6cd4055..6e53af7 100644 --- a/src/main/java/com/oronaminc/join/question/dto/QuestionCreateResponse.java +++ b/src/main/java/com/oronaminc/join/question/dto/QuestionCreateResponse.java @@ -2,6 +2,7 @@ import com.oronaminc.join.global.dto.WriterDto; +import com.oronaminc.join.websocket.common.EventType; import io.swagger.v3.oas.annotations.media.Schema; import java.time.LocalDateTime; import lombok.Builder; @@ -10,7 +11,7 @@ @Schema(description = "질문 생성 응답 DTO") public record QuestionCreateResponse( @Schema(description = "", example = "CREATE") - String event, + EventType event, @Schema(description = "질문 ID", example = "11") Long questionId, @Schema(description = "질문 내용", example = "질문있습니다. 질문생성DTO가 맞나요?") diff --git a/src/main/java/com/oronaminc/join/question/dto/QuestionDeleteResponse.java b/src/main/java/com/oronaminc/join/question/dto/QuestionDeleteResponse.java index a140a2a..a3f1044 100644 --- a/src/main/java/com/oronaminc/join/question/dto/QuestionDeleteResponse.java +++ b/src/main/java/com/oronaminc/join/question/dto/QuestionDeleteResponse.java @@ -1,11 +1,12 @@ package com.oronaminc.join.question.dto; +import com.oronaminc.join.websocket.common.EventType; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; @Schema(description = "질문 삭제 응답 DTO") public record QuestionDeleteResponse( - String event, + EventType event, Long questionId ) { } diff --git a/src/main/java/com/oronaminc/join/question/dto/QuestionUpdateResponse.java b/src/main/java/com/oronaminc/join/question/dto/QuestionUpdateResponse.java index efd0396..ee4388e 100644 --- a/src/main/java/com/oronaminc/join/question/dto/QuestionUpdateResponse.java +++ b/src/main/java/com/oronaminc/join/question/dto/QuestionUpdateResponse.java @@ -1,12 +1,13 @@ package com.oronaminc.join.question.dto; +import com.oronaminc.join.websocket.common.EventType; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Builder; @Builder @Schema(description = "질문 수정 응답 DTO") public record QuestionUpdateResponse( - String event, + EventType event, Long questionId, String content diff --git a/src/main/java/com/oronaminc/join/question/service/QuestionService.java b/src/main/java/com/oronaminc/join/question/service/QuestionService.java index 3a99b8d..cb5e226 100644 --- a/src/main/java/com/oronaminc/join/question/service/QuestionService.java +++ b/src/main/java/com/oronaminc/join/question/service/QuestionService.java @@ -42,9 +42,7 @@ public class QuestionService { public Question create(Long roomId, Long memberId, QuestionRequest requestDto) { Member member = memberReader.getById(memberId); - Room room = roomReader.getById(roomId); - participantService.validateParticipant(memberId, roomId); Question question = QuestionMapper.toQuestion(room, member, requestDto); @@ -117,7 +115,6 @@ public Long delete(Long memberId, Long roomId, Long questionId) { return question.getId(); } - @Transactional public void deleteByRoomId(Long roomId) { List questions = questionReader.findByRoomId(roomId); diff --git a/src/main/java/com/oronaminc/join/question/util/QuestionMapper.java b/src/main/java/com/oronaminc/join/question/util/QuestionMapper.java index 9a784f0..4a045e8 100644 --- a/src/main/java/com/oronaminc/join/question/util/QuestionMapper.java +++ b/src/main/java/com/oronaminc/join/question/util/QuestionMapper.java @@ -12,6 +12,7 @@ import com.oronaminc.join.question.dto.QuestionListResponse; import com.oronaminc.join.question.dto.QuestionUpdateResponse; import com.oronaminc.join.room.domain.Room; +import com.oronaminc.join.websocket.common.EventType; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.springframework.data.domain.Slice; @@ -25,7 +26,7 @@ public static Question toQuestion(Room room, Member member, QuestionRequest requ public static QuestionCreateResponse toQuestionCreateResponse (Question question) { return QuestionCreateResponse.builder() - .event("CREATE") + .event(EventType.CREATE) .questionId(question.getId()) .content(question.getContent()) .emojiCount(0L) @@ -56,7 +57,7 @@ public static QuestionAssembleResponse toQuestionListResponse(QuestionFlatRespon public static QuestionUpdateResponse toQuestionUpdateResponse(Question question) { return QuestionUpdateResponse.builder() - .event("UPDATE") + .event(EventType.UPDATE) .questionId(question.getId()) .content(question.getContent()) .build(); @@ -64,7 +65,7 @@ public static QuestionUpdateResponse toQuestionUpdateResponse(Question question) public static QuestionDeleteResponse toQuestionDeleteResponse(Long questionId) { return new QuestionDeleteResponse( - "DELETE", + EventType.DELETE, questionId ); } diff --git a/src/main/java/com/oronaminc/join/websocket/common/EventType.java b/src/main/java/com/oronaminc/join/websocket/common/EventType.java new file mode 100644 index 0000000..b3bb363 --- /dev/null +++ b/src/main/java/com/oronaminc/join/websocket/common/EventType.java @@ -0,0 +1,5 @@ +package com.oronaminc.join.websocket.common; + +public enum EventType { + CREATE, UPDATE, DELETE +} From 27e6838bf0b1b2c2295012b52d9097be7d205b96 Mon Sep 17 00:00:00 2001 From: chaechae Date: Thu, 17 Jul 2025 14:37:59 +0900 Subject: [PATCH 3/8] =?UTF-8?q?refactor:=20=EC=98=88=EC=99=B8=20=EB=A9=94?= =?UTF-8?q?=EC=8B=9C=EC=A7=80=20=ED=8F=AC=ED=95=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../join/global/exception/ErrorException.java | 18 +++++++++++++++++- .../join/global/exception/ExceptionAdvice.java | 2 +- .../join/question/service/QuestionService.java | 3 ++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/oronaminc/join/global/exception/ErrorException.java b/src/main/java/com/oronaminc/join/global/exception/ErrorException.java index 979f2c1..6e15771 100644 --- a/src/main/java/com/oronaminc/join/global/exception/ErrorException.java +++ b/src/main/java/com/oronaminc/join/global/exception/ErrorException.java @@ -1,5 +1,7 @@ package com.oronaminc.join.global.exception; +import com.oronaminc.join.global.util.StringUtil; +import java.text.MessageFormat; import lombok.AllArgsConstructor; import lombok.Getter; @@ -8,5 +10,19 @@ public class ErrorException extends RuntimeException { private final ErrorCode errorCode; + private final String errorMessage; -} + public ErrorException(ErrorCode errorCode) { + this(errorCode, null); + } + + public static ErrorException of(ErrorCode errorCode, String message, Object... args) { + String errorMessage = createMessage(message, args); + return new ErrorException(errorCode, errorMessage); + } + + public String createMessage(String message, Object... args) { + return StringUtil.format(message, args); + } + +} \ No newline at end of file diff --git a/src/main/java/com/oronaminc/join/global/exception/ExceptionAdvice.java b/src/main/java/com/oronaminc/join/global/exception/ExceptionAdvice.java index c166075..3572740 100644 --- a/src/main/java/com/oronaminc/join/global/exception/ExceptionAdvice.java +++ b/src/main/java/com/oronaminc/join/global/exception/ExceptionAdvice.java @@ -18,7 +18,7 @@ public class ExceptionAdvice { public ResponseEntity handleErrorException(ErrorException ex) { ErrorCode errorCode = ex.getErrorCode(); - log.error(errorCode.getMessage(), ex); + log.error("ErrorCode: {}, ErrorMessage: {}", ex.getErrorCode(), ex.getErrorMessage()); HttpStatus httpStatus = switch (errorCode.getErrorStatus()) { case NOT_FOUND -> HttpStatus.NOT_FOUND; diff --git a/src/main/java/com/oronaminc/join/question/service/QuestionService.java b/src/main/java/com/oronaminc/join/question/service/QuestionService.java index cb5e226..3eccb5c 100644 --- a/src/main/java/com/oronaminc/join/question/service/QuestionService.java +++ b/src/main/java/com/oronaminc/join/question/service/QuestionService.java @@ -81,7 +81,8 @@ public Question update(Long memberId, Long roomId, Long questionId, QuestionRequ // 참여자가 아님 if (!participantReader.existsByRoomIdAndMemberId(roomId, memberId)) { - throw new ErrorException(ErrorCode.NOT_FOUND_PARTICIPANT); + throw ErrorException.of(ErrorCode.NOT_FOUND_PARTICIPANT, + "{}번 발표방에는 {}번 회원이 잠가 중이지 않습니다.", roomId, memberId); } // 작성자가 아님 From fe978c2c008a90594db24454eb371ed860c22159 Mon Sep 17 00:00:00 2001 From: chaechae Date: Thu, 17 Jul 2025 15:23:10 +0900 Subject: [PATCH 4/8] =?UTF-8?q?feat:=20errorcode=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/oronaminc/join/global/exception/ErrorCode.java | 3 +-- .../com/oronaminc/join/global/exception/ErrorException.java | 2 +- .../join/websocket/api/AnswerWebsocketController.java | 3 ++- .../join/websocket/config/ParticipantEventHandler.java | 5 +++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/oronaminc/join/global/exception/ErrorCode.java b/src/main/java/com/oronaminc/join/global/exception/ErrorCode.java index bd4260b..dd3b563 100644 --- a/src/main/java/com/oronaminc/join/global/exception/ErrorCode.java +++ b/src/main/java/com/oronaminc/join/global/exception/ErrorCode.java @@ -31,7 +31,6 @@ public enum ErrorCode { UNAUTHORIZED_LIMIT_PARTICIPANT("PARTICIPANT-005", "인원이 가득 차 참가할 수 없습니다.", UNAUTHORIZED), UNAUTHORIZED_NOT_JOIN_ROOM("PARTICIPANT-005", "발표방에 참여하지 않았습니다. 먼저 참여해주세요.", UNAUTHORIZED), - FILE_UPLOAD_FAILED("FILE-001", "파일 업로드에 실패하였습니다.", INTERNAL_SERVER_ERROR), NOT_FOUND_FILE("FILE-002", "존재하지 않는 파일입니다.", NOT_FOUND), @@ -48,7 +47,6 @@ public enum ErrorCode { UNAUTHORIZED_EDIT_ANSWER("ANSWER-005", "작성자가 아니면 해당 댓글을 수정할 수 없습니다.", UNAUTHORIZED), UNAUTHORIZED_DELETE_ANSWER("ANSWER-006", "작성자 혹은 팀원, 발표자가 아니면 해당 댓글을 삭제할 수 없습니다.", UNAUTHORIZED), - ACCESS_DENIED_SESSION("SESSION-1201", "접근 권한이 없습니다.", FORBIDDEN), NOT_FOUND_SESSION("SESSION-1202", "세션이 유효하지 않습니다.", UNAUTHORIZED), EXPIRED_SESSION("SESSION-1203", "세션이 만료되었습니다.", UNAUTHORIZED), @@ -59,6 +57,7 @@ public enum ErrorCode { SOCKET_BAD_REQUEST_PATH("SOCKET-1002", "경로가 유효하지 않습니다.", BAD_REQUEST), SOCKET_BAD_REQUEST_MEMBER("SOCKET-1003", "회원이 유효하지 않습니다.", BAD_REQUEST), + STOMP_INVALID_DESTINATION("STOMP-001", "경로가 유효하지 않습니다.", BAD_REQUEST), CONFLICT_EMOJI("EMOJI-001", "공감 처리 중 충돌이 발생했습니다.", CONFLICT), NOT_FOUND_EMOJI("EMOJI-002", "해당 이모지가 존재하지 않습니다.", NOT_FOUND), diff --git a/src/main/java/com/oronaminc/join/global/exception/ErrorException.java b/src/main/java/com/oronaminc/join/global/exception/ErrorException.java index 6e15771..76828f7 100644 --- a/src/main/java/com/oronaminc/join/global/exception/ErrorException.java +++ b/src/main/java/com/oronaminc/join/global/exception/ErrorException.java @@ -21,7 +21,7 @@ public static ErrorException of(ErrorCode errorCode, String message, Object... a return new ErrorException(errorCode, errorMessage); } - public String createMessage(String message, Object... args) { + public static String createMessage(String message, Object... args) { return StringUtil.format(message, args); } diff --git a/src/main/java/com/oronaminc/join/websocket/api/AnswerWebsocketController.java b/src/main/java/com/oronaminc/join/websocket/api/AnswerWebsocketController.java index d87702b..df4f58e 100644 --- a/src/main/java/com/oronaminc/join/websocket/api/AnswerWebsocketController.java +++ b/src/main/java/com/oronaminc/join/websocket/api/AnswerWebsocketController.java @@ -11,6 +11,7 @@ import com.oronaminc.join.answer.service.AnswerService; import com.oronaminc.join.answer.util.PermissionValidator; import com.oronaminc.join.global.exception.ErrorException; +import com.oronaminc.join.websocket.common.EventType; import jakarta.validation.Valid; import java.security.Principal; import lombok.RequiredArgsConstructor; @@ -79,7 +80,7 @@ public AnswerDeleteResponse delete( answerService.delete(answerId); - return new AnswerDeleteResponse(answerId, "DELETE"); + return new AnswerDeleteResponse(answerId, EventType.DELETE); } private Long getMemberId(Principal principal) { diff --git a/src/main/java/com/oronaminc/join/websocket/config/ParticipantEventHandler.java b/src/main/java/com/oronaminc/join/websocket/config/ParticipantEventHandler.java index c798c5e..7f214ab 100644 --- a/src/main/java/com/oronaminc/join/websocket/config/ParticipantEventHandler.java +++ b/src/main/java/com/oronaminc/join/websocket/config/ParticipantEventHandler.java @@ -2,6 +2,7 @@ import static com.oronaminc.join.global.exception.ErrorCode.*; +import com.oronaminc.join.global.exception.ErrorCode; import java.security.Principal; import java.util.Set; @@ -30,7 +31,7 @@ public void handleSubscribe(SessionSubscribeEvent event) { Principal principal = accessor.getUser(); if (destination == null) { - throw new ErrorException(SOCKET_BAD_REQUEST_PATH); + throw new ErrorException(STOMP_INVALID_DESTINATION); } if (!destination.startsWith(ROOM_PREFIX)) { @@ -66,7 +67,7 @@ private Long parseRoomId(String destination) { String[] parts = destination.split("/"); return Long.valueOf(parts[3]); } catch (Exception e) { - throw new ErrorException(SOCKET_BAD_REQUEST_PATH); + throw new ErrorException(STOMP_INVALID_DESTINATION); } } From 1ccb43f826c1d07c8353e1e7ac57739c00ac456a Mon Sep 17 00:00:00 2001 From: chaechae Date: Fri, 18 Jul 2025 09:22:54 +0900 Subject: [PATCH 5/8] =?UTF-8?q?feat:=20commons-lang=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 3 +++ .../com/oronaminc/join/room/util/CodeGenerator.java | 13 ++++--------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/build.gradle b/build.gradle index 83ce1a5..cc528da 100644 --- a/build.gradle +++ b/build.gradle @@ -58,6 +58,9 @@ dependencies { // bucket4j implementation 'com.bucket4j:bucket4j_jdk17-core:8.14.0' + + // commons-lang3 + implementation 'org.apache.commons:commons-lang3:3.18.0' } tasks.named('test') { diff --git a/src/main/java/com/oronaminc/join/room/util/CodeGenerator.java b/src/main/java/com/oronaminc/join/room/util/CodeGenerator.java index 39b86c4..558077a 100644 --- a/src/main/java/com/oronaminc/join/room/util/CodeGenerator.java +++ b/src/main/java/com/oronaminc/join/room/util/CodeGenerator.java @@ -1,21 +1,16 @@ package com.oronaminc.join.room.util; -import java.util.Random; - import lombok.AccessLevel; import lombok.NoArgsConstructor; +import org.apache.commons.lang3.RandomStringUtils; @NoArgsConstructor(access = AccessLevel.PRIVATE) public class CodeGenerator { + private static final String CHAR_POOL = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - private static final Random random = new Random(); public static String generateCode(int length) { - StringBuilder sb = new StringBuilder(length); - for (int i = 0; i < length; i++) { - int idx = random.nextInt(CHAR_POOL.length()); - sb.append(CHAR_POOL.charAt(idx)); - } - return sb.toString(); + + return RandomStringUtils.random(length, CHAR_POOL); } } From 942863e3d1bae56591f7240bab16787876e0f46d Mon Sep 17 00:00:00 2001 From: chaechae Date: Fri, 25 Jul 2025 12:46:15 +0900 Subject: [PATCH 6/8] =?UTF-8?q?fix:=20roomId=20=EA=B2=BD=EB=A1=9C=EB=B3=80?= =?UTF-8?q?=EC=88=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/oronaminc/join/question/api/QuestionController.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/oronaminc/join/question/api/QuestionController.java b/src/main/java/com/oronaminc/join/question/api/QuestionController.java index 2d183ee..901cfb7 100644 --- a/src/main/java/com/oronaminc/join/question/api/QuestionController.java +++ b/src/main/java/com/oronaminc/join/question/api/QuestionController.java @@ -10,6 +10,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseStatus; @@ -30,7 +31,7 @@ public ResponseEntity getQuestions( @RequestParam(required = false) Long lastEmojiCount, @RequestParam(defaultValue = "10") int size, @RequestParam Long memberId, - @RequestParam Long roomId + @PathVariable Long roomId ) { Slice result = questionService.getQuestions( sort, lastId, lastEmojiCount, size, memberId, roomId From a12574f9c5fe37452454cf959af72e9293af113e Mon Sep 17 00:00:00 2001 From: chaechae Date: Fri, 25 Jul 2025 12:58:50 +0900 Subject: [PATCH 7/8] =?UTF-8?q?refactor:=20=EC=98=88=EC=99=B8=20=EB=A9=94?= =?UTF-8?q?=EC=8B=9C=EC=A7=80=20=EA=B5=AC=EC=B2=B4=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../oronaminc/join/question/service/QuestionService.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/oronaminc/join/question/service/QuestionService.java b/src/main/java/com/oronaminc/join/question/service/QuestionService.java index ac0837e..7a283a1 100644 --- a/src/main/java/com/oronaminc/join/question/service/QuestionService.java +++ b/src/main/java/com/oronaminc/join/question/service/QuestionService.java @@ -90,7 +90,8 @@ public Question update(Long memberId, Long roomId, Long questionId, QuestionRequ // 작성자가 아님 if (!question.getMember().getId().equals(memberId)) { - throw new ErrorException(ErrorCode.UNAUTHORIZED_EDIT_QUESTION); + throw ErrorException.of(ErrorCode.UNAUTHORIZED_EDIT_QUESTION, + "{}번 회원은 {}번 질문을 수정할 권한이 없습니다.", memberId, questionId); } question.updateContent(request.content()); @@ -104,13 +105,15 @@ public Long delete(Long memberId, Long roomId, Long questionId) { // 참여자가 아님 if (!participantReader.existsByRoomIdAndMemberId(roomId, memberId)) { - throw new ErrorException(ErrorCode.NOT_FOUND_PARTICIPANT); + throw ErrorException.of(ErrorCode.NOT_FOUND_PARTICIPANT, + "{}번 발표방에는 {}번 회원이 잠가 중이지 않습니다.", roomId, memberId); } // 관리자가 아님 && 작성자도 아님 if (!participantReader.existsPresenterOrTeamByMemberId(roomId, memberId) && !question.getMember().getId().equals(memberId)) { - throw new ErrorException(ErrorCode.UNAUTHORIZED_DELETE_QUESTION); + throw ErrorException.of(ErrorCode.UNAUTHORIZED_DELETE_QUESTION, + "{}번 회원은 {}번 질문을 삭제할 권한이 없습니다.", memberId, questionId); } answerService.deleteByQuestion(questionId); From dd933a40c180c1581605f9810c8baf41f43dd785 Mon Sep 17 00:00:00 2001 From: chaechae Date: Fri, 25 Jul 2025 13:38:02 +0900 Subject: [PATCH 8/8] =?UTF-8?q?test:=20enum=20=EC=B6=94=EA=B0=80=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../join/emoji/service/EmojiServiceTests.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/test/java/com/oronaminc/join/emoji/service/EmojiServiceTests.java b/src/test/java/com/oronaminc/join/emoji/service/EmojiServiceTests.java index bea6d9d..e369c8d 100644 --- a/src/test/java/com/oronaminc/join/emoji/service/EmojiServiceTests.java +++ b/src/test/java/com/oronaminc/join/emoji/service/EmojiServiceTests.java @@ -20,6 +20,7 @@ import com.oronaminc.join.question.service.QuestionReader; import com.oronaminc.join.room.domain.Room; import com.oronaminc.join.room.service.RoomReader; +import com.oronaminc.join.websocket.common.EventType; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -83,7 +84,7 @@ void toggleEmoji_createRoomEmoji_success() { new EmojiRequest(targetType, targetId)); // then - assertThat(response.event()).isEqualTo("CREATE"); + assertThat(response.event()).isEqualTo(EventType.CREATE); assertThat(response.targetType()).isEqualTo(targetType); assertThat(response.targetId()).isEqualTo(targetId); assertThat(response.emojiCount()).isEqualTo(emojiCount + 1); @@ -121,7 +122,7 @@ void toggleEmoji_createQuestionEmoji_success() { new EmojiRequest(targetType, targetId)); // then - assertThat(response.event()).isEqualTo("CREATE"); + assertThat(response.event()).isEqualTo(EventType.CREATE); assertThat(response.targetType()).isEqualTo(targetType); assertThat(response.targetId()).isEqualTo(targetId); assertThat(response.emojiCount()).isEqualTo(emojiCount + 1); @@ -159,7 +160,7 @@ void toggleEmoji_createAnswerEmoji_success() { new EmojiRequest(targetType, targetId)); // then - assertThat(response.event()).isEqualTo("CREATE"); + assertThat(response.event()).isEqualTo(EventType.CREATE); assertThat(response.targetType()).isEqualTo(targetType); assertThat(response.targetId()).isEqualTo(targetId); assertThat(response.emojiCount()).isEqualTo(emojiCount + 1); @@ -228,7 +229,7 @@ void toggleEmoji_deleteRoomEmoji_success() { new EmojiRequest(targetType, targetId)); // then - assertThat(response.event()).isEqualTo("DELETE"); + assertThat(response.event()).isEqualTo(EventType.DELETE); assertThat(response.targetType()).isEqualTo(targetType); assertThat(response.targetId()).isEqualTo(targetId); assertThat(response.emojiCount()).isEqualTo(emojiCount - 1); @@ -264,7 +265,7 @@ void toggleEmoji_deleteQuestionEmoji_success() { new EmojiRequest(targetType, targetId)); // then - assertThat(response.event()).isEqualTo("DELETE"); + assertThat(response.event()).isEqualTo(EventType.DELETE); assertThat(response.targetType()).isEqualTo(targetType); assertThat(response.targetId()).isEqualTo(targetId); assertThat(response.emojiCount()).isEqualTo(emojiCount - 1); @@ -300,7 +301,7 @@ void toggleEmoji_deleteAnswerEmoji_success() { new EmojiRequest(targetType, targetId)); // then - assertThat(response.event()).isEqualTo("DELETE"); + assertThat(response.event()).isEqualTo(EventType.DELETE); assertThat(response.targetType()).isEqualTo(targetType); assertThat(response.targetId()).isEqualTo(targetId); assertThat(response.emojiCount()).isEqualTo(emojiCount - 1);