From b9a4ce3e92e654d1daccff34f8e0f9c3e44ee0e5 Mon Sep 17 00:00:00 2001 From: limkanghyun Date: Mon, 14 Jul 2025 15:30:49 +0900 Subject: [PATCH 1/9] =?UTF-8?q?:sparkles:=20feat:=20quizId=EB=A1=9C=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=ED=95=9C=20Quiz=EB=A1=9C=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5=EC=97=90=20=ED=8F=AC=ED=95=A8=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/game/app/RoomService.java | 41 ++++++++++--------- .../backend/domain/quiz/app/QuizService.java | 5 +++ 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/backend/src/main/java/io/f1/backend/domain/game/app/RoomService.java b/backend/src/main/java/io/f1/backend/domain/game/app/RoomService.java index a9d6f324..518f0d30 100644 --- a/backend/src/main/java/io/f1/backend/domain/game/app/RoomService.java +++ b/backend/src/main/java/io/f1/backend/domain/game/app/RoomService.java @@ -12,17 +12,19 @@ import io.f1.backend.domain.game.dto.response.RoomListResponse; import io.f1.backend.domain.game.dto.response.RoomResponse; import io.f1.backend.domain.game.dto.response.RoomSettingResponse; +import io.f1.backend.domain.game.event.RoomCreatedEvent; import io.f1.backend.domain.game.model.GameSetting; import io.f1.backend.domain.game.model.Player; import io.f1.backend.domain.game.model.Room; import io.f1.backend.domain.game.model.RoomSetting; import io.f1.backend.domain.game.model.RoomState; import io.f1.backend.domain.game.store.RoomRepository; +import io.f1.backend.domain.quiz.app.QuizService; import io.f1.backend.domain.quiz.entity.Quiz; -import io.f1.backend.domain.user.entity.User; import lombok.RequiredArgsConstructor; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import java.util.List; @@ -33,8 +35,10 @@ @RequiredArgsConstructor public class RoomService { + private final QuizService quizService; private final RoomRepository roomRepository; private final AtomicLong roomIdGenerator = new AtomicLong(0); + private final ApplicationEventPublisher eventPublisher; public RoomCreateResponse saveRoom(RoomCreateRequest request, Map loginUser) { @@ -46,7 +50,14 @@ public RoomCreateResponse saveRoom(RoomCreateRequest request, Map rooms = roomRepository.findAll(); - List roomResponses = - rooms.stream() - .map( - room -> { - User user = new User(); // 임시 유저 객체 - user.setNickname("임시 유저 닉네임"); - - Quiz quiz = new Quiz(); // 임시 퀴즈 객체 - quiz.setTitle("임시 퀴즈 제목"); - quiz.setDescription("임시 퀴즈 설명"); - quiz.setThumbnailUrl("임시 이미지"); - quiz.setQuestions(List.of()); - quiz.setCreator(user); - - return toRoomResponse(room, quiz); - }) - .toList(); + List roomResponses = rooms.stream() + .map(room -> { + Long quizId = room.getGameSetting().getQuizId(); + Quiz quiz = quizService.getQuizById(quizId); + + return toRoomResponse(room, quiz); + }) + .toList(); return new RoomListResponse(roomResponses); } } diff --git a/backend/src/main/java/io/f1/backend/domain/quiz/app/QuizService.java b/backend/src/main/java/io/f1/backend/domain/quiz/app/QuizService.java index ffe46c50..3055c2f5 100644 --- a/backend/src/main/java/io/f1/backend/domain/quiz/app/QuizService.java +++ b/backend/src/main/java/io/f1/backend/domain/quiz/app/QuizService.java @@ -91,4 +91,9 @@ private String convertToThumbnailPath(MultipartFile thumbnailFile) throws IOExce private String getExtension(String filename) { return filename.substring(filename.lastIndexOf(".") + 1); } + + public Quiz getQuizById(Long quizId) { + return quizRepository.findById(quizId) + .orElseThrow(() -> new RuntimeException("E404002: 존재하지 않는 퀴즈입니다.")); + } } From dab4a28609975f7c29a5126166f5518f0aeff72d Mon Sep 17 00:00:00 2001 From: github-actions <> Date: Mon, 14 Jul 2025 06:31:07 +0000 Subject: [PATCH 2/9] =?UTF-8?q?chore:=20Java=20=EC=8A=A4=ED=83=80=EC=9D=BC?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/game/app/RoomService.java | 18 ++++++++++-------- .../backend/domain/quiz/app/QuizService.java | 5 +++-- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/backend/src/main/java/io/f1/backend/domain/game/app/RoomService.java b/backend/src/main/java/io/f1/backend/domain/game/app/RoomService.java index 518f0d30..1ae0e82a 100644 --- a/backend/src/main/java/io/f1/backend/domain/game/app/RoomService.java +++ b/backend/src/main/java/io/f1/backend/domain/game/app/RoomService.java @@ -116,14 +116,16 @@ public RoomInitialData enterRoom(Long roomId, String sessionId) { public RoomListResponse getAllRooms() { List rooms = roomRepository.findAll(); - List roomResponses = rooms.stream() - .map(room -> { - Long quizId = room.getGameSetting().getQuizId(); - Quiz quiz = quizService.getQuizById(quizId); - - return toRoomResponse(room, quiz); - }) - .toList(); + List roomResponses = + rooms.stream() + .map( + room -> { + Long quizId = room.getGameSetting().getQuizId(); + Quiz quiz = quizService.getQuizById(quizId); + + return toRoomResponse(room, quiz); + }) + .toList(); return new RoomListResponse(roomResponses); } } diff --git a/backend/src/main/java/io/f1/backend/domain/quiz/app/QuizService.java b/backend/src/main/java/io/f1/backend/domain/quiz/app/QuizService.java index 3055c2f5..dde9f6f3 100644 --- a/backend/src/main/java/io/f1/backend/domain/quiz/app/QuizService.java +++ b/backend/src/main/java/io/f1/backend/domain/quiz/app/QuizService.java @@ -93,7 +93,8 @@ private String getExtension(String filename) { } public Quiz getQuizById(Long quizId) { - return quizRepository.findById(quizId) - .orElseThrow(() -> new RuntimeException("E404002: 존재하지 않는 퀴즈입니다.")); + return quizRepository + .findById(quizId) + .orElseThrow(() -> new RuntimeException("E404002: 존재하지 않는 퀴즈입니다.")); } } From 9606b1080f2b77af4406eec2eef71faecc6ea62f Mon Sep 17 00:00:00 2001 From: limkanghyun Date: Mon, 14 Jul 2025 15:39:04 +0900 Subject: [PATCH 3/9] =?UTF-8?q?:sparkles:=20feat:=20Room=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1,=20=EC=88=98=EC=A0=95,=20=EC=82=AD=EC=A0=9C=EC=97=90?= =?UTF-8?q?=20=EB=8C=80=ED=95=9C=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EB=A6=AC?= =?UTF-8?q?=EC=8A=A4=EB=84=88=20=EC=B6=94=EA=B0=80=20-=20=EC=9D=B4?= =?UTF-8?q?=EB=B2=A4=ED=8A=B8=20=ED=83=80=EC=9E=85=20=EC=A0=95=EC=9D=98=20?= =?UTF-8?q?enum=20=EC=B6=94=EA=B0=80=20-=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=A0=84=EB=8B=AC=20=EA=B0=9D=EC=B2=B4=20=EC=B6=94=EA=B0=80(Ro?= =?UTF-8?q?omCreatedEvent,=20RoomUpdatedEvent,=20RoomDeletedEvent)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/game/event/RoomCreatedEvent.java | 8 ++++++ .../domain/game/event/RoomDeletedEvent.java | 5 ++++ .../domain/game/event/RoomUpdatedEvent.java | 7 +++++ .../listener/RoomCreatedEventListener.java | 27 +++++++++++++++++++ .../listener/RoomDeletedEventListener.java | 24 +++++++++++++++++ .../listener/RoomUpdatedEventListener.java | 23 ++++++++++++++++ 6 files changed, 94 insertions(+) create mode 100644 backend/src/main/java/io/f1/backend/domain/game/event/RoomCreatedEvent.java create mode 100644 backend/src/main/java/io/f1/backend/domain/game/event/RoomDeletedEvent.java create mode 100644 backend/src/main/java/io/f1/backend/domain/game/event/RoomUpdatedEvent.java create mode 100644 backend/src/main/java/io/f1/backend/domain/game/sse/listener/RoomCreatedEventListener.java create mode 100644 backend/src/main/java/io/f1/backend/domain/game/sse/listener/RoomDeletedEventListener.java create mode 100644 backend/src/main/java/io/f1/backend/domain/game/sse/listener/RoomUpdatedEventListener.java diff --git a/backend/src/main/java/io/f1/backend/domain/game/event/RoomCreatedEvent.java b/backend/src/main/java/io/f1/backend/domain/game/event/RoomCreatedEvent.java new file mode 100644 index 00000000..ff645eef --- /dev/null +++ b/backend/src/main/java/io/f1/backend/domain/game/event/RoomCreatedEvent.java @@ -0,0 +1,8 @@ +package io.f1.backend.domain.game.event; + +import io.f1.backend.domain.game.model.Room; +import io.f1.backend.domain.quiz.entity.Quiz; + +public record RoomCreatedEvent(Room room, Quiz quiz) { +} + diff --git a/backend/src/main/java/io/f1/backend/domain/game/event/RoomDeletedEvent.java b/backend/src/main/java/io/f1/backend/domain/game/event/RoomDeletedEvent.java new file mode 100644 index 00000000..2e319a75 --- /dev/null +++ b/backend/src/main/java/io/f1/backend/domain/game/event/RoomDeletedEvent.java @@ -0,0 +1,5 @@ +package io.f1.backend.domain.game.event; + +public record RoomDeletedEvent(Long roomId) { +} + diff --git a/backend/src/main/java/io/f1/backend/domain/game/event/RoomUpdatedEvent.java b/backend/src/main/java/io/f1/backend/domain/game/event/RoomUpdatedEvent.java new file mode 100644 index 00000000..a6a2beb9 --- /dev/null +++ b/backend/src/main/java/io/f1/backend/domain/game/event/RoomUpdatedEvent.java @@ -0,0 +1,7 @@ +package io.f1.backend.domain.game.event; + +import io.f1.backend.domain.game.model.Room; +import io.f1.backend.domain.quiz.entity.Quiz; + +public record RoomUpdatedEvent(Room room, Quiz quiz) { +} diff --git a/backend/src/main/java/io/f1/backend/domain/game/sse/listener/RoomCreatedEventListener.java b/backend/src/main/java/io/f1/backend/domain/game/sse/listener/RoomCreatedEventListener.java new file mode 100644 index 00000000..810a2c9b --- /dev/null +++ b/backend/src/main/java/io/f1/backend/domain/game/sse/listener/RoomCreatedEventListener.java @@ -0,0 +1,27 @@ +package io.f1.backend.domain.game.sse.listener; + +import io.f1.backend.domain.game.event.RoomCreatedEvent; +import io.f1.backend.domain.game.sse.app.SseService; +import io.f1.backend.domain.game.sse.dto.LobbySseEvent; +import io.f1.backend.domain.game.sse.dto.RoomCreatedPayload; +import lombok.RequiredArgsConstructor; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; + +import static io.f1.backend.domain.game.sse.mapper.SseMapper.*; + +@Component +@RequiredArgsConstructor +public class RoomCreatedEventListener { + + private final SseService sseService; + + @Async + @EventListener + public void roomCreate(RoomCreatedEvent event) { + LobbySseEvent sseEvent = fromRoomCreated(event); + sseService.notifyLobbyUpdate(sseEvent); + } + +} diff --git a/backend/src/main/java/io/f1/backend/domain/game/sse/listener/RoomDeletedEventListener.java b/backend/src/main/java/io/f1/backend/domain/game/sse/listener/RoomDeletedEventListener.java new file mode 100644 index 00000000..451217c9 --- /dev/null +++ b/backend/src/main/java/io/f1/backend/domain/game/sse/listener/RoomDeletedEventListener.java @@ -0,0 +1,24 @@ +package io.f1.backend.domain.game.sse.listener; + +import io.f1.backend.domain.game.event.RoomDeletedEvent; +import io.f1.backend.domain.game.sse.app.SseService; +import io.f1.backend.domain.game.sse.dto.LobbySseEvent; +import io.f1.backend.domain.game.sse.dto.RoomDeletedPayload; +import lombok.RequiredArgsConstructor; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; + +import static io.f1.backend.domain.game.sse.mapper.SseMapper.*; + +@RequiredArgsConstructor +public class RoomDeletedEventListener { + + private final SseService sseService; + + @Async + @EventListener + public void roomDelete(RoomDeletedEvent event) { + LobbySseEvent sseEvent = fromRoomDeleted(event); + sseService.notifyLobbyUpdate(sseEvent); + } +} diff --git a/backend/src/main/java/io/f1/backend/domain/game/sse/listener/RoomUpdatedEventListener.java b/backend/src/main/java/io/f1/backend/domain/game/sse/listener/RoomUpdatedEventListener.java new file mode 100644 index 00000000..8dd28f57 --- /dev/null +++ b/backend/src/main/java/io/f1/backend/domain/game/sse/listener/RoomUpdatedEventListener.java @@ -0,0 +1,23 @@ +package io.f1.backend.domain.game.sse.listener; + +import io.f1.backend.domain.game.event.RoomUpdatedEvent; +import io.f1.backend.domain.game.sse.app.SseService; +import io.f1.backend.domain.game.sse.dto.LobbySseEvent; +import io.f1.backend.domain.game.sse.dto.RoomUpdatedPayload; +import io.f1.backend.domain.game.sse.mapper.SseMapper; +import lombok.RequiredArgsConstructor; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; + +@RequiredArgsConstructor +public class RoomUpdatedEventListener { + + private final SseService sseService; + + @Async + @EventListener + public void roomUpdate(RoomUpdatedEvent event) { + LobbySseEvent sseEvent = SseMapper.fromRoomUpdated(event); + sseService.notifyLobbyUpdate(sseEvent); + } +} From 69c69d7219f14e44708911fe54f694d47a2943f1 Mon Sep 17 00:00:00 2001 From: github-actions <> Date: Mon, 14 Jul 2025 06:39:36 +0000 Subject: [PATCH 4/9] =?UTF-8?q?chore:=20Java=20=EC=8A=A4=ED=83=80=EC=9D=BC?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io/f1/backend/domain/game/event/RoomCreatedEvent.java | 4 +--- .../io/f1/backend/domain/game/event/RoomDeletedEvent.java | 4 +--- .../io/f1/backend/domain/game/event/RoomUpdatedEvent.java | 3 +-- .../domain/game/sse/listener/RoomCreatedEventListener.java | 7 ++++--- .../domain/game/sse/listener/RoomDeletedEventListener.java | 6 ++++-- .../domain/game/sse/listener/RoomUpdatedEventListener.java | 2 ++ 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/backend/src/main/java/io/f1/backend/domain/game/event/RoomCreatedEvent.java b/backend/src/main/java/io/f1/backend/domain/game/event/RoomCreatedEvent.java index ff645eef..545ae3e1 100644 --- a/backend/src/main/java/io/f1/backend/domain/game/event/RoomCreatedEvent.java +++ b/backend/src/main/java/io/f1/backend/domain/game/event/RoomCreatedEvent.java @@ -3,6 +3,4 @@ import io.f1.backend.domain.game.model.Room; import io.f1.backend.domain.quiz.entity.Quiz; -public record RoomCreatedEvent(Room room, Quiz quiz) { -} - +public record RoomCreatedEvent(Room room, Quiz quiz) {} diff --git a/backend/src/main/java/io/f1/backend/domain/game/event/RoomDeletedEvent.java b/backend/src/main/java/io/f1/backend/domain/game/event/RoomDeletedEvent.java index 2e319a75..caa9f408 100644 --- a/backend/src/main/java/io/f1/backend/domain/game/event/RoomDeletedEvent.java +++ b/backend/src/main/java/io/f1/backend/domain/game/event/RoomDeletedEvent.java @@ -1,5 +1,3 @@ package io.f1.backend.domain.game.event; -public record RoomDeletedEvent(Long roomId) { -} - +public record RoomDeletedEvent(Long roomId) {} diff --git a/backend/src/main/java/io/f1/backend/domain/game/event/RoomUpdatedEvent.java b/backend/src/main/java/io/f1/backend/domain/game/event/RoomUpdatedEvent.java index a6a2beb9..204a21d8 100644 --- a/backend/src/main/java/io/f1/backend/domain/game/event/RoomUpdatedEvent.java +++ b/backend/src/main/java/io/f1/backend/domain/game/event/RoomUpdatedEvent.java @@ -3,5 +3,4 @@ import io.f1.backend.domain.game.model.Room; import io.f1.backend.domain.quiz.entity.Quiz; -public record RoomUpdatedEvent(Room room, Quiz quiz) { -} +public record RoomUpdatedEvent(Room room, Quiz quiz) {} diff --git a/backend/src/main/java/io/f1/backend/domain/game/sse/listener/RoomCreatedEventListener.java b/backend/src/main/java/io/f1/backend/domain/game/sse/listener/RoomCreatedEventListener.java index 810a2c9b..6806401c 100644 --- a/backend/src/main/java/io/f1/backend/domain/game/sse/listener/RoomCreatedEventListener.java +++ b/backend/src/main/java/io/f1/backend/domain/game/sse/listener/RoomCreatedEventListener.java @@ -1,16 +1,18 @@ package io.f1.backend.domain.game.sse.listener; +import static io.f1.backend.domain.game.sse.mapper.SseMapper.*; + import io.f1.backend.domain.game.event.RoomCreatedEvent; import io.f1.backend.domain.game.sse.app.SseService; import io.f1.backend.domain.game.sse.dto.LobbySseEvent; import io.f1.backend.domain.game.sse.dto.RoomCreatedPayload; + import lombok.RequiredArgsConstructor; + import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; -import static io.f1.backend.domain.game.sse.mapper.SseMapper.*; - @Component @RequiredArgsConstructor public class RoomCreatedEventListener { @@ -23,5 +25,4 @@ public void roomCreate(RoomCreatedEvent event) { LobbySseEvent sseEvent = fromRoomCreated(event); sseService.notifyLobbyUpdate(sseEvent); } - } diff --git a/backend/src/main/java/io/f1/backend/domain/game/sse/listener/RoomDeletedEventListener.java b/backend/src/main/java/io/f1/backend/domain/game/sse/listener/RoomDeletedEventListener.java index 451217c9..eee8d11e 100644 --- a/backend/src/main/java/io/f1/backend/domain/game/sse/listener/RoomDeletedEventListener.java +++ b/backend/src/main/java/io/f1/backend/domain/game/sse/listener/RoomDeletedEventListener.java @@ -1,15 +1,17 @@ package io.f1.backend.domain.game.sse.listener; +import static io.f1.backend.domain.game.sse.mapper.SseMapper.*; + import io.f1.backend.domain.game.event.RoomDeletedEvent; import io.f1.backend.domain.game.sse.app.SseService; import io.f1.backend.domain.game.sse.dto.LobbySseEvent; import io.f1.backend.domain.game.sse.dto.RoomDeletedPayload; + import lombok.RequiredArgsConstructor; + import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.Async; -import static io.f1.backend.domain.game.sse.mapper.SseMapper.*; - @RequiredArgsConstructor public class RoomDeletedEventListener { diff --git a/backend/src/main/java/io/f1/backend/domain/game/sse/listener/RoomUpdatedEventListener.java b/backend/src/main/java/io/f1/backend/domain/game/sse/listener/RoomUpdatedEventListener.java index 8dd28f57..5f957de2 100644 --- a/backend/src/main/java/io/f1/backend/domain/game/sse/listener/RoomUpdatedEventListener.java +++ b/backend/src/main/java/io/f1/backend/domain/game/sse/listener/RoomUpdatedEventListener.java @@ -5,7 +5,9 @@ import io.f1.backend.domain.game.sse.dto.LobbySseEvent; import io.f1.backend.domain.game.sse.dto.RoomUpdatedPayload; import io.f1.backend.domain.game.sse.mapper.SseMapper; + import lombok.RequiredArgsConstructor; + import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.Async; From 6e1454f181b0f13735f28ee60da901b7f8499ae2 Mon Sep 17 00:00:00 2001 From: limkanghyun Date: Mon, 14 Jul 2025 15:40:31 +0900 Subject: [PATCH 5/9] =?UTF-8?q?:sparkles:=20feat:=20=EC=9D=B4=EB=B2=A4?= =?UTF-8?q?=ED=8A=B8=EC=97=90=20=EB=8C=80=ED=95=9C=20=EB=B8=8C=EB=A1=9C?= =?UTF-8?q?=EB=93=9C=20=EC=BA=90=EC=8A=A4=ED=8C=85=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80=20-=20=EC=9D=B4=EB=B2=A4?= =?UTF-8?q?=ED=8A=B8=20=ED=83=80=EC=9E=85=20=EB=B3=84=20SSE=20=EB=B3=B8?= =?UTF-8?q?=EB=AC=B8=20=EA=B0=9D=EC=B2=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/game/sse/app/SseService.java | 15 +++++ .../domain/game/sse/dto/LobbySseEvent.java | 4 ++ .../game/sse/dto/RoomCreatedPayload.java | 17 ++++++ .../game/sse/dto/RoomDeletedPayload.java | 5 ++ .../game/sse/dto/RoomUpdatedPayload.java | 13 +++++ .../domain/game/sse/dto/SseEventType.java | 7 +++ .../domain/game/sse/mapper/SseMapper.java | 56 +++++++++++++++++++ 7 files changed, 117 insertions(+) create mode 100644 backend/src/main/java/io/f1/backend/domain/game/sse/dto/LobbySseEvent.java create mode 100644 backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomCreatedPayload.java create mode 100644 backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomDeletedPayload.java create mode 100644 backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomUpdatedPayload.java create mode 100644 backend/src/main/java/io/f1/backend/domain/game/sse/dto/SseEventType.java create mode 100644 backend/src/main/java/io/f1/backend/domain/game/sse/mapper/SseMapper.java diff --git a/backend/src/main/java/io/f1/backend/domain/game/sse/app/SseService.java b/backend/src/main/java/io/f1/backend/domain/game/sse/app/SseService.java index adfd41dc..fc399dc6 100644 --- a/backend/src/main/java/io/f1/backend/domain/game/sse/app/SseService.java +++ b/backend/src/main/java/io/f1/backend/domain/game/sse/app/SseService.java @@ -1,5 +1,6 @@ package io.f1.backend.domain.game.sse.app; +import io.f1.backend.domain.game.sse.dto.LobbySseEvent; import io.f1.backend.domain.game.sse.store.SseEmitterRepository; import lombok.RequiredArgsConstructor; @@ -28,4 +29,18 @@ public SseEmitter subscribe() { } return emitter; } + + // 로비로 SSE 메시지를 쏘기위한 메서드 + public void notifyLobbyUpdate(LobbySseEvent event) { + for (SseEmitter emitter : emitterRepository.getAll()) { + try { + emitter.send(SseEmitter.event() + .name(event.type()) + .data(event) + ); + } catch (IOException e) { + emitterRepository.remove(emitter); + } + } + } } diff --git a/backend/src/main/java/io/f1/backend/domain/game/sse/dto/LobbySseEvent.java b/backend/src/main/java/io/f1/backend/domain/game/sse/dto/LobbySseEvent.java new file mode 100644 index 00000000..cefb9adf --- /dev/null +++ b/backend/src/main/java/io/f1/backend/domain/game/sse/dto/LobbySseEvent.java @@ -0,0 +1,4 @@ +package io.f1.backend.domain.game.sse.dto; + +public record LobbySseEvent(String type, T payload) { +} diff --git a/backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomCreatedPayload.java b/backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomCreatedPayload.java new file mode 100644 index 00000000..ba2286f7 --- /dev/null +++ b/backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomCreatedPayload.java @@ -0,0 +1,17 @@ +package io.f1.backend.domain.game.sse.dto; + +public record RoomCreatedPayload( + Long roomId, + String roomName, + Integer maxUserCount, + int currentUserCount, + boolean locked, + String roomState, + String quizTitle, + String description, + String creator, + Integer numberOfQuestion, + String thumbnailUrl +) { + +} diff --git a/backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomDeletedPayload.java b/backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomDeletedPayload.java new file mode 100644 index 00000000..416af14a --- /dev/null +++ b/backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomDeletedPayload.java @@ -0,0 +1,5 @@ +package io.f1.backend.domain.game.sse.dto; + +public record RoomDeletedPayload(Long roomId) { + +} diff --git a/backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomUpdatedPayload.java b/backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomUpdatedPayload.java new file mode 100644 index 00000000..d0344710 --- /dev/null +++ b/backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomUpdatedPayload.java @@ -0,0 +1,13 @@ +package io.f1.backend.domain.game.sse.dto; + +public record RoomUpdatedPayload( + Long roomId, + int currentUserCount, + String roomState, + String quizTitle, + String description, + String creator, + int numberOfQuestion, + String thumbnailUrl +) { +} diff --git a/backend/src/main/java/io/f1/backend/domain/game/sse/dto/SseEventType.java b/backend/src/main/java/io/f1/backend/domain/game/sse/dto/SseEventType.java new file mode 100644 index 00000000..ce913a58 --- /dev/null +++ b/backend/src/main/java/io/f1/backend/domain/game/sse/dto/SseEventType.java @@ -0,0 +1,7 @@ +package io.f1.backend.domain.game.sse.dto; + +public enum SseEventType { + CREATE, + UPDATE, + DELETE +} diff --git a/backend/src/main/java/io/f1/backend/domain/game/sse/mapper/SseMapper.java b/backend/src/main/java/io/f1/backend/domain/game/sse/mapper/SseMapper.java new file mode 100644 index 00000000..fcbe1fe7 --- /dev/null +++ b/backend/src/main/java/io/f1/backend/domain/game/sse/mapper/SseMapper.java @@ -0,0 +1,56 @@ +package io.f1.backend.domain.game.sse.mapper; + +import io.f1.backend.domain.game.event.RoomCreatedEvent; +import io.f1.backend.domain.game.event.RoomDeletedEvent; +import io.f1.backend.domain.game.event.RoomUpdatedEvent; +import io.f1.backend.domain.game.model.Room; +import io.f1.backend.domain.game.sse.dto.RoomCreatedPayload; +import io.f1.backend.domain.game.sse.dto.RoomDeletedPayload; +import io.f1.backend.domain.game.sse.dto.LobbySseEvent; +import io.f1.backend.domain.game.sse.dto.RoomUpdatedPayload; +import io.f1.backend.domain.game.sse.dto.SseEventType; +import io.f1.backend.domain.quiz.entity.Quiz; + +public class SseMapper { + + public static LobbySseEvent fromRoomCreated(RoomCreatedEvent event) { + Room room = event.room(); + Quiz quiz = event.quiz(); + RoomCreatedPayload payload = new RoomCreatedPayload( + room.getId(), + room.getRoomSetting().roomName(), + room.getRoomSetting().maxUserCount(), + room.getPlayerSessionMap().size(), + room.getRoomSetting().locked(), + room.getState().name(), + quiz.getTitle(), + quiz.getDescription(), + quiz.getCreator().getNickname(), + quiz.getQuestions().size(), + quiz.getThumbnailUrl() + ); + return new LobbySseEvent<>(SseEventType.CREATE.name(), payload); + } + + public static LobbySseEvent fromRoomUpdated(RoomUpdatedEvent event) { + Room room = event.room(); + Quiz quiz = event.quiz(); + RoomUpdatedPayload payload = new RoomUpdatedPayload( + room.getId(), + room.getPlayerSessionMap().size(), + room.getState().name(), + quiz.getTitle(), + quiz.getDescription(), + quiz.getCreator().getNickname(), + quiz.getQuestions().size(), + quiz.getThumbnailUrl() + ); + return new LobbySseEvent<>(SseEventType.UPDATE.name(), payload); + } + + public static LobbySseEvent fromRoomDeleted(RoomDeletedEvent event) { + Long roomId = event.roomId(); + RoomDeletedPayload payload = new RoomDeletedPayload(roomId); + return new LobbySseEvent<>(SseEventType.DELETE.name(), payload); + } +} From f87d0f1b4ca5adbb8c147de8cef0dc7871b8b1ee Mon Sep 17 00:00:00 2001 From: github-actions <> Date: Mon, 14 Jul 2025 06:40:53 +0000 Subject: [PATCH 6/9] =?UTF-8?q?chore:=20Java=20=EC=8A=A4=ED=83=80=EC=9D=BC?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/game/sse/app/SseService.java | 5 +- .../domain/game/sse/dto/LobbySseEvent.java | 3 +- .../game/sse/dto/RoomCreatedPayload.java | 25 +++++----- .../game/sse/dto/RoomDeletedPayload.java | 4 +- .../game/sse/dto/RoomUpdatedPayload.java | 18 ++++--- .../domain/game/sse/mapper/SseMapper.java | 48 +++++++++---------- 6 files changed, 46 insertions(+), 57 deletions(-) diff --git a/backend/src/main/java/io/f1/backend/domain/game/sse/app/SseService.java b/backend/src/main/java/io/f1/backend/domain/game/sse/app/SseService.java index fc399dc6..71a54c19 100644 --- a/backend/src/main/java/io/f1/backend/domain/game/sse/app/SseService.java +++ b/backend/src/main/java/io/f1/backend/domain/game/sse/app/SseService.java @@ -34,10 +34,7 @@ public SseEmitter subscribe() { public void notifyLobbyUpdate(LobbySseEvent event) { for (SseEmitter emitter : emitterRepository.getAll()) { try { - emitter.send(SseEmitter.event() - .name(event.type()) - .data(event) - ); + emitter.send(SseEmitter.event().name(event.type()).data(event)); } catch (IOException e) { emitterRepository.remove(emitter); } diff --git a/backend/src/main/java/io/f1/backend/domain/game/sse/dto/LobbySseEvent.java b/backend/src/main/java/io/f1/backend/domain/game/sse/dto/LobbySseEvent.java index cefb9adf..a0f73697 100644 --- a/backend/src/main/java/io/f1/backend/domain/game/sse/dto/LobbySseEvent.java +++ b/backend/src/main/java/io/f1/backend/domain/game/sse/dto/LobbySseEvent.java @@ -1,4 +1,3 @@ package io.f1.backend.domain.game.sse.dto; -public record LobbySseEvent(String type, T payload) { -} +public record LobbySseEvent(String type, T payload) {} diff --git a/backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomCreatedPayload.java b/backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomCreatedPayload.java index ba2286f7..0652fb77 100644 --- a/backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomCreatedPayload.java +++ b/backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomCreatedPayload.java @@ -1,17 +1,14 @@ package io.f1.backend.domain.game.sse.dto; public record RoomCreatedPayload( - Long roomId, - String roomName, - Integer maxUserCount, - int currentUserCount, - boolean locked, - String roomState, - String quizTitle, - String description, - String creator, - Integer numberOfQuestion, - String thumbnailUrl -) { - -} + Long roomId, + String roomName, + Integer maxUserCount, + int currentUserCount, + boolean locked, + String roomState, + String quizTitle, + String description, + String creator, + Integer numberOfQuestion, + String thumbnailUrl) {} diff --git a/backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomDeletedPayload.java b/backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomDeletedPayload.java index 416af14a..0ddf6b18 100644 --- a/backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomDeletedPayload.java +++ b/backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomDeletedPayload.java @@ -1,5 +1,3 @@ package io.f1.backend.domain.game.sse.dto; -public record RoomDeletedPayload(Long roomId) { - -} +public record RoomDeletedPayload(Long roomId) {} diff --git a/backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomUpdatedPayload.java b/backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomUpdatedPayload.java index d0344710..54df4128 100644 --- a/backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomUpdatedPayload.java +++ b/backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomUpdatedPayload.java @@ -1,13 +1,11 @@ package io.f1.backend.domain.game.sse.dto; public record RoomUpdatedPayload( - Long roomId, - int currentUserCount, - String roomState, - String quizTitle, - String description, - String creator, - int numberOfQuestion, - String thumbnailUrl -) { -} + Long roomId, + int currentUserCount, + String roomState, + String quizTitle, + String description, + String creator, + int numberOfQuestion, + String thumbnailUrl) {} diff --git a/backend/src/main/java/io/f1/backend/domain/game/sse/mapper/SseMapper.java b/backend/src/main/java/io/f1/backend/domain/game/sse/mapper/SseMapper.java index fcbe1fe7..efdd94c8 100644 --- a/backend/src/main/java/io/f1/backend/domain/game/sse/mapper/SseMapper.java +++ b/backend/src/main/java/io/f1/backend/domain/game/sse/mapper/SseMapper.java @@ -4,9 +4,9 @@ import io.f1.backend.domain.game.event.RoomDeletedEvent; import io.f1.backend.domain.game.event.RoomUpdatedEvent; import io.f1.backend.domain.game.model.Room; +import io.f1.backend.domain.game.sse.dto.LobbySseEvent; import io.f1.backend.domain.game.sse.dto.RoomCreatedPayload; import io.f1.backend.domain.game.sse.dto.RoomDeletedPayload; -import io.f1.backend.domain.game.sse.dto.LobbySseEvent; import io.f1.backend.domain.game.sse.dto.RoomUpdatedPayload; import io.f1.backend.domain.game.sse.dto.SseEventType; import io.f1.backend.domain.quiz.entity.Quiz; @@ -16,35 +16,35 @@ public class SseMapper { public static LobbySseEvent fromRoomCreated(RoomCreatedEvent event) { Room room = event.room(); Quiz quiz = event.quiz(); - RoomCreatedPayload payload = new RoomCreatedPayload( - room.getId(), - room.getRoomSetting().roomName(), - room.getRoomSetting().maxUserCount(), - room.getPlayerSessionMap().size(), - room.getRoomSetting().locked(), - room.getState().name(), - quiz.getTitle(), - quiz.getDescription(), - quiz.getCreator().getNickname(), - quiz.getQuestions().size(), - quiz.getThumbnailUrl() - ); + RoomCreatedPayload payload = + new RoomCreatedPayload( + room.getId(), + room.getRoomSetting().roomName(), + room.getRoomSetting().maxUserCount(), + room.getPlayerSessionMap().size(), + room.getRoomSetting().locked(), + room.getState().name(), + quiz.getTitle(), + quiz.getDescription(), + quiz.getCreator().getNickname(), + quiz.getQuestions().size(), + quiz.getThumbnailUrl()); return new LobbySseEvent<>(SseEventType.CREATE.name(), payload); } public static LobbySseEvent fromRoomUpdated(RoomUpdatedEvent event) { Room room = event.room(); Quiz quiz = event.quiz(); - RoomUpdatedPayload payload = new RoomUpdatedPayload( - room.getId(), - room.getPlayerSessionMap().size(), - room.getState().name(), - quiz.getTitle(), - quiz.getDescription(), - quiz.getCreator().getNickname(), - quiz.getQuestions().size(), - quiz.getThumbnailUrl() - ); + RoomUpdatedPayload payload = + new RoomUpdatedPayload( + room.getId(), + room.getPlayerSessionMap().size(), + room.getState().name(), + quiz.getTitle(), + quiz.getDescription(), + quiz.getCreator().getNickname(), + quiz.getQuestions().size(), + quiz.getThumbnailUrl()); return new LobbySseEvent<>(SseEventType.UPDATE.name(), payload); } From 2d9678dbf9037d1aea99dbcfb7aa69d5e2349661 Mon Sep 17 00:00:00 2001 From: limkanghyun Date: Mon, 14 Jul 2025 17:27:00 +0900 Subject: [PATCH 7/9] =?UTF-8?q?:recycle:=20emitter.onCompletion=20?= =?UTF-8?q?=EB=B6=80=EB=B6=84=20=EC=A4=91=EA=B4=84=ED=98=B8=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/game/sse/store/SseEmitterRepository.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/backend/src/main/java/io/f1/backend/domain/game/sse/store/SseEmitterRepository.java b/backend/src/main/java/io/f1/backend/domain/game/sse/store/SseEmitterRepository.java index 4cf61242..c5236dec 100644 --- a/backend/src/main/java/io/f1/backend/domain/game/sse/store/SseEmitterRepository.java +++ b/backend/src/main/java/io/f1/backend/domain/game/sse/store/SseEmitterRepository.java @@ -14,10 +14,7 @@ public class SseEmitterRepository { public void save(SseEmitter emitter) { emitters.add(emitter); // 연결종료 객체정리 - emitter.onCompletion( - () -> { - emitters.remove(emitter); - }); + emitter.onCompletion(() -> emitters.remove(emitter)); emitter.onTimeout(() -> emitters.remove(emitter)); emitter.onError(error -> emitters.remove(emitter)); } From 32a802da6ce18150226aa54e3aeafaa980dcd912 Mon Sep 17 00:00:00 2001 From: limkanghyun Date: Mon, 14 Jul 2025 17:27:43 +0900 Subject: [PATCH 8/9] =?UTF-8?q?:recycle:=20RoomCreatedPayload=20Integer=20?= =?UTF-8?q?->=20int=EB=A1=9C=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../game/sse/dto/RoomCreatedPayload.java | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomCreatedPayload.java b/backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomCreatedPayload.java index 0652fb77..fbbd9254 100644 --- a/backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomCreatedPayload.java +++ b/backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomCreatedPayload.java @@ -1,14 +1,17 @@ package io.f1.backend.domain.game.sse.dto; public record RoomCreatedPayload( - Long roomId, - String roomName, - Integer maxUserCount, - int currentUserCount, - boolean locked, - String roomState, - String quizTitle, - String description, - String creator, - Integer numberOfQuestion, - String thumbnailUrl) {} + Long roomId, + String roomName, + int maxUserCount, + int currentUserCount, + boolean locked, + String roomState, + String quizTitle, + String description, + String creator, + int numberOfQuestion, + String thumbnailUrl +) { + +} From 8683a675dff2d6fcc93074286c51c3ca4f6624bf Mon Sep 17 00:00:00 2001 From: github-actions <> Date: Mon, 14 Jul 2025 08:27:56 +0000 Subject: [PATCH 9/9] =?UTF-8?q?chore:=20Java=20=EC=8A=A4=ED=83=80=EC=9D=BC?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../game/sse/dto/RoomCreatedPayload.java | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomCreatedPayload.java b/backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomCreatedPayload.java index fbbd9254..08c7e4fd 100644 --- a/backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomCreatedPayload.java +++ b/backend/src/main/java/io/f1/backend/domain/game/sse/dto/RoomCreatedPayload.java @@ -1,17 +1,14 @@ package io.f1.backend.domain.game.sse.dto; public record RoomCreatedPayload( - Long roomId, - String roomName, - int maxUserCount, - int currentUserCount, - boolean locked, - String roomState, - String quizTitle, - String description, - String creator, - int numberOfQuestion, - String thumbnailUrl -) { - -} + Long roomId, + String roomName, + int maxUserCount, + int currentUserCount, + boolean locked, + String roomState, + String quizTitle, + String description, + String creator, + int numberOfQuestion, + String thumbnailUrl) {}