페이스북은 React를 어떻게 서빙할까? (코드 레벨로 보는 전 메타 엔지니어의 증언)

우리가 매일 사용하는 페이스북이나 인스타그램의 웹사이트는 모두 React로 만들어졌습니다.

React를 만든 곳이 바로 페이스북(현 메타)이니 어찌 보면 당연한 일이죠.

하지만 문득 이런 궁금증이 생깁니다.

'과연 페이스북은 그 거대한 규모의 React 애플리케이션을 어떤 방식으로 사용자에게 전달(서빙)할까?', 'Next.js나 Remix 같은 오픈소스 프레임워크를 사용할까, 아니면 완전히 다른 무언가가 있을까?'

최근 한 온라인 커뮤니티에서 이 질문에 대한 전직 메타 엔지니어들의 흥미로운 답변이 오고 갔습니다.

오늘은 그들의 증언을 바탕으로, 단순한 이름 나열을 넘어 각 기술이 실제로 어떻게 생겼고 왜 사용되는지 코드와 함께 그 내부를 깊숙이 들여다보겠습니다.

두 가지 종류의 'React' 서빙 방식

한 전직 메타 엔지니어의 설명에 따르면, 페이스북은 크게 두 가지 종류의 'React' 결과물을 서빙한다고 합니다.

하나는 '정적인 JS(JavaScript)'이고, 다른 하나는 '동적인 HTML/JS'입니다.

1. 정적 JS: 'MakeHaste'와 CDN

정적인 JS 파일들은 Babel을 통해 컴파일된 후, 'MakeHaste'라는 이름의 자체 개발한 사내 번들러로 묶입니다.

여기서 잠깐, 왜 Webpack이나 Vite 같은 훌륭한 오픈소스 대신 굳이 사내 번들러를 만들었을까요?

이는 페이스북의 코드베이스가 상상 이상으로 거대하고, 수많은 팀이 의존성을 공유하는 독특한 환경이기 때문입니다.

'MakeHaste'는 페이스북의 모노레포(monorepo) 구조와 고유한 의존성 관리 시스템에 극도로 최적화되어 있어, 수백만 개의 모듈을 믿을 수 없는 속도로 처리할 수 있습니다.

이렇게 만들어진 최종 결과물은 CDN을 통해 전 세계 사용자에게 전달됩니다.

2. 동적 콘텐츠: 'Hack', 'HHVM', 'Hermes'의 삼중주

사용자마다 다른 내용을 보여줘야 하는 동적인 웹 콘텐츠는 페이스북 기술 스택의 진수가 담긴 영역입니다.

핵심은 'Hack' 언어와 'HHVM' 실행 환경, 그리고 'Hermes' 자바스크립트 엔진입니다.

'Hack' 언어는 어떻게 생겼을까?

'Hack'은 페이스북이 PHP의 단점을 보완하기 위해 만든 언어입니다.

가장 큰 특징은 '점진적 타입 시스템(Gradual Typing)'을 도입했다는 점입니다.

실제로 코드를 보면 그 차이가 더 명확해집니다.

// 일반적인 PHP 코드
function greet($name) {
  // $name이 문자열인지, 숫자인지 알 수 없습니다.
  return "Hello, " . $name;
}


위 코드에서 $name 변수에 어떤 타입의 값이 들어올지 알 수 없어 잠재적인 버그를 유발할 수 있습니다.

이제 'Hack' 코드를 볼까요.

// Hack 코드
// 함수의 인자와 반환값에 명확한 타입을 지정합니다.
function greet(string $name): string {
  // $name은 반드시 문자열이어야 함을 컴파일 시점에 보장합니다.
  return "Hello, " . $name;
}


이처럼 'Hack'은 타입 힌트를 통해 코드의 안정성과 가독성을 크게 높였습니다.

전직 엔지니어들이 "PHP에 대한 안 좋은 기억이 있었는데도 Hack은 정말 재밌었다"고 말하는 이유를 짐작할 수 있는 부분입니다.

'HHVM'과 'Hermes'의 역할 분담

'HHVM(HipHop Virtual Machine)'은 이 Hack 코드를 JIT(Just-In-Time) 컴파일하여 매우 빠르게 실행하는 가상 머신입니다.

서버의 메인 엔진 역할을 하는 셈이죠.

여기서 가장 흥미로운 부분은 '서버 사이드 렌더링(SSR)'입니다.

서버에서 React 컴포넌트를 실행하여 HTML을 만드는 이 과정에는 'Hermes' 엔진이 사용됩니다.

'Hermes'는 본래 React Native 앱의 시작 속도와 메모리 사용량을 최적화하기 위해 만들어진 경량 자바스크립트 엔진입니다.

V8(Node.js가 사용하는) 같은 범용 엔진보다 특정 작업(React 렌더링)에 더 최적화되어 있어, 서버 환경에서도 빠르고 효율적인 SSR을 가능하게 합니다.

즉, HHVM이 전체 요청을 처리하는 주체라면, 그 안에서 자바스크립트 코드(React) 실행이 필요할 때 'Hermes'라는 전문가를 호출하는 구조입니다.

React 서버 컴포넌트(RSC)는 왜 사용하지 않을까?

그렇다면 최신 React의 화두인 '서버 컴포넌트'는 어떨까요?

한 전직 엔지니어는 놀라운 사실을 알려줍니다.

페이스북은 이미 'Relay'라는 기술을 통해 RSC와 거의 동일한 이점을 누리고 있다는 것입니다.

'Relay'는 어떻게 동작할까?

'Relay'는 페이스북이 만든 또 다른 오픈소스 기술로, GraphQL과 함께 사용되는 데이터 페칭 라이브러리입니다.

핵심은 **'컴포넌트가 필요한 데이터를 스스로 선언한다'**는 개념입니다.

# UserProfile.js 컴포넌트가 사용할 데이터 조각(Fragment)
fragment UserProfile_user on User {
  id
  name
  profile_picture(scale: 2) {
    uri
  }
}


위와 같이 GraphQL 프래그먼트를 정의한 뒤, React 컴포넌트 안에서 이 데이터를 사용합니다.

// UserProfile.js
import {graphql, useFragment} from 'react-relay';

function UserProfile(props) {
  // 프래그먼트를 통해 필요한 데이터만 정확히 받아옵니다.
  const data = useFragment(
    graphql`
      fragment UserProfile_user on User { ... }
    `,
    props.user,
  );

  return (
    <div>
      <img src={data.profile_picture.uri} />
      <h1>{data.name}</h1>
    </div>
  );
}


이러한 '데이터 요구사항의 컴포넌트 단위 분리'가 서버 렌더링과 결합되면, 서버는 각 컴포넌트가 정확히 어떤 데이터를 필요로 하는지 알 수 있습니다.

이를 통해 불필요한 데이터 페칭을 줄이고 렌더링을 최적화할 수 있는데, 이것이 바로 RSC가 해결하려는 핵심 문제 중 하나입니다.

따라서 페이스북 입장에서는 이미 'Relay + SSR' 조합으로 충분한 성능을 내고 있기에, 막대한 비용을 들여 RSC로 전환할 필요성을 크게 느끼지 못하는 것입니다.

필요가 발명을 낳는다

이번 엔지니어들의 증언을 통해, 우리는 페이스북이 단순히 기술을 소비하는 것을 넘어, 자신들의 문제를 해결하기 위해 언어, 가상 머신, 엔진, 번들러, 데이터 페칭 라이브러리까지 직접 창조해내는 '기술 개척자'의 모습을 엿볼 수 있었습니다.

우리가 사용하는 React의 배경에는 이처럼 치열한 고민과 고도로 최적화된 기술 생태계가 존재하고 있었던 것이죠.

이는 단순히 '어떤 기술을 쓴다'를 넘어, '왜 그 기술을 만들고 선택했는가'에 대한 깊은 통찰을 줍니다.

다음에 페이스북을 스크롤할 때, 그 부드러운 화면 뒤에서 일어나는 이 거대한 기술의 협주를 한번 상상해 보는 것은 어떨까요.