| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
| 29 | 30 | 31 |
Tags
- reactivity
- golang
- component
- map
- Server
- Refactoring
- websocket
- go
- localStorage
- goroutine
- Vue
- CDN
- toggle
- cli
- 행렬
- container
- PROPS
- todo-list
- Vue.js
- method
- TODO
- emit
- Dictionary
- channel
- graceful shutdown
- SFC
- URL
- Matrix
- goroutines
- App.vue
Archives
- Today
- Total
ksundev 님의 블로그
SPA와 WebSocket: 실제론 하나의 HTML⁉️ 본문
웹 개발을 하다 보면 실시간 기능을 구현해야 할 때가 있습니다. 채팅, 알림, 실시간 업데이트 등을 위해 WebSocket을 사용하는데, 이때 중요한 것이 바로 연결의 지속성입니다. 오늘은 SPA(Single Page Application)와 WebSocket의 조합이 왜 강력한지 알아보겠습니다.
전통적인 웹사이트 vs SPA
전통적인 웹사이트 (Multi-Page Application)
전통적인 웹사이트는 여러 개의 HTML 파일로 구성됩니다:
프로젝트 구조:
├── login.html
├── dashboard.html
├── patients.html
└── settings.html
사용자가 페이지를 이동할 때마다:
- 새로운 HTML 파일을 서버에서 받아옴
- 페이지가 완전히 새로고침됨
- 이전 페이지의 모든 JavaScript가 사라짐
SPA (Single Page Application)
SPA는 단 하나의 HTML 파일로 구성됩니다:
프로젝트 구조:
├── index.html (단 하나의 HTML!)
├── src/
│ ├── App.vue
│ ├── components/
│ │ ├── LoginComponent.vue
│ │ ├── DashboardComponent.vue
│ │ └── PatientsComponent.vue
│ └── router/
│ └── index.js
핵심 포인트: 우리가 보는 페이지는 처음부터 끝까지 index.html 하나뿐입니다.
SPA에서 페이지 이동이 일어나는 방식
1. 사용자가 보는 것
브라우저 주소창:
https://hospital.com/login → 로그인 화면
https://hospital.com/dashboard → 대시보드 화면
https://hospital.com/patients → 환자 관리 화면
2. 실제로 일어나는 것
<!-- 실제로는 계속 같은 index.html -->
<!DOCTYPE html>
<html>
<head><title>요양보호사 시스템</title></head>
<body>
<div id="app">
<!-- App.vue가 여기서 라우팅 담당 -->
</div>
</body>
</html>
3. App.vue가 하는 일
<template>
<div id="app">
<!-- 주소에 따라 다른 컴포넌트 표시 -->
<router-view></router-view>
</div>
</template>
<script>
export default {
mounted() {
// 앱 시작 시 WebSocket 연결 - 한 번만!
this.socket = new WebSocket('ws://localhost:8080/ws');
}
}
</script>
App.vue가 라우터 역할을 하면서 주소에 따라 다른 컴포넌트를 보여줍니다.
페이지 이동 시 실제 동작
전통적인 웹사이트
// login.html에서 WebSocket 연결
const socket = new WebSocket('ws://localhost:8080/ws');
// 사용자가 dashboard.html로 이동
// → 페이지 새로고침 → 모든 JavaScript 사라짐 → WebSocket 끊어짐
// dashboard.html에서 다시 WebSocket 연결 필요
const socket = new WebSocket('ws://localhost:8080/ws'); // 새로운 연결
SPA
// App.vue에서 WebSocket 연결
const socket = new WebSocket('ws://localhost:8080/ws');
// 사용자가 /login → /dashboard → /patients로 이동
// → 페이지 새로고침 없음 → App.vue 유지됨 → WebSocket 연결 유지!
핵심 개념: 같은 HTML, 다른 화면
브라우저 개발자 도구에서 확인하기
- Network 탭 확인:
- 전통적인 웹사이트: 페이지 이동 시마다 HTML 파일 다운로드
- SPA: 최초 한 번만 HTML 파일 다운로드
- Elements 탭 확인:
- 전통적인 웹사이트: 페이지 이동 시 완전히 새로운 HTML 구조
- SPA: 계속 같은 HTML 구조, 내용만 변경
실제 예시
<!-- 우리가 보는 페이지는 항상 이것! -->
<!DOCTYPE html>
<html>
<head><title>요양보호사 시스템</title></head>
<body>
<div id="app">
<!-- /login 주소일 때 -->
<div class="login-component">
<h1>로그인</h1>
<form>...</form>
</div>
<!-- /dashboard 주소일 때 -->
<div class="dashboard-component">
<h1>대시보드</h1>
<div>환자 현황...</div>
</div>
<!-- /patients 주소일 때 -->
<div class="patients-component">
<h1>환자 관리</h1>
<table>...</table>
</div>
</div>
</body>
</html>
중요: 실제로는 한 번에 하나의 컴포넌트만 표시되지만, 모든 것이 같은 HTML 안에서 일어납니다.
WebSocket 연결이 끊기지 않는 이유
1. HTML이 새로고침되지 않음
전통적인 웹사이트:
login.html → dashboard.html (HTML 교체, 새로고침 발생)
SPA:
index.html → index.html (같은 HTML, 내용만 변경)
2. JavaScript 환경이 유지됨
// App.vue에서 생성한 WebSocket
export default {
data() {
return {
socket: null
}
},
mounted() {
this.socket = new WebSocket('ws://localhost:8080/ws');
}
}
// 페이지 이동해도 App.vue는 그대로 있음
// → this.socket도 그대로 유지됨
// → WebSocket 연결도 그대로 유지됨
3. 연결 상태 확인
// 어떤 페이지에 있든 항상 연결 상태
console.log(this.socket.readyState); // 1 (OPEN)
// 페이지 이동 후에도
this.$router.push('/patients');
console.log(this.socket.readyState); // 여전히 1 (OPEN)
실제 사용 예시
요양보호사 관리 시스템
// App.vue - 앱 전체에서 하나의 WebSocket 관리
export default {
data() {
return {
socket: null
}
},
mounted() {
this.socket = new WebSocket('ws://localhost:8080/ws');
this.socket.onmessage = (event) => {
const data = JSON.parse(event.data);
// 긴급 알림이 오면 어떤 페이지에 있든 표시
if (data.type === 'emergency_alert') {
alert(`긴급 상황: ${data.message}`);
}
};
}
}
시나리오:
- 사용자가 로그인 페이지에서 로그인
- 대시보드로 이동
- 환자 관리 페이지로 이동
- 모든 페이지에서 실시간 긴급 알림 수신 가능
왜? 같은 HTML 안에서 계속 App.vue가 살아있기 때문입니다.
정리
SPA의 핵심 개념
- 우리가 보는 페이지는 항상
index.html하나 - App.vue가 주소에 따라 다른 컴포넌트를 보여주는 라우터 역할
- 페이지 이동 = HTML 교체가 아닌 JavaScript로 화면 변경
WebSocket이 끊기지 않는 이유
- HTML 새로고침 없음
- JavaScript 환경 유지
- App.vue에서 생성한 WebSocket 연결 지속
결론
HTML이 새로고침되지 않으니 Socket도 끊기지 않는다
이것이 바로 SPA와 WebSocket 조합이 실시간 웹 애플리케이션에서 강력한 이유입니다. 사용자가 어떤 페이지에 있든 끊김 없는 실시간 경험을 제공할 수 있습니다.