22.03 / 대기열 구현하기

이슈

유저가 자신의 작업이 언제 시작되는지 모름,

현재 작업 진행 상황을 파악하기 어려움

원인

// 대략적인 초창기 코드
class DriverService {
    .....
    
    public synchronized boolean isAvailable(){
        return isRunning;
    }

    .....
}


class MapController {

    private final DriverService driverService; 

    @GetMapping
    public boolean availalbe(){
        return driverService.isAvailable();
    }

    @PostMapping
    public byte[] doJob(){
        return driverService.execute();
    }

}

초기 설계 자체가 문제였다. 1명씩 이미지 생성을 하기 위해 단순하게 현재 크롬 드라이버가 작업 중인지 판단하고, 작업 중이 아니라면 작업을 시작하는 방식이었다. 이 방식의 문제점은,

  • 클라이언트에서 계속 요청을 쏘며 확인해봐야함

  • 순서 개념이 없음

    • 요청 순서에 관계없이 타이밍이 잘 맞으면 먼저 시작 가능

새로운 설계가 필요한 시점이었다.

해결

풀어야 하는 문제는 2가지였다.

  1. 유저 요청이 오는 순서대로 처리

  2. 현재 진행 상황을 알려줘야함

1번 문제는 유저 요청을 큐에 등록, 꺼내서 처리하는 방식으로 비교적 수월하게 진행되었다.

문제는 2번이었는데, 실시간으로 유저에게 데이터를 보내는 방법으로는

  • Websocket

  • SSE (Server Sent Event)

두 가지 방식 정도가 있었다. 결국은 웹소켓을 사용하기로 결정했는데, 여기에는 몇가지 이유가 있었다.

  1. IE와의 호환성

  2. 유저 커넥션 관리

내 서비스에는 IE로 접속하는 사람이 생각보다 많다(20%). 그래서 IE를 배제하고 기술을 선택하기에는 부담스러운 면이 있는데, SSE가 IE에서는 지원을 하지를 않았다.

두 번째가 가장 큰 이유인데, SSE는 서버에서 클라이언트 연결이 끊겼을 때 감지하기가 어려웠다. 만약에 유저가 작업을 요청했는데 대기열이 길어서 서비스를 그냥 나갔을 때 대처할 방법이 필요했는데, SSE는 마땅한 수가 없던 반면에 웹소켓은 각각의 이벤트 상황별로 코드가 깔끔하게 작성이 가능했다.

배운점

  • 설계의 중요성

    • 초창기에 방향이 엇나가면 나중에 개고생한다

    • 당장 필요한 기능 구현에만 급급하지 말것

  • 기술 선택의 기준점

    • 단방향 실시간 통신만으로 충분한 상황

    • 하지만 향후 코드 구성의 용이함과 에러 케이스를 고려해야함

    • 단순히 필요에 매몰될 것인가, 그 너머를 볼 것인가

      • 필요한 기능 구현은 가능한 기술

      • But 특정 상황에 대처할 방법이 마땅치 않은 기술

      • 에러 터지면 조상님이 해결해주나?

      • 결국 내가 대처해야함. 생각나는 상황들은 미리 고려

Last updated