Skip to main content

Protocol Handler Vulnerability Fix

· 3 min read

Electron 앱의 커스텀 프로토콜 핸들러에서 원격 코드 실행 취약점이 발견되었다. 이 취약점은 CVE 식별자 CVE-2018-1000006로 지정되었다.

영향을 받는 플랫폼

Windows에서 실행되도록 설계된 Electron 앱 중 myapp://과 같은 프로토콜의 기본 핸들러로 등록된 앱은 이 취약점에 노출될 수 있다.

이러한 앱은 프로토콜이 어떻게 등록되었는지와 상관없이 영향을 받을 수 있다. 예를 들어 네이티브 코드를 사용하거나, Windows 레지스트리를 통해, 혹은 Electron의 app.setAsDefaultProtocolClient API를 통해 등록된 경우 모두 해당된다.

macOS와 Linux는 이 이슈에 취약하지 않다.

취약점 완화

이 취약점을 해결한 새로운 버전의 Electron을 출시했다: 1.8.2-beta.5, 1.7.12, 그리고 1.6.17. 모든 Electron 개발자가 즉시 최신 안정 버전으로 앱을 업데이트할 것을 강력히 권장한다.

어떤 이유로든 Electron 버전을 업그레이드할 수 없는 경우, app.setAsDefaultProtocolClient를 호출할 때 마지막 인자로 --를 추가하면 Chromium이 추가 옵션을 파싱하지 못하게 할 수 있다. 이중 대시 --는 커맨드 옵션의 끝을 나타내며, 이후에는 위치 매개변수만 허용된다.

app.setAsDefaultProtocolClient(protocol, process.execPath, [
'--your-switches-here',
'--',
]);

자세한 내용은 app.setAsDefaultProtocolClient API를 참고한다.

Electron 앱의 보안을 유지하는 최선의 방법에 대해 더 알고 싶다면, security tutorial을 확인한다.

Electron에서 발견한 취약점을 보고하려면 security@electronjs.org로 이메일을 보낸다.

Electron 2.0 and Beyond - Semantic Versioning

· 3 min read

Electron의 새로운 주요 버전이 개발 중이며, 버전 관리 전략에도 몇 가지 변화가 생긴다. 2.0.0 버전부터 Electron은 시맨틱 버저닝(Semantic Versioning)을 엄격히 준수할 예정이다.


이번 변경으로 주요 버전 업데이트가 더 자주 발생할 것이며, 대부분 Chromium의 주요 업데이트를 포함할 것이다. 패치 릴리스도 더 안정적으로 제공될 예정인데, 이제는 새로운 기능 없이 버그 수정만 포함되기 때문이다.

주요 버전 업데이트 사항

  • Chromium 버전 업데이트
  • Node.js 주요 버전 업데이트
  • Electron의 호환성을 깨는 API 변경

부 버전 업데이트 사항

  • Node.js 부 버전 업데이트
  • Electron의 호환성을 유지하는 API 변경

패치 버전 업데이트 사항

  • Node.js 패치 버전 업데이트
  • Chromium의 버그 수정 패치
  • Electron의 버그 수정

이제 Electron의 시맨틱 버저닝 범위가 더 명확해졌기 때문에, npm의 기본 --save-dev 플래그를 사용해 Electron을 설치할 것을 권장한다. 이렇게 하면 버전 앞에 ^가 붙어 부 버전과 패치 업데이트를 안전하게 따라갈 수 있다:

npm install --save-dev electron

버그 수정만 원하는 개발자는 물결표(~)를 사용해 ~2.0.0과 같이 버전을 지정하면 된다. 이렇게 하면 새로운 기능이 추가되지 않고 안정성을 높이는 수정만 적용된다.

더 자세한 내용은 electronjs.org/docs/tutorial/electron-versioning에서 확인할 수 있다.

Electron의 새로운 국제화 웹사이트

· 11 min read

Electron의 새로운 웹사이트가 electronjs.org로 이전했다! 기존의 정적 Jekyll 사이트를 Node.js 웹 서버로 교체하면서, 사이트를 다국어로 지원할 수 있는 유연성을 확보했고, 더 많은 흥미로운 기능을 추가할 수 있는 기반을 마련했다.

🌍 다국어 지원

Electron 앱 개발을 전 세계 개발자들이 더 쉽게 접근할 수 있도록 웹사이트의 국제화 작업을 시작했다. GitHub과 연동되는 Crowdin이라는 현지화 플랫폼을 사용하며, 콘텐츠가 다양한 언어로 번역될 때마다 자동으로 풀 리퀘스트를 생성하고 업데이트한다.

Electron Nav in Simplified Chinese

지금까지 조용히 진행해온 이 프로젝트에 75명 이상의 Electron 커뮤니티 멤버들이 자발적으로 참여했다. 웹사이트를 국제화하고 Electron 문서를 20개 이상의 언어로 번역하는 작업에 힘을 보태고 있다. 현재 프랑스어, 베트남어, 인도네시아어, 중국어 등의 언어 번역이 활발히 진행 중이며, 전 세계에서 매일 기여가 이뤄지고 있다.

원하는 언어를 선택하고 번역 진행 상황을 확인하려면 electronjs.org/languages를 방문하면 된다.

Translations in progress on Crowdin

여러 언어에 능통하고 Electron 문서 및 웹사이트 번역에 관심이 있다면 electron/electron-i18n 저장소를 방문하거나, GitHub 계정으로 로그인하여 바로 Crowdin에서 번역 작업에 참여할 수 있다.

현재 Crowdin에서 Electron 프로젝트를 위해 21개 언어가 활성화되어 있다. 더 많은 언어를 추가하는 것은 간단하므로, 번역에 관심이 있지만 원하는 언어가 목록에 없다면 알려주기만 하면 해당 언어를 활성화할 것이다.

원본 마크다운 문서 읽기

원본 마크다운 파일로 문서를 읽고 싶다면, 이제 어떤 언어로든 가능하다:

git clone https://github.com/electron/electron-i18n
ls electron-i18n/content

앱 페이지

현재 모든 Electron 앱은 Electron 사이트에 자체 페이지를 쉽게 가질 수 있다. 몇 가지 예제로는 Etcher, 1Clipboard, 또는 GraphQL Playground를 확인할 수 있다. 여기서는 일본어 버전의 사이트에 표시된 GraphQL Playground를 보여준다:

GraphQL Playground

현존하는 Electron 앱 중에는 놀라운 것들이 많지만, 항상 쉽게 찾을 수 있는 것은 아니다. 또한 모든 개발자가 앱을 홍보하고 배포하기 위한 적절한 웹사이트를 구축할 시간과 리소스를 갖고 있지도 않다.

PNG 아이콘 파일과 약간의 앱 메타데이터만 사용하면 주어진 앱에 대한 많은 정보를 수집할 수 있다. GitHub에서 수집한 데이터를 활용해 앱 페이지는 스크린샷, 다운로드 링크, 버전, 릴리스 노트, 그리고 공개 저장소가 있는 모든 앱의 README를 표시할 수 있다. 각 앱의 아이콘에서 추출한 색상 팔레트를 사용해 대담하고 접근성이 좋은 색상을 생성함으로써 각 앱 페이지에 시각적 차별성을 부여할 수 있다.

앱 인덱스 페이지는 이제 카테고리와 키워드 필터를 제공해 GraphQL GUIp2p 도구와 같은 흥미로운 앱을 찾을 수 있게 한다.

만약 여러분의 Electron 앱을 이 사이트에 소개하고 싶다면, electron/electron-apps 저장소에 풀 리퀘스트를 열어보자.

Homebrew로 한 줄로 설치하기

macOS용 패키지 관리자인 Homebrew에는 cask라는 서브커맨드가 있다. 이 명령어를 사용하면 터미널에서 단 한 줄의 명령어로 데스크톱 앱을 쉽게 설치할 수 있다. 예를 들어 brew cask install atom과 같은 명령어를 사용할 수 있다.

우리는 인기 있는 Electron 앱의 Homebrew cask 이름을 수집하기 시작했고, cask가 있는 모든 앱 페이지에 macOS 사용자를 위한 설치 명령어를 표시하고 있다.

플랫폼에 맞춘 설치 옵션: macOS, Windows, Linux

Homebrew cask 이름이 있는 모든 앱을 보려면 electronjs.org/apps?q=homebrew를 방문하면 된다. 만약 우리가 아직 인덱싱하지 않은 cask가 있는 다른 앱을 알고 있다면, 추가해 주세요!

🌐 새로운 도메인으로 이전

이제 사이트를 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 사이의 기술적 차이를 더 명확히 하고자 한다.

🐢🚀 Node.js를 어디서나 활용하기

이전의 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을 개선하는 데 기여한 모든 분들에게 특별한 감사를 표합니다. 오픈소스 커뮤니티의 열정은 Electron의 성공에 큰 힘이 되었습니다. 정말 감사합니다!

Thumbs up!

Chromium RCE Vulnerability Fix

· 2 min read

Google Chromium에서 원격 코드 실행 취약점이 발견되었으며, 이는 최신 버전의 Electron 모두에 영향을 미친다. sandbox 옵션이 활성화되었는지 여부와 상관없이, 원격 콘텐츠에 접근하는 모든 Electron 앱은 이 취약점에 노출될 수 있다.

이 취약점을 해결한 두 가지 새로운 버전인 Electron 1.7.81.6.14를 출시했다. 모든 Electron 개발자가 최신 안정 버전으로 앱을 즉시 업데이트할 것을 강력히 권장한다:

npm i electron@latest --save-dev

Electron 앱의 보안을 유지하기 위한 모범 사례에 대해 더 알아보려면 보안 튜토리얼을 참고한다.

Electron에서 발견한 취약점을 보고하려면 security@electronjs.org로 연락한다.

Announcing TypeScript support in Electron

· 8 min read

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가 있다.

설치

Electron 버전 1.6.10부터 모든 릴리스에는 자체 TypeScript 정의 파일이 포함된다. npm에서 electron 패키지를 설치하면 electron.d.ts 파일이 자동으로 설치된 패키지와 함께 번들로 제공된다.

Electron을 설치하는 가장 안전한 방법은 정확한 버전 번호를 사용하는 것이다:

npm install electron --save-dev --save-exact

혹은 yarn을 사용한다면:

yarn add electron --dev --exact

이미 @types/electron이나 @types/node와 같은 서드파티 정의를 사용하고 있었다면, 충돌을 방지하기 위해 Electron 프로젝트에서 이를 제거해야 한다.

정의 파일은 구조화된 API 문서에서 파생되었기 때문에, 항상 Electron의 API 문서와 일치한다. 단순히 electron을 설치하면 사용 중인 Electron 버전에 맞는 최신 TypeScript 정의를 항상 얻을 수 있다.

사용 방법

Electron의 새로운 TypeScript 어노테이션을 설치하고 사용하는 방법에 대한 요약은 다음 짧은 데모 스크린캐스트를 참고한다:

Visual Studio Code를 사용한다면, 이미 TypeScript 지원이 내장되어 있다. 또한 커뮤니티에서 관리하는 플러그인도 사용할 수 있다. Atom, Sublime, vim, 그리고 기타 에디터를 위한 플러그인이 있다.

에디터에서 TypeScript를 설정하면, 자동 완성 제안, 인라인 메서드 참조, 인자 검사 등과 같은 컨텍스트 인식 동작을 확인할 수 있다.

메서드 자동 완성

메서드 참조

인자 검사

TypeScript 시작하기

TypeScript가 처음이라면, Microsoft의 입문 동영상을 통해 이 언어가 왜 만들어졌는지, 어떻게 동작하는지, 사용 방법과 앞으로의 방향에 대해 간략히 살펴볼 수 있다.

또한 공식 TypeScript 웹사이트에서 핸드북플레이그라운드를 제공한다.

TypeScript는 JavaScript의 상위 집합이므로, 기존 JavaScript 코드는 이미 유효한 TypeScript 코드이다. 이는 기존 JavaScript 프로젝트를 점진적으로 TypeScript로 전환할 수 있으며, 필요에 따라 새로운 언어 기능을 추가할 수 있음을 의미한다.

감사의 말

이 프로젝트는 Electron 오픈소스 커뮤니티의 도움 없이는 가능하지 않았을 것입니다. 특히 Samuel Attard, Felix Rieseberg, Birunthan Mohanathas, Milan Burda, Brendan Forster를 비롯한 많은 분들이 버그 수정, 문서 개선, 기술적 조언 등으로 큰 도움을 주셨습니다. 여러분의 기여에 깊은 감사를 드립니다.

지원

Electron의 새로운 TypeScript 정의 파일을 사용하면서 문제가 발생하면, electron-typescript-definitions 저장소에 이슈를 등록하세요.

TypeScript를 즐겁게 사용하세요!

이번 주 프로젝트: Jasper

· 9 min read

이번 주에는 GitHub 알림을 관리하기 위한 Electron 기반 도구인 Jasper의 창시자를 인터뷰했다.

안녕하세요! 저는 누구일까요?

저는 마루야마 료라고 합니다. 일본에서 소프트웨어 개발자로 활동 중이며, JasperESDoc를 개발하고 있습니다.

Jasper란 무엇인가?

Jasper는 GitHub 이슈를 읽기 위한 유연하고 강력한 도구다. github.com과 GitHub Enterprise의 이슈와 풀 리퀘스트를 지원한다.

Jasper App Screenshot

왜 만들었나?

직장이나 오픈소스 활동에서 GitHub를 사용하는 사람들은 매일 많은 알림을 받는다. 이러한 알림을 구독하는 방법으로 GitHub는 이메일과 웹 알림을 제공한다. 나도 몇 년 동안 이를 사용했지만 다음과 같은 문제에 직면했다:

  • 내가 언급된 이슈, 내가 댓글을 단 이슈, 내가 주시하고 있는 이슈를 쉽게 놓치곤 했다.
  • 나중에 확인하려고 머릿속 한구석에 이슈를 두곤 했지만, 가끔 까먹곤 했다.
  • 이슈를 잊지 않기 위해 브라우저에 많은 탭을 열어두곤 했다.
  • 나와 관련된 모든 이슈를 확인하기가 어려웠다.
  • 팀의 모든 활동을 파악하기가 어려웠다.

이러한 문제를 해결하기 위해 많은 시간과 에너지를 소모하고 있었기 때문에, 나는 이러한 문제를 효율적으로 해결할 수 있는 GitHub 이슈 리더를 만들기로 결심했고, Jasper 개발을 시작했다.

Jasper을 누가 사용하나요?

Jasper는 GitHub를 사용하는 여러 회사의 개발자, 디자이너, 매니저들이 활용하고 있다. 물론 일부 오픈소스 개발자들도 사용 중이다. GitHub 내부 직원들도 Jasper를 사용하고 있다!

Jasper의 작동 원리

Jasper를 설정하면 다음과 같은 화면이 나타난다. 왼쪽부터 차례로 "스트림 목록", "이슈 목록", "이슈 본문"을 확인할 수 있다.

Jasper 시작 화면

이 "스트림"은 Jasper의 핵심 기능이다. 예를 들어, "electron/electron 저장소에서 @zeke에게 할당된 이슈"를 보고 싶다면 다음과 같은 스트림을 생성한다:

repo:electron/electron assignee:zeke is:issue

Jasper 시작 화면 2

스트림을 생성하고 몇 초 정도 기다리면, 조건에 맞는 이슈들을 확인할 수 있다.

Jasper 시작 화면 3

스트림을 활용해 무엇을 할 수 있을까?

스트림을 활용할 수 있는 다양한 조건에 대해 알아보자.

사용자와 팀

스트림이슈
mentions:cat mentions:dog사용자 cat 또는 dog가 언급된 이슈
author:cat author:dog사용자 cat 또는 dog가 생성한 이슈
assignee:cat assignee:dog사용자 cat 또는 dog에게 할당된 이슈
commenter:cat commenter:dog사용자 cat 또는 dog가 댓글을 단 이슈
involves:cat involves:dog사용자 cat 또는 dog와 관련된 이슈
team:animal/white-cat team:animal/black-doganimal/white-cat 또는 animal/black-dog가 언급된 이슈

involvesmention, author, assignee, commenter 중 하나를 의미한다.

저장소와 조직

스트림이슈
repo:cat/jump repo:dog/runcat/jump 또는 dog/run의 이슈
org:electron user:cat user:dogelectron, cat, 또는 dog의 이슈

orguser와 동일하다

속성

스트림이슈
repo:cat/jump milestone:v1.0.0 milestone:v1.0.1cat/jump에서 v1.0.0 또는 v1.0.1에 연결된 이슈
repo:cat/jump label:bug label:blockercat/jump에서 bugblocker 라벨이 모두 붙은 이슈
electron OR atomshellelectron 또는 atomshell이 포함된 이슈

리뷰 상태

스트림문제점
is:pr review:requiredcat/jump에서 리뷰가 필요한 이슈
is:pr review-requested:catcat이 리뷰를 요청한 이슈
하지만 아직 리뷰되지 않은 상태
is:pr reviewed-by:catcat이 리뷰한 이슈

이 표를 통해 확인할 수 있듯이, 스트림은 GitHub의 검색 쿼리를 사용할 수 있다. 스트림과 검색 쿼리를 사용하는 방법에 대한 자세한 내용은 다음 URL을 참고한다.

Jasper는 읽지 않은 이슈 관리, 읽지 않은 댓글 관리, 별표 표시, 알림 업데이트, 이슈 필터링, 키보드 단축키 등의 기능도 제공한다.

Jasper는 유료 제품인가요? 가격은 얼마인가요?

Jasper는 12달러입니다. 하지만 무료 체험판을 30일 동안 사용할 수 있습니다.

Jasper를 Electron 기반으로 개발한 이유는 무엇인가?

Electron의 다음과 같은 장점이 마음에 들었다:

  • 자바스크립트, CSS, HTML로 앱을 개발할 수 있다.
  • 윈도우, 맥, 리눅스 플랫폼 모두에서 동작하는 앱을 만들 수 있다.
  • Electron은 활발하게 개발되고 있으며 커뮤니티도 크다.

이러한 특징 덕분에 데스크톱 애플리케이션을 빠르고 간단하게 개발할 수 있다. 정말 훌륭한 도구다! 여러분도 제품 아이디어가 있다면 꼭 Electron을 고려해 보길 바란다.

Jasper 개발 과정에서 어떤 어려움을 겪었나요?

"스트림" 개념을 이해하는 데 어려움을 겪었다. 처음에는 GitHub의 Notifications API를 사용하려고 했다. 하지만 이 API가 특정 사용 사례를 지원하지 않는다는 것을 알게 되었다. 그 후 Issues APIPull Requests API를 Notifications API와 함께 사용하는 방법을 고민했다. 하지만 원하는 결과를 얻지 못했다. 다양한 방법을 고민하던 중 GitHub의 Search API를 폴링하는 것이 가장 유연한 방법이라는 것을 깨달았다. 이 과정에 약 한 달이 걸렸고, 이후 스트림 개념을 적용한 Jasper 프로토타입을 이틀 만에 구현했다.

참고: 폴링은 최대 10초에 한 번으로 제한된다. GitHub API의 제한 사항을 고려할 때 이는 충분히 허용 가능한 수준이다.

다음에 추가될 기능

다음과 같은 기능을 개발할 계획이다:

  • 필터링된 스트림: 스트림에 특정 조건으로 이슈를 필터링하는 기능을 추가할 예정이다. SQL의 뷰와 유사한 개념이다.
  • 다중 계정 지원: github.com과 GHE(GitHub Enterprise)를 동시에 사용할 수 있게 될 것이다.
  • 성능 개선: 현재 WebView에서 이슈를 로딩하는 속도가 일반 브라우저보다 느린 문제를 해결할 예정이다.

업데이트 소식은 @jasperappio 트위터 계정을 팔로우하면 확인할 수 있다.

이번 주 프로젝트: WebTorrent

· 17 min read

이번 주에는 @feross@dcposch와 함께 WebTorrent에 대해 이야기를 나눴다. WebTorrent는 웹 기반의 토렌트 클라이언트로, 사용자들을 연결해 분산형 브라우저 간 네트워크를 형성한다.

WebTorrent란 무엇인가?

WebTorrent는 브라우저에서 동작하는 최초의 토렌트 클라이언트이다. 완전히 JavaScript로 작성되었으며, WebRTC를 사용해 피어 간 통신을 가능하게 한다. 브라우저 플러그인, 확장 프로그램, 또는 별도의 설치가 필요하지 않다.

WebTorrent는 오픈 웹 표준을 활용해 웹사이트 사용자들을 연결하여 분산되고 탈중앙화된 브라우저 간 네트워크를 형성한다. 이를 통해 효율적인 파일 전송이 가능하다.

WebTorrent의 동작 데모는 webtorrent.io에서 확인할 수 있다.

webtorrent homepage

이게 왜 멋질까?

YouTube 같은 비디오 사이트를 상상해보자. 하지만 이번에는 방문자들이 사이트 콘텐츠를 호스팅하는 데 직접 참여한다. WebTorrent로 구동되는 웹사이트를 더 많은 사람이 사용할수록, 사이트는 더 빠르고 안정적으로 작동한다.

브라우저 간 직접 통신은 중개자를 없애고, 사람들이 자신의 방식으로 소통할 수 있게 한다. 더 이상 클라이언트/서버 구조가 아니다. 모든 사람이 동등한 네트워크의 일원이 된다. WebTorrent는 웹을 다시 분산화하는 여정의 첫걸음이다.

Electron이 왜 필요했을까?

약 1년 전, 우리는 WebTorrent를 데스크톱 앱으로 실행하는 WebTorrent Desktop을 만들기로 결정했다.

WebTorrent Desktop 플레이어 윈도우

WebTorrent Desktop을 만든 이유는 세 가지다:

  1. 깔끔하고 가벼우며 광고 없이 오픈소스로 제공되는 토렌트 앱을 원했다.
  2. 스트리밍 지원이 잘 되는 토렌트 앱을 원했다.
  3. BitTorrent와 WebTorrent 네트워크를 연결하는 "하이브리드 클라이언트"가 필요했다.

웹 브라우저에서 토렌트를 다운로드할 수 있는데, 왜 데스크톱 앱이 필요할까?

먼저, WebTorrent의 설계 배경을 간단히 살펴보자.

webtorrent desktop logo

초기에는 BitTorrent가 TCP를 전송 프로토콜로 사용했다. 이후 uTP가 등장하면서 TCP보다 더 나은 성능과 추가적인 장점을 제공했다. 모든 주요 토렌트 클라이언트는 결국 uTP를 채택했고, 현재는 두 프로토콜 모두를 사용할 수 있다. WebRTC 프로토콜은 논리적인 다음 단계다. 이 프로토콜은 웹 브라우저와의 상호 운용성을 제공하며, 모든 데스크톱 BitTorrent 클라이언트와 수백만 개의 웹 브라우저로 구성된 거대한 P2P 네트워크를 가능하게 한다.

"웹 피어"(웹 브라우저에서 실행되는 토렌트 피어)는 수백만 개의 새로운 피어를 추가함으로써 BitTorrent 네트워크를 더 강력하게 만들고, BitTorrent를 다양한 새로운 사용 사례로 확장한다. WebTorrent는 기존 BitTorrent 클라이언트가 WebTorrent를 쉽게 지원할 수 있도록 BitTorrent 사양을 최대한 따르도록 설계했다.

Vuze와 같은 일부 토렌트 앱은 이미 웹 피어를 지원하지만, 나머지 클라이언트가 이를 지원할 때까지 기다리고 싶지 않았다. 즉, WebTorrent Desktop은 WebTorrent 프로토콜의 채택 속도를 높이기 위한 우리의 방법이었다. 사람들이 정말로 사용하고 싶어 하는 훌륭한 토렌트 앱을 만들어 웹 피어(웹사이트 사용자)와 토렌트를 공유할 수 있는 네트워크 내 피어의 수를 늘리는 것이 목표였다.

토렌트의 잘 알려지지 않은 흥미로운 활용 사례

WebTorrent의 가장 흥미로운 활용 사례 중 하나는 피어 지원 전송(peer-assisted delivery)이다. 위키백과인터넷 아카이브와 같은 비영리 프로젝트는 방문자들이 함께 참여하도록 함으로써 대역폭과 호스팅 비용을 줄일 수 있다. 인기 있는 콘텐츠는 브라우저 간에 빠르고 저렴하게 전송할 수 있다. 드물게 접근되는 콘텐츠는 오리진 서버에서 HTTP를 통해 안정적으로 제공할 수 있다.

인터넷 아카이브는 이미 토렌트 파일을 업데이트해 WebTorrent와 잘 작동하도록 했다. 따라서 인터넷 아카이브 콘텐츠를 사이트에 임베드하려는 경우, 아카이브의 호스팅 비용을 줄이는 방식으로 구현할 수 있다. 이를 통해 아카이브는 웹 아카이빙에 더 많은 자원을 투자할 수 있다.

또한 CDN부터 P2P를 통한 앱 배포까지 다양한 비즈니스 활용 사례도 있다.

WebTorrent를 사용한 멋진 프로젝트들

gaia app 스크린샷

WebTorrent로 만들어진 가장 멋진 프로젝트는 단연 Gaia 3D Star Map이다. 이 프로젝트는 은하수를 3D로 구현한 인터랙티브 시뮬레이션이다. 데이터는 토렌트를 통해 브라우저에서 직접 로드된다. 은하계를 날아다니며 인간이 얼마나 작은 존재인지 깨닫게 되는 경험은 정말 감동적이다.

이 프로젝트가 어떻게 만들어졌는지는 Torrenting The Galaxy라는 블로그 포스트에서 확인할 수 있다. 저자 Charlie Hoey는 WebGL과 WebTorrent를 사용해 이 별 지도를 어떻게 만들었는지 설명한다.

brave 로고

Brave도 매우 인상적인 프로젝트다. Brave는 광고와 트래커를 자동으로 차단해 웹을 더 빠르고 안전하게 만드는 브라우저다. 최근 Brave는 토렌트 지원을 추가해 별도의 앱 없이 전통적인 토렌트를 볼 수 있게 했다. 이 기능은 WebTorrent로 구현되었다.

대부분의 브라우저가 PDF 파일을 렌더링할 수 있는 것처럼, Brave는 마그넷 링크와 토렌트 파일을 렌더링할 수 있다. 이제 토렌트는 브라우저가 기본적으로 지원하는 또 하나의 콘텐츠 타입이 된 셈이다.

Brave의 공동 창업자 중 한 명은 JavaScript의 창시자인 Brendan Eich다. WebTorrent도 JavaScript로 작성되었기 때문에 Brave가 WebTorrent를 통합한 점이 매우 의미 있다고 생각한다.

WebTorrent Desktop을 Electron으로 개발한 이유

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은 우리가 필요로 하는 기능을 모두 갖추고 있었고, 기록적으로 빠른 시간 안에 견고하고 세련된 앱을 출시할 수 있게 해주었다.

Electron의 가장 좋은 점은 무엇인가?

WebTorrent 라이브러리는 오픈 소스 사이드 프로젝트로 2년 동안 개발되어 왔다. 우리는 WebTorrent Desktop을 단 4주 만에 만들었다. 이렇게 빠르게 앱을 개발하고 출시할 수 있었던 주된 이유는 Electron 덕분이다.

Node.js가 jQuery를 사용하던 프론트엔드 개발자들에게 서버 프로그래밍을 가능하게 한 것처럼, Electron은 웹이나 Node.js 개발에 익숙한 누구나 네이티브 앱 개발을 할 수 있게 해준다. Electron은 정말 강력한 도구다.

웹사이트와 데스크톱 클라이언트가 코드를 공유하나요?

네, webtorrent npm 패키지는 Node.js, 브라우저, 그리고 Electron에서 동작한다. 정확히 동일한 코드가 모든 환경에서 실행될 수 있다. 이것이 바로 JavaScript의 매력이다. JavaScript는 현대의 보편적인 런타임 환경이다. Java 애플릿은 "한 번 작성하고 어디서든 실행"되는 앱을 약속했지만, 여러 가지 이유로 그 비전은 실현되지 못했다. Electron은 다른 어떤 플랫폼보다도 이 이상에 상당히 근접한 성과를 보여주고 있다.

WebTorrent 개발 과정에서 어떤 어려움을 겪었나요?

초기 버전의 앱에서 UI 성능 문제로 고생했다. 토렌트 엔진을 메인 앱 윈도우를 그리는 렌더러 프로세스에 함께 배치했는데, 이로 인해 토렌트 엔진에서 CPU 사용량이 급증할 때마다(예: 피어로부터 받은 토렌트 조각을 검증하는 경우) 앱이 느려지는 문제가 발생했다.

이 문제를 해결하기 위해 토렌트 엔진을 두 번째, 보이지 않는 렌더러 프로세스로 이동시켰다. 그리고 IPC를 통해 이 프로세스와 통신하도록 구조를 변경했다. 이렇게 하면 해당 프로세스에서 CPU를 많이 사용하더라도 UI 스레드에 영향을 미치지 않는다. 부드러운 스크롤링과 애니메이션은 정말 만족스럽다.

참고: 토렌트 엔진을 렌더러 프로세스에 배치한 이유는 WebRTC에 접근해야 하기 때문이다. WebRTC는 렌더러 프로세스에서만 사용할 수 있다.

Electron의 개선이 필요한 부분은 무엇인가?

프로덕션 준비가 된 앱을 빌드하고 배포하는 방법에 대한 더 나은 문서화가 필요하다. 특히 코드 서명(code signing)과 자동 업데이트(auto-updating)와 같은 복잡한 주제에 대한 설명이 부족하다. 우리는 소스 코드를 뒤지고 Twitter에서 질문을 올리는 방식으로 최적의 방법을 직접 찾아야 했다.

WebTorrent Desktop는 완성되었나요? 아니라면, 다음에 어떤 기능이 추가될 예정인가요?

현재 버전의 WebTorrent Desktop은 훌륭하지만, 여전히 개선의 여지가 있다고 생각한다. 현재는 사용 편의성, 성능, 자막 지원, 그리고 비디오 코덱 지원을 개선하기 위해 노력 중이다.

프로젝트에 참여하고 싶다면 GitHub 페이지를 확인해 보자!

다른 개발자에게 유용할만한 Electron 개발 팁

WebTorrent Desktop 기여자 중 한 명인 Feross는 NodeConf Argentina에서 _"Real world Electron: JavaScript로 크로스 플랫폼 데스크톱 앱 만들기"_라는 주제로 발표했다. 이 발표는 기본적으로 동작하는 앱을 더욱 세련되고 전문적으로 다듬는 단계에 있는 개발자에게 특히 유용한 팁을 담고 있다.

영상 보기:

슬라이드 보기:

또 다른 WebTorrent 기여자인 DC는 앱을 더 세련되고 네이티브하게 느껴지도록 만들기 위한 체크리스트를 작성했다. 이 체크리스트에는 코드 예제가 포함되어 있으며, macOS 독 통합, 드래그 앤 드롭, 데스크톱 알림, 앱 로딩 속도 개선 등의 주제를 다룬다.

Touch Bar 지원

· 4 min read

Electron 1.6.3 베타 버전이 macOS Touch Bar에 대한 초기 지원을 포함하고 있다.

새로운 Touch Bar API를 통해 버튼, 라벨, 팝오버, 색상 선택기, 슬라이더, 그리고 간격 조절기를 추가할 수 있다. 이러한 엘리먼트들은 동적으로 업데이트할 수 있으며, 사용자와 상호작용할 때 이벤트를 발생시킨다.

이 API는 첫 번째 릴리스이기 때문에 향후 몇 번의 Electron 릴리스에 걸쳐 발전할 예정이다. 추가 업데이트는 릴리스 노트를 확인하고, 문제나 누락된 기능이 있다면 이슈를 열어보길 바란다.

이 버전은 npm install electron@beta를 통해 설치할 수 있으며, TouchBarBrowserWindow Electron 문서에서 더 자세한 내용을 확인할 수 있다.

이 기능을 Electron에 기여한 @MarshallOfSound에게 큰 감사를 표한다. 🎉

터치 바 예제

터치 바 Gif

아래는 터치 바를 활용해 간단한 슬롯 머신 게임을 만드는 예제이다. 이 예제는 터치 바를 생성하고 아이템을 스타일링하며, 윈도우와 연결하고 버튼 클릭 이벤트를 처리하며, 레이블을 동적으로 업데이트하는 방법을 보여준다.

const { app, BrowserWindow, TouchBar } = require('electron');

const { TouchBarButton, TouchBarLabel, TouchBarSpacer } = TouchBar;

let spinning = false;

// 릴 레이블
const reel1 = new TouchBarLabel();
const reel2 = new TouchBarLabel();
const reel3 = new TouchBarLabel();

// 스핀 결과 레이블
const result = new TouchBarLabel();

// 스핀 버튼
const spin = new TouchBarButton({
label: '🎰 Spin',
backgroundColor: '#7851A9',
click: () => {
// 이미 스핀 중이면 클릭 무시
if (spinning) {
return;
}

spinning = true;
result.label = '';

let timeout = 10;
const spinLength = 4 * 1000; // 4초
const startTime = Date.now();

const spinReels = () => {
updateReels();

if (Date.now() - startTime >= spinLength) {
finishSpin();
} else {
// 각 스핀마다 속도를 조금씩 늦춤
timeout *= 1.1;
setTimeout(spinReels, timeout);
}
};

spinReels();
},
});

const getRandomValue = () => {
const values = ['🍒', '💎', '7️⃣', '🍊', '🔔', '⭐', '🍇', '🍀'];
return values[Math.floor(Math.random() * values.length)];
};

const updateReels = () => {
reel1.label = getRandomValue();
reel2.label = getRandomValue();
reel3.label = getRandomValue();
};

const finishSpin = () => {
const uniqueValues = new Set([reel1.label, reel2.label, reel3.label]).size;
if (uniqueValues === 1) {
// 3개 모두 같은 경우
result.label = '💰 Jackpot!';
result.textColor = '#FDFF00';
} else if (uniqueValues === 2) {
// 2개가 같은 경우
result.label = '😍 Winner!';
result.textColor = '#FDFF00';
} else {
// 모두 다른 경우
result.label = '🙁 Spin Again';
result.textColor = null;
}
spinning = false;
};

const touchBar = new TouchBar([
spin,
new TouchBarSpacer({ size: 'large' }),
reel1,
new TouchBarSpacer({ size: 'small' }),
reel2,
new TouchBarSpacer({ size: 'small' }),
reel3,
new TouchBarSpacer({ size: 'large' }),
result,
]);

let window;

app.once('ready', () => {
window = new BrowserWindow({
frame: false,
titleBarStyle: 'hidden-inset',
width: 200,
height: 200,
backgroundColor: '#000',
});
window.loadURL('about:blank');
window.setTouchBar(touchBar);
});

이번 주 프로젝트: Voltra

· 11 min read

이번 주에는 Aprile ElcichPaolo Fragomeni를 만나 Electron 기반의 음악 플레이어인 Voltra에 대해 이야기를 나눴다.

Voltra란 무엇인가?

Voltra는 음악을 소유하고 싶은 사람들을 위한 음악 플레이어다. 또한, 이미 소유한 음악을 기반으로 새로운 음악을 발견하고 구매할 수 있는 스토어 기능도 제공한다. 광고가 없으며 데스크톱과 모바일에서 모두 사용할 수 있는 크로스 플랫폼이다. 사용자를 추적하거나 감시하지도 않는다.

voltra-artistview

Voltra는 누구를 위한 서비스인가?

음악을 듣는 모든 이를 위한 서비스다.

Voltra를 만든 이유는 무엇인가?

라디오는 항상 많은 청취자를 확보해 왔다. 이제 라디오는 공중파를 벗어나 인터넷으로 이동하고 있다. 주문형 음악 대여가 가능해지면서 라디오의 부활이 일어나고 있다! 이로 인해 다양한 새로운 제품과 서비스가 등장했지만, 스트리밍 라디오는 여전히 다른 사람이 음악과 그 경험을 통제한다.

우리는 사용자가 소유한 음악에 완전히 초점을 맞춘 제품을 원했다. 아티스트나 레이블로부터 직접 새 음악을 발견하고 구매할 수 있게 해주는 무언가가 필요했다.

무료 버전이 있나요?

데스크톱 플레이어는 완전히 무료입니다. 음악 판매도 무료로 제공합니다! 광고 지원 방식이 아닙니다.

앱이 무료이기 때문에, 추후 오픈소스로 공개할 가능성이 있습니다. 현재는 이를 관리할 여유가 없습니다. 또한 기능과 발전 방향에 대해 구체적인 아이디어를 가지고 있습니다. 활발한 베타 커뮤니티가 있으며, 사용자 피드백을 소중히 받아들입니다.

어떻게 수익을 창출하나요?

우리는 프리미엄 기능을 제공합니다!

Voltra Audio Archive는 음악을 위해 특별히 설계된 클라우드 백업 서비스입니다. 데이터 블록을 압축하거나 공유하지 않습니다. 여러분의 음악 컬렉션을 물리적으로 백업해 드립니다.

아티스트와 레이블을 위한 Pro Membership은 분석 도구와 전문 아티스트 웹페이지와 같은 도구를 제공하여 더 많은 관련 청중에게 도달할 수 있도록 돕습니다.

Voltra의 차별화된 특징은 무엇인가?

디자인과 사용성은 우리에게 매우 중요하다. 우리는 청취자들이 방해받지 않고 음악을 즐길 수 있는 환경을 제공하고자 한다. 현재 시장에는 다양한 음악 플레이어와 스토어가 존재한다. 하지만 많은 제품들이 제작자의 의도와 달리 복잡하고 사용하기 어렵다. 우리는 Voltra를 가능한 많은 사람들이 쉽게 사용할 수 있도록 만들고자 한다.

또한, 우리는 아티스트나 레이블로부터 수수료를 받지 않는다. 이는 우리의 핵심 차별점 중 하나다. 이는 아티스트들이 자신의 음악을 시장에 내놓는 데 있어 진입 장벽을 낮추는 중요한 요소다.

어떤 디자인 및 기술적 결정을 내렸는가?

Voltra를 설계하면서 네이티브 앱과 웹의 UI 관례를 고려했을 뿐만 아니라, 무엇을 제거할 수 있을지 깊이 고민했다. 지난 몇 달 동안 활발히 활동한 비공개 베타 테스트 그룹으로부터 중요한 피드백을 받았다.

앨범 아트와 사진이 사용자들에게 매우 중요하다는 사실을 발견했다. 많은 플레이어가 단순히 파일 목록으로 구성되어 있다. 물리적 앨범을 소유하는 멋진 점 중 하나는 앨범 아트이며, Voltra 데스크톱 앱에서 이를 강조하고 싶었다.

voltra-albumview

또한 사용자의 파일을 건드리지 않도록 주의했다. 파일 감시 기능을 사용해 파일을 원하는 곳에 배치할 수 있게 했고, 파일 이름을 변경하거나 이동시키지 않는다. 감시 중인 디렉터리의 상태를 추적하기 위해 내장 데이터베이스를 사용해 프로세스가 실행 중이 아닐 때도 새로운 내용을 파악할 수 있다.

Voltra를 개발하며 마주한 도전 과제는 무엇인가?

성능 최적화에 많은 시간을 투자했다. 처음에는 프레임워크를 사용했지만, 결국 바닐라 자바스크립트로 전환했다. 우리의 경험에 따르면, 프레임워크가 제공하는 일반화된 추상화는 성능 저하와 추가적인 복잡성을 감수할 만한 가치가 있다.

현재는 매우 큰 컬렉션을 효율적으로 처리할 수 있다. 여기서 '큰 컬렉션'은 수만 개의 이미지를 의미한다! Node.js의 파일 시스템 모듈을 렌더링 프로세스에서 직접 사용할 수 있어, DOM 이벤트에 따라 많은 이미지를 빠르게 지연 로딩하고 언로드하는 작업이 매우 쉬워졌다.

일반적으로 setImmediaterequestIdleCallback은 UI의 반응성을 유지하면서 많은 처리를 수행하는 데 매우 중요한 도구로 사용되었다. 특히, CPU 집약적인 작업을 별도의 프로세스로 분산시키는 것이 사용자 인터페이스의 반응성을 유지하는 데 큰 도움이 되었다. 예를 들어, 실제 오디오 컨텍스트를 별도의 프로세스로 옮기고, IPC를 통해 통신함으로써 바쁜 UI로 인한 잠재적인 중단을 피할 수 있었다.

Voltra를 Electron으로 개발한 이유

브라우저의 샌드박스는 우리 앱에 너무 제한적이다. 하지만 웹 플레이어도 함께 개발 중이다. 따라서 두 구현체 간 거의 100%의 코드를 공유할 수 있다는 점은 큰 장점이다.

처음에는 Swift로 네이티브 앱을 개발하려고 했다. 하지만 너무 많은 부분을 직접 구현해야 한다는 문제점을 발견했다. 웹은 세계에서 가장 큰 오픈소스 생태계를 가지고 있다. 그래서 빠르게 Electron으로 전환했다.

가장 중요한 점은, Electron을 사용하면 한 번 개발하면 모든 주요 플랫폼에서 작동해야 한다는 것이다. 완벽히 보장되지는 않지만, 각 플랫폼별로 네이티브 코드를 작성하는 비용은 Electron이 도입하는 다른 비용보다 확실히 더 크다.

Electron의 가장 좋은 점은 무엇인가?

효율성: Node.js의 네트워킹 스택과 Chromium의 프레젠테이션 레이어가 함께 제공되어 작업을 빠르게 처리할 수 있다.

전문성: 웹 기술 스택을 그대로 사용하기 때문에, 우리 팀 전체가 제품 개발에 직접 참여할 수 있다.

커뮤니티: 매우 체계적이고 소통이 원활한 커뮤니티가 있다. 이런 지원 속에서 개발할 수 있어 매우 만족스럽다.

Electron의 개선이 필요한 부분은 무엇인가?

Electron이 단일 패키저를 공식적으로 지원해 주길 바란다. 패키저는 Node에서의 패키지 관리자만큼 Electron에게도 중요하다. 현재 사용자 영역에는 여러 패키저가 존재하며, 각각 흥미로운 기능을 제공하지만 버그도 함께 존재한다. 커뮤니티의 합의는 기여자들이 쏟는 에너지를 올바른 방향으로 이끄는 데 도움을 줄 것이다.

다음에 어떤 일이 벌어질까?

현재 모바일 앱을 개발 중이며, 아티스트와 레이블과 협력해 Voltra 상점에 음악을 추가하고 있다. 아티스트나 레이블이라면 지금 바로 가입하세요! 목표인 1천만 트랙을 달성하면 상점을 열 예정이다.

Electron Internals: Building Chromium as a Library

· 13 min read

Electron은 Google의 오픈소스 프로젝트인 Chromium을 기반으로 한다. Chromium은 원래 다른 프로젝트에서 사용하기 위해 설계된 것은 아니다. 이 글은 Chromium이 어떻게 Electron에서 사용할 수 있는 라이브러리로 구축되었는지, 그리고 빌드 시스템이 시간이 지나며 어떻게 발전해 왔는지를 소개한다.

CEF 사용하기

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를 직접 사용하는 방식으로 전환했다.

Chromium의 일부로 빌드하기

Chromium은 공식적으로 외부 프로젝트를 지원하지 않지만, 코드베이스가 모듈식으로 구성되어 있어 최소한의 브라우저를 쉽게 구축할 수 있다. 브라우저 인터페이스를 제공하는 핵심 모듈은 Content Module이라고 한다.

Content Module을 사용해 프로젝트를 개발하려면, Chromium의 일부로 프로젝트를 빌드하는 것이 가장 간단한 방법이다. 이를 위해 먼저 Chromium의 소스 코드를 체크아웃한 다음, 프로젝트를 Chromium의 DEPS 파일에 추가한다.

NW.js와 초기 버전의 Electron은 이 방식을 사용해 빌드했다.

하지만 Chromium은 매우 큰 코드베이스이기 때문에 강력한 머신이 필요하다. 일반적인 노트북에서는 5시간 이상 걸릴 수 있다. 이는 프로젝트에 기여할 수 있는 개발자 수를 크게 제한하고, 개발 속도도 느리게 만든다.

Chromium을 단일 공유 라이브러리로 빌드하기

Content Module을 사용하는 Electron은 대부분의 경우 Chromium 코드를 수정할 필요가 없다. 따라서 Electron 빌드를 개선하는 명확한 방법은 Chromium을 공유 라이브러리로 빌드한 다음, Electron에서 이를 링크하는 것이다. 이 방식은 개발자가 Electron에 기여할 때 Chromium 전체를 빌드할 필요가 없게 해준다.

이러한 목적으로 @arobenlibchromiumcontent 프로젝트를 만들었다. 이 프로젝트는 Chromium의 Content Module을 공유 라이브러리로 빌드하고, Chromium 헤더와 사전 빌드된 바이너리를 다운로드할 수 있게 제공한다. libchromiumcontent 초기 버전의 코드는 이 링크에서 확인할 수 있다.

brightray 프로젝트도 libchromiumcontent의 일부로 탄생했으며, Content Module 주변에 얇은 레이어를 제공한다.

libchromiumcontent와 brightray를 함께 사용하면 개발자는 Chromium 빌드의 세부 사항에 깊이 들어가지 않고도 빠르게 브라우저를 빌드할 수 있다. 또한 이 방식은 프로젝트 빌드를 위해 빠른 네트워크와 강력한 머신이 필요하지 않게 해준다.

Electron 외에도 Breach browser와 같은 다른 Chromium 기반 프로젝트들도 이 방식으로 빌드되었다.

내보낸 심볼 필터링

Windows에서는 하나의 공유 라이브러리가 내보낼 수 있는 심볼의 수에 제한이 있다. Chromium 코드베이스가 커지면서 libchromiumcontent에서 내보내는 심볼의 수가 이 제한을 넘어섰다.

이 문제를 해결하기 위해 DLL 파일을 생성할 때 필요하지 않은 심볼을 필터링하는 방법을 도입했다. 이 방법은 링커에 .def 파일을 제공한 후, 특정 네임스페이스 아래의 심볼을 내보낼지 여부를 판단하는 스크립트를 사용해 구현했다.

이 접근 방식을 통해 Chromium이 새로운 내보낸 심볼을 계속 추가하더라도, libchromiumcontent는 더 많은 심볼을 제거함으로써 공유 라이브러리 파일을 생성할 수 있었다.

컴포넌트 빌드

libchromiumcontent의 다음 단계를 설명하기 전에, 먼저 Chromium의 컴포넌트 빌드 개념을 소개하는 것이 중요하다.

Chromium은 거대한 프로젝트이기 때문에 빌드 시 링크 단계에서 많은 시간이 소요된다. 일반적으로 개발자가 작은 변경을 가할 때, 최종 결과물을 확인하려면 10분 이상 걸릴 수 있다. 이를 해결하기 위해 Chromium은 컴포넌트 빌드를 도입했다. 이 방식은 Chromium의 각 모듈을 별도의 공유 라이브러리로 빌드하여, 최종 링크 단계에서 소요되는 시간을 거의 없앤다.

원시 바이너리 배포

Chromium이 계속 성장하면서, Chromium에서 내보내는 심볼이 너무 많아져 Content Module과 Webkit의 심볼도 제한을 초과했다. 단순히 심볼을 제거해서 사용 가능한 공유 라이브러리를 생성하는 것은 불가능했다.

결국, Chromium의 원시 바이너리를 배포하는 방법을 선택했다. 단일 공유 라이브러리를 생성하는 대신 이 방식을 채택했다.

앞서 소개한 것처럼 Chromium에는 두 가지 빌드 모드가 있다. 원시 바이너리를 배포하게 되면서, libchromiumcontent에서 두 가지 다른 바이너리 배포판을 제공해야 했다. 하나는 static_library 빌드로, Chromium의 일반 빌드에서 생성된 각 모듈의 정적 라이브러리를 모두 포함한다. 다른 하나는 shared_library 빌드로, 컴포넌트 빌드에서 생성된 각 모듈의 공유 라이브러리를 모두 포함한다.

Electron에서는 Debug 버전이 libchromiumcontent의 shared_library 버전과 링크된다. 이 버전은 다운로드 크기가 작고, 최종 실행 파일을 링크하는 데 시간이 적게 걸리기 때문이다. 반면 Release 버전은 libchromiumcontent의 static_library 버전과 링크된다. 이렇게 하면 컴파일러가 디버깅에 중요한 전체 심볼을 생성할 수 있고, 링커가 필요한 오브젝트 파일을 정확히 알고 있기 때문에 더 나은 최적화를 수행할 수 있다.

일반적인 개발 과정에서는 개발자가 Debug 버전만 빌드하면 된다. 이 버전은 네트워크나 강력한 머신이 필요하지 않다. Release 버전은 더 좋은 하드웨어가 필요하지만, 더 최적화된 바이너리를 생성할 수 있다.

gn 업데이트

세계에서 가장 큰 프로젝트 중 하나인 Chromium을 빌드하기에는 일반적인 시스템이 적합하지 않다. Chromium 팀은 자체 빌드 도구를 개발했다.

이전 버전의 Chromium은 gyp를 빌드 시스템으로 사용했지만, 속도가 느리고 복잡한 프로젝트에서는 설정 파일을 이해하기 어려웠다. 수년간의 개발 끝에 Chromium은 더 빠르고 명확한 구조를 가진 gn으로 빌드 시스템을 전환했다.

gn의 개선점 중 하나는 source_set을 도입한 것이다. source_set은 오브젝트 파일 그룹을 나타낸다. gyp에서는 각 모듈이 static_libraryshared_library로 표현되었고, Chromium의 일반적인 빌드에서 각 모듈은 정적 라이브러리를 생성한 후 최종 실행 파일에 함께 링크되었다. gn을 사용하면 이제 각 모듈이 오브젝트 파일 묶음을 생성하고, 최종 실행 파일이 모든 오브젝트 파일을 함께 링크한다. 따라서 중간 정적 라이브러리 파일은 더 이상 생성되지 않는다.

이러한 개선은 libchromiumcontent에게 큰 문제를 일으켰다. libchromiumcontent는 실제로 중간 정적 라이브러리 파일이 필요했기 때문이다.

이 문제를 해결하기 위한 첫 번째 시도는 gn을 패치하여 정적 라이브러리 파일을 생성하게 하는 것이었다. 이 방법은 문제를 해결했지만, 적절한 해결책과는 거리가 멀었다.

두 번째 시도는 @alespergl오브젝트 파일 목록에서 커스텀 정적 라이브러리를 생성하는 방법을 제안한 것이다. 이 방법은 더미 빌드를 먼저 실행해 생성된 오브젝트 파일 목록을 수집한 후, 그 목록을 gn에 제공해 실제로 정적 라이브러리를 빌드하는 트릭을 사용했다. 이 방법은 Chromium의 소스 코드를 최소한으로 변경했고, Electron의 빌드 구조를 그대로 유지할 수 있었다.

요약

Chromium을 일부로 포함해 Electron을 빌드하는 방식과 Chromium을 라이브러리로 빌드하는 방식을 비교해 보면, 후자가 더 많은 노력과 지속적인 유지보수를 필요로 한다. 하지만 Chromium을 라이브러리로 빌드하면 강력한 하드웨어 없이도 Electron을 빌드할 수 있어, 더 많은 개발자가 Electron을 빌드하고 기여할 수 있게 된다. 이러한 노력은 충분히 가치가 있다.