SSE(Server-Sent Events)를 이용한 비동기 작업 상태 전달 구조 설계 (백엔드 관점)
1. 왜 SSE를 도입하려고 했는가?
백엔드에서 시간이 오래 걸리는 비동기 작업을 처리할 때, 클라이언트가 해당 작업의 완료 시점을 알아야 하는 요구사항이 있었다.
일반적으로 비동기 작업의 흐름은 다음과 같다.
- 클라이언트가 작업 요청
- 서버에서 비동기 작업 수행
- 작업 완료 시점에 결과 상태 변경
- 클라이언트는 완료 여부를 확인해야 함
이때 가장 먼저 떠올릴 수 있는 방법은 클라이언트가 일정 주기로 상태 조회 API를 호출하는 폴링(Polling) 방식이다.
하지만 이 방식은 작업이 완료되지 않았더라도 불필요한 요청이 반복적으로 발생한다는 단점이 있다.
이 문제를 해결하기 위해 서버가 작업 완료 시점에 직접 이벤트를 전달하는 구조를 고민하게 되었고, 그 대안으로 SSE(Server-Sent Events)를 설계하게 되었다.
2. SSE(Server-Sent Events)란 무엇인가?
SSE(Server-Sent Events)는 서버에서 클라이언트로 지속적으로 이벤트를 스트리밍 방식으로 전달하는 기술이다.
클라이언트는 한 번 연결을 맺으면 서버에서 이벤트가 발생할 때마다 데이터를 실시간으로 수신할 수 있다.
즉, 다음과 같은 특징을 가진다.
- HTTP 기반 스트리밍 통신
- 서버 → 클라이언트 단방향 이벤트 전달
- 연결을 유지하면서 이벤트를 순차적으로 수신
- 작업 상태 변경 알림에 적합
특히 "비동기 작업 완료 알림"과 같은 시나리오에서 매우 유용하다.
3. 전체 구조 개요
이번에 설계한 구조의 핵심 흐름은 다음과 같다.
Client → Backend → 비동기 작업 수행
↓
SSE 연결 유지
↓
작업 완료 이벤트 발생 → Client에 전달
즉,
- 클라이언트는 서버와 SSE 연결을 유지하고
- 서버는 비동기 작업 상태를 관리하며
- 작업 완료 시점에 이벤트를 즉시 전달하는 구조다.
4. 폴링(Polling) 대신 SSE를 선택한 이유
4.1 폴링 방식의 구조
가장 단순한 구조는 다음과 같다.
Client → 일정 주기로 상태 조회 API 호출
Server → 현재 작업 상태 반환
이 방식은 구현이 쉽지만 다음과 같은 문제가 있다.
- 작업이 완료되지 않아도 계속 요청 발생
- 서버 부하 증가
- 완료 시점에 즉시 반영되지 않을 수 있음
특히 작업 시간이 일정하지 않은 경우, 폴링 주기를 짧게 하면 부하가 커지고 길게 하면 반영이 늦어지는 문제가 생긴다.
4.2 SSE 방식의 구조
SSE를 사용하면 흐름이 단순해진다.
Client → SSE 연결 요청
Server → 작업 완료 시점에 이벤트 전송
즉, 필요할 때만 이벤트가 전달되므로 불필요한 반복 요청을 줄일 수 있다.
5. SSE 기반 상태 전달 흐름
5.1 클라이언트 SSE 연결
클라이언트는 특정 리소스에 대해 SSE 연결을 맺는다.
Client → /events/stream 연결
Server → 스트림 연결 유지
이 연결은 작업 상태가 변경될 때까지 유지된다.
5.2 비동기 작업 수행
클라이언트가 작업을 요청하면 서버는 해당 작업을 비동기로 수행한다.
Client → 작업 요청
Backend → 비동기 작업 시작
이때 작업 수행 자체는 일반적인 API 호출과 동일하게 처리된다.
5.3 작업 완료 이벤트 전달
비동기 작업이 완료되면 서버는 연결되어 있는 SSE 스트림으로 이벤트를 전송한다.
비동기 작업 완료
→ 서버에서 이벤트 생성
→ SSE 스트림으로 Client에 전달
이 구조를 통해 클라이언트는 별도의 새로고침 없이 즉시 상태 변경을 반영할 수 있다.
6. 장기 연결에서의 인증 고려 사항
SSE는 연결이 장시간 유지되는 특성이 있기 때문에 인증 토큰 만료에 대한 설계가 중요하다.
특히 다음과 같은 상황을 고려해야 한다.
- SSE 연결 중 Access Token 만료
- 토큰 재발급 이후 연결 유지 전략
- 쿠키 기반 인증 vs 헤더 기반 인증 선택
따라서 SSE 설계는 단순한 스트리밍 통신 문제가 아니라, 인증 구조와도 밀접하게 연결된 설계 요소라고 볼 수 있다.
7. WebSocket 대신 SSE를 선택한 이유
실시간 통신이라고 해서 항상 WebSocket이 필요한 것은 아니다. 이번 구조에서는 서버에서 클라이언트로 상태 변경 알림만 전달하면 충분했다.
즉, 양방향 통신이 필수적인 상황은 아니었다.
이 경우 SSE의 장점은 다음과 같다.
- HTTP 기반이라 인프라 구성이 단순함
- 단방향 이벤트 전달에 적합
- 구현 난이도가 낮음
- 방화벽이나 프록시 환경에서도 안정적
따라서 단순 상태 알림 목적이라면 WebSocket보다 SSE가 더 적합한 선택이 될 수 있다.
8. SSE 설계 시 고려해야 할 핵심 포인트
이번 구조를 설계하면서 다음과 같은 요소를 중점적으로 고려했다.
- 비동기 작업 완료 시점 이벤트 전달 방식
- 서버 내부 작업 상태와 SSE 스트림 연동 방법
- 장기 연결 환경에서의 인증 토큰 만료 처리
- 폴링 방식 대비 서버 부하 감소 효과
특히 "언제 이벤트를 발생시킬 것인가"가 중요한 설계 포인트였다. 작업 완료 시점에 정확하게 이벤트를 전달해야 클라이언트가 불필요한 재요청 없이 상태를 갱신할 수 있기 때문이다.
9. 정리
SSE(Server-Sent Events)는 단순한 실시간 통신 기술이 아니라, 백엔드에서 비동기 작업 상태를 효율적으로 전달하기 위한 설계 도구라고 볼 수 있다.
SSE를 도입함으로써 다음과 같은 장점을 얻을 수 있다.
- 불필요한 폴링 요청 감소
- 작업 완료 시점 즉시 반영
- 사용자 경험 개선
- 서버 자원 효율적 사용
특히 비동기 작업 완료 알림과 같은 시나리오에서는 SSE가 WebSocket보다 단순하고 적합한 선택이 될 수 있다.
10. 결론
비동기 작업의 완료 시점을 클라이언트에 전달해야 하는 상황에서는 주기적으로 상태를 조회하는 구조보다 서버가 이벤트를 직접 전달하는 구조가 더 효율적이다.
이러한 요구사항을 충족하기 위해 SSE(Server-Sent Events)를 활용한 백엔드 중심의 상태 전달 구조를 설계할 수 있다.
이 구조는 인증 토큰 재발급 흐름과 결합하여 장기 연결 환경에서도 안정적으로 확장할 수 있다.