React Playground의 시스템 아키텍처: 실제로 무슨 일이 일어나는가

발행: (2026년 5월 1일 PM 10:55 GMT+9)
7 분 소요
원문: Dev.to

Source: Dev.to

고수준 개요

  • 프론트엔드는 IDE처럼 동작합니다.
  • 백엔드는 코디네이터 역할을 합니다.
  • 워커가 실제로 제출된 코드를 실행합니다.
  • Redis가 모든 것을 연결합니다.
  • S3는 사용자 솔루션을 저장합니다.

프론트엔드: 에디터와 프리뷰

편집

  1. Monaco Editor가 사용자가 입력한 JSX를 캡처합니다.
  2. **Babel (standalone)**이 JSX → JavaScript 로 트랜스파일합니다.
  3. 결과 JavaScript가 iframe에 삽입됩니다.

왜 iframe인가?

사용자 코드가 오류가 나면 iframe이 실패를 격리시켜 나머지 앱이 살아 있도록 합니다. iframe은 다음을 제공합니다:

  • 별도의 DOM
  • 별도의 JavaScript 컨텍스트

React와 ReactDOM은 CDN을 통해 iframe 내부에 로드되고, 컴포넌트가 그곳에서 렌더링되어 즉시 피드백을 제공합니다.

코드 제출

사용자가 “Submit” 버튼을 클릭하면:

  1. 트랜스파일된 코드가 아닌 원본 JSX가 백엔드로 전송됩니다.
  2. 백엔드가 solutionId를 생성하고 이를 프론트엔드에 반환합니다.

이 시점에서는 아직 실행되지 않았습니다.

실시간 통신

  • 프론트엔드는 WebSocket 연결을 열고 solutionId를 사용해 등록합니다.
  • 백엔드는 이 소켓을 통해 결과를 푸시합니다(폴링 없음).

백엔드 코디네이션

작업 큐잉

코드를 메인 서버에서 직접 실행하는 대신, 백엔드는:

  1. 작업을 BullMQ 큐에 푸시합니다.
  2. 작업 페이로드에 코드와 관련 메타데이터를 포함합니다.

큐를 사용하는 이유

  • 실행이 느리고 예측 불가능하며 잠재적으로 위험합니다.
  • 메인 서버에서 실행하면 다른 요청을 차단하고 성능 위험이 발생합니다.

워커 프로세스

전용 워커가 BullMQ 큐를 지속적으로 청취합니다. 작업이 도착하면:

  1. 워커가 작업을 가져와 Babel을 사용해 JSX를 다시 트랜스파일합니다.
  2. Puppeteer를 실행하고 코드를 실제 브라우저 환경에 주입한 뒤, 버튼 찾기, 클릭하기, UI 업데이트 확인 등 사용자 행동을 시뮬레이션합니다.

이 접근 방식이 제공하는 것:

  • 실제 DOM 및 이벤트 루프
  • Node.js만으로는 에뮬레이션할 수 없는 브라우저 수준 동작

격리와 안전성

  • 각 실행은 새 Puppeteer 페이지에서 이루어지며 공유 상태가 없습니다.
  • 워커는 백엔드와 별도 프로세스로 실행돼 실패가 격리됩니다.

결과 전달

  1. 실행이 끝나면 워커가 BullMQ에서 작업을 completed 로 표시합니다.
  2. 백엔드는 큐 이벤트를 청취하고 solutionId를 사용해 올바른 WebSocket을 찾아 결과를 전송합니다.
  3. 프론트엔드는 결과를 즉시 받아 UI를 업데이트합니다.

Redis 사용

  • BullMQ 큐 데이터를 저장합니다.
  • 작업 이벤트(완료/실패)를 퍼블리시합니다.
  • 더 빠른 읽기를 위한 캐시 레이어 역할을 합니다.

Raw Pub/Sub에서 BullMQ로 전환하면서 내장된 라이프사이클 이벤트, 재시도 처리, 더 깔끔한 코드를 제공해 아키텍처가 단순해졌습니다.

사용자 코드 저장

  • 코드는 AWS S3에 저장되고, 파일 키만 데이터베이스에 보관됩니다.
  • 필요할 때 백엔드가 signed URL을 생성해 프론트엔드가 코드를 가져오게 합니다.

이점

  • 보안(공개 접근 차단)
  • 확장성
  • 메타데이터와 대용량 코드 블롭을 명확히 분리

엔드‑투‑엔드 흐름

  1. 사용자가 코드를 작성 → 프리뷰가 iframe에서 실행.
  2. 사용자가 제출 → 백엔드가 solutionId 반환.
  3. 프론트엔드가 WebSocket 열기 ID 사용.
  4. 백엔드가 작업을 BullMQ 큐에 푸시.
  5. 워커가 Puppeteer로 코드 실행.
  6. 워커가 작업 완료 표시; 백엔드가 이벤트 수신.
  7. 백엔드가 WebSocket을 통해 결과 전송.
  8. 프론트엔드가 UI를 업데이트 검증 결과 표시.

주요 장점

  • 프론트엔드는 빠른 프리뷰를 담당하고, 백엔드는 실제 DOM을 이용한 신뢰성 있는 검증을 담당합니다.
  • 워커가 독립적으로 실행돼 메인 서버가 차단되지 않습니다.
  • WebSocket을 통한 실시간 업데이트로 부하가 감소하고 확장성이 향상됩니다.
  • 책임이 명확히 분리돼 더 깔끔하고 유지보수하기 쉬운 아키텍처를 구현합니다.
0 조회
Back to Blog

관련 글

더 보기 »

OpenSearch에서 검색 쿼리의 생애

OpenSearch는 Apache Lucene을 기반으로 구축된 오픈‑소스 검색 및 분석 엔진입니다. 검색 요청을 보낼 때, 복잡한 구성 요소들의 연동이 백그라운드에서 작동합니다.

Google이 방금 Control Plane 경계를 이동했습니다

스케일링, 격리, 그리고 새로운 스케일 단위 더 많은 용량이 필요하신가요? 클러스터를 추가하세요. 워크로드 격리가 필요하신가요? 클러스터를 추가하세요. 지역 분리가 필요하신가요? 클러스터를 추가하세요.