저번에 웹소켓을 이용하여 React로 채팅을 구현한 경험이 있다. [바로가기]
위의 글에선 사용자가 채팅을 이용할 때 네트워크 연결에 성공한 케이스만 다뤘었다. 하지만 언제나 그렇듯 항상 행복한 상황만 나오진 않는다. 실패 케이스도 처리를 해줘야 한다.
그래서 어떠한 방법이 있는지 구글링을 통해 알아냈고, 이를 블로깅 하려고 한다. 어렵지 않은 내용이니 글을 모두 읽으면 구현하는데 어렵지 않을 거라고 믿는다.
우선, 네트워크가 실패하면 네트워크 연결 재시도를 보내야 한다.
그렇다면 "재시도의 재시도가 실패하면 어떻게 해야 할까?", "재시도와 재시도 간격은 얼마나 해야할까?", "재시도가 계속 실패한다면 어떻게 해야 할까?" 등등 꼬리에 꼬리를 무는 생각이 들 수밖에 없다. 이에 대한 해결책으로 지수 백오프라는 전략을 들고 왔다.
지수 백오프란?
지수 백오프는 네트워크 상에서 일시적인 오류가 발생했을 때, 재시도 간격을 점진적으로 늘려가며 재시도를 수행하는 알고리즘이다. 이 방법은 주로 네트워크의 혼잡을 피하거나, 서버가 과부하 상태일 때 과도한 요청을 방지하기 위해 사용된다. 이 방법의 핵심은, "지수적으로" 대기 시간을 늘리는 것이다.
지수 백오프의 필요성
네트워크 통신 중 오류가 발생할 경우, 클라이언트는 보통 재시도를 통해 이를 해결하려고 한다. 하지만 모든 클라이언트가 동시에 재시도를 한다면, 서버는 한꺼번에 많은 요청을 처리해야 하므로 부하가 증가할 수 있다. 이러한 현상을 '재시도 폭주'라고 하며, 이를 방지하기 위해 지수 백오프가 필요하다.
지수 백오프의 이점
지수 백오프는 '재시도 폭주'를 방지하고, 네트워크와 서버의 부하를 줄이는 데 큰 도움이 된다. 또한, 과도한 요청으로 인한 비용 증가를 막을 수 있다. 이 밖에도, 지수 백오프를 사용하면 서버와 클라이언트 사이의 트래픽을 좀 더 효과적으로 관리할 수 있다.
지수 백오프 구현
파일을 만들어서 지수 백오프 알고리즘을 구현하는 함수를 작성하자.
export const exponentialBackoff = (minDelay = 1000, maxDelay = 120000) => {
let delay = minDelay;
let failCount = 0;
return {
backoff: () => {
failCount += 1;
delay = minDelay * 2 ** (failCount - 1);
if (delay > maxDelay) {
delay = maxDelay;
}
console.log(`Retry #${failCount} in ${delay}ms`);
return delay;
},
reset: () => {
failCount = 0;
delay = minDelay;
}
};
};
이 전략은 초기 지연 시간부터 시작하여, 지연 시간을 지수적으로 증가시키며 재시도를 수행한다.
내용 자체가 어렵지 않아서 직접 구현했지만 잘 모르시겠다 하시는 분들은 밑에 백오프에 관한 npm 주소를 남겨놓겠다.
지수 백오프 적용 예시
다음은 웹소켓 연결에 지수 백오프를 적용한 예시이다. 이 예시에서는 서버와의 연결이 끊어졌을 때, 지수 백오프를 이용하여 재연결을 시도한다.
import { exponentialBackoff } from './exponentialBackoff';
const backoff = exponentialBackoff();
const connect = () => {
client.current = new StompJs.Client({
brokerURL: 'ws://api.projectsassy.net:8080/ws',
onConnect: () => {
console.log('success');
subscribe();
publishOnWait();
backoff.reset(); // 연결 성공하면 대기 시간 초기화
},
onStompError: (error) => {
// 연결 실패 시
console.log('Error:', error);
setTimeout(connect, backoff.backoff()); // 지수 백오프를 적용하여 재연결 시도
},
});
client.current.activate();
};
connect();
return () => disconnect();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [userId]);
위 코드에서는 연결이 성공적으로 이루어지면 reset 함수를 호출하여 대기 시간을 초기화하고, 연결에 실패하면 backoff 함수를 이용하여 지수 백오프에 따른 대기 시간 후에 다시 연결을 시도한다.
지수 백오프는 이처럼 네트워크 통신 중 일시적인 오류를 효과적으로 대처할 수 있게 해 주며, 트래픽 조절 및 서버 부하 감소 등 다양한 이점을 제공한다. 이를 이해하고 적절히 활용하면, 더욱 견고한 네트워크 통신을 구현할 수 있다.
참고한 사이트
https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/
https://www.npmjs.com/package/backoff
'토이프로젝트 > ProjectSassy' 카테고리의 다른 글
리액트에서 캐러셀 구현 (0) | 2023.05.07 |
---|---|
인프런에서의 첫 스터디..! (3) | 2023.05.05 |
리액트 웹소켓(Stomp) (0) | 2023.04.24 |