프론트엔드 개발을 하다 보면 한 번쯤 이런 요구사항을 만나게 됩니다.
“새 알림이 오면 바로 화면에 보여주세요.”
“상태가 바뀌면 새로고침 없이 반영되게 해주세요.”
“채팅처럼 실시간으로 메시지가 오가야 해요.”
“AI 답변이 한 글자씩 출력되면 좋겠어요.”
처음에는 이런 요구사항을 들으면 자연스럽게 WebSocket이 떠오릅니다.
“실시간이면 WebSocket 아닌가?”
저도 처음에는 이렇게 생각했습니다.
그런데 공부해보니 실시간 통신이라고 해서 전부 WebSocket을 써야 하는 건 아니었습니다.
상황에 따라서는 SSE(Server-Sent Events)가 더 단순하고, 더 적절한 선택이 될 수 있습니다.
이번 글에서는 SSE와 WebSocket이 어떻게 다른지, 어떤 상황에서 어떤 방식을 선택하면 좋은지 정리해보겠습니다.
일반적인 웹 통신은 대부분 HTTP 요청과 응답 구조로 동작합니다.
클라이언트가 서버에 요청합니다.
데이터 주세요.
서버가 응답합니다.
여기 있습니다.

이 방식은 단순하고 안정적입니다.
하지만 서버의 데이터가 바뀌었을 때 클라이언트가 그 사실을 바로 알 수 없다는 문제가 있습니다.
예를 들어 승인 요청 목록 화면을 보고 있다고 가정해보겠습니다.
사용자는 현재 승인 목록을 보고 있습니다.
그런데 다른 사용자가 새로운 승인 요청을 등록했습니다.
서버에는 새로운 데이터가 생겼지만, 클라이언트 화면은 그대로입니다.
왜냐하면 클라이언트가 서버에 다시 요청하지 않았기 때문입니다.
이 문제를 해결하려면 클라이언트가 계속 서버에 물어보거나, 서버가 클라이언트에게 직접 알려줘야 합니다.
이때 자주 등장하는 방식이 다음 세 가지입니다.
| 방식 | 설명 |
|---|---|
| Polling | 일정 시간마다 서버에 계속 물어보는 방식 |
| SSE | 서버가 클라이언트에게 이벤트를 보내는 방식 |
| WebSocket | 서버와 클라이언트가 서로 실시간으로 주고받는 방식 |
Polling은 가장 단순한 방식입니다.
setInterval(() => {
fetch('/api/notifications');
},5000);
5초마다 서버에 물어봅니다.
새 알림 있어요?
새 알림 있어요?
새 알림 있어요?
구현은 쉽습니다.
하지만 약간 귀찮은 친구처럼 계속 물어보는 구조입니다.
문제는 알림이 없어도 계속 요청을 보낸다는 점입니다.
서버 입장에서는 이렇게 느낄 수도 있습니다.

없다니까...
아직 없다니까...
아직도 없다니까...
그리고 5초마다 요청한다면, 실제 데이터가 생겨도 최대 5초 늦게 화면에 반영될 수 있습니다.
그래서 실시간성이 더 필요하거나 불필요한 요청을 줄이고 싶다면 SSE나 WebSocket을 고려하게 됩니다.
SSE는 Server-Sent Events의 약자입니다.
이름 그대로 서버가 보내는 이벤트입니다.
클라이언트가 서버에 한 번 연결을 열어두면, 서버는 연결을 유지하다가 필요한 시점에 데이터를 보내줍니다.
클라이언트 → 서버 : 연결할게요.
서버 → 클라이언트 : 새 알림이 있습니다.
서버 → 클라이언트 : 상태가 변경되었습니다.
서버 → 클라이언트 : 작업이 완료되었습니다.
여기서 중요한 점은 SSE가 단방향 통신이라는 것입니다.
즉, 기본 흐름은 이렇습니다.
서버 → 클라이언트
클라이언트는 서버가 보내주는 이벤트를 받습니다.
하지만 같은 연결로 서버에게 메시지를 보내지는 않습니다.
프론트엔드에서는 EventSource를 사용합니다.
consteventSource=newEventSource('/api/events');
eventSource.onmessage= (event) => {
constdata=JSON.parse(event.data);
console.log(data);
};
코드만 보면 꽤 간단합니다.
SSE는 쉽게 말해 라디오 방송에 가깝습니다.
방송국이 말을 합니다.
청취자는 듣습니다.

방송국 → 청취자
서버 → 클라이언트
서버가 “새 알림 왔어요”, “상태 바뀌었어요”, “진행률 80%예요”라고 알려주면 클라이언트는 그것을 받아서 화면에 반영합니다.
WebSocket은 서버와 클라이언트가 하나의 연결을 유지하면서 양방향으로 데이터를 주고받는 방식입니다.
클라이언트 → 서버 : 채팅방 들어갈게요.
서버 → 클라이언트 : 입장 완료입니다.
클라이언트 → 서버 : 메시지 보낼게요.
서버 → 클라이언트 : 새 메시지가 도착했습니다.
핵심은 양방향입니다.
서버 ↔ 클라이언트
클라이언트도 서버에게 메시지를 보낼 수 있고, 서버도 클라이언트에게 메시지를 보낼 수 있습니다.
프론트엔드에서는 이렇게 사용할 수 있습니다.
constsocket=newWebSocket('wss://example.com/socket');
socket.onopen= () => {
socket.send(JSON.stringify({
type:'JOIN_ROOM',
roomId:1,
}));
};
socket.onmessage= (event) => {
constdata=JSON.parse(event.data);
console.log(data);
};
WebSocket은 쉽게 말해 전화 통화에 가깝습니다.
나도 말하고, 상대방도 말합니다.

나 ↔ 상대방
클라이언트 ↔ 서버
그래서 채팅, 게임, 협업 편집처럼 서로 계속 데이터를 주고받아야 하는 기능에 잘 맞습니다.

두 기술의 차이를 표로 정리하면 다음과 같습니다.
| 구분 | SSE | WebSocket |
|---|---|---|
| 정식 명칭 | Server-Sent Events | WebSocket |
| 통신 방향 | 단방향 | 양방향 |
| 데이터 흐름 | 서버 → 클라이언트 | 서버 ↔ 클라이언트 |
| 브라우저 API | EventSource | WebSocket |
| 기반 | HTTP | WebSocket Protocol |
| 구현 난이도 | 비교적 쉬움 | 상대적으로 복잡 |
| 자동 재연결 | 기본 지원 | 직접 구현 필요 |
| 클라이언트 → 서버 전송 | 별도 HTTP 요청 필요 | 같은 연결에서 가능 |
| 데이터 형식 | 주로 텍스트 | 텍스트, 바이너리 가능 |
| 적합한 기능 | 알림, 상태 변경, 진행률, 로그 | 채팅, 게임, 협업 편집 |
| 운영 복잡도 | 낮은 편 | 높은 편 |
표만 보면 WebSocket이 더 강력해 보입니다.
양방향도 되고, 데이터 형식도 자유롭고, 다양한 기능을 만들 수 있기 때문입니다.
하지만 강력하다고 항상 좋은 선택은 아닙니다.
칼이 좋다고 해서 종이 한 장 자를 때도 꼭 식칼을 꺼낼 필요는 없습니다.
요구사항에 맞는 도구를 쓰는 것이 더 중요합니다.
개념만 보면 조금 추상적입니다.
그래서 실제 사용 사례를 보면 이해가 더 쉽습니다.
SSE는 서버가 클라이언트에게 정보를 알려주기만 하면 되는 기능에 잘 맞습니다.
예를 들면 이런 기능입니다.
| 기능 | SSE가 어울리는 이유 |
|---|---|
| 알림 | 서버가 새 알림을 보내주면 됨 |
| 승인 상태 변경 | 상태가 바뀔 때 서버가 알려주면 됨 |
| 파일 처리 진행률 | 서버가 진행률을 계속 보내주면 됨 |
| 실시간 로그 | 서버 로그를 클라이언트가 받기만 하면 됨 |
| AI 응답 스트리밍 | 서버가 생성된 응답을 순차적으로 보내면 됨 |
예를 들어 AI 답변 스트리밍을 생각해볼 수 있습니다.
사용자가 질문을 보냅니다.
그다음 서버는 생성된 답변을 조금씩 내려보냅니다.
서버 → 클라이언트 : 안녕하세요.
서버 → 클라이언트 : 요청하신 내용을
서버 → 클라이언트 : 아래와 같이
서버 → 클라이언트 : 정리해드리겠습니다.
클라이언트는 서버에게 계속 말할 필요가 없습니다.
처음 질문을 보낸 뒤에는 서버 응답을 받기만 하면 됩니다.
이런 구조에서는 WebSocket보다 SSE가 더 단순하고 자연스럽습니다.
WebSocket은 서버와 클라이언트가 서로 계속 데이터를 주고받아야 하는 기능에 잘 맞습니다.
| 기능 | WebSocket이 어울리는 이유 |
|---|---|
| 채팅 | 사용자가 메시지를 보내고 서버가 다시 전달해야 함 |
| 실시간 게임 | 클라이언트 조작과 서버 상태가 계속 오가야 함 |
| 협업 문서 편집 | 여러 사용자의 수정 내용을 실시간 동기화해야 함 |
| 실시간 위치 공유 | 클라이언트 위치를 서버로 계속 보내야 함 |
| 타이핑 중 표시 | 사용자의 입력 상태를 서버에 계속 알려야 함 |
예를 들어 채팅은 전형적인 WebSocket 사례입니다.
사용자 A → 서버 : 안녕하세요.
서버 → 사용자 B : 사용자 A가 메시지를 보냈습니다.
사용자 B → 서버 : 반갑습니다.
서버 → 사용자 A : 사용자 B가 메시지를 보냈습니다.
이 구조에서는 클라이언트도 서버에게 계속 메시지를 보내야 합니다.
그래서 SSE만으로는 부족하고 WebSocket이 더 적합합니다.
SSE와 WebSocket은 실제 서비스에서도 많이 사용됩니다.
AI 서비스의 응답 스트리밍은 SSE와 잘 어울리는 대표적인 사례입니다.
사용자가 질문을 보내면 서버가 답변을 한 번에 완성해서 내려주는 것이 아니라, 생성되는 토큰을 순차적으로 내려보냅니다.

그래서 화면에서는 답변이 실시간으로 작성되는 것처럼 보입니다.
이런 구조는 클라이언트가 서버에 계속 메시지를 보낼 필요가 없고, 서버가 생성한 결과를 클라이언트가 받기만 하면 되기 때문에 SSE와 잘 맞습니다.
또한 관리자 페이지의 알림, 서버 작업 진행률, 로그 스트리밍 같은 기능도 SSE를 적용하기 좋은 영역입니다.
WebSocket은 채팅 서비스나 협업 서비스에서 많이 사용됩니다.
예를 들어 Discord 같은 채팅 기반 서비스는 실시간 메시지 송수신이 핵심입니다.
사용자가 메시지를 보내고, 서버는 그 메시지를 같은 채널에 있는 사용자들에게 즉시 전달해야 합니다.
Figma 같은 협업 도구도 WebSocket과 잘 어울리는 사례입니다.
여러 사용자가 동시에 같은 파일을 보고 수정하면, 한 사용자의 변경 사항이 다른 사용자 화면에도 거의 실시간으로 반영되어야 합니다.
이런 기능은 단순히 서버가 알려주기만 하는 구조가 아닙니다.
클라이언트의 입력과 서버의 상태가 계속 오가야 합니다.
그래서 WebSocket이 더 자연스럽습니다.
기술을 선택할 때는 “SSE가 좋은가요, WebSocket이 좋은가요?”보다
“내 기능은 어떤 데이터 흐름을 가지고 있나요?”라고 묻는 것이 더 좋습니다.
아래 질문으로 판단하면 조금 쉬워집니다.
그렇다면 SSE를 먼저 고려할 수 있습니다.
예시:
새 알림
상태 변경
작업 진행률
실시간 로그
AI 응답 스트리밍
이런 기능은 대부분 서버에서 클라이언트로 데이터가 흐릅니다.
서버 → 클라이언트
그렇다면 WebSocket이 더 적합합니다.
예시:
채팅 메시지 전송
타이핑 중 표시
사용자 위치 전송
게임 조작 이벤트
협업 편집 내용 전송
이런 기능은 서버와 클라이언트가 서로 데이터를 주고받습니다.
서버 ↔ 클라이언트
그렇다면 Polling도 충분할 수 있습니다.
예를 들어 30초마다 한 번 갱신되어도 괜찮은 관리자 통계 화면이라면 굳이 SSE나 WebSocket을 도입하지 않아도 됩니다.
무조건 실시간 기술을 붙인다고 좋은 구조가 되는 것은 아닙니다.
| 상황 | 추천 방식 |
|---|---|
| 새 알림을 바로 보여주고 싶다 | SSE |
| 승인 상태 변경을 화면에 반영하고 싶다 | SSE |
| 파일 처리 진행률을 보여주고 싶다 | SSE |
| AI 응답을 스트리밍하고 싶다 | SSE |
| 서버 로그를 실시간으로 보고 싶다 | SSE |
| 채팅을 만들어야 한다 | WebSocket |
| 사용자가 입력 중인지 보여줘야 한다 | WebSocket |
| 실시간 협업 편집이 필요하다 | WebSocket |
| 게임처럼 빠른 양방향 통신이 필요하다 | WebSocket |
| 10초~30초마다 갱신되어도 괜찮다 | Polling |
공부하면서 가장 크게 느낀 점은, SSE와 WebSocket은 경쟁 관계라기보다 역할이 다른 기술이라는 점이었습니다.
처음에는 실시간 통신이라고 하면 WebSocket이 먼저 떠올랐습니다.
하지만 실제 요구사항을 보면 굳이 WebSocket까지 필요하지 않은 경우도 많았습니다.
예를 들어 알림이나 진행률처럼 서버가 알려주기만 하면 되는 기능은 SSE가 더 단순합니다.
서버야, 바뀌는 거 있으면 알려줘.
반대로 채팅이나 협업 편집처럼 클라이언트도 계속 서버에게 말해야 하는 기능은 WebSocket이 더 자연스럽습니다.
서버야, 나도 계속 말할게. 너도 계속 알려줘.
이렇게 생각하면 선택 기준이 꽤 명확해집니다.
SSE는 구독에 가깝고, WebSocket은 대화에 가깝습니다.
SSE와 WebSocket은 둘 다 실시간 기능을 구현할 때 사용할 수 있는 기술입니다.
하지만 두 기술은 목적이 다릅니다.
SSE는 서버에서 클라이언트로 이벤트를 보내는 단방향 통신입니다.
그래서 알림, 상태 변경, 작업 진행률, 로그 스트리밍, AI 응답 스트리밍처럼 서버 이벤트를 받기만 하면 되는 기능에 잘 어울립니다.
WebSocket은 서버와 클라이언트가 서로 메시지를 주고받는 양방향 통신입니다.
그래서 채팅, 게임, 협업 편집, 실시간 위치 공유처럼 클라이언트도 계속 서버에 데이터를 보내야 하는 기능에 적합합니다.
정리하면 이렇게 볼 수 있습니다.
서버가 말하고 클라이언트가 듣기만 하면 SSE
서버와 클라이언트가 서로 대화해야 하면 WebSocket
실시간 통신이라고 해서 무조건 WebSocket을 선택할 필요는 없습니다.
중요한 것은 기술 이름이 아니라 데이터가 어느 방향으로 흐르는지입니다.
이번에 SSE와 WebSocket을 비교하면서 느낀 점은, 기술 선택은 “더 좋아 보이는 것”을 고르는 일이 아니라 “현재 요구사항에 더 잘 맞는 것”을 고르는 일이라는 것이었습니다.
여전히 좋은 글이군요!!