Skip to content

Commit a31a150

Browse files
committed
refactor: 실시간에 대한 로직 확립 후 RoomMember 엔티티 수정
1 parent 4ff2a9f commit a31a150

File tree

2 files changed

+380
-93
lines changed

2 files changed

+380
-93
lines changed

src/main/java/com/back/domain/studyroom/entity/RoomMember.java

Lines changed: 37 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -8,187 +8,131 @@
88

99
import java.time.LocalDateTime;
1010

11-
/*
12-
RoomMember 엔티티 - 방과 사용자 간의 멤버십 관계를 나타냄
13-
연관관계 :
14-
- Room (1) : RoomMember (N) - 한 방에 여러 멤버가 있을 수 있음
15-
- User (1) : RoomMember (N) - 한 사용자가 여러 방의 멤버가 될 수 있음
16-
@JoinColumn vs @JoinTable 선택 이유:
17-
- @JoinColumn: 외래키를 이용한 직접 관계 (현재 변경)
18-
- @JoinTable: 별도의 연결 테이블을 만드는 관계
19-
RoomMember 테이블에서 그냥 room_id와 user_id 외래키로 직접 연결.
11+
/**
12+
* RoomMember 엔티티 - 방과 사용자 간의 영구적인 멤버십 관계를 나타냄
13+
* room (1) : RoomMember (N) - 한 방에 여러 멤버
14+
* user (1) : RoomMember (N) - 한 사용자가 여러 방의 멤버
2015
*/
2116
@Entity
2217
@NoArgsConstructor
2318
@Getter
2419
@Table(uniqueConstraints = @UniqueConstraint(columnNames = {"room_id", "user_id"}))
2520
public class RoomMember extends BaseEntity {
2621

27-
// 방 정보 - 어떤 방의 멤버인지
22+
// ==================== 영구 데이터 (DB에서 관리) ====================
2823
@ManyToOne(fetch = FetchType.LAZY)
29-
@JoinColumn(name = "room_id") // room_member 테이블의 room_id 컬럼이 room 테이블의 id를 참조
24+
@JoinColumn(name = "room_id", nullable = false)
3025
private Room room;
3126

32-
// 사용자 정보 - 누가 이 방의 멤버인지
3327
@ManyToOne(fetch = FetchType.LAZY)
34-
@JoinColumn(name = "user_id") // room_member 테이블의 user_id 컬럼이 users 테이블의 id를 참조
28+
@JoinColumn(name = "user_id", nullable = false)
3529
private User user;
3630

37-
// 방 내에서의 역할 (방장, 부방장, 멤버, 방문객)
3831
@Enumerated(EnumType.STRING)
3932
@Column(nullable = false)
4033
private RoomRole role = RoomRole.VISITOR;
4134

42-
// 멤버십 기본 정보
4335
@Column(nullable = false)
44-
private LocalDateTime joinedAt; // 방에 처음 입장한 시간
45-
private LocalDateTime lastActiveAt; // 마지막으로 활동한 시간
36+
private LocalDateTime joinedAt; // 방에 처음 가입한 시간 (불변)
4637

47-
// 실시간 상태 관리 필드들
48-
@Column(nullable = false)
49-
private boolean isOnline = false; // 현재 방에 온라인 상태인지
50-
51-
private String connectionId; // WebSocket 연결 ID (실시간 통신용)
52-
53-
private LocalDateTime lastHeartbeat; // 마지막 heartbeat 시간 (연결 상태 확인용)
38+
private LocalDateTime lastActiveAt; // 마지막 활동 시간 (참고용, 정확성 낮음)
5439

55-
// 💡 권한 확인 메서드들 (RoomRole enum의 메서드를 위임)
40+
// ==================== 권한 확인 메서드 ====================
5641

5742
/**
58-
* 방 관리 권한이 있는지 확인 (방장, 부방장)
59-
방 설정 변경, 공지사항 작성 등의 권한이 필요할 때
43+
* 방 관리 권한 확인 (방장, 부방장)
44+
* 사용: 방 설정 변경, 공지사항 작성
6045
*/
6146
public boolean canManageRoom() {
6247
return role.canManageRoom();
6348
}
6449

6550
/**
66-
* 멤버 추방 권한이 있는지 확인 (방장, 부방장)
67-
다른 멤버를 추방하려고 할
51+
* 멤버 추방 권한 확인 (방장, 부방장)
52+
* 사용: 다른 멤버를 추방할
6853
*/
6954
public boolean canKickMember() {
7055
return role.canKickMember();
7156
}
7257

7358
/**
74-
* 공지사항 관리 권한이 있는지 확인 (방장, 부방장)
75-
공지사항을 작성하거나 삭제할 때
59+
* 공지사항 관리 권한 확인 (방장, 부방장)
60+
* 사용: 공지사항 작성/삭제
7661
*/
7762
public boolean canManageNotices() {
7863
return role.canManageNotices();
7964
}
8065

8166
/**
82-
* 방장인지 확인
83-
방 소유자만 가능한 작업 (방 삭제, 호스트 권한 이양 등)
67+
* 방장 여부 확인
68+
* 사용: 방 삭제, 호스트 권한 이양 등
8469
*/
8570
public boolean isHost() {
8671
return role.isHost();
8772
}
8873

8974
/**
90-
* 정식 멤버인지 확인 (방문객이 아닌 멤버, 부방장, 방장)
91-
멤버만 접근 가능한 기능 (파일 업로드, 학습 기록 등)
75+
* 정식 멤버 여부 확인 (방문객이 아닌 멤버, 부방장, 방장)
76+
* 사용: 멤버만 접근 가능한 기능
9277
*/
9378
public boolean isMember() {
9479
return role.isMember();
9580
}
9681

97-
/**
98-
* 현재 활성 상태인지 확인
99-
온라인 멤버 목록 표시, 비활성 사용자 정리 등
100-
온라인 상태이고 최근 설정된 시간 이내에 heartbeat가 있었던 경우
101-
*/
102-
public boolean isActive(int timeoutMinutes) {
103-
return isOnline && lastHeartbeat != null &&
104-
lastHeartbeat.isAfter(LocalDateTime.now().minusMinutes(timeoutMinutes));
105-
}
106-
82+
// ==================== 정적 팩토리 메서드 ====================
10783

10884
/**
109-
기본 멤버 생성 메서드, 처음 입장 시 사용
85+
* 기본 멤버 생성
11086
*/
111-
public static RoomMember create(Room room, User user, RoomRole role) {
87+
private static RoomMember create(Room room, User user, RoomRole role) {
11288
RoomMember member = new RoomMember();
11389
member.room = room;
11490
member.user = user;
11591
member.role = role;
11692
member.joinedAt = LocalDateTime.now();
11793
member.lastActiveAt = LocalDateTime.now();
118-
member.isOnline = true; // 생성 시 온라인 상태
119-
member.lastHeartbeat = LocalDateTime.now();
120-
12194
return member;
12295
}
12396

124-
// 방장 멤버 생성 -> 새로운 방을 생성할 때 방 생성자를 방장으로 등록
97+
/**
98+
* 방장 멤버 생성
99+
* 사용: 방 생성 시 생성자를 방장으로 등록
100+
*/
125101
public static RoomMember createHost(Room room, User user) {
126102
return create(room, user, RoomRole.HOST);
127103
}
128104

129105
/**
130-
* 일반 멤버 생성, 권한 자동 변경
131-
- 비공개 방에서 초대받은 사용자를 정식 멤버로 등록할 때 (로직 검토 중)
106+
* 일반 멤버 생성
107+
* 사용: 비공개 방에 초대된 사용자를 정식 멤버로 등록
132108
*/
133109
public static RoomMember createMember(Room room, User user) {
134110
return create(room, user, RoomRole.MEMBER);
135111
}
136112

137113
/**
138114
* 방문객 생성
139-
* 사용 상황: 공개 방에 처음 입장하는 사용자를 임시 방문객으로 등록
115+
* 사용: 공개 방에 처음 입장하는 사용자를 임시 방문객으로 등록
140116
*/
141117
public static RoomMember createVisitor(Room room, User user) {
142118
return create(room, user, RoomRole.VISITOR);
143119
}
144120

121+
// ==================== 상태 변경 메서드 ====================
122+
145123
/**
146-
* 멤버의 역할 변경
147-
방장이 멤버를 부방장으로 승격시키거나 강등시킬 때
124+
* 멤버 역할 변경
125+
* 사용: 방장이 멤버를 승격/강등시킬 때
148126
*/
149127
public void updateRole(RoomRole newRole) {
150128
this.role = newRole;
151129
}
152130

153131
/**
154-
* 온라인 상태 변경
155-
* 사용 상황: 멤버가 방에 입장하거나 퇴장할 때
156-
활동 시간도 함께 업데이트, 온라인이 되면 heartbeat도 갱신
132+
* 마지막 활동 시간 업데이트
133+
* 참고용이며, 정확한 활동 추적은 Redis의 WebSocketSessionManager를 사용하세요.
157134
*/
158-
public void updateOnlineStatus(boolean online) {
159-
this.isOnline = online;
135+
public void updateLastActivity() {
160136
this.lastActiveAt = LocalDateTime.now();
161-
if (online) {
162-
this.lastHeartbeat = LocalDateTime.now();
163-
}
164-
}
165-
166-
/**
167-
* WebSocket 연결 ID 업데이트
168-
* 사용 상황: 멤버가 웹소켓으로 방에 연결될 때
169-
+ heartbeat도 함께 갱신
170-
*/
171-
public void updateConnectionId(String connectionId) {
172-
this.connectionId = connectionId;
173-
this.lastHeartbeat = LocalDateTime.now();
174-
}
175-
176-
/**
177-
* 사용 : 클라이언트에서 주기적으로 서버에 연결 상태를 알릴 때
178-
* 목적: 연결이 끊어진 멤버를 자동으로 감지하기 위해 사용, 별도의 다른 것으로 변경 가능
179-
*/
180-
public void heartbeat() {
181-
this.lastHeartbeat = LocalDateTime.now();
182-
this.lastActiveAt = LocalDateTime.now();
183-
this.isOnline = true;
184-
}
185-
186-
/**
187-
* 방 퇴장 처리 (명시적 퇴장과 연결 끊김 상태 로직 분할 예정임.. 일단은 임시로 통합 상태)
188-
멤버가 방을 나가거나 연결이 끊어졌을 때, 오프라인 상태로 변경하고 연결 ID 제거
189-
*/
190-
public void leave() {
191-
this.isOnline = false;
192-
this.connectionId = null;
193137
}
194138
}

0 commit comments

Comments
 (0)