Skip to content

리액트를 배우셨군요 유감입니다 2편 (JSX와 컴포넌트, 아무도 원치 않았던 그 아이)

Published: at 오후 03:40

1편에서는 리액트가 대체 왜 태어났는지, 그리고 우리 모두를 지치게 만드는 ‘자바스크립트 피로감’의 역사에 대해 알아봤죠.

오늘은 리액트의 가장 눈에 띄는 특징이자 가장 논란이 많은 두 가지, 바로 ‘JSX’와 ‘컴포넌트’에 대해 이 책이 얼마나 신랄하게 비판하는지 함께 들여다보려고 합니다.

리액트 개발자들은 “이건 그냥 자바스크립트야!”라고 외치지만, 나머지 우리들은 “이게 어딜 봐서 자바스크립트야?”라고 되묻게 만드는 바로 그 지점이죠.

JSX 아무도 원치 않았던 그 아이

JSX는 리액트의 가장 대표적인 기능이면서 동시에 가장 큰 논란거리이기도 한데요.

마치 HTML을 쓰는 건지 자바스크립트를 쓰는 건지 결정하지 못해서, 둘 다를 동시에 어설프게 쓰는 것과 같은 모습이죠.

리액트 공식 문서에 따르면 JSX는 ‘자바스크립트에 대한 구문 확장’이라고 하는데요.

이건 마치 오리너구리를 보고 “오리에 대한 포유류 확장”이라고 말하는 것과 같습니다.

기술적으로는 사실일지 몰라도, 듣는 사람을 아주 심란하게 만들죠.

트랜스파일이라는 세금

JSX의 가장 큰 비밀은 바로 브라우저가 이걸 전혀 이해하지 못한다는 건데요.

우리가 작성한 아름다운 JSX 코드는 실행되기 전에 반드시 일반 자바스크립트로 변환되어야만 합니다.

// 우리가 작성하는 코드
<div className="hello">
  <h1>Hello, {name}</h1>
</div>;

// 실제로 브라우저에서 실행되는 코드
React.createElement(
  "div",
  { className: "hello" },
  React.createElement("h1", null, "Hello, ", name)
);

우리가 작성하는 모든 태그 하나하나가 결국 React.createElement라는 함수 호출로 바뀌는 겁니다.

이 말인즉슨, 우리는 Babel 같은 트랜스파일러가 필요하고, 빌드 과정이 필요하며, Webpack이나 Vite 같은 빌드 도구 설정이 필요하다는 뜻이죠.

단지 자바스크립트 안에서 HTML 비슷한 문법을 쓰기 위해서 말입니다.

온갖 이상한 규칙들

”JSX는 HTML과 거의 똑같아!”라고 리액트 개발자들은 말하지만, 실상은 전혀 다른데요.

classclassName이 되고, forhtmlFor가 됩니다.

style 속성은 더 이상 문자열이 아니라, 카멜케이스로 된 속성명을 가진 자바스크립트 객체여야 하죠.

// HTML 스타일
<div style="color: red; font-size: 16px;">Hello</div>

// JSX 스타일
<div style={{ color: 'red', fontSize: '16px' }}>Hello</div>

저 중괄호 두 개는 오타가 아닙니다.

바깥쪽 중괄호는 “이제부터 자바스크립트 시작!”이라는 뜻이고, 안쪽 중괄호는 객체를 정의하는 문법이죠.

게다가 font-sizefontSize로 바뀐 것처럼, 우리가 알던 모든 CSS 속성명을 머릿속에서 카멜케이스로 번역해야만 합니다.

조건부 렌더링을 하고 싶다고요?

이제 ‘삼항 연산자 지옥’에 오신 것을 환영합니다.

{
  isLoggedIn ? (
    <p>Welcome back!</p>
  ) : isGuest ? (
    <p>Welcome, guest!</p>
  ) : (
    <p>Please log in</p>
  );
}

심지어 주석조차 평범하지 않은데요.

<!-- 주석 --> 대신 {/* 주석 */}이라는 기괴한 문법을 써야만 합니다.

개발자 친화적이라는 말이 무색하게, 주석 하나 다는 것조차 복잡하게 만들어 버렸죠.

그래도 딱 하나 좋은 점 XSS 방지

그래도 딱 한 가지, JSX가 정말 잘하는 게 있는데요.

바로 XSS(Cross-Site Scripting) 공격을 자동으로 방어해준다는 점입니다.

JSX는 중괄호 안에 들어오는 모든 값을 문자열로 처리해서, 악성 스크립트가 실행되는 것을 원천적으로 차단하죠.

물론 정말로 HTML을 렌더링하고 싶을 때는 dangerouslySetInnerHTML이라는 무시무시한 이름의 속성을 써야만 하는데요.

마치 “그래, 정 쓰고 싶으면 쓰시든가.

대신 ‘위험하다’는 단어를 직접 타이핑하게 만들어서 우리가 얼마나 이걸 못마땅해하는지 똑똑히 알려주겠어.”라고 말하는 것 같죠.

컴포넌트 망치를 들면 모든 것이 못으로 보인다

리액트의 세계에서는 모든 것이 컴포넌트인데요.

헤더도 컴포넌트, 버튼도 컴포넌트, 단어 사이의 공백조차도 컴포넌트로 만들어야 직성이 풀리는 것 같죠.

‘재사용 가능한 UI 조각’이라는 합리적인 아이디어를 가져다가, 모든 divdiv를 반환하는 함수로 감싸야만 하는 종교로 만들어버렸습니다.

평범한 div였으면 좋았을 것을

제가 본 최악의 리액트 안티패턴 중 하나는 바로 ‘단순 div를 위한 컴포넌트’인데요.

const Container = ({ children }) => <div className="container">{children}</div>;

const Wrapper = ({ children }) => <div className="wrapper">{children}</div>;

const Box = ({ children }) => <div className="box">{children}</div>;

축하합니다.

당신은 방금 div에 클래스 하나 붙이면 될 일을, 더 많은 코드와 복잡성, 그리고 버그의 가능성을 추가해서 세 개의 컴포넌트로 만들어냈습니다.

Props 끝없이 내려가는 문제 덩어리

Props는 리액트 컴포넌트들이 소통하는 방식인데요.

마치 여러 사람이 한 줄로 서서 메시지를 전달하는 ‘전화기 게임’과 같습니다.

모든 사람이 명시적으로 메시지를 전달해야 하고, 한 명이라도 잊어버리면 모든 것이 망가지죠.

버튼 컴포넌트 하나를 만드는데, 그 설정 옵션(props)이 독일제 자동차보다 많아지는 경우도 허다합니다.

그리고 새로운 prop을 하나 추가하려면, 그 컴포넌트를 사용하는 모든 곳을 다 찾아다니며 코드를 수정해야만 하죠.

컴포넌트 구성과 ‘프로바이더 지옥’

리액트는 ‘상속보다 구성(Composition over inheritance)‘을 장려하는데요.

이 말은 그럴듯하게 들리지만, 실제로는 컴포넌트를 러시아 인형처럼 끝없이 중첩시키는 결과를 낳습니다.

<ThemeProvider>
  <AuthProvider>
    <RouterProvider>
      <StoreProvider>
        <IntlProvider>
          <ErrorBoundary>
            <Suspense>
              <App />
            </Suspense>
          </ErrorBoundary>
        </IntlProvider>
      </StoreProvider>
    </RouterProvider>
  </AuthProvider>
</ThemeProvider>

이것이 바로 ‘프로바이더 지옥(Provider Hell)‘이라고 불리는 현상입니다.

모든 기능이 자신만의 래퍼 컴포넌트를 필요로 할 때 발생하죠.

우리의 실제 앱은 마치 디지털 고고학 유적지처럼, 일곱 겹의 추상화 계층 아래 깊숙이 묻혀버립니다.

마치며

이 책의 저자가 말하려는 건 명확한데요.

JSX와 컴포넌트라는 개념 자체는 분명히 장점이 있습니다.

컴포넌트 단위로 UI를 생각하면 복잡한 화면을 체계적으로 구성할 수 있고, JSX는 자바스크립트의 모든 능력을 템플릿 안에서 활용할 수 있게 해주죠.

하지만 우리는 그 편리함을 위해 너무 많은 것을 포기해야만 했습니다.

단순했던 HTML과 CSS, 그리고 명료했던 DOM 조작의 시대를 뒤로하고, 복잡한 빌드 과정과 기묘한 규칙들, 그리고 끝없는 추상화의 세계로 들어온 거죠.

결국 스톡홀름 증후군이 발현될 때쯤이면, 우리도 JSX를 좋아하게 되고, 포럼에서 “그건 그냥 자바스크립트야!”라고 외치며 JSX를 옹호하게 될지도 모릅니다.

그때가 바로 리액트가 완전히 승리한 순간이겠죠.

다음 편에서는 이 모든 문제의 근원인 ‘상태 관리(State Management)‘에 대해 이 책이 어떻게 독설을 퍼붓는지 살펴보도록 하겠습니다.