React - A High-Level Perspective

2023. 4. 30.


면책 조항: 이 글은 작성자인 박정욱(@hatchling13)이 공부한 내용을 바탕으로 정리하고 개인적인 의견을 더한 글로, 정확한 사실이 될 수 없으며 잘못된 내용이 포함될 수 있습니다. 또한 React라는 기술의 방향성에 공감하며 작성된 글이기 때문에, 의도치 않게 편향된 시선으로 작성될 수 있음을 알립니다. 오류 지적과 내용 보충을 환영합니다!

2020년대 기준으로 따져봤을때, React는 프론트엔드 개발 직종에 취업하기 원하는 초보자가 처음 잡게 될 가능성이 가장 큰 도구라고 볼 수 있다. 글이 업로드된 현재(2023년 4월) 기준, 한국에서 흔히 말하는 ‘JS 프론트엔드 3대장’ 라이브러리인 React/Vue/Angular다운로드 수가 가장 많고, 구글 검색 결과도 가장 많이 나온다.

남들이 많이 가는 길을 선택하는 것은 나쁜 선택이 아니다. 나도 본격적으로 프론트엔드 엔지니어를 지망하게 되었을 때 처음 고른 도구는 React였고, 그 이유 또한 위에서 이야기했듯, 가장 인기있(어 보이)는 라이브러리였기 때문이다.

대부분의 인기 있는 도구는 기존 방식에 한계를 느낀 사람들이 나름의 고민을 통해 찾아낸 풀이법과도 같다. 따라서 어떤 도구의 필요성을 온전히 느끼기 위해서는 해당 도구를 만들게 된 이유, 즉 제작자들이 해결하고 싶었던 문제를 살펴보는 것이 꽤 중요하다고 생각한다.

React는 사용자 인터페이스(User Interface, UI)를 만들기 위한 라이브러리이다. 위의 주장과 합쳐 이야기하자면, React는 기존에 UI를 만드는 방식이 마음에 들지 않던 사람들, 즉 당시 페이스북의 엔지니어들이 고민한 결과물이라고 이야기할 수 있겠다. 이들은 기존 방식의 어떤 부분에서 한계를 느끼게 된 것일까? 페이스북은 2014년 자사 컨퍼런스인 F8에서 ”Hacker Way: Rethinking Web App Development at Facebook”(이하 “Hacker Way”)이라는 발표를 통해 이를 보여준다.

당시의 페이스북은 일종의 ‘모순’에 직면해있었다. 고품질의 소프트웨어를 만들기 위해서는 그만큼의 시간을 들여야 하지만, 그들은 동시에 경쟁사보다 제품을 빠르게 시장에 출시하기를 원했다. 품질이 좋지 않다면 고객에게 선택받지 못할 것이고, 그렇다고 시간을 너무 많이 쓰면 경쟁사가 비슷한 아이디어의 서비스를 먼저 출시하여 선수를 빼앗기게 될 지도 모른다. 즉, 소프트웨어의 품질과 개발 속도라는 두 가지의 기술적 특성이 서로 충돌하는 ‘기술적 모순’의 일종이라고 볼 수 있는 것이다. 페이스북은 이러한 모순을 해결하기 위한 해법의 핵심 요소로 코드의 ‘예측 가능성’을 제시했다.

발표의 시작을 연 Tom Occhino(@tomocchino)는 예측 불가능한 대규모 코드베이스 위에서 새로운 작업자가 실제로 의미있는 작업을 진행할 수 있게 되는 데에는 굉장히 많은 시간이 소요되었다고 했다. 무슨 일이 벌어질 지 예상할 수 없기 때문에, 코드를 변경하는 것이 굉장히 두렵다는 것이다. 만약 코드의 예측 가능성을 높일 수 있다면, 작업 시 일어날 변경 사항을 쉽게 알 수 있게 되어 코드 변경을 더 ‘자신있게’ 할 수 있을 것이며, 결과적으로 생산적인 작업을 수행하게 되기까지의 시간은 짧아질 것이다. 높은 소프트웨어 품질 + 빠른 개발 속도라는 기술적 모순을, 단순히 코드를 좀 더 예측 가능하게 구조화하는 것만으로 해결할 수 있다는 말이다. “Hacker Way”에서는 이러한 ‘예측 가능성’을 높이는 방안 중 하나로 선언적 사용자 인터페이스 라이브러리인 React를 제시하였다.

선언적 컴포넌트

React를 공개했던 첫 발표 당시, 다른 기술들과의 차별점으로 가장 먼저 제시된 점이 바로 ‘선언적’이라는 속성이었다. 사용자 인터페이스 개발에 있어 기존의 명령형 접근은 큰 문제점을 안고 있었다. 상술한 발표의 발표자 중 한 명인 Pete Hunt(@floydophone)가 이 우주에서 가장 어려운 문제이며 ‘만악의 근원’이라고도 주장한 바 있는, 시간에 따라 바뀌는 데이터가 바로 그것이다.

Pete Hunt는 UI의 초기 상태와 일련의 사건을 차례로 빠르게 보여주며, 해당 사건들이 발생한 후 UI의 상태를 예측할 수 있는지 묻는다(해당 장면을 꼭 보고 오자). 물론 머리 좋은 사람들에게 이 정도는 가능할지도 모르지만, 사건의 개수가 늘어나고 UI가 표시해야 하는 정보의 개수가 많아진다면 어떨까? 그는 시간에 따라 순차적으로 이루어지는 작업의 결과는 추론하기 매우 어렵다고 말하며, 전산학의 고전 논문 중 하나로도 뽑히는 Edsger W. Dijkstra의 ”Go To Statement Considered Harmful”의 일부를 인용하여 자신의 주장에 대한 근거를 제시하였다.

명령형으로 바라본 UI는 ‘유한하고 순차적인 변화(Mutation) 사건 집합’이 실행된 결과로 생각할 수 있다. 문제는 위에서도 확인했듯, 순차적 변화의 결과는 인간이 추론하기 어려운 문제라는 사실이다. 선언형으로 바라본 UI는 임의의 시점에 주어질 수 있는 일관된 형식의 데이터를 제공하여, 특정 상황에 UI가 어떠한 상태일지 추론할 수 있는 ‘예측 가능성’을 높여준다. 웹 프론트엔드 뿐만 아니라 모바일 세상에서도 Jetpack Compose(2021년 7월), SwiftUI(2019년 6월) 등 선언형 UI가 등장하여 인기를 얻고 있는 것을 보면 적어도 UI에 있어서는 선언형이 올바른 길이 맞구나 하는 확신이 든다.

물론 React가 UI 개발에 있어 처음으로 선언적 접근을 한 것은 아니다. 멀리 갈 것도 없이 웹 프론트엔드 세상에서 먼저 선언적 접근을 시도해 인기를 얻었던 예시로 AngularJS가 존재한다. 그러나 타 기술에 비해 React가 많은 이들의 이목을 끌며 결국은 현 시점에서 제일 많은 사용자 수를 확보하고, 타 프레임워크/라이브러리에 큰 영향을 끼칠 수 있게 된 데에는 가장 근본적인 개념이자 도구인 ‘React 컴포넌트’ 이야기를 빼놓을 수 없을 것이다.

UI 개발의 기본 ‘구성 요소’(Component)

React가 처음 세상에 공개된 후, 프론트엔드 세상은 의심의 눈초리로 React의 개발자들을 바라보았다. Facebook에서는 이렇게 합니다! 라며 자신있게 공개한 방식이 기존과는 사뭇 달랐기 때문이었다. 사실 이 표현은 당시의 실제 반응에 비해 꽤 관대하다고 볼 수 있다. 많은 사람들이 페이스북의 엔지니어들이 틀렸다고 말하며 React를 비판하였다. 이에 있어 가장 큰 점유율을 차지하고 있던 주제는 바로 JSX의 첫인상이였다(심지어 JSX는 필수가 아니었음에도!).

관심사 분리는 전산학에 있어 기초가 되는 설계 원칙이다. React 이전의 웹 프론트엔드는 애플리케이션의 구조를 정의하는 마크업, 시각적 외형을 정의하는 스타일, 동작을 제어하는 코드의 3가지 관심사를 각각 별도의 파일로 분리하여 구조화하는 것이 Best Practice로 받아들여지고 있었다. 이는 어디선가 갑자기 튀어나온 것이 아니라, 수십 년 동안 세상을 지배하던 3계층 아키텍처에 그 근본이 있다. 이러한 관점에서 보자면, React의 첫 공개 발표 자료의 코드는 애플리케이션의 구조 정의와 동작 제어라는 두 가지의 관심사를 섞어버린, 말도 안 되는 퇴보였다. Tom Occhino는 “우리가 해결하려는 문제가 무엇인지 제대로 말하지도 않았고, 우리가 처한 문제를 왜 이렇게 풀었는지도, 설계 원칙도 없이 ‘쨘’하고 JS에 XML을 섞은 코드를 보여줬다”며 씁쓸하게 당시 발표를 회상한 바 있다.

Svelte의 개발자인 Rich Harris(@Rich_Harris)는 ”프레임워크는 코드가 아닌, 사용자의 사고방식을 관리하는 도구이다”라는 말을 남긴 바 있다. 해당 문맥에서 이 말이 시사하는 바는 ‘프레임워크가 강제하는 구조의 코드가 최종 사용자에게까지 전달될 필요는 없다’이지만, 문맥을 제외하고 있는 그대로만 생각해본다면 ‘프레임워크는 사용자를 일정한 방향으로만 사고하도록 만든다’는 의미로도 해석할 수 있다. 어떠한 문제가 주어졌을 때, 한 가지의 방법만으로 비슷한 문제를 풀어오던 사람은 다른 해결책을 찾을 가능성이 그렇지 않은 사람보다 낮을 것이다.

프레임워크란, 특정 문제에 대해 먼저 고민해본 사람들이 내놓은 일종의 가이드라인과도 같다. 해당 문제를 해결하기 위해 미리 관심사를 분리해놓았기 때문에, 프레임워크 사용자들은 자신의 제품에 알맞게 적절한 로직을 제공하기만 하면 되는 것이다. 그러나 풀고자 하는 문제가 추상적이면 추상적일수록, 특정한 설계 방향성을 가지고 미리 분리된 관심사는 프레임워크 사용자들의 요구사항을 만족하지 못하게 된다. Pete Hunt는 이러한 현상을 ‘프레임워크는 사용자(즉, 당신)를 위해 관심사를 분리하는 방법을 알 수 없다’는 문장으로 표현한다. 조금 더 페이스북의 입장에 서서 말하자면, 기존처럼 웹 애플리케이션 개발의 관심사가 마크업/스타일/동작 제어로 분리되는 것은 진정한 관심사의 분리가 아니라, 기술의 분리일 뿐이다1. 그렇기에 프레임워크는 사용자가 직접 관심사를 분리할 수 있도록 해주는 ‘도구’를 제공하기만 하면 된다. React가 그러한 도구로 제시한 것이 바로 ‘React 컴포넌트’이다(JSX는 단순히 React 컴포넌트를 보기 편하게 만들어주는 요소이기 때문에, 디자이너와의 협업이 쉬워진다는 것 외에는 크게 의미가 없다고 본다).

React 컴포넌트의 본질은 함수라고 볼 수 있다. 이는 컴포넌트의 외형(클래스/함수)와는 상관이 없으며, 그보다는 수학의 대응 관계를 의미한다. 컴포넌트는 props를 입력으로 하고, element를 출력으로 하는 함수로 해석할 수 있는데, 그냥 함수가 아닌 멱등함수이다. 멱등성은 단번에 이해하기는 힘든 개념이기 때문에, 새로운 공식 문서에서는 단순히 함수의 순수성에 대해서만 설명하고 있다. 컴포넌트의 순수함과 멱등성에 대한 관계성은 React의 개발자 중 한 명인 Sebastian Markbåge(@sebmarkbage)가 작성한 The Rules of React에 자세히 설명되어 있다(먼저 말한 바 있듯, 이러한 특성은 컴포넌트의 형태가 클래스든 함수이든 똑같이 적용된다).

React 컴포넌트가 이러한 형태와 속성을 가지고 있는 것은 결국, 이 글의 초반부에서 이야기했던 ‘예측 가능성’을 높이기 위함이다. React 컴포넌트는 순수 함수이기 때문에, 같은 입력에 대해 항상 같은 출력을 보장한다. 코드의 실행 결과가 달라졌다면 데이터가 어디에선가 달라졌다는 것으로 이해할 수 있다. 또한 React 컴포넌트는 멱등함수이기 때문에, 여러 번 호출되어도 그 결과가 달라지지 않는다. 같은 코드를 여러 번 실행했는데 결과가 다르게 나온다면 그것은 React가 아닌 코드베이스 내 다른 부분에 문제가 있음을 의미한다. 이렇게, React컴포넌트에는 UI 개발에서 발생할 수 있는 오류의 원인을 추론하기 쉽게 하기 위해 많은 개념들이 녹아있음을 알 수 있다. 이러한 컴포넌트식 접근 방식은 좋든 싫든 이후의 기술들에 크게 영향을 미치게 되어, 2023년 현 시점에 있어서는 VueAngular 등의 성숙한 기술들은 물론 새로이 개발되는 웹 프론트엔드 기술들(예를 들자면 Solid, Svelte, Qwik 등)에 빠질 수 없는 개념이 되었다.

정리

React는 페이스북이 사용자 인터페이스 개발이라는 문제를 ‘높은 예측 가능성’이라는 중심 가치를 통해 해결한 결과물이다. React는 선언형 UI를 통해, 원래라면 개발자가 일일이 수동으로 관리해야했던 DOM 조작에 대한 책임을 덜어주었다. 또한 기존 Best Practice에 안주하지 않고 사용자가 직접 관심사를 분리할 수 있는 자유도를 주었다.

이 글에서 React가 가지고 있는 가치를 전부 다 설명한 것은 아니다. 몇 가지는 2023년 지금에도 충분히 논쟁거리가 될 수 있는 것이다. 예시 중 하나로 MVC 패턴과 양방향 데이터 바인딩의 복잡성을 들 수 있다. 페이스북이 자신들의 단방향 데이터 바인딩을 이야기하며 말했던 양방향 데이터 바인딩은 정말 그렇게 복잡해질 수밖에 없는 것인가? 양쪽 다를 충분히 경험해보지 못한 나로써는 결론짓기 힘든 질문이다. 이 부분은 함부로 재단할 수 없기 때문에 앞으로도 다루지 않을 예정이다.

또 몇 가지는 추상적인 레벨에서 짚고 가기에는 설명이 부족한 면이 있다. 예를 들어 “Just re-render everything”이라는 단순명쾌한 멘탈 모델은 일견 비효율적으로 보일 수밖에 없다. React가 처음 공개되었던 발표에서도 발표자들은 해당 문제를 짚고 넘어간 바가 있다. 이는 Virtual DOM을 알지 못하고서는 납득하기 힘든 부분이며, 구체적인 내부 설명 없이는 그저 겉핥기밖에 되지 않을 것이다. 이러한 부분들은 각각에 대해 별도로 시간을 할애하여 글을 쓸 예정이다.

Footnotes

  1. 사실 이 부분은 개인적으로 페이스북이 100% 맞다고 생각하지는 않고, 그저 우리가 문제를 대하는 관점이 하나 더 늘어난 것뿐이라고 생각한다. ’은총알은 없다’는 말이 있는 만큼, 공학은 단 하나의 접근이 모든 문제를 해결하는 가장 올바른 방식인 분야가 아니기 때문에 당면한 문제를 해결하는 데에 있어 더 효과적인 접근 방식을 취하는 것이 효율적일 것이다.