-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from wnsrl1228/develop
feat: 채팅 기능추가
- Loading branch information
Showing
49 changed files
with
639 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
<div align="center"> | ||
|
||
## [짤 제목 바로가기](https://memetitle.com) | ||
<br> | ||
<img src="https://github.com/wnsrl1228/meme-title/assets/67573836/cd3395a0-62a6-4bf7-826a-f52acef32b5c" width="15%"> | ||
|
||
<br> | ||
<img src="https://github.com/wnsrl1228/meme-title/assets/67573836/18e4c209-b3bb-4801-a699-89f743af616d" > | ||
|
||
|
||
<br> | ||
|
||
</div> | ||
|
||
<br> | ||
|
||
## 기술 스택 | ||
|
||
### 프론트엔드 | ||
|
||
<img width="50%" src="https://github.com/wnsrl1228/meme-title/assets/67573836/c4b0adb9-0034-4049-8d08-3141de84803d"> | ||
|
||
### 백엔드 | ||
|
||
<img width="63%" src="https://github.com/wnsrl1228/meme-title/assets/67573836/e489e0f4-59f2-4031-b418-0a58ba68aacc"> | ||
|
||
### 인프라 | ||
|
||
<img width="65%" src="https://github.com/wnsrl1228/meme-title/assets/67573836/ce70a05a-0948-44f3-8605-47324db62268"> | ||
|
||
<br> | ||
|
||
## 서비스 요청 흐름도 | ||
|
||
<img width="100%" src="https://github.com/wnsrl1228/meme-title/assets/67573836/51577ce9-6083-46f4-909e-2ab3384550e3"> | ||
|
||
## 배포 과정 | ||
|
||
<img width="100%" src="https://github.com/wnsrl1228/meme-title/assets/67573836/680b2bb6-65c2-422a-b5c6-d1ef6ed0380e"> | ||
|
||
## DB ERD | ||
<img width="100%" src="https://github.com/wnsrl1228/meme-title/assets/67573836/8b8d9be3-7617-4bf3-a345-86c9d1a9ac42"> | ||
|
||
## API 문서 | ||
<img width="100%" src="https://github.com/wnsrl1228/meme-title/assets/67573836/0067e481-6066-44c8-8dd8-f72209eac2bd"> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 1 addition & 3 deletions
4
src/main/java/com/memetitle/auth/AdminMemberArgumentResolver.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
39 changes: 39 additions & 0 deletions
39
src/main/java/com/memetitle/chat/config/CustomHandshakeInterceptor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package com.memetitle.chat.config; | ||
|
||
import com.memetitle.chat.domain.ChatRoom; | ||
import com.memetitle.chat.repository.ChatRoomRepository; | ||
import com.memetitle.global.exception.InvalidException; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.http.server.ServerHttpRequest; | ||
import org.springframework.http.server.ServerHttpResponse; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.web.socket.WebSocketHandler; | ||
import org.springframework.web.socket.server.HandshakeInterceptor; | ||
|
||
import java.util.Map; | ||
|
||
import static com.memetitle.global.exception.ErrorCode.NOT_FOUND_CHATROOM_ID; | ||
|
||
@Component | ||
@RequiredArgsConstructor | ||
public class CustomHandshakeInterceptor implements HandshakeInterceptor { | ||
|
||
private final ChatRoomRepository chatRoomRepository; | ||
|
||
@Override | ||
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception { | ||
String path = request.getURI().getPath(); | ||
String roomId = path.split("/")[2]; | ||
ChatRoom chatRoom = chatRoomRepository.findById(Long.parseLong(roomId)) | ||
.orElseThrow(() -> new InvalidException(NOT_FOUND_CHATROOM_ID)); | ||
|
||
if (chatRoom.getMemberCount() == chatRoom.getMaxCapacity()) { | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
@Override | ||
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {} | ||
} |
35 changes: 35 additions & 0 deletions
35
src/main/java/com/memetitle/chat/config/WebSocketConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package com.memetitle.chat.config; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.messaging.simp.config.ChannelRegistration; | ||
import org.springframework.messaging.simp.config.MessageBrokerRegistry; | ||
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; | ||
import org.springframework.web.socket.config.annotation.StompEndpointRegistry; | ||
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; | ||
|
||
@Configuration | ||
@EnableWebSocketMessageBroker | ||
@RequiredArgsConstructor | ||
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { | ||
|
||
private final WebSocketInterceptor webSocketInterceptor; | ||
private final CustomHandshakeInterceptor customHandshakeInterceptor; | ||
@Override | ||
public void registerStompEndpoints(StompEndpointRegistry registry) { | ||
registry.addEndpoint("/ws/{roomId}") // socket 연결 url | ||
.setAllowedOrigins("https://memetitle.com", "http://localhost:3000") | ||
.addInterceptors(customHandshakeInterceptor); | ||
} | ||
|
||
@Override | ||
public void configureMessageBroker(MessageBrokerRegistry config) { | ||
config.enableSimpleBroker("/sub"); // 구독 url(채팅방 참여=구독) | ||
config.setApplicationDestinationPrefixes("/pub"); // 메세지 발행 prefixes 설정 | ||
} | ||
|
||
@Override | ||
public void configureClientInboundChannel(ChannelRegistration registration) { | ||
registration.interceptors(webSocketInterceptor); | ||
} | ||
} |
54 changes: 54 additions & 0 deletions
54
src/main/java/com/memetitle/chat/config/WebSocketInterceptor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package com.memetitle.chat.config; | ||
|
||
import com.memetitle.chat.repository.ChatRoomStorage; | ||
import com.memetitle.chat.service.ChatService; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.messaging.Message; | ||
import org.springframework.messaging.MessageChannel; | ||
import org.springframework.messaging.simp.stomp.StompCommand; | ||
import org.springframework.messaging.simp.stomp.StompHeaderAccessor; | ||
import org.springframework.messaging.support.ChannelInterceptor; | ||
import org.springframework.stereotype.Component; | ||
|
||
/** | ||
* 채팅방 인원 관리용 인터셉터 | ||
*/ | ||
@Slf4j | ||
@Component | ||
@RequiredArgsConstructor | ||
public class WebSocketInterceptor implements ChannelInterceptor { | ||
|
||
private final ChatService chatService; | ||
private final ChatRoomStorage chatRoomStorage; | ||
|
||
@Override | ||
public Message<?> preSend(Message<?> message, MessageChannel channel) { | ||
StompHeaderAccessor stompHeaderAccessor = StompHeaderAccessor.wrap(message); | ||
|
||
if (stompHeaderAccessor != null) { | ||
StompCommand command = stompHeaderAccessor.getCommand(); | ||
|
||
switch (command) { | ||
case SUBSCRIBE -> { | ||
String simpDestination = (String) message.getHeaders().get("simpDestination"); | ||
String roomId = simpDestination.split("/")[3]; | ||
chatService.increaseMemberCount(Long.parseLong(roomId)); | ||
|
||
String sessionId = (String) message.getHeaders().get("simpSessionId"); | ||
chatRoomStorage.storage(sessionId, Long.parseLong(roomId)); | ||
|
||
log.info("websocket subscribe"); | ||
} | ||
case DISCONNECT -> { | ||
String sessionId = (String) message.getHeaders().get("simpSessionId"); | ||
Long roomId = chatRoomStorage.getRoomId(sessionId); | ||
chatService.decreaseMemberCount(roomId); | ||
chatRoomStorage.delete(sessionId); | ||
log.info("websocket disconnect"); | ||
} | ||
} | ||
} | ||
return message; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package com.memetitle.chat.domain; | ||
|
||
import jakarta.persistence.*; | ||
import lombok.AccessLevel; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import org.springframework.data.annotation.CreatedDate; | ||
import org.springframework.data.jpa.domain.support.AuditingEntityListener; | ||
|
||
import java.time.LocalDateTime; | ||
|
||
@Entity | ||
@Getter | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
@EntityListeners(AuditingEntityListener.class) | ||
public class ChatRoom { | ||
|
||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
|
||
@Column(nullable = false, length = 50) | ||
private String name; | ||
|
||
@Column(nullable = false) | ||
private int memberCount; | ||
|
||
@Column(name = "max_capacity", nullable = false) | ||
private int maxCapacity = 10; | ||
|
||
@CreatedDate | ||
@Column(updatable = false) | ||
private LocalDateTime createdAt; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package com.memetitle.chat.dto; | ||
|
||
import com.memetitle.chat.domain.ChatRoom; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
|
||
import java.time.LocalDateTime; | ||
|
||
@Getter | ||
@Builder | ||
public class ChatRoomElement { | ||
|
||
private Long id; | ||
private String name; | ||
private int memberCount; | ||
private int maxCapacity; | ||
private LocalDateTime createdAt; | ||
|
||
public static ChatRoomElement of(ChatRoom chatRoom) { | ||
return ChatRoomElement.builder() | ||
.id(chatRoom.getId()) | ||
.name(chatRoom.getName()) | ||
.memberCount(chatRoom.getMemberCount()) | ||
.maxCapacity(chatRoom.getMaxCapacity()) | ||
.createdAt(chatRoom.getCreatedAt()) | ||
.build(); | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
src/main/java/com/memetitle/chat/dto/request/ChatMessageRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package com.memetitle.chat.dto.request; | ||
|
||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Getter | ||
@NoArgsConstructor | ||
public class ChatMessageRequest { | ||
|
||
private String nickname; | ||
private String message; | ||
private String date; | ||
|
||
public ChatMessageRequest(String nickname, String message, String date) { | ||
this.nickname = nickname; | ||
this.message = message; | ||
this.date = date; | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
src/main/java/com/memetitle/chat/dto/response/ChatMessageResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package com.memetitle.chat.dto.response; | ||
|
||
import lombok.Builder; | ||
import lombok.Getter; | ||
|
||
@Getter | ||
@Builder | ||
public class ChatMessageResponse { | ||
|
||
private String nickname; | ||
private String message; | ||
private Long roomId; | ||
private String date; | ||
|
||
} | ||
|
Oops, something went wrong.