Dev/ETC
[자원] 경쟁상태 Race Condition?
헝그리둘기
2025. 10. 28. 14:27
개념
두 가지 이상의 프로세스의 실행 순서가 보장되지 않고 서로 경쟁 상태에 있어, 최종 결과값을 알 수 없는 상태.
예를들어, 여러 트랜잭션이 한 자원에 대해 락을 획득해야 하는데, 어떤 트랜잭션이 먼저 획득할지 모르는 상태.
예시
1. Nextjs에서 <Image> 태그로 이미지를 렌더링 해야하는 상황.
기본 saveFilePath상태의 값은 공백이고, 페이지 렌더링 시 외부 API를 호출하여 savefile 파라미터의 값을 채우는 구조.
import Image from "next/image"
const uri = "https://www.abc.com/download?savefile="
const [saveFilePath, setSaveFilePath] = useState<string>("")
// 외부 API 요청 후 파일경로 세팅
const fetch = async () => {
const res = await getFilePathService()
setSaveFilePath(res.path) // res.path의 기댓값은 test.png
...
}
// 마운트 후 패치
useEffect(() => {
fetch()
}), [])
return (
<Image
src={`${uri}${saveFilePath}`} // imageSrc의 기댓값은 https://www.abc.com/download?savefile=test.png
alt={alt}
width={width || 100}
height={height || 100}
className={className}
onLoad={onLoad}
unoptimized={unoptimized}
onError={() => {
if (imageSrc !== `${frontClientUrl}${defaultImagePath}`) { // 무한 루프 방지
setIsError(true)
}
}}
/>
)
2. 예상 기댓값은 src속성 값에 https://www.abc.com/download?savefile=test.png 라는 값이 들어가고, 해당 서버에서 파일 자원을 요청하여 이미지를 렌더링.
결과는, 예상과 달리 API 요청보다 이미지태그 렌더링이 빨리 일어나서 src속성에 https://www.abc.com/download?savefile= 라는 값이 할당되는 경우가 종종 발생. 즉, 비동기 요청과 이미지 렌더링이 서로 경쟁상태(Race Condition)
따라서 해당 주소로 파일 요청을 보내개 되고, 받은 응답(404라고 가정)이 이미 캐싱되어버리기 때문에, 뒤늦게 imageSrc값이 변경된다 해도 이미지 렌더링이 다시 일어나지 않음.
3. 해결책으로, 렌더링 순서를 보장하기 위해 API호출 후 saveFilePath값이 존재할 때만 이미지를 렌더링하도록 변경.
{saveFilePath && (
<Image
src={`${uri}${saveFilePath}`} // imageSrc의 기댓값은 https://www.abc.com/download?savefile=test.png
alt={alt}
width={width || 100}
height={height || 100}
className={className}
onLoad={onLoad}
unoptimized={unoptimized}
onError={() => {
if (imageSrc !== `${frontClientUrl}${defaultImagePath}`) { // 무한 루프 방지
setIsError(true)
}
}}
/>
)}