Windows에서 실행되도록 설계된 Electron 앱 중 myapp://과 같은 프로토콜의 기본 핸들러로 등록된 앱은 이 취약점에 노출될 수 있다.
이러한 앱은 프로토콜이 어떻게 등록되었는지와 상관없이 영향을 받을 수 있다. 예를 들어 네이티브 코드를 사용하거나, Windows 레지스트리를 통해, 혹은 Electron의 app.setAsDefaultProtocolClient API를 통해 등록된 경우 모두 해당된다.
이 취약점을 해결한 새로운 버전의 Electron을 출시했다:
1.8.2-beta.5,
1.7.12,
그리고 1.6.17.
모든 Electron 개발자가 즉시 최신 안정 버전으로 앱을 업데이트할 것을 강력히 권장한다.
어떤 이유로든 Electron 버전을 업그레이드할 수 없는 경우,
app.setAsDefaultProtocolClient를 호출할 때 마지막 인자로 --를 추가하면 Chromium이 추가 옵션을 파싱하지 못하게 할 수 있다.
이중 대시 --는 커맨드 옵션의 끝을 나타내며, 이후에는 위치 매개변수만 허용된다.
Electron 앱 개발을 전 세계 개발자들이 더 쉽게 접근할 수 있도록 웹사이트의 국제화 작업을 시작했다. GitHub과 연동되는 Crowdin이라는 현지화 플랫폼을 사용하며, 콘텐츠가 다양한 언어로 번역될 때마다 자동으로 풀 리퀘스트를 생성하고 업데이트한다.
지금까지 조용히 진행해온 이 프로젝트에 75명 이상의 Electron 커뮤니티 멤버들이 자발적으로 참여했다. 웹사이트를 국제화하고 Electron 문서를 20개 이상의 언어로 번역하는 작업에 힘을 보태고 있다. 현재 프랑스어, 베트남어, 인도네시아어, 중국어 등의 언어 번역이 활발히 진행 중이며, 전 세계에서 매일 기여가 이뤄지고 있다.
현재 모든 Electron 앱은 Electron 사이트에 자체 페이지를 쉽게 가질 수 있다. 몇 가지 예제로는 Etcher, 1Clipboard, 또는 GraphQL Playground를 확인할 수 있다. 여기서는 일본어 버전의 사이트에 표시된 GraphQL Playground를 보여준다:
현존하는 Electron 앱 중에는 놀라운 것들이 많지만, 항상 쉽게 찾을 수 있는 것은 아니다. 또한 모든 개발자가 앱을 홍보하고 배포하기 위한 적절한 웹사이트를 구축할 시간과 리소스를 갖고 있지도 않다.
PNG 아이콘 파일과 약간의 앱 메타데이터만 사용하면 주어진 앱에 대한 많은 정보를 수집할 수 있다. GitHub에서 수집한 데이터를 활용해 앱 페이지는 스크린샷, 다운로드 링크, 버전, 릴리스 노트, 그리고 공개 저장소가 있는 모든 앱의 README를 표시할 수 있다. 각 앱의 아이콘에서 추출한 색상 팔레트를 사용해 대담하고 접근성이 좋은 색상을 생성함으로써 각 앱 페이지에 시각적 차별성을 부여할 수 있다.
이제 사이트를 electron.atom.io에서 새로운 도메인인 electronjs.org로 옮겼다.
Electron 프로젝트는 GitHub의 오픈소스 텍스트 에디터인 Atom에서 시작되었다. Atom은 웹 기술을 기반으로 구축된 에디터다. Electron은 원래 atom-shell이라는 이름으로 불렸다. Atom이 이 기술을 처음 사용한 앱이었지만, 이 마법 같은 Chromium과 Node 런타임이 다양한 애플리케이션에 활용될 수 있다는 사실이 금방 알려졌다. Microsoft와 Slack 같은 회사들이 atom-shell을 사용하기 시작하면서, 이 프로젝트에 새로운 이름이 필요하다는 점이 명확해졌다.
그렇게 "Electron"이 탄생했다. 2016년 초, GitHub은 Atom과 별도로 Electron 개발과 유지보수에 집중할 새로운 팀을 꾸렸다. 그 이후로 Electron은 수천 명의 앱 개발자에게 채택되었으며, 이제는 많은 대기업에서 필수적인 기술로 자리 잡았다. 이들 중 상당수는 자체 Electron 팀을 운영하고 있다.
Atom과 GitHub Desktop 같은 GitHub의 Electron 프로젝트를 지원하는 것은 여전히 우리 팀의 우선순위다. 하지만 새로운 도메인으로 이전함으로써 Atom과 Electron 사이의 기술적 차이를 더 명확히 하고자 한다.
이전의 Electron 웹사이트는 Ruby 기반의 정적 사이트 생성기인 Jekyll로 구축되었다. Jekyll은 정적 웹사이트를 만드는 데 훌륭한 도구지만, 웹사이트가 점점 더 복잡해지면서 한계를 느끼기 시작했다. 우리는 적절한 리다이렉트와 동적 콘텐츠 렌더링과 같은 더 많은 동적 기능을 원했고, Node.js 서버가 명백한 선택이었다.
Electron 생태계는 Python부터 C++, Bash까지 다양한 프로그래밍 언어로 작성된 컴포넌트를 포함하고 있다. 하지만 JavaScript는 Electron의 기반이자 커뮤니티에서 가장 많이 사용되는 언어다.
웹사이트를 Ruby에서 Node.js로 마이그레이션함으로써, 우리는 웹사이트에 기여하고자 하는 사람들의 진입 장벽을 낮추고자 한다.
여러분의 시스템에 Node.js (8 버전 이상)와 git이 설치되어 있다면, 로컬에서 사이트를 쉽게 실행할 수 있다:
git clone https://github.com/electron/electronjs.org cd electronjs.org npm install npm run dev
새로운 웹사이트는 Heroku에 호스팅된다. 우리는 배포 파이프라인과 Review Apps 기능을 사용하며, 이 기능은 모든 풀 리���스트에 대해 실행 가능한 앱 복사본을 자동으로 생성한다. 이를 통해 리뷰어가 사이트의 실제 복사본에서 풀 리���스트의 효과를 쉽게 확인할 수 있다.
electron npm 패키지에는 이제 Electron API 전체에 대한 상세한 주석을 제공하는 TypeScript 정의 파일이 포함되어 있다. 이 주석들은 순수 JavaScript를 작성하더라도 Electron 개발 경험을 향상시킬 수 있다. 프로젝트에서 최신 Electron 타입 정의를 사용하려면 npm install electron을 실행하면 된다.
TypeScript는 Microsoft가 만든 오픈소스 프로그래밍 언어다. JavaScript의 상위 집합으로, 정적 타입 지원을 추가해 언어를 확장한다. 최근 몇 년 동안 TypeScript 커뮤니티는 빠르게 성장했으며, 최근 Stack Overflow 개발자 설문조사에서 가장 사랑받는 프로그래밍 언어 중 하나로 꼽혔다. TypeScript는 "확장 가능한 JavaScript"로 불리며, GitHub, Slack, Microsoft와 같은 팀들이 수백만 명이 사용하는 확장 가능한 Electron 앱을 작성하는 데 활용하고 있다.
TypeScript는 클래스, 객체 구조 분해, async/await와 같은 JavaScript의 최신 언어 기능을 지원하지만, 진정한 차별점은 타입 주석이다. 프로그램의 입력 및 출력 데이터 타입을 선언하면 컴파일 시 오류를 찾는 데 도움을 주어 버그를 줄일 수 있으며, 주석은 프로그램의 작동 방식에 대한 공식적인 선언 역할도 한다.
라이브러리가 순수 JavaScript로 작성된 경우, 타입은 종종 문서 작성 시 부차적으로 모호하게 정의된다. 함수는 문서화된 것보다 더 많은 타입을 허용할 수 있거나, 문서화되지 않은 숨겨진 제약 조건이 있을 수 있어 런타임 오류로 이어질 수 있다.
TypeScript는 정의 파일로 이 문제를 해결한다. TypeScript 정의 파일은 라이브러리의 모든 함수와 예상되는 입력 및 출력 타입을 설명한다. 라이브러리 작성자가 배포된 라이브러리에 TypeScript 정의 파일을 포함시키면, 라이브러리 사용자는 에디터 내에서 바로 API를 탐색할 수 있으며, 종종 라이브러리 문서를 참조하지 않고도 바로 사용할 수 있다.
Angular, Vue.js, node-github (그리고 이제 Electron!)과 같은 많은 인기 프로젝트들은 자체 정의 파일을 컴파일하여 배포된 npm 패키지에 포함시킨다. 자체 정의 파일을 포함하지 않는 프로젝트의 경우, 커뮤니티에서 관리하는 정의 파일의 제3자 생태계인 DefinitelyTyped가 있다.
TypeScript는 JavaScript의 상위 집합이므로, 기존 JavaScript 코드는 이미 유효한 TypeScript 코드이다. 이는 기존 JavaScript 프로젝트를 점진적으로 TypeScript로 전환할 수 있으며, 필요에 따라 새로운 언어 기능을 추가할 수 있음을 의미한다.
"스트림" 개념을 이해하는 데 어려움을 겪었다. 처음에는 GitHub의 Notifications API를 사용하려고 했다. 하지만 이 API가 특정 사용 사례를 지원하지 않는다는 것을 알게 되었다. 그 후 Issues API와 Pull Requests API를 Notifications API와 함께 사용하는 방법을 고민했다. 하지만 원하는 결과를 얻지 못했다. 다양한 방법을 고민하던 중 GitHub의 Search API를 폴링하는 것이 가장 유연한 방법이라는 것을 깨달았다. 이 과정에 약 한 달이 걸렸고, 이후 스트림 개념을 적용한 Jasper 프로토타입을 이틀 만에 구현했다.
참고: 폴링은 최대 10초에 한 번으로 제한된다. GitHub API의 제한 사항을 고려할 때 이는 충분히 허용 가능한 수준이다.
초기에는 BitTorrent가 TCP를 전송 프로토콜로 사용했다. 이후 uTP가 등장하면서 TCP보다 더 나은 성능과 추가적인 장점을 제공했다. 모든 주요 토렌트 클라이언트는 결국 uTP를 채택했고, 현재는 두 프로토콜 모두를 사용할 수 있다. WebRTC 프로토콜은 논리적인 다음 단계다. 이 프로토콜은 웹 브라우저와의 상호 운용성을 제공하며, 모든 데스크톱 BitTorrent 클라이언트와 수백만 개의 웹 브라우저로 구성된 거대한 P2P 네트워크를 가능하게 한다.
"웹 피어"(웹 브라우저에서 실행되는 토렌트 피어)는 수백만 개의 새로운 피어를 추가함으로써 BitTorrent 네트워크를 더 강력하게 만들고, BitTorrent를 다양한 새로운 사용 사례로 확장한다. WebTorrent는 기존 BitTorrent 클라이언트가 WebTorrent를 쉽게 지원할 수 있도록 BitTorrent 사양을 최대한 따르도록 설계했다.
Vuze와 같은 일부 토렌트 앱은 이미 웹 피어를 지원하지만, 나머지 클라이언트가 이를 지원할 때까지 기다리고 싶지 않았다. 즉, WebTorrent Desktop은 WebTorrent 프로토콜의 채택 속도를 높이기 위한 우리의 방법이었다. 사람들이 정말로 사용하고 싶어 하는 훌륭한 토렌트 앱을 만들어 웹 피어(웹사이트 사용자)와 토렌트를 공유할 수 있는 네트워크 내 피어의 수를 늘리는 것이 목표였다.
WebTorrent의 가장 흥미로운 활용 사례 중 하나는 피어 지원 전송(peer-assisted delivery)이다. 위키백과나 인터넷 아카이브와 같은 비영리 프로젝트는 방문자들이 함께 참여하도록 함으로써 대역폭과 호스팅 비용을 줄일 수 있다. 인기 있는 콘텐츠는 브라우저 간에 빠르고 저렴하게 전송할 수 있다. 드물게 접근되는 콘텐츠는 오리진 서버에서 HTTP를 통해 안정적으로 제공할 수 있다.
인터넷 아카이브는 이미 토렌트 파일을 업데이트해 WebTorrent와 잘 작동하도록 했다. 따라서 인터넷 아카이브 콘텐츠를 사이트에 임베드하려는 경우, 아카이브의 호스팅 비용을 줄이는 방식으로 구현할 수 있다. 이를 통해 아카이브는 웹 아카이빙에 더 많은 자원을 투자할 수 있다.
WebTorrent로 만들어진 가장 멋진 프로젝트는 단연 Gaia 3D Star Map이다. 이 프로젝트는 은하수를 3D로 구현한 인터랙티브 시뮬레이션이다. 데이터는 토렌트를 통해 브라우저에서 직접 로드된다. 은하계를 날아다니며 인간이 얼마나 작은 존재인지 깨닫게 되는 경험은 정말 감동적이다.
이 프로젝트가 어떻게 만들어졌는지는 Torrenting The Galaxy라는 블로그 포스트에서 확인할 수 있다. 저자 Charlie Hoey는 WebGL과 WebTorrent를 사용해 이 별 지도를 어떻게 만들었는지 설명한다.
Brave도 매우 인상적인 프로젝트다. Brave는 광고와 트래커를 자동으로 차단해 웹을 더 빠르고 안전하게 만드는 브라우저다. 최근 Brave는 토렌트 지원을 추가해 별도의 앱 없이 전통적인 토렌트를 볼 수 있게 했다. 이 기능은 WebTorrent로 구현되었다.
대부분의 브라우저가 PDF 파일을 렌더링할 수 있는 것처럼, Brave는 마그넷 링크와 토렌트 파일을 렌더링할 수 있다. 이제 토렌트는 브라우저가 기본적으로 지원하는 또 하나의 콘텐츠 타입이 된 셈이다.
Brave의 공동 창업자 중 한 명은 JavaScript의 창시자인 Brendan Eich다. WebTorrent도 JavaScript로 작성되었기 때문에 Brave가 WebTorrent를 통합한 점이 매우 의미 있다고 생각한다.
Electron 앱은 모든 앱에 Chrome 콘텐츠 모듈을 포함하기 때문에 "부풀려졌다"는 이야기가 있다. 경우에 따라 이는 부분적으로 사실이다. Electron 앱 설치 프로그램은 보통 ~40MB인 반면, 운영체제별 앱 설치 프로그램은 보통 ~20MB 정도다.
하지만 WebTorrent Desktop의 경우, 정상적인 작동 과정에서 거의 모든 Electron 기능과 수십 가지 Chrome 기능을 사용한다. 각 플랫폼별로 이러한 기능을 처음부터 구현하려면 앱 개발에 몇 달에서 몇 년이 더 걸렸을 것이다. 아니면 단일 플랫폼에서만 출시할 수 있었을 것이다.
예를 들어, 다운로드 진행 상황을 보여주기 위해 Electron의 dock 통합, 백그라운드에서 실행하기 위한 메뉴 바 통합, 마그넷 링크를 열기 위한 프로토콜 핸들러 등록, 비디오 재생 중 절전 모드 방지를 위한 절전 모드 차단, 그리고 자동 업데이터를 사용한다. Chrome 기능도 많이 사용한다: 다양한 비디오 형식을 재생하기 위한 <video> 태그, 자막 지원을 위한 <track> 태그, 드래그 앤 드롭 지원, 그리고 네이티브 앱에서 사용하기 까다로운 WebRTC 등이 있다.
또한, 우리의 토렌트 엔진은 JavaScript로 작성되었으며, 특히 TCP 및 UDP 소켓 지원을 위한 require('net')과 require('dgram')과 같은 많은 Node API의 존재를 가정한다.
기본적으로 Electron은 우리가 필요로 하는 기능을 모두 갖추고 있었고, 기록적으로 빠른 시간 안에 견고하고 세련된 앱을 출시할 수 있게 해주었다.
네, webtorrent npm 패키지는 Node.js, 브라우저, 그리고 Electron에서 동작한다. 정확히 동일한 코드가 모든 환경에서 실행될 수 있다. 이것이 바로 JavaScript의 매력이다. JavaScript는 현대의 보편적인 런타임 환경이다. Java 애플릿은 "한 번 작성하고 어디서든 실행"되는 앱을 약속했지만, 여러 가지 이유로 그 비전은 실현되지 못했다. Electron은 다른 어떤 플랫폼보다도 이 이상에 상당히 근접한 성과를 보여주고 있다.
초기 버전의 앱에서 UI 성능 문제로 고생했다. 토렌트 엔진을 메인 앱 윈도우를 그리는 렌더러 프로세스에 함께 배치했는데, 이로 인해 토렌트 엔진에서 CPU 사용량이 급증할 때마다(예: 피어로부터 받은 토렌트 조각을 검증하는 경우) 앱이 느려지는 문제가 발생했다.
이 문제를 해결하기 위해 토렌트 엔진을 두 번째, 보이지 않는 렌더러 프로세스로 이동시켰다. 그리고 IPC를 통해 이 프로세스와 통신하도록 구조를 변경했다. 이렇게 하면 해당 프로세스에서 CPU를 많이 사용하더라도 UI 스레드에 영향을 미치지 않는다. 부드러운 스크롤링과 애니메이션은 정말 만족스럽다.
참고: 토렌트 엔진을 렌더러 프로세스에 배치한 이유는 WebRTC에 접근해야 하기 때문이다. WebRTC는 렌더러 프로세스에서만 사용할 수 있다.
프로덕션 준비가 된 앱을 빌드하고 배포하는 방법에 대한 더 나은 문서화가 필요하다. 특히 코드 서명(code signing)과 자동 업데이트(auto-updating)와 같은 복잡한 주제에 대한 설명이 부족하다. 우리는 소스 코드를 뒤지고 Twitter에서 질문을 올리는 방식으로 최적의 방법을 직접 찾아야 했다.
WebTorrent Desktop는 완성되었나요? 아니라면, 다음에 어떤 기능이 추가될 예정인가요?
현재 버전의 WebTorrent Desktop은 훌륭하지만, 여전히 개선의 여지가 있다고 생각한다. 현재는 사용 편의성, 성능, 자막 지원, 그리고 비디오 코덱 지원을 개선하기 위해 노력 중이다.
WebTorrent Desktop 기여자 중 한 명인 Feross는 NodeConf Argentina에서 _"Real world Electron: JavaScript로 크로스 플랫폼 데스크톱 앱 만들기"_라는 주제로 발표했다. 이 발표는 기본적으로 동작하는 앱을 더욱 세련되고 전문적으로 다듬는 단계에 있는 개발자에게 특히 유용한 팁을 담고 있다.
Voltra는 음악을 소유하고 싶은 사람들을 위한 음악 플레이어다. 또한, 이미 소유한 음악을 기반으로 새로운 음악을 발견하고 구매할 수 있는 스토어 기능도 제공한다. 광고가 없으며 데스크톱과 모바일에서 모두 사용할 수 있는 크로스 플랫폼이다. 사용자를 추적하거나 감시하지도 않는다.
라디오는 항상 많은 청취자를 확보해 왔다. 이제 라디오는 공중파를 벗어나 인터넷으로 이동하고 있다. 주문형 음악 대여가 가능해지면서 라디오의 부활이 일어나고 있다! 이로 인해 다양한 새로운 제품과 서비스가 등장했지만, 스트리밍 라디오는 여전히 다른 사람이 음악과 그 경험을 통제한다.
우리는 사용자가 소유한 음악에 완전히 초점을 맞춘 제품을 원했다. 아티스트나 레이블로부터 직접 새 음악을 발견하고 구매할 수 있게 해주는 무언가가 필요했다.
디자인과 사용성은 우리에게 매우 중요하다. 우리는 청취자들이 방해받지 않고 음악을 즐길 수 있는 환경을 제공하고자 한다. 현재 시장에는 다양한 음악 플레이어와 스토어가 존재한다. 하지만 많은 제품들이 제작자의 의도와 달리 복잡하고 사용하기 어렵다. 우리는 Voltra를 가능한 많은 사람들이 쉽게 사용할 수 있도록 만들고자 한다.
또한, 우리는 아티스트나 레이블로부터 수수료를 받지 않는다. 이는 우리의 핵심 차별점 중 하나다. 이는 아티스트들이 자신의 음악을 시장에 내놓는 데 있어 진입 장벽을 낮추는 중요한 요소다.
Voltra를 설계하면서 네이티브 앱과 웹의 UI 관례를 고려했을 뿐만 아니라, 무엇을 제거할 수 있을지 깊이 고민했다. 지난 몇 달 동안 활발히 활동한 비공개 베타 테스트 그룹으로부터 중요한 피드백을 받았다.
앨범 아트와 사진이 사용자들에게 매우 중요하다는 사실을 발견했다. 많은 플레이어가 단순히 파일 목록으로 구성되어 있다. 물리적 앨범을 소유하는 멋진 점 중 하나는 앨범 아트이며, Voltra 데스크톱 앱에서 이를 강조하고 싶었다.
또한 사용자의 파일을 건드리지 않도록 주의했다. 파일 감시 기능을 사용해 파일을 원하는 곳에 배치할 수 있게 했고, 파일 이름을 변경하거나 이동시키지 않는다. 감시 중인 디렉터리의 상태를 추적하기 위해 내장 데이터베이스를 사용해 프로세스가 실행 중이 아닐 때도 새로운 내용을 파악할 수 있다.
성능 최적화에 많은 시간을 투자했다. 처음에는 프레임워크를 사용했지만, 결국 바닐라 자바스크립트로 전환했다. 우리의 경험에 따르면, 프레임워크가 제공하는 일반화된 추상화는 성능 저하와 추가적인 복잡성을 감수할 만한 가치가 있다.
현재는 매우 큰 컬렉션을 효율적으로 처리할 수 있다. 여기서 '큰 컬렉션'은 수만 개의 이미지를 의미한다! Node.js의 파일 시스템 모듈을 렌더링 프로세스에서 직접 사용할 수 있어, DOM 이벤트에 따라 많은 이미지를 빠르게 지연 로딩하고 언로드하는 작업이 매우 쉬워졌다.
일반적으로 setImmediate와 requestIdleCallback은 UI의 반응성을 유지하면서 많은 처리를 수행하는 데 매우 중요한 도구로 사용되었다. 특히, CPU 집약적인 작업을 별도의 프로세스로 분산시키는 것이 사용자 인터페이스의 반응성을 유지하는 데 큰 도움이 되었다. 예를 들어, 실제 오디오 컨텍스트를 별도의 프로세스로 옮기고, IPC를 통해 통신함으로써 바쁜 UI로 인한 잠재적인 중단을 피할 수 있었다.
Electron이 단일 패키저를 공식적으로 지원해 주길 바란다. 패키저는 Node에서의 패키지 관리자만큼 Electron에게도 중요하다. 현재 사용자 영역에는 여러 패키저가 존재하며, 각각 흥미로운 기능을 제공하지만 버그도 함께 존재한다. 커뮤니티의 합의는 기여자들이 쏟는 에너지를 올바른 방향으로 이끄는 데 도움을 줄 것이다.
Electron은 Google의 오픈소스 프로젝트인 Chromium을 기반으로 한다. Chromium은 원래 다른 프로젝트에서 사용하기 위해 설계된 것은 아니다. 이 글은 Chromium이 어떻게 Electron에서 사용할 수 있는 라이브러리로 구축되었는지, 그리고 빌드 시스템이 시간이 지나며 어떻게 발전해 왔는지를 소개한다.
Chromium Embedded Framework(CEF)는 Chromium을 라이브러리로 변환하고, Chromium 코드베이스를 기반으로 안정적인 API를 제공하는 프로젝트다. Atom 에디터와 NW.js의 초기 버전은 CEF를 사용했다.
안정적인 API를 유지하기 위해 CEF는 Chromium의 모든 세부 사항을 숨기고 Chromium의 API를 자체 인터페이스로 감싼다. 따라서 웹 페이지에 Node.js를 통합하는 것과 같이 Chromium의 내부 API에 접근해야 할 때, CEF의 장점이 오히려 방해 요소가 되었다.
결국 Electron과 NW.js는 Chromium API를 직접 사용하는 방식으로 전환했다.
Content Module을 사용하는 Electron은 대부분의 경우 Chromium 코드를 수정할 필요가 없다. 따라서 Electron 빌드를 개선하는 명확한 방법은 Chromium을 공유 라이브러리로 빌드한 다음, Electron에서 이를 링크하는 것이다. 이 방식은 개발자가 Electron에 기여할 때 Chromium 전체를 빌드할 필요가 없게 해준다.
이러한 목적으로 @aroben이 libchromiumcontent 프로젝트를 만들었다. 이 프로젝트는 Chromium의 Content Module을 공유 라이브러리로 빌드하고, Chromium 헤더와 사전 빌드된 바이너리를 다운로드할 수 있게 제공한다. libchromiumcontent 초기 버전의 코드는 이 링크에서 확인할 수 있다.
brightray 프로젝트도 libchromiumcontent의 일부로 탄생했으며, Content Module 주변에 얇은 레이어를 제공한다.
libchromiumcontent와 brightray를 함께 사용하면 개발자는 Chromium 빌드의 세부 사항에 깊이 들어가지 않고도 빠르게 브라우저를 빌드할 수 있다. 또한 이 방식은 프로젝트 빌드를 위해 빠른 네트워크와 강력한 머신이 필요하지 않게 해준다.
Electron 외에도 Breach browser와 같은 다른 Chromium 기반 프로젝트들도 이 방식으로 빌드되었다.
libchromiumcontent의 다음 단계를 설명하기 전에, 먼저 Chromium의 컴포넌트 빌드 개념을 소개하는 것이 중요하다.
Chromium은 거대한 프로젝트이기 때문에 빌드 시 링크 단계에서 많은 시간이 소요된다. 일반적으로 개발자가 작은 변경을 가할 때, 최종 결과물을 확인하려면 10분 이상 걸릴 수 있다. 이를 해결하기 위해 Chromium은 컴포넌트 빌드를 도입했다. 이 방식은 Chromium의 각 모듈을 별도의 공유 라이브러리로 빌드하여, 최종 링크 단계에서 소요되는 시간을 거의 없앤다.
앞서 소개한 것처럼 Chromium에는 두 가지 빌드 모드가 있다. 원시 바이너리를 배포하게 되면서, libchromiumcontent에서 두 가지 다른 바이너리 배포판을 제공해야 했다. 하나는 static_library 빌드로, Chromium의 일반 빌드에서 생성된 각 모듈의 정적 라이브러리를 모두 포함한다. 다른 하나는 shared_library 빌드로, 컴포넌트 빌드에서 생성된 각 모듈의 공유 라이브러리를 모두 포함한다.
Electron에서는 Debug 버전이 libchromiumcontent의 shared_library 버전과 링크된다. 이 버전은 다운로드 크기가 작고, 최종 실행 파일을 링크하는 데 시간이 적게 걸리기 때문이다. 반면 Release 버전은 libchromiumcontent의 static_library 버전과 링크된다. 이렇게 하면 컴파일러가 디버깅에 중요한 전체 심볼을 생성할 수 있고, 링커가 필요한 오브젝트 파일을 정확히 알고 있기 때문에 더 나은 최적화를 수행할 수 있다.
일반적인 개발 과정에서는 개발자가 Debug 버전만 빌드하면 된다. 이 버전은 네트워크나 강력한 머신이 필요하지 않다. Release 버전은 더 좋은 하드웨어가 필요하지만, 더 최적화된 바이너리를 생성할 수 있다.
세계에서 가장 큰 프로젝트 중 하나인 Chromium을 빌드하기에는 일반적인 시스템이 적합하지 않다. Chromium 팀은 자체 빌드 도구를 개발했다.
이전 버전의 Chromium은 gyp를 빌드 시스템으로 사용했지만, 속도가 느리고 복잡한 프로젝트에서는 설정 파일을 이해하기 어려웠다. 수년간의 개발 끝에 Chromium은 더 빠르고 명확한 구조를 가진 gn으로 빌드 시스템을 전환했다.
gn의 개선점 중 하나는 source_set을 도입한 것이다. source_set은 오브젝트 파일 그룹을 나타낸다. gyp에서는 각 모듈이 static_library나 shared_library로 표현되었고, Chromium의 일반적인 빌드에서 각 모듈은 정적 라이브러리를 생성한 후 최종 실행 파일에 함께 링크되었다. gn을 사용하면 이제 각 모듈이 오브젝트 파일 묶음을 생성하고, 최종 실행 파일이 모든 오브젝트 파일을 함께 링크한다. 따라서 중간 정적 라이브러리 파일은 더 이상 생성되지 않는다.
이러한 개선은 libchromiumcontent에게 큰 문제를 일으켰다. libchromiumcontent는 실제로 중간 정적 라이브러리 파일이 필요했기 때문이다.
두 번째 시도는 @alespergl이 오브젝트 파일 목록에서 커스텀 정적 라이브러리를 생성하는 방법을 제안한 것이다. 이 방법은 더미 빌드를 먼저 실행해 생성된 오브젝트 파일 목록을 수집한 후, 그 목록을 gn에 제공해 실제로 정적 라이브러리를 빌드하는 트릭을 사용했다. 이 방법은 Chromium의 소스 코드를 최소한으로 변경했고, Electron의 빌드 구조를 그대로 유지할 수 있었다.
Chromium을 일부로 포함해 Electron을 빌드하는 방식과 Chromium을 라이브러리로 빌드하는 방식을 비교해 보면, 후자가 더 많은 노력과 지속적인 유지보수를 필요로 한다. 하지만 Chromium을 라이브러리로 빌드하면 강력한 하드웨어 없이도 Electron을 빌드할 수 있어, 더 많은 개발자가 Electron을 빌드하고 기여할 수 있게 된다. 이러한 노력은 충분히 가치가 있다.