SSE로 인한 Timeout 수정하기
SSE가 작동하고 있는 동안에는 다른 모든 요청이 느려진다.
axios로 api를 호출하면 timeout이 발생한다.
useRef를 붙여서 eventSource 객체를 관리해봤는데 이상하게 해결이 됐다.
⇒ (나중에는 결국 백엔드에서의 이슈였던 것으로 밝혀졌다고…)
useRef의 원리에 따라서 증거를 찾아나가 보면,
모든 렌더링에서 동일한 객체를 제공하기 때문인 것 같다.
원래는 eventSource 생성을 함수 최상단에서 다음과 같이 생성했었다.
const evtSource = new EventSource(${process.env.REACT\_APP\_API\_URL}/api/sse/rooms);
const evtSource = useRef(null);
const closeEvtSource = () => {
evtSource.current.close();
console.log('evtSource closed!');
console.log(evtSource);
};
const openEvtSource = () => {
evtSource.current.onerror = async (err) => {
console.error('EventSource failed:', err);
closeEvtSource();
// 재연결 시도
openEvtSource()
};
// 연결됐을때 방 정보 받아오기
evtSource.current.addEventListener('connect', async (event) => {
console.log('evtSource connected!');
console.log(evtSource);
const data = JSON.parse(event.data);
setRooms(data);
});
// 방 정보가 변할 때 방 정보 받아오기
evtSource.current.addEventListener('changeRoom', async (event) => {
console.log('evtSource changeRoom!');
console.log(evtSource);
const data = JSON.parse(event.data);
setRooms(data);
});
};
useEffect(() => {
evtSource.current = new EventSource(`${process.env.REACT_APP_API_URL}/api/sse/rooms`);
openEvtSource();
return () => {
closeEvtSource();
};
}, []);
하지만 이 과정에서 방 정보가 변한다면 eventSource 객체를 재생성하게 되니 이 부분에서 문제가 생기지 않았을까 싶다.
근데 재연결 시도하는 부분이 조금 마음에 안든다. 연결이 되지 않고 계속해서 에러가 난다면 무한 재귀가 발생할 수 있는 부분이라고 생각이 든다.
호출 스케줄링 (setTimeout vs SetInterval)
일정 시간이 지난 후에 원하는 함수를 예약 실행(호출)할 수 있게 하는 것을 '호출 스케줄링(scheduling a call)'이라고 한다
- setTimeout을 이용해 일정 시간이 지난 후에 함수를 실행하는 방법
- setInterval을 이용해 일정 시간 간격을 두고 함수를 실행하는 방법
여기서 간단하게 타임아웃만 설정해주면 된다.
evtSource.current.onerror = async (err) => {
console.error('EventSource failed:', err);
closeEvtSource();
// 재연결 시도
setTimeout(openEvtSource(), 3000);
};
적절한 시간이 3초라고 생각해서 3초로 적용해놓았다.
D2
D2는 Declarative Diagramming(선언적 다이어그래밍)이다.
프로젝트 발표할 때 스트럭쳐 소개할때 항상 고민이 되는 부분인데, 개발자답게 다이어그램할 수 있는 언어가 나오게 된 것 같아서 굉장히 기쁘다. 디자인도 꽤 다양하게 지원하고 있고 러닝커브도 굉장히 높고 쉬워서 앞으로 써봄직함한 것 같다.
사용성 높이기 (UX)
방생성 모달에서 편의성을 위한 두가지 피드백이 있었다
1. 모달이 생성되면 input에 자동 focus하기
useRef를 써도 되고 다양한 방법이 있겠지만, 가장 쉬운 방법은 autoFocus 속성을 추가해주는 것이다.
<input autoFocus ... />
2. 엔터를 누르면 버튼이 작동되게하기
=> children을 감싸고 있는 Content 컴포넌트에 onKeyPress 이벤트 리스너를 추가해줌
function Modal({ children, title, btnText, onConfirm }) {
const { closeModal } = useModal();
const handleClose = () => {
closeModal();
};
const handleKeyPress = (event) => {
if (event.key === 'Enter') {
onConfirm();
}
};
return (
<Overlay>
<ModalWrap>
<CloseButton onClick={handleClose}>
<img src={cancel} alt="X" />
</CloseButton>
<ContentsWrap>
<Title>{title}</Title>
<Content onKeyPress={handleKeyPress}>{children}</Content>
<BtnArea>
<FlatButton onClick={onConfirm}>{btnText}</FlatButton>
</BtnArea>
</ContentsWrap>
</ModalWrap>
</Overlay>
);
}
잘된다!!
'개발일기' 카테고리의 다른 글
[TIL] 죽어있는 웹사이트에 생명 불어넣기 (0) | 2023.02.08 |
---|---|
[TIL] 소셜 로그인 한페이지에서 함께 처리하기 (0) | 2023.01.24 |
[TIL] 왜 이렇게 바쁜가요?😭 (0) | 2023.01.19 |
[TIL] 실전에서 배우기 (0) | 2023.01.14 |
[TIL] 느려터진 apt를 구제해주세요 (0) | 2023.01.13 |