유저에게 보다 더 좋은 페이지를 제공하자 (SSE event 리팩토링)

yeezze·2023년 1월 5일
0

form 프로젝트

목록 보기
6/7

기존에 간단하게만 구현했던 서버와 클라이언트 통신 기능을 리팩토링해야하는 순간이 찾아왔다.

기존

기존 로직은 서버에서 event data로 각 참여자별로 상황에 맞는 string 값을 넘겨주고 클라이언트는 웹에 그대로 출력하는 형태였다.

  • 대기하는 화면

  • 성공했을 경우

  • 선착순에 실패했을 경우

추가 요구사항

밋밋한 화면을 보고 생각을 하다보니 유저가 저 화면을 봤을 때 자신의 상태를 잘 알 수 없을 것 같다는 생각이 들었다.
때문에 이렇게 바꾸면 좋겠다 싶어서 추가 요구사항이 생겼다.

참여자가 대기하는 페이지에 상황별로 사진을 넣어서 보다 동적인 페이지를 보여주자!

어떻게 구현할까? 고민

해당 프로젝트는 웹페이지를 thymeleaf로 구현하고 있다.
서버에서 세가지 상태 중 현재 전송하는 이벤트가 속하는 상태를 함께 클라이언트에 보내줘야한다.
클라이언트는 받은 상태값을 확인하고 조건에 맞는 사진을 띄운다.

그렇다면 서버에서 이벤트 내에 상태값을 어떻게 보내줘야할까?
이벤트 한개에 기존에 보내주던 string 값과 상태값을 함께 보내줘야한다.

클라이언트는 EventSource라는 객체를 생성해서 서버에서 보낸 이벤트를 수신한다. 그래서 해당 객체에서 수신하는 이벤트 객체가 받을 수 있는 파라미터가 어떤게 있는지 확인해봤다.

https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#event_stream_format
여기서 Event stream format 부분을 보면 event, data, id, retry의 필드를 가지고 있다.
별도로 사용할만한 파라미터는 보이지 않았다.

좀 더 밑으로 내려가서 Named events 부분을 보자
JSON 문자열을 값으로 갖는 data 필드도 있다는 내용이 나온다.

event: order
data: {"msg": "대기번호는 5번입니다.", "status": "WAIT"}

서버에서 이런식으로 보내주면 되겠다!

구현

처음에 서버에서 data 내에 String 형태로 넣어서 보내면 되는 줄 알고 객체가 아닌 String을 JSON 형태로 작성해서 보내는 실수를 저질렀다.
String을 보내주게 되면 JSON.parse(event.data); 클라이언트 코드가 에러가 날 것이다.
JSON으로 통신하고 싶다면 객체 그대로 보내줘야한다!

서버 코드

public enum EventStatus {

    WAIT, SUCCESS, FAIL;
}

각 참여자들의 상태는 enum으로 관리하도록 구현했다.

@Getter
public class EventStreamDataJson {

    private final String msg;
    private final EventStatus status;

    protected EventStreamDataJson(String msg, EventStatus status) {
        this.msg = msg;
        this.status = status;
    }
}

데이터 객체를 생성해주고 생성자를 protected로 선언하여 불필요한 객체 생성을 방어하고자했다.

클라이언트 코드

sse.addEventListener('order', function (event) {
   let data = JSON.parse(event.data);
   if (data.status === "WAIT") {
     createDiv(data.msg, "/media/queue.png");
   } else if (data.status === "SUCCESS") {
     createDiv(data.msg, "/media/winner.png");
   } else {
     createDiv(data.msg, "/media/the-end.png");
   }
});

구현 완료 화면

  • 성공
  • 마감
  • 대기

변경 후의 화면이 훨씬 다채로워졌다! 😆

관련 커밋 내역은 여기서 확인할 수 있다!

profile
백엔드 개발자 😊

0개의 댓글