Changsoon's Note Backend Developer

비동기 요청의 순서 제어하기

문제 상황

회사에서 기능을 구현하다 프론트에서 보낸 요청 중 저장 후 저장한 객체를 조회하는 로직 부분에서 오류가 발생했다.

원인을 분석해보니 프론트 비동기 요청에서 해당 요청을 동시에 여러개를 보내서 순서가 보장되지 않는 문제를 발견했다.

해당 상황을 샘플 코드로 알아보자

예를 들어, 프론트에서 axios 요청을 진행했다고 가정해보자.

백엔드에서는 해당 요청의 내용과 쓰레드 정보를 출력한다.

요청 실행 결과를 확인해보면 해당 요청의 순서가 보장되지 않는다.

20240618-1

또한 DB에 저장하는 로직을 생성해서 저장되는 것을 보아도 순서가 보장되지 않는다.

alt text

문제가 생기는 이유가 무엇일까?

이유는 답은 비동기 요청 자체에 있다. 비동기 요청은 해당 요청의 반환을 기다리지 않는다.

그래서 요청 후에 그 값이 저장되기 전에 다른 요청을 보내버리니 순서가 꼬여버린다.

그렇다면 백엔드에서 해당 문제 해결 방법은 없을까?

synchronized 키워드를 사용해서 한번에 하나씩 사용하면 순서가 보장되지 않을까?

synchronized 키워드는 한번에 하나의 요청을 처리할 뿐이지 순서를 보장해서 처리하진 않는다.

alt text

클라이언트에서 10개의 요청을 순차적으로 동시에 보내더라도, 서버에 각각의 요청이 도착하는 순서는 다를 수 있기 때문에 클라이언트 요청과 서버에서의 처리 순서가 일치하지 않을 수 있다.

클라이언트에서 요청을 보낼 때 요청의 순서를 유지할 수 있는 방법을 찾아야 한다.

해결 방법은?

요청 순서를 기억하는 메커니즘 구현

각 요청에 고유한 식별자를 붙이고, 서버에서 요청을 순서대로 처리한다.

비동기 처리 후 결과를 정렬해서 반환

모든 요청을 비동기적으로 처리한 후에 결과를 정렬해서 반환한다.

클라이언트에서 요청의 순서를 보장할 수는 있지만, 처리 시간이 오래 걸리거나 요청이 많을 경우에는 효율적이지 않다.

클라이언트에서 순차적으로 요청을 보내기

클라이언트에서 요청을 순차적으로 보내고 서버에서 순서대로 처리한다.

요청의 순서를 보장할 수는 있지만, 처리 시간이 오래 걸리는 경우 클라이언트에서 불필요하게 대기해야 한다.

클라이언트에서 async, await를 사용하여 하나의 요청이 완료되고 기다렸다가 다시 요청 보내기

결과

alt text