ํฐ์คํ ๋ฆฌ ๋ทฐ
728x90
<๋ชฉ์ฐจ>
Spring
๐ Web Socket Dependency ์ถ๊ฐ
ํด๋น ํจํค์ง์ stom๋ ๋ด์ฅ๋์ด์๋ค.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-websocket'
}
๐ Web Socket Config ์ค์
โ๏ธ ํ์ฉํ๋ origin์ vue adress๋ฅผ ์ถ๊ฐํด์ค๋ค.
package com.project.mnm.config;
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;
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/send");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/").setAllowedOrigins("http://localhost:8080").withSockJS();
}
}
๐ Chatting Model
package com.project.mnm.domain;
import lombok.*;
import javax.persistence.*;
import java.sql.Timestamp;
@Builder
@Getter
@Setter
@ToString
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "chattings")
public class Chatting {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@OneToOne
@JoinColumn(name = "uid")
private User user;
@Column(name = "message")
private String message;
@Column(name = "send_at")
private Timestamp sendAt;
@Column(name = "is_request")
private Boolean isRequest;
}
๐ Chatting Service
๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฑํ ๋ด์ฉ์ ์ ์ฅํ๋ค.
package com.project.mnm.service;
import com.project.mnm.domain.Chatting;
import com.project.mnm.domain.User;
import com.project.mnm.repository.ChattingRepository;
import com.project.mnm.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@RequiredArgsConstructor
@Service
public class ChattingService {
private final UserRepository userRepository;
private final ChattingRepository chattingRepository;
public Chatting chattingHandler(Chatting chatting) {
User user = userRepository.findById(chatting.getUser().getId())
.orElseThrow(() -> new IllegalArgumentException("๊ฐ์
๋์ง ์์ ์ฌ์ฉ์์
๋๋ค."));
chatting.setUser(user);
return chattingRepository.save(chatting);
}
}
๐ Chatting Controller
โ๏ธ /receive๋ก ์ฑํ ๋ด์ฉ์ ๋ฐ๋๋ค.
โ๏ธ /send๋ก ์ฑํ ๋ด์ฉ์ ๋ณด๋ธ๋ค.
package com.project.mnm.controller;
import com.project.mnm.domain.Chatting;
import com.project.mnm.service.ChattingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;
@Controller
public class ChattingController {
@Autowired
private ChattingService chattingService;
@MessageMapping("/receive")
@SendTo("/send")
public Chatting chattingHandler(Chatting chatting) {
return chattingService.chattingHandler(chatting);
}
}
Vue
๐ Web Socket, Stomp ์ค์น
โ๏ธ sockjs-client๋ ์น์์ผ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ธฐ ์ํด ์ค์นํ๋ค.
โ๏ธ webstomp-client๋ stomp์ ์ฌ์ฉํ๊ธฐ ์ํด ์ค์นํ๋ค.
(test_front) D:\mnm\project-mnm-test-front>npm i webstomp-client sockjs-client
๐ ChattingView.vue
<template>
<v-container>
<v-expansion-panel>
<v-expansion-panel-header><h1>์ฑํ
</h1></v-expansion-panel-header>
<v-expansion-panel-content>
<v-card class="mt-2">
<v-card-title><h2>์ฑํ
ํ
์คํธ</h2></v-card-title>
<v-card-text>
<v-alert
dense
type="info"
color="teal lighten-3"
>๋๊ฐ ์ด์์ ๋ธ๋ผ์ฐ์ ๋ฅผ ๋์ ๊ฐ๋จํ ์ฑํ
์ ํ์ธํด ๋ณผ ์ ์๋ค.</v-alert>
<v-container>
uid :
<input
v-model="uid"
type="text"
>
message :
<input
v-model="message"
type="text"
@keyup="sendMessage"
>
<div
class="mt-2"
v-for="(item, idx) in recvList"
:key="idx"
>
<v-card
class="mt-2 mb-2"
color="teal lighten-3"
dark
max-width="400"
>
<v-card-text>
<div>uid : {{ item.user.id }}</div>
<div>{{ item.message }}</div>
<div>{{ item.sendAt }}</div>
</v-card-text>
</v-card>
</div>
</v-container>
</v-card-text>
</v-card>
</v-expansion-panel-content>
</v-expansion-panel>
</v-container>
</template>
<script lang="js">
import Stomp from 'webstomp-client'
import SockJS from 'sockjs-client'
export default {
data() {
return {
uid: '',
message: '',
recvList: []
}
},
created() {
this.connect() // ChattingView.vue ์์ฑ ์ ์์ผ ์ฐ๊ฒฐ ์๋
},
methods: {
sendMessage(e) {
if(e.keyCode === 13 && this.uid !== '' && this.message !== '') {
this.send();
this.message = '';
}
},
send() {
console.log("Send message:" + this.message);
if (this.stompClient && this.stompClient.connected) {
const msg = {
user: {
id: this.uid
},
message: this.message,
sendAt: Date.now(),
isRequest: false,
};
this.stompClient.send("/receive", JSON.stringify(msg), {});
}
},
connect() {
const serverURL = "http://localhost:5050"
let socket = new SockJS(serverURL);
this.stompClient = Stomp.over(socket);
console.log(`์์ผ ์ฐ๊ฒฐ์ ์๋ํฉ๋๋ค. ์๋ฒ ์ฃผ์: ${serverURL}`)
this.stompClient.connect(
{},
frame => {
this.connected = true;
console.log('์์ผ ์ฐ๊ฒฐ ์ฑ๊ณต', frame);
this.stompClient.subscribe("/send", res => {
console.log('๊ตฌ๋
์ผ๋ก ๋ฐ์ ๋ฉ์์ง ์
๋๋ค.', res.body);
this.recvList.push(JSON.parse(res.body))
});
},
error => {
console.log('์์ผ ์ฐ๊ฒฐ ์คํจ', error);
this.connected = false;
}
);
}
}
}
</script>
๐ ์ฑํ ํ ์คํธ
์ฐฝ์ ์ฌ๋ฌ๊ฐ ๋์์ ์ฑํ ์ ํ ์คํธํด๋ณผ ์ ์๋ค.
๋ฐ์ดํฐ๋ฒ ์ด์ค์๋ ์ฑํ ๋ด์ฉ์ด ์ ์ ์ฅ๋๋ ๋ชจ์ต์ ํ์ธ ํ ์ ์๋ค.
Ref.
vue spring boot ์น์์ผ ์ฑํ ๋ง๋ค๊ธฐ (velog.io)
728x90
'ํ๋ก์ ํธ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[ํ๋ก์ ํธ/mnm] Spring Boot ์๋ฒ EC2์ ๋ฐฐํฌํ๊ธฐ (0) | 2021.11.24 |
---|---|
[ํ๋ก์ ํธ/mnm] Django ์๋ฒ AWS EC2์ ๋ฐฐํฌํ๊ธฐ (0) | 2021.11.22 |
[ํ๋ก์ ํธ/mnm] Spring - ๋งค์นญ ์ ๋ณด ๊ด๋ฆฌ REST API ๊ตฌํ (2) | 2021.11.17 |
[ํ๋ก์ ํธ/mnm] Spring - ๊ฑฐ์ฃผ ์ ๋ณด ๊ด๋ฆฌ REST API ๊ตฌํ (0) | 2021.11.17 |
[ํ๋ก์ ํธ/mnm] Spring - ์ด๋ฏธ์ง ์ ์ฅ, ์กฐํ REST API ๊ตฌํ (4) | 2021.11.17 |
๋๊ธ
๊ณต์ง์ฌํญ
์ต๊ทผ์ ์ฌ๋ผ์จ ๊ธ