useEffect내에서 비동기 처리
useEffect
훅에서 비동기 함수 호출을 감싸는 이유를 전문적으로 설명하면 다음과 같다.
React의 useEffect
훅은 컴포넌트가 렌더링될 때 특정 작업을 수행할 수 있게 해주는 훅이다. useEffect
의 리턴 값은 클린업 함수 또는 undefined
여야 하며, 이는 다음 렌더링 전에 수행할 정리 작업을 정의한다. 따라서 useEffect
는 프로미스(Promise)를 리턴할 수 없다.
비동기 함수를 직접적으로 useEffect
에 전달하면 함수가 프로미스를 리턴하게 된다. 그러나 useEffect
는 클린업 함수를 기대하므로 프로미스를 직접 반환하는 것은 올바르지 않다. 이에 따라 비동기 작업을 useEffect
내부에서 수행하려면 즉시 실행 함수(IIFE, Immediately Invoked Function Expression) 또는 다른 방법으로 비동기 함수를 호출해야 한다.
아래 코드를 예로 들어 설명하겠다.
useEffect(() => {
(async () => {
const user = await supabase.auth.getUser();
setUserResponse(user);
})(); // useEffect내에서는 이렇게 감싸야됨
}, []);
여기서 (async () => { ... })()
구문은 즉시 실행 비동기 함수 표현식이다. 이는 useEffect
내부에서 비동기 작업을 수행하면서도 useEffect
가 기대하는 방식대로 작동하게 해준다.
useEffect
훅은 다음과 같은 이유로 즉시 실행 함수로 감싸 비동기 작업을 수행해야 한다:
- 프로미스 반환 방지:
useEffect
는 클린업 함수 또는undefined
를 리턴해야 한다. 비동기 함수는 프로미스를 반환하므로, 이를 직접 사용하면useEffect
가 프로미스를 리턴하게 되어 오류가 발생할 수 있다. - 비동기 작업 수행: 컴포넌트가 마운트되거나 특정 상태 또는 프롭스가 변경될 때 비동기 작업을 안전하게 수행할 수 있다. 이 패턴을 사용하면
useEffect
내부에서 비동기 작업을 처리할 수 있다.
정리하면, useEffect
내부에서 비동기 작업을 수행할 때 비동기 함수를 즉시 실행 함수로 감싸는 것은 useEffect
의 리턴 값 규칙을 준수하면서 비동기 작업을 수행하기 위한 권장 방법이다. 이 패턴은 컴포넌트의 마운트와 언마운트 시점에서 비동기 작업을 안전하게 처리하고, useEffect
의 클린업 함수와의 충돌을 방지한다.
onClick함수 내에서 비동기 처리
비동기 함수를 onClick
핸들러로 사용하는 것은 특정 작업의 완료를 보장하고 그 다음 작업을 실행하는 데 중요하다. 이 경우, supabase.auth.signOut()
가 비동기 함수이므로, 이를 비동기로 처리해야 로그아웃 작업이 완료된 후 페이지 이동이 일어날 수 있다. 이렇게 하지 않으면 로그아웃이 완료되기 전에 페이지 이동이 일어날 수 있어 예기치 않은 동작이 발생할 수 있다.
하지만 supabase.auth.signOut()
와 router.push('/')
사이의 순서가 중요하지 않거나 로그아웃 요청을 기다릴 필요가 없는 경우, 비동기로 처리하지 않아도 된다. 다만, 안전하게 처리하기 위해서는 비동기로 처리하는 것이 좋다.
현재 작성한 코드에서는 비동기 처리(즉, async
및 await
키워드 사용)가 적절하게 되어 있다. 다음은 원래 코드이다:
<button
onClick={async () => {
await supabase.auth.signOut();
router.push('/');
}}
className="rounded-md bg-gray-800 px-2 py-2 text-white"
>
로그아웃
</button>
이 코드는 supabase.auth.signOut()
가 완료된 후 router.push('/')
가 실행되도록 한다. 비동기 처리를 제거하면 로그아웃 요청이 완료되기 전에 페이지 이동이 일어날 수 있다.
비동기 처리를 제거한 코드는 다음과 같다:
<button
onClick={() => {
supabase.auth.signOut();
router.push('/');
}}
className="rounded-md bg-gray-800 px-2 py-2 text-white"
>
로그아웃
</button>
위 코드에서는 supabase.auth.signOut()
가 완료되기를 기다리지 않고 곧바로 router.push('/')
가 실행된다. 이는 로그아웃 요청이 백그라운드에서 실행되지만, 사용자는 곧바로 홈 페이지로 이동하게 된다.
일반적으로는 비동기 처리를 유지하는 것이 좋다. 따라서 처음 작성한 코드를 사용하는 것을 권장한다.
'Frontend > Javascript Typescript' 카테고리의 다른 글
[Typescript] 제네릭을 사용하는 타입 정의 (0) | 2024.12.11 |
---|---|
삼항연산자보다 더 간결하게 쓰기(논리연산자, nullish 널 병합연산자 `??`) (0) | 2024.12.09 |
[TIL] 왜 !!를 사용하는가? (double negation operator, double bang) (0) | 2024.08.08 |
Javascript 클로저 (0) | 2024.08.08 |
디바운싱과 쓰로틀링(Debouncing&Throttling) (0) | 2024.08.08 |