Skip to content

Commit cf25ffa

Browse files
authored
✨ feat: SSE 알림 기능 구현 (#29)
* ✨ feat: quizId로 조회한 Quiz로 응답에 포함하는 기능 추가 * chore: Java 스타일 수정 * ✨ feat: Room 생성, 수정, 삭제에 대한 이벤트 리스너 추가 - 이벤트 타입 정의 enum 추가 - 이벤트 전달 객체 추가(RoomCreatedEvent, RoomUpdatedEvent, RoomDeletedEvent) * chore: Java 스타일 수정 * ✨ feat: 이벤트에 대한 브로드 캐스팅 메서드 추가 - 이벤트 타입 별 SSE 본문 객체 추가 * chore: Java 스타일 수정 * ♻️ emitter.onCompletion 부분 중괄호 삭제 * ♻️ RoomCreatedPayload Integer -> int로 통일 * chore: Java 스타일 수정 --------- Co-authored-by: github-actions <>
1 parent 3699062 commit cf25ffa

16 files changed

+222
-16
lines changed

backend/src/main/java/io/f1/backend/domain/game/app/RoomService.java

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,19 @@
1212
import io.f1.backend.domain.game.dto.response.RoomListResponse;
1313
import io.f1.backend.domain.game.dto.response.RoomResponse;
1414
import io.f1.backend.domain.game.dto.response.RoomSettingResponse;
15+
import io.f1.backend.domain.game.event.RoomCreatedEvent;
1516
import io.f1.backend.domain.game.model.GameSetting;
1617
import io.f1.backend.domain.game.model.Player;
1718
import io.f1.backend.domain.game.model.Room;
1819
import io.f1.backend.domain.game.model.RoomSetting;
1920
import io.f1.backend.domain.game.model.RoomState;
2021
import io.f1.backend.domain.game.store.RoomRepository;
22+
import io.f1.backend.domain.quiz.app.QuizService;
2123
import io.f1.backend.domain.quiz.entity.Quiz;
22-
import io.f1.backend.domain.user.entity.User;
2324

2425
import lombok.RequiredArgsConstructor;
2526

27+
import org.springframework.context.ApplicationEventPublisher;
2628
import org.springframework.stereotype.Service;
2729

2830
import java.util.List;
@@ -33,8 +35,10 @@
3335
@RequiredArgsConstructor
3436
public class RoomService {
3537

38+
private final QuizService quizService;
3639
private final RoomRepository roomRepository;
3740
private final AtomicLong roomIdGenerator = new AtomicLong(0);
41+
private final ApplicationEventPublisher eventPublisher;
3842

3943
public RoomCreateResponse saveRoom(RoomCreateRequest request, Map<String, Object> loginUser) {
4044

@@ -46,7 +50,14 @@ public RoomCreateResponse saveRoom(RoomCreateRequest request, Map<String, Object
4650

4751
Long newId = roomIdGenerator.incrementAndGet();
4852

49-
roomRepository.saveRoom(new Room(newId, roomSetting, gameSetting, host));
53+
Room room = new Room(newId, roomSetting, gameSetting, host);
54+
55+
roomRepository.saveRoom(room);
56+
57+
Long quizId = room.getGameSetting().getQuizId();
58+
Quiz quiz = quizService.getQuizById(quizId);
59+
60+
eventPublisher.publishEvent(new RoomCreatedEvent(room, quiz));
5061

5162
return new RoomCreateResponse(newId);
5263
}
@@ -103,22 +114,14 @@ public RoomInitialData enterRoom(Long roomId, String sessionId) {
103114
destination, roomSettingResponse, gameSettingResponse, playerListResponse);
104115
}
105116

106-
// todo quizService에서 퀴즈 조회 메서드로 변경
107117
public RoomListResponse getAllRooms() {
108118
List<Room> rooms = roomRepository.findAll();
109119
List<RoomResponse> roomResponses =
110120
rooms.stream()
111121
.map(
112122
room -> {
113-
User user = new User(); // 임시 유저 객체
114-
user.setNickname("임시 유저 닉네임");
115-
116-
Quiz quiz = new Quiz(); // 임시 퀴즈 객체
117-
quiz.setTitle("임시 퀴즈 제목");
118-
quiz.setDescription("임시 퀴즈 설명");
119-
quiz.setThumbnailUrl("임시 이미지");
120-
quiz.setQuestions(List.of());
121-
quiz.setCreator(user);
123+
Long quizId = room.getGameSetting().getQuizId();
124+
Quiz quiz = quizService.getQuizById(quizId);
122125

123126
return toRoomResponse(room, quiz);
124127
})
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package io.f1.backend.domain.game.event;
2+
3+
import io.f1.backend.domain.game.model.Room;
4+
import io.f1.backend.domain.quiz.entity.Quiz;
5+
6+
public record RoomCreatedEvent(Room room, Quiz quiz) {}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package io.f1.backend.domain.game.event;
2+
3+
public record RoomDeletedEvent(Long roomId) {}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package io.f1.backend.domain.game.event;
2+
3+
import io.f1.backend.domain.game.model.Room;
4+
import io.f1.backend.domain.quiz.entity.Quiz;
5+
6+
public record RoomUpdatedEvent(Room room, Quiz quiz) {}

backend/src/main/java/io/f1/backend/domain/game/sse/app/SseService.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.f1.backend.domain.game.sse.app;
22

3+
import io.f1.backend.domain.game.sse.dto.LobbySseEvent;
34
import io.f1.backend.domain.game.sse.store.SseEmitterRepository;
45

56
import lombok.RequiredArgsConstructor;
@@ -28,4 +29,15 @@ public SseEmitter subscribe() {
2829
}
2930
return emitter;
3031
}
32+
33+
// 로비로 SSE 메시지를 쏘기위한 메서드
34+
public <T> void notifyLobbyUpdate(LobbySseEvent<T> event) {
35+
for (SseEmitter emitter : emitterRepository.getAll()) {
36+
try {
37+
emitter.send(SseEmitter.event().name(event.type()).data(event));
38+
} catch (IOException e) {
39+
emitterRepository.remove(emitter);
40+
}
41+
}
42+
}
3143
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package io.f1.backend.domain.game.sse.dto;
2+
3+
public record LobbySseEvent<T>(String type, T payload) {}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package io.f1.backend.domain.game.sse.dto;
2+
3+
public record RoomCreatedPayload(
4+
Long roomId,
5+
String roomName,
6+
int maxUserCount,
7+
int currentUserCount,
8+
boolean locked,
9+
String roomState,
10+
String quizTitle,
11+
String description,
12+
String creator,
13+
int numberOfQuestion,
14+
String thumbnailUrl) {}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package io.f1.backend.domain.game.sse.dto;
2+
3+
public record RoomDeletedPayload(Long roomId) {}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package io.f1.backend.domain.game.sse.dto;
2+
3+
public record RoomUpdatedPayload(
4+
Long roomId,
5+
int currentUserCount,
6+
String roomState,
7+
String quizTitle,
8+
String description,
9+
String creator,
10+
int numberOfQuestion,
11+
String thumbnailUrl) {}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package io.f1.backend.domain.game.sse.dto;
2+
3+
public enum SseEventType {
4+
CREATE,
5+
UPDATE,
6+
DELETE
7+
}

0 commit comments

Comments
 (0)