JS와 관련해서 흥미로운 사실을 찾았다.
시스템프로그래밍이나 OS 수업에서 한 번쯤 들어봤을 race condition이 프론트엔드에서도 발생할 수 있다는 것이다.
Race Condition?
race condition은 두 개 이상의 프로세스, 스레드가 공유되는 자원(critical section)에 접근해서 값을 쓰려고 할 때 발생한다.
race condition이 발생하면 공유 자원의 값이 의도치 않게 변경되는 문제점이 생긴다.
백엔드에서의 레이스 컨디션은 실제 바뀐 값으로 권한 상승 등이 일어날 수 있어 CTF에서도 종종 출제되고 보안적으로 상당히 심각하게 다뤄지는 문제이다.
반면 프론트엔드에서는 보여지는 화면만 바뀌는 것이니 그렇게까지 위험하지는 않을 것 같고, Race Condition이 발생할 수 있는지를 생각해본 적이 없었는데 이번 기회에 알아보게 되었다.
JS Engine은 싱글 스레드인데 어떻게 Race Condition이 발생하는가?
그런데 JS Engine은 싱글 스레드 기반인데 어디서 레이스 컨디션이 발생하는 건지 궁금증이 생겼다.
JS 런타임의 안의 memory heap과 call stack은 싱글 스레드 상에서 동작하니 문제가 없어 보인다.
그렇다면 JS 런타임의 DOM, fetch 등 Web API 스레드들이 callback queue에 동시에 접근하는 것이니, callback queue에서 race condition이 발생하는 것일까?
이 코드는 JavaScript에서 Race Condition이 발생하는 예시이다.
var x = 1;
async function foo() {
var y = x;
await setTimeout(100); // whatever async here
x = y+1;
}
//비동기 함수를 동시에 실행하면 Race condition이 발생한다.
await Promise.all([foo(), foo(), foo()]);
console.log(x); // 2
//동시에 실행되지 않고 순차적이라면 다음과 같다.
await foo();
await foo();
await foo();
console.log(x); // 4
아래 Stackoverflow 답변을 참고하면, 동시성(Concurrency)과 병렬성(Parallel)에 관해 JS는 싱글 스레드 기반이므로 스레드 병렬성은 없지만 비동기 함수를 가져서 동시성을 가지고 작동한다.
동시성 때문에 JS에서 여러 비동기 요청(fetch, setTimeout ..)을 여러 번 보냈을 때 그 응답은 순서가 보장되지 않는다.
따라서 await 등으로 순서를 보장해 주지 않으면 DOM이나 변수에 원하지 않는 값이 들어갈 수 있다.
JS 엔진을 쓰는 Node.js에서의 Race Condition과 이를 막기 위한 방법
Race Condition을 막는 방법은 SystemProgramming에서 나오는 것과 같다. 공유되는 자원 Critical Section에 접근하는 것을 한 번에 하나씩 접근하도록 제한하면 된다.
JS 엔진을 쓰는 Node.js 계열에서도 레이스 컨디션을 막기 위한 mutex, semaphore 라이브러리가 구현되어 있다.
https://fourjae.tistory.com/entry/Nodejs-Race-Condition
- 조금 더 찾아보니 threading과 concurrency(동시성)은 별개의 개념이고, 싱글 스레드에서도 동시적 접근으로 인한 race condition이 발생할 수도 있다고 한다.
싱글스레드 Node.js에서 race condition 예시 : https://stackoverflow.com/questions/21438207/can-node-js-code-result-in-race-conditions
참고 자료
https://velog.io/@pjc0247/프론트엔드와-Race-Condition
https://tecoble.techcourse.co.kr/post/2021-09-12-race-condition-handling/
'프로그래밍 > Frontend (React, Javascript, Typescript)' 카테고리의 다른 글
전역 상태(zustand)에서 배열 concat의 side effect, 해결 방안 (feat. React Strict Mode) (0) | 2024.12.15 |
---|---|
Vite Proxy with Base URL & CORS 해결 (2) | 2024.11.28 |
10분 만에 웹사이트에 PWA 적용해서 웹앱 만들기! (2) | 2024.11.14 |
React Component와 객체지향의 차이에 관하여 (2) | 2024.09.29 |
Fixed Menu, 메뉴 바 상단 고정 구현 시 content에 margin-top을 주면 위험한 이유 (feat. margin collapsing) (4) | 2024.09.28 |