-
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 #2 from yudonggeun/chatting
Chatting
- Loading branch information
Showing
78 changed files
with
3,510 additions
and
101 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 |
---|---|---|
@@ -1,53 +1,53 @@ | ||
plugins { | ||
id 'java' | ||
id 'org.springframework.boot' version '3.1.3' | ||
id 'io.spring.dependency-management' version '1.1.3' | ||
id 'org.asciidoctor.jvm.convert' version '3.3.2' | ||
id 'java' | ||
id 'org.springframework.boot' version '3.1.3' | ||
id 'io.spring.dependency-management' version '1.1.3' | ||
id 'org.asciidoctor.jvm.convert' version '3.3.2' | ||
} | ||
|
||
group = 'com.websocket' | ||
version = '0.0.1-SNAPSHOT' | ||
|
||
java { | ||
sourceCompatibility = '17' | ||
sourceCompatibility = '17' | ||
} | ||
|
||
configurations { | ||
compileOnly { | ||
extendsFrom annotationProcessor | ||
} | ||
compileOnly { | ||
extendsFrom annotationProcessor | ||
} | ||
} | ||
|
||
repositories { | ||
mavenCentral() | ||
mavenCentral() | ||
} | ||
|
||
ext { | ||
set('snippetsDir', file("build/generated-snippets")) | ||
set('snippetsDir', file("build/generated-snippets")) | ||
} | ||
|
||
dependencies { | ||
implementation 'org.springframework.boot:spring-boot-starter-actuator' | ||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' | ||
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' | ||
implementation 'org.springframework.boot:spring-boot-starter-validation' | ||
implementation 'org.springframework.boot:spring-boot-starter-web' | ||
implementation 'org.springframework.boot:spring-boot-starter-websocket' | ||
compileOnly 'org.projectlombok:lombok' | ||
developmentOnly 'org.springframework.boot:spring-boot-devtools' | ||
implementation 'org.springframework.boot:spring-boot-starter-actuator' | ||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' | ||
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' | ||
implementation 'org.springframework.boot:spring-boot-starter-validation' | ||
implementation 'org.springframework.boot:spring-boot-starter-web' | ||
implementation 'org.springframework.boot:spring-boot-starter-websocket' | ||
compileOnly 'org.projectlombok:lombok' | ||
developmentOnly 'org.springframework.boot:spring-boot-devtools' | ||
// developmentOnly 'org.springframework.boot:spring-boot-docker-compose' | ||
runtimeOnly 'com.h2database:h2' | ||
annotationProcessor 'org.projectlombok:lombok' | ||
testImplementation 'org.springframework.boot:spring-boot-starter-test' | ||
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' | ||
runtimeOnly 'com.h2database:h2' | ||
annotationProcessor 'org.projectlombok:lombok' | ||
testImplementation 'org.springframework.boot:spring-boot-starter-test' | ||
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' | ||
} | ||
|
||
tasks.named('test') { | ||
outputs.dir snippetsDir | ||
useJUnitPlatform() | ||
outputs.dir snippetsDir | ||
useJUnitPlatform() | ||
} | ||
|
||
tasks.named('asciidoctor') { | ||
inputs.dir snippetsDir | ||
dependsOn test | ||
} | ||
inputs.dir snippetsDir | ||
dependsOn test | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file.
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,70 @@ | ||
# 실시간 채팅 웹 사이트 | ||
|
||
Version1 : From 23-09-13 To 23-09-20 | ||
|
||
## 1. 기획 의도 | ||
|
||
- STOMP 프로토콜을 이용한 실시간 채팅 서비스 기능을 개발하여 STOMP 기술을 익힌다. | ||
- 채팅 기능 구현을 통해서 동기화를 고려한 개발을 진행해본다. | ||
- 메시지 브로커 (RabbitMQ, Kafka) 서비스를 이용해서 아키텍처를 구성한다. | ||
|
||
## 2. 개발 기능 | ||
|
||
- 회원 기능 | ||
- 간단 회원가입 | ||
- 로그인 | ||
- 친구 추가 | ||
- 친구 삭제 | ||
- 친구 목록 조회 | ||
- 채팅 기능 | ||
- 채팅 입력 | ||
- 채팅 삭제 | ||
- 채팅 목록 조회 | ||
- 채팅방 기능 | ||
- 채팅방 생성 | ||
- 채팅방 조회 | ||
- 채팅방 나가기 | ||
- 친구 초대하기 | ||
- 채팅방 배경색 설정 | ||
- 채팅 안 읽음 확인 | ||
|
||
## 3. 아키텍처 | ||
|
||
### version 1 | ||
|
||
browser → server → db | ||
|
||
### version 2 | ||
|
||
browser → messageQueue → server → db | ||
|
||
## 4. ERD 설계 | ||
![erd image](/file/erd.png) | ||
[erd cloud link](https://www.erdcloud.com/d/44AHnBQQtTh4HtfwD) | ||
|
||
## 5. 사용 기술 | ||
|
||
version 1 | ||
|
||
- `spring boot` `spring websocket` `STOMP` `JPA` | ||
|
||
version 2 | ||
|
||
- `rabbitMQ` | ||
|
||
|
||
## 6. 개발 UI | ||
|
||
| 이름 | 상세 | 화면 | | ||
|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------| | ||
| 로그인 페이지 | 닉네임과 비밀번호를 통한 로그인 페이지로서 모든 입력 값을 입력해야 로그인 버튼이 동작한다. | ![로그인](/file/login.png) | | ||
| 회원가입 페이지 | 닉네임과 비밀번호를 통한 회원가입 페이지로서 모든 입력 값을 입력해야 회원가입 버튼이 동작한다. | ![회원가입](/file/welcome.png) | | ||
| 친구추가 페이지 | 친구의 닉네임으로 친구를 추가할 수 있다. | ![친구추가](/file/addFriend.png) | | ||
| 서비스 간단 설명 페이지 | 1. 채팅방 만들기 : `채팅방 만들기` 버튼을 클릭하면 채팅방 추가를 위한 인터페이스 제공한다. 말풍선 아이콘을 클릭하면 채팅방을 생성한다.<br/><br/> 2. 채팅방 변경 : 채팅방 목록에서 채팅방을 클릭하면 해당 채팅방으로 이동한다. <br/><br/> 3. 채팅 삭제 : 스스로 생성한 하얀색 채팅은 클릭시 삭제된다.<br/><br/> 4. 친구 초대: 친구의 닉네임 입력후 초대 아이콘을 클릭하면 친구 해당 채팅방에 초대한다. | ![간단설명](/file/chat_info.png) | | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
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 @@ | ||
test |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package com.websocket.demo; | ||
|
||
import com.websocket.demo.interceptor.ChatHandshakeInterceptor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.context.annotation.Configuration; | ||
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; | ||
|
||
@Slf4j | ||
@Configuration | ||
@EnableWebSocketMessageBroker | ||
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { | ||
|
||
@Autowired | ||
ChatHandshakeInterceptor chatHandshakeInterceptor; | ||
@Override | ||
public void configureMessageBroker(MessageBrokerRegistry config) { | ||
config.enableSimpleBroker("/topic"); | ||
config.setApplicationDestinationPrefixes("/app"); | ||
} | ||
|
||
@Override | ||
public void registerStompEndpoints(StompEndpointRegistry registry){ | ||
registry.addEndpoint("/chatting") | ||
.addInterceptors(chatHandshakeInterceptor); | ||
|
||
} | ||
} |
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 @@ | ||
package com.websocket.demo.api; | ||
|
||
import com.websocket.demo.request.*; | ||
import com.websocket.demo.response.ApiResponse; | ||
import com.websocket.demo.service.ChatService; | ||
import com.websocket.demo.service.UserService; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.web.bind.annotation.*; | ||
|
||
import static com.websocket.demo.response.ApiResponse.success; | ||
|
||
@RestController | ||
@RequestMapping | ||
@RequiredArgsConstructor | ||
public class ApiController { | ||
|
||
private final ChatService chatService; | ||
private final UserService userService; | ||
|
||
@GetMapping("/chat") | ||
public ApiResponse getChattingList(@ModelAttribute FindChatListRequest request) { | ||
return success(chatService.findChatList(request)); | ||
} | ||
|
||
@GetMapping("/room") | ||
public ApiResponse getRoomList(@SessionAttribute("user") LoginRequest userInfo) { | ||
return success(chatService.findRoomList(userInfo.getNickname())); | ||
} | ||
|
||
@PostMapping("/room") | ||
public ApiResponse createRoomList(@RequestBody CreateRoomRequest request) { | ||
return success(chatService.createRoom(request)); | ||
} | ||
|
||
@PutMapping("/room") | ||
public ApiResponse updateRoomConfig(@RequestBody UpdateRoomConfigRequest request, @SessionAttribute("user") LoginRequest userInfo) { | ||
return success(chatService.updateRoom(request, userInfo.getNickname())); | ||
} | ||
|
||
@DeleteMapping("/friend") | ||
public ApiResponse deleteFriend(@RequestBody DeleteFriendRequest request, @SessionAttribute("user") LoginRequest userInfo){ | ||
userService.removeFriendByNickname(userInfo.getNickname(), request.getFriendNickname()); | ||
return success(null); | ||
} | ||
} |
61 changes: 61 additions & 0 deletions
61
src/main/java/com/websocket/demo/controller/ChatWebsocketController.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,61 @@ | ||
package com.websocket.demo.controller; | ||
|
||
import com.websocket.demo.request.*; | ||
import com.websocket.demo.response.ChatStompResponse; | ||
import com.websocket.demo.service.ChatService; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.messaging.handler.annotation.MessageMapping; | ||
import org.springframework.messaging.simp.SimpMessageHeaderAccessor; | ||
import org.springframework.messaging.simp.SimpMessagingTemplate; | ||
import org.springframework.stereotype.Controller; | ||
|
||
@Controller | ||
@RequiredArgsConstructor | ||
public class ChatWebsocketController { | ||
|
||
private final ChatService chatService; | ||
private final SimpMessagingTemplate simpMessagingTemplate; | ||
|
||
@MessageMapping("/chat/new") | ||
public void newChat(CreateChatRequest request) { | ||
var message = ChatStompResponse.createChat(chatService.createChat(request)); | ||
sendTo(request.getRoomId(), message); | ||
} | ||
|
||
@MessageMapping("/chat/delete") | ||
public void deleteChat(DeleteChatRequest request, SimpMessageHeaderAccessor accessor) { | ||
var nickname = (String) accessor.getSessionAttributes().get("nickname"); | ||
var message = ChatStompResponse.deleteChat(chatService.deleteChat(request, nickname)); | ||
sendTo(request.getRoomId(), message); | ||
} | ||
|
||
@MessageMapping("/room/out") | ||
public void roomOut(RoomOutRequest request, SimpMessageHeaderAccessor accessor) { | ||
var nickname = (String) accessor.getSessionAttributes().get("nickname"); | ||
var message = ChatStompResponse.getOutRoom(chatService.getOutRoom(request, nickname)); | ||
sendTo(request.getId(), message); | ||
} | ||
|
||
@MessageMapping("/room/in") | ||
public void roomIn(InViteUserRequest request, SimpMessageHeaderAccessor accessor) { | ||
var host = (String) accessor.getSessionAttributes().get("nickname"); | ||
var message = ChatStompResponse.friendComeInRoom(chatService.inviteUser(request, host)); | ||
sendTo(request.getRoomId(), message); | ||
sendTo(request.getNickname(), message); | ||
} | ||
|
||
@MessageMapping("/room/check") | ||
public void readChat(CheckRoomRequest request, SimpMessageHeaderAccessor accessor){ | ||
var host = (String) accessor.getSessionAttributes().get("nickname"); | ||
var message = ChatStompResponse.readChat(chatService.checkRoom(request, host)); | ||
sendTo(request.getRoomId(), message); | ||
} | ||
|
||
private void sendTo(Long roomId, Object message){ | ||
simpMessagingTemplate.convertAndSend("/topic/chat-" + roomId, message); | ||
} | ||
|
||
private void sendTo(String nickname, Object message){ | ||
simpMessagingTemplate.convertAndSend("/topic/chat-" + nickname, message); | ||
} | ||
} |
55 changes: 55 additions & 0 deletions
55
src/main/java/com/websocket/demo/controller/PageController.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,55 @@ | ||
package com.websocket.demo.controller; | ||
|
||
import com.websocket.demo.request.FindChatListRequest; | ||
import com.websocket.demo.request.LoginRequest; | ||
import com.websocket.demo.response.ChatInfo; | ||
import com.websocket.demo.response.FriendInfo; | ||
import com.websocket.demo.response.RoomInfo; | ||
import com.websocket.demo.service.ChatService; | ||
import com.websocket.demo.service.UserService; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.stereotype.Controller; | ||
import org.springframework.ui.Model; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RequestParam; | ||
import org.springframework.web.bind.annotation.SessionAttribute; | ||
|
||
import java.util.List; | ||
|
||
@Controller | ||
@RequestMapping | ||
@RequiredArgsConstructor | ||
@Slf4j | ||
public class PageController { | ||
|
||
private final ChatService chatService; | ||
private final UserService userService; | ||
@RequestMapping("/") | ||
public String mainPage(@SessionAttribute(name = "user", required = false) LoginRequest loginInfo, Model model, | ||
@RequestParam(required = false) Long roomId) { | ||
if(loginInfo == null) return "login"; | ||
String nickname = loginInfo.getNickname(); | ||
List<RoomInfo> roomList = chatService.findRoomList(nickname); | ||
List<FriendInfo> friends = userService.friendList(nickname); | ||
|
||
FindChatListRequest request = new FindChatListRequest(); | ||
request.setRoomId(roomId); | ||
|
||
List<ChatInfo> chatList = chatService.findChatList(request); | ||
RoomInfo roomInfo = null; | ||
for (RoomInfo info : roomList) { | ||
if(info.getId().equals(roomId)) { | ||
roomInfo = info; | ||
} | ||
} | ||
|
||
model.addAttribute("nickname", nickname); | ||
model.addAttribute("roomList", roomList); | ||
model.addAttribute("friends", friends); | ||
model.addAttribute("chatList", chatList); | ||
model.addAttribute("targetRoom", roomInfo); | ||
|
||
return "index"; | ||
} | ||
} |
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
Oops, something went wrong.