Search
💡

제5장: Facebook의 비밀 무기와 세상이 싫어한 라이브러리 (2009-2013)

프롤로그: 2009년, Facebook이 너무 느리다

2009년, Facebook의 엔지니어들은 잠을 설쳤을 겁니다.[100]
사이트가 끔찍하게 느렸거든요. 사용자가 Facebook 홈페이지를 열면 12초를 기다려야 했어요. 스마트폰 시대가 시작되던 시절, 이건 용납할 수 없었습니다.[91,100]
문제는 명백했습니다. 전통적인 서버 렌더링 방식:[91]
사용자가 페이지 요청 → 서버가 데이터베이스에서 모든 데이터를 가져옴 (느림) → PHP가 HTML 전체를 생성 (느림) → 네트워크로 전송 (느림) → 브라우저가 파싱하고 렌더링 (느림)
Plain Text
복사
모든 게 순차적이었어요. 한 단계가 완전히 끝나야 다음 단계가 시작됐습니다.[91]
Facebook은 목표를 세웠습니다: "6개월 안에 Facebook을 2배 빠르게 만들자."[100]
2009년 6월부터 시작. 목표 달성 기한은 2009년 말.

1막: Marcel Laverdet의 미친 생각 (2009-2010)

PHP의 지옥

Facebook 엔지니어 Marcel Laverdet는 매일 PHP 코드를 봤습니다.[81] 그리고 매일 한숨을 쉬었어요.
<?php // 2009년 Facebook 코드베이스의 전형 if ($user_name) { echo '<div class="welcome">'; echo 'Hello, '.htmlspecialchars($user_name); echo '</div>'; } else { echo '<form method="post">'; echo '<input type="text" name="username" />'; echo '<input type="submit" value="Login" />'; echo '</form>'; } ?>
PHP
복사
Laverdet는 이 코드를 보며 속이 뒤틀렸을 겁니다.
무엇이 문제였을까요? 모든 게 문제였어요.[81]
먼저, 보안. htmlspecialchars를 꼭 써야 합니다. 안 그러면? XSS(Cross-Site Scripting) 공격에 당해요. 해커가 악성 스크립트를 주입할 수 있습니다.
하지만 개발자가 깜빡하면? 끝입니다. 보안 구멍.[81]
그리고 가독성. PHP 태그(<?php, ?>)와 HTML이 뒤죽박죽. 어디서 무엇이 시작되고 끝나는지 눈으로 쫓기 힘들어요. 태그를 제대로 닫았는지도 모릅니다.[81]
게다가 재사용. Like 버튼을 100번 만들어야 한다면? 100번 똑같은 HTML을 복붙해야 했습니다.
Laverdet는 밤새 생각했을 겁니다. "더 나은 방법이 있을 텐데..."

번뜩임

어느 날, Laverdet는 생각했습니다:[81]
"HTML을 PHP 안에... 그냥 넣으면 안 될까? 문자열이 아니라, 언어의 일부로?"
말이 안 되는 소리 같았어요. PHP는 PHP고, HTML은 HTML이잖아요?
하지만 선례는 있었습니다. ECMAScript for XML (E4X). JavaScript에 XML을 넣으려던 시도. 실패하긴 했지만, 개념 자체는 흥미로웠어요.[81,82]
Laverdet는 실험을 시작했습니다. PHP의 파서를 확장하는 거예요. PHP가 HTML을 "이해"하게 만드는 겁니다.
몇 달의 작업 끝에, 프로토타입이 나왔습니다.
XHP (eXtensible HyperText Preprocessor).[81]
<?php // XHP로 작성한 코드 if ($user_name) { echo <div class="welcome">Hello, {$user_name}</div>; } else { echo <form method="post"> <input type="text" name="username" /> <input type="submit" value="Login" /> </form>; } ?>
PHP
복사
보이시나요? 따옴표가 없어요. echo "..." 아니라 echo <div>...</div>
HTML이 PHP 표현식이 된 겁니다![81]

마법 같은 일들

XHP가 가져온 변화는 놀라웠습니다.
자동 이스케이핑. {$user_name}는 자동으로 안전하게 처리됩니다.[81,88] XSS 공격? 불가능. 개발자가 신경 쓸 필요 없어요.
컴파일 타임 검증. <div> 태그를 </span>으로 닫으려고 하면? PHP가 컴파일을 거부합니다.[81,88] 문법 에러. 실행도 안 돼요.
<?php // 이건 에러! echo <div>Hello</span>; // ← PHP가 컴파일 거부 ?>
PHP
복사
그리고 가장 혁명적인 것: 커스텀 컴포넌트.[81,87]
<?php class :fb:like-button extends :x:element { protected function render() { $url = $this->getAttribute('url'); return <div class="like-button"> <a href={$url}> <img src="thumbs-up.png" /> Like this! </a> </div>; } } // 이제 어디서든 이렇게 쓸 수 있습니다 echo <fb:like-button url="http://facebook.com/post/123" />; ?>
PHP
복사
한번 정의하면, <fb:like-button />을 마치 HTML 태그처럼 쓸 수 있어요. 재사용 가능한 UI 컴포넌트. 2010년에.[82]

2010년 2월 9일, 대담한 공개

Laverdet는 Facebook Engineering 블로그에 글을 올렸습니다:[81]
"XHP: A New Way to Write PHP"
그는 조심스럽게 설명했어요. 이게 얼마나 이상하게 보일지 알고 있었거든요.
"XHP는 PHP의 문법을 확장합니다. PHP가 XML 문서 조각을 이해하게 만들어요..."
반응은 즉각적이었습니다.
PHP 창시자 Rasmus Lerdorf가 댓글을 달았습니다:[86]
"흥미롭군요. PHP가 이제 출력할 XML을 이해하니까, 컨텍스트에 맞는 필터링을 할 수 있겠네요."
기술적 찬사였습니다.
하지만 걱정도 있었어요. 초기 벤치마크에서 XHP는 75% 느렸거든요.[86] 오버헤드가 컸습니다.
Laverdet는 자신감 있게 답했습니다:[81,83]
"Facebook Lite는 전부 XHP로 만들어졌습니다. 더 빠른 웹사이트를 만들 수 있었어요."
XHP는 Facebook 내부에서 빠르게 퍼졌습니다. 2020년까지, Facebook 앱의 거의 모든 서버 사이드 HTML이 XHP로 만들어졌어요.[82]

2막: Changhao Jiang과 파이프라인의 꿈 (2009-2010)

하지만 XHP만으로는 충분하지 않았습니다. Facebook은 여전히 느렸어요.

병목의 발견

Facebook Research Scientist Changhao Jiang.[91] 그는 컴퓨터 구조(Computer Architecture)를 공부한 사람이었어요. CPU 파이프라인, 병렬 처리, 그런 것들.
Jiang은 Facebook 홈페이지 로딩을 분석하고 있었습니다. 그리고 문제를 발견했어요:[91]
1. 서버: 뉴스피드 데이터 조회 (5초) → 기다림 2. 서버: 친구 목록 조회 (3초) → 기다림 3. 서버: 광고 조회 (2초) → 기다림 4. 서버: HTML 생성 (1초) 5. 네트워크: 전송 (2초) 6. 브라우저: 파싱, 렌더링 (2초) 총: 15초
Plain Text
복사
모든 게 순차적이었어요.[91] 뉴스피드가 끝나야 친구 목록 시작. 친구 목록이 끝나야 광고 시작.
왜? 왜 순차적이어야 하죠?
Jiang은 생각했습니다:
"CPU는 명령어를 파이프라인으로 처리하잖아? 여러 명령어를 동시에, 다른 단계에서. 웹페이지도 그렇게 할 수 있지 않을까?"

파이프라인의 비전

CPU 파이프라인은 이렇게 작동합니다:
명령어 1: [Fetch] [Decode] [Execute] [Write] 명령어 2: [Fetch] [Decode] [Execute] [Write] 명령어 3: [Fetch] [Decode] [Execute] [Write]
Plain Text
복사
동시에! 병렬로!
Jiang은 웹페이지도 그렇게 할 수 있다고 봤습니다:[91]
뉴스피드: [서버 조회] [HTML 생성] [전송] [렌더링] 친구 목록: [서버 조회] [HTML 생성] [전송] [렌더링] 광고: [서버 조회] [HTML 생성] [전송] [렌더링]
Plain Text
복사
Jiang은 이걸 BigPipe라고 불렀습니다.[91] 큰 파이프. 데이터가 쉼 없이 흐르는.

Pagelet - 작은 조각들

Jiang은 웹페이지를 쪼갰습니다. 작은 독립적인 조각들로.[91]
Facebook 홈페이지를 보세요:
왼쪽 네비게이션
상단 헤더
뉴스피드
오른쪽 광고
채팅 창
각각을 **"Pagelet"**이라고 불렀습니다.[91,94] 작은 페이지 조각.
핵심: 각 Pagelet은 독립적입니다. 뉴스피드가 준비되기를 기다릴 필요 없이, 네비게이션을 먼저 보낼 수 있어요.

BigPipe의 마법

작동 방식은 이랬습니다:[91,94]
사용자가 Facebook에 접속합니다.
단계 1: 서버가 즉시 응답합니다. 하지만 빈 껍데기만:
<html> <head> <script src="bigpipe.js"></script> </head> <body> <div id="left_column"> <div id="pagelet_navigation"></div> </div> <div id="middle_column"> <div id="pagelet_newsfeed"></div> </div> <div id="right_column"> <div id="pagelet_ads"></div> </div> <!-- </html>을 닫지 않습니다! -->
HTML
복사
사용자는 즉시 페이지 구조를 봅니다! 빈 칸들이지만, 최소한 뭔가 보여요.
단계 2: 서버는 연결을 유지한 채, Pagelet들을 준비하는 대로 스트리밍합니다:
<script> bigpipe.onPageletArrive({ "id": "pagelet_navigation", "content": "<ul><li>Home</li><li>Profile</li></ul>" }); </script>
HTML
복사
네비게이션이 도착! 브라우저가 즉시 렌더링합니다. 사용자는 네비게이션을 봅니다.
<script> bigpipe.onPageletArrive({ "id": "pagelet_ads", "content": "<div>광고...</div>" }); </script>
HTML
복사
광고가 도착! 오른쪽에 나타납니다.
<script> bigpipe.onPageletArrive({ "id": "pagelet_newsfeed", "content": "<div>친구 소식들...</div>" }); </script> </body> </html> <!-- 이제 닫습니다 -->
HTML
복사
뉴스피드가 마지막에 도착. 완성!
사용자는 기다리는 동안 이미 네비게이션과 광고를 보고 있었어요. 빈 화면이 아니었습니다.

2010년 6월 4일, Velocity 컨퍼런스

Changhao Jiang이 무대에 올랐습니다.[91,96]
발표 제목: "BigPipe: Pipelining Web Pages for High Performance"
그는 벤치마크를 보여줬습니다:[91,94]
Chrome: 2000ms → 1000ms (50% 개선) Safari: 2500ms → 1200ms (52% 개선) IE 8: 2500ms → 1200ms (52% 개선)
청중은 숨을 죽였습니다. 모든 브라우저에서 체감 속도가 절반으로.
Firefox만 예외였어요. 2500ms → 2450ms. 겨우 50ms 개선.[91] 왜? Firefox 3.6의 JavaScript 엔진 문제였습니다. 하지만 그것도 22% 개선이었으니, 나쁘지 않았어요.

승리의 선언

2009년 6월에 시작한 프로젝트. 목표: 2009년 말까지 Facebook을 2배 빠르게.
2009년 12월 22일. Facebook 엔지니어들이 측정했습니다.[100]
목표 달성.
심지어 9일이나 여유 있게.
XHP로 코드가 깔끔해졌고, BigPipe로 페이지가 빨라졌습니다. Facebook은 성공했어요.

3막: Jordan Walke와 광고의 악몽 (2011)

2011년, Facebook의 다른 문제가 터졌습니다.

Ads 대시보드의 지옥

Facebook Ads. 광고주들이 광고를 관리하는 대시보드.[72,74]
엄청나게 복잡했어요. 예산 설정, 타겟팅, A/B 테스트, 실시간 통계... 수백 개의 UI 요소가 서로 연동되었습니다.
jQuery로 만들어져 있었는데... 유지보수가 불가능했습니다.[72,74,80]
코드를 상상해보세요:
// 예산을 바꾸면... $('#budget').on('change', function() { var budget = $(this).val(); // 일일 예산 업데이트 $('#daily-budget').text(budget / 30); // 경고 표시/숨김 if (budget > 1000) { $('#warning').show(); } else { $('#warning').hide(); } // 최적화 버튼 활성화/비활성화 if (budget > 1000 && targetAudienceSize > 100000) { $('#optimize-button').removeClass('disabled'); } else { $('#optimize-button').addClass('disabled'); } // 그래프 업데이트 updateChart(budget); // 추천 업데이트 if (budget > 5000) { showPremiumRecommendations(); } // 100줄 더... }); // 그런데 타겟 설정을 바꾸면... $('#target-audience').on('change', function() { // 위의 로직을 또 반복... // 예산도 확인해야 하고... // 복붙 복붙 복붙... });
JavaScript
복사
상태가 모든 곳에 흩어져 있었어요. 한 곳을 고치면 다른 곳이 깨졌습니다. 버그를 고치는 데 일주일씩 걸렸어요.
Jordan Walke는 이 코드를 보며 머리를 쥐어뜯었을 겁니다.[71,73]

XHP를 본 사람

Walke는 Facebook 내부에서 XHP를 알고 있었습니다.[71,73,85] PHP에서 UI 컴포넌트를 만드는 그 방식.
XHP는 선언적이었어요:
<fb:like-button url={$url} />
PHP
복사
"어떻게 렌더링하라"가 아니라 "무엇을 렌더링하라".
Walke는 생각했습니다:
"이걸 JavaScript로 할 수 있지 않을까? 클라이언트에서?"
상상해보세요:
<AdBudgetControl budget={this.state.budget} onBudgetChange={this.handleBudgetChange} />
JavaScript
복사
한 줄. 깔끔. 재사용 가능.

FaxJS의 탄생

2011년, Walke는 프로토타입을 만들기 시작했습니다.[73,74,78]
이름은 "FaxJS". (F는 Facebook, ax는... 뭐였는지는 모르겠지만)[75] 나중에 F-Bolt로 바뀌었다가, 결국 이름을 정했습니다.
핵심 아이디어는 세 가지였어요:
컴포넌트. UI를 재사용 가능한 조각으로 쪼개기.
선언적. "어떻게"가 아니라 "무엇을" 렌더링할지.
Virtual DOM. DOM을 직접 조작하지 않고, 가상의 표현을 만들어서 React가 알아서 최적화.
그리고... XHP처럼, HTML을 JavaScript 안에 넣었습니다:[85]
var AdBudget = { render: function() { return <div>예산: {this.props.budget}</div>; } };
JavaScript
복사
Facebook Ads 검색 기능에 먼저 적용했습니다.[72] 작동했어요. 코드가 깔끔해졌고, 버그가 줄었습니다.
그리고 Ads 대시보드에도. 천천히, 조심스럽게, FaxJS는 Facebook 내부로 퍼져나갔습니다.[72,74]

4막: Instagram의 압박과 오픈소스의 길 (2012-2013)

2012년 4월 9일. Facebook이 Instagram을 인수했습니다.[72]
Instagram 팀은 Facebook의 새 기술들을 써보고 싶어 했어요. 특히 FaxJS.
하지만 문제가 있었습니다. FaxJS는 Facebook 코드베이스에 깊숙이 박혀있었거든요.[72] Facebook 전용 라이브러리들, 내부 도구들과 엮여있었습니다.
Instagram이 쓰려면? FaxJS를 분리해야 했어요. 독립적인 라이브러리로.
압박이 시작됐습니다. 그리고 Facebook은 결정했습니다: 오픈소스로 만들자.[72]
프로젝트 이름도 바뀌었습니다. F-Bolt → React.[75] 화학에서 "반응"이죠. 상태가 바뀌면 UI가 "반응"한다는 의미였을 겁니다.

JSX - XHP의 후계자

그리고 HTML-in-JavaScript 문법을 정식화해야 했어요.
Marcel Laverdet(XHP 창시자)가 만들었던 사이드 프로젝트가 있었습니다. js-xml-literal.[85] JavaScript에 XML을 넣는 실험.
Jordan Walke가 그걸 포크했습니다. 이름을 따서 JSX라고 불렀어요.[85] JavaScript XML.
// JSX function Welcome(props) { return <h1>Hello, {props.name}</h1>; } // 컴파일되면 이렇게 변환됩니다 function Welcome(props) { return React.createElement('h1', null, 'Hello, ', props.name); }
JavaScript
복사
XHP의 DNA가 JSX로 이어졌습니다. PHP → JavaScript. 서버 → 클라이언트.[85]
계보: XHP (2010) → js-xml-literal → JSX (2013).

5막: 2013년 5월 29일, 세상의 충격

JSConf US 2013. 플로리다.[72,101]
Jordan Walke가 무대에 올랐습니다. 약간 긴장했을 거예요. 이게 얼마나 이상하게 보일지 알고 있었으니까.
스크린에 코드가 나타났습니다:
var HelloMessage = React.createClass({ render: function() { return <div>Hello {this.props.name}</div>; } });
JavaScript
복사
청중은 코드를 응시했습니다. <div>가... JavaScript 안에 있었어요.
몇 초간 침묵.
그리고 웅성거림이 시작됐습니다.
"...뭐야?" "HTML을 JavaScript에 박았어?" "진심인가?"
Walke는 계속 설명했습니다. Virtual DOM, 컴포넌트, 재사용성...
하지만 청중의 절반은 이미 마음을 닫았습니다.[72,101]

분노의 폭발

컨퍼런스가 끝나고, Twitter가 폭발했습니다.[101,102]
"Facebook이 미쳤나? 10년 전으로 돌아가는 거야?" "분리된 관심사(Separation of Concerns)를 배우지 않았나?" "JSX는 웹 개발의 후퇴다!"
블로그 포스트들이 쏟아졌어요:[101]
"Why React is Wrong for the Web" "Facebook Doesn't Understand Separation of Concerns" "JSX: The Worst Idea in Web Development"
한 개발자가 나중에 회고했습니다:[102,106]
"React를 처음 봤을 때, 충격받았어요. JSX를 보고 제정신이 아니라고 생각했습니다. 'HTML이 JavaScript 안에? Facebook이 커뮤니티에서 아무것도 배우지 못했나?' 제 못생긴 아기를 남들에게 보여주는 기분이었어요."
분리된 관심사. 이게 10년 넘게 웹 개발의 황금률이었거든요:[102,106]
HTML 파일: 구조
CSS 파일: 스타일
JavaScript 파일: 동작
각각 분리. 섞지 않기. 이게 "깨끗한 코드"였습니다.
React는? 전부 섞었어요. HTML도 JavaScript에, 나중에는 CSS까지(CSS-in-JS).
커뮤니티는 배신감을 느꼈습니다.

잘못된 청중

React 팀은 나중에 실수를 깨달았습니다.[72]
JSConf에 온 사람들은 얼리 어답터들이었어요. 이미 Backbone, Angular를 쓰고 있는 사람들. 검증된 기술을 원하는 사람들.
하지만 React는? 혁신가를 위한 거였습니다. 파격적인 아이디어를 받아들일 준비가 된 사람들.[72]
잘못된 방에서 발표한 거였죠.

6막: Pete Hunt의 설득 (2013 가을)

React 팀은 전략을 바꿨습니다.[72]
순회 설득 투어를 시작했어요. "React Tour". 회의론자들을 지지자로 만들기 위한.

JSConfEU, 2013년 9월

Berlin. JSConfEU.[72]
Facebook 엔지니어 Pete Hunt가 무대에 섰습니다.
발표 제목: "Rethinking Best Practices" (모범 사례를 다시 생각하기)
Hunt는 정면 돌파를 택했습니다. 도망치지 않았어요.
그는 말했습니다:
"여러분, '분리된 관심사'의 진짜 의미가 뭔지 아시나요?"
청중이 조용해졌습니다.
"HTML 파일 하나, CSS 파일 하나, JavaScript 파일 하나. 이게 관심사 분리인가요?"
"아닙니다. 이건 그냥 파일 분리일 뿐입니다."
"진짜 관심사 분리는 기능 단위여야 합니다. 버튼 컴포넌트는 버튼의 구조(HTML), 스타일(CSS), 동작(JavaScript)을 모두 포함해야 해요. 한 곳에서."
그는 코드를 보여줬습니다:
var LikeButton = React.createClass({ getInitialState: function() { return {liked: false}; }, handleClick: function() { this.setState({liked: !this.state.liked}); }, render: function() { var text = this.state.liked ? 'Unlike' : 'Like'; return ( <button className="like-button" onClick={this.handleClick}> {text} </button> ); } });
JavaScript
복사
"보세요. 한 컴포넌트. 한 파일. 버튼의 모든 것. 이게 진짜 관심사 분리입니다."
"Angular, Ember는 'JavaScript를 HTML에' 넣었어요. React는 'HTML을 JavaScript에' 넣은 겁니다. 뭐가 더 논리적일까요?"
청중 일부는 고개를 끄덕이기 시작했습니다.

David Nolen의 증언

2013년 12월, 뜻밖의 지원군이 나타났습니다.[72]
Clojure 커뮤니티의 David Nolen. 그는 Om이라는 라이브러리를 만들었어요. React 위에 만들어진 ClojureScript 래퍼.
Nolen은 블로그에 글을 썼습니다:
"React가 왜 Angular, Backbone, Ember보다 나은지 설명하겠습니다."
벤치마크를 보여줬어요. React + ClojureScript가 다른 프레임워크들보다 훨씬 빨랐습니다.[72]
숫자는 거짓말을 하지 않았습니다.
얼리 어답터들이 드디어 귀를 기울이기 시작했습니다.

7막: 라이센스 폭탄 (2013-2017)

하지만 React에는 또 다른 시한폭탄이 있었습니다.

BSD + Patents

React의 라이센스: BSD + Patents.[101]
BSD는 관대한 오픈소스 라이센스예요. 하지만 Facebook이 특허 조항을 추가했습니다:
"React를 사용하는 동안 Facebook을 특허로 고소하면, React 사용권을 즉시 잃습니다."
일반 회사들은 괜찮았어요. Facebook과 특허 분쟁? 없을 일이었으니까.
하지만 Facebook과 경쟁하는 회사들은?
공포에 떨었습니다.[101]
스타트업이 React로 앱을 만들었어요. 잘 되어서 성장했습니다. 그런데 Facebook이 그 스타트업의 아이디어를 베낀다면? 스타트업이 특허로 대응하려 하면?
React를 더 이상 쓸 수 없게 됩니다. 전체 앱을 재작성해야 해요.

WordPress의 반란

2017년, WordPress가 선언했습니다:[101]
"Gutenberg 에디터에서 React를 제거하겠습니다."
Gutenberg는 WordPress의 새 에디터였어요. React로 만들어지고 있었습니다. 하지만 라이센스 위험 때문에 포기하기로 한 거죠.
WordPress. 인터넷의 40%를 차지하는 플랫폼. React를 버린다고.
커뮤니티는 분노했습니다. 오픈소스 프로젝트들이 React 사용을 재고하기 시작했어요.

2017년 9월, Facebook의 항복

압박이 너무 컸습니다.
2017년 9월, Facebook은 발표했습니다:[101]
"React, Jest, Flow, Immutable.js의 라이센스를 MIT로 변경합니다."
MIT. 가장 관대한 오픈소스 라이센스. 특허 조항 없음.
커뮤니티는 안도의 한숨을 쉬었습니다.
드디어, 법적 장벽이 사라졌습니다.

에필로그: 천천히, 그러나 확실하게

2018년, 모두가 인정했습니다:[101]
"React가 웹 개발을 영원히 바꿔놨다."
2013년 JSConf의 그 분노는 어디 갔을까요?
사라졌습니다. React는 이겼어요.
Virtual DOM으로 성능 문제를 해결했고,[101] 컴포넌트로 코드를 깔끔하게 만들었고,[101] 2015년 React Native로 모바일까지 정복했습니다.[101]
그리고 2016년, Next.js가 나오면서 서버 렌더링도 쉬워졌습니다.[101]
Facebook은 포기하지 않았어요. 계속 개선했습니다. 커뮤니티는 성장했고, 생태계는 폭발했습니다.
하지만 이야기는 끝나지 않았습니다.
React의 renderToString? 여전히 블로킹이었거든요. 전체 컴포넌트 트리가 렌더링될 때까지 기다려야 했습니다.
BigPipe처럼 스트리밍? 불가능했습니다.
그리고 isomorphic의 근본적 한계? 여전했어요. 서버에서 db.query()는 못 썼습니다. 클라이언트와 공유하는 코드는 제한적이었죠.
React는 승리했지만, SSR의 여정은 아직 끝나지 않았습니다.
다음 장 예고:
2016년, 개발자들은 새로운 지옥을 경험하고 있었습니다.
webpack 설정 파일: 500줄. Babel, ESLint, Jest, Prettier, PostCSS... "이걸 다 설정해야 Hello World를 띄운다고?"
*"JavaScript Fatigue"**가 절정에 달했습니다.
그때, 어떤 회사가 나타나 말합니다:
"설정 파일? 필요 없습니다. 그냥 작동합니다. Zero config."
Next.js의 이야기가 시작됩니다.
참고 문헌 표기: [71-80] React 역사, Jordan Walke, FaxJS [81-90] XHP, Marcel Laverdet
[91-100] BigPipe, Changhao Jiang, Facebook 성능 개선 [101-110] React 초기 반응, JSX 논란, 라이센스 문제