Merge pull request #39 from minwook-shin/ko_translation

[WIP] Add korean translations
This commit is contained in:
Jen Looper
2020-11-29 11:19:28 -05:00
committed by GitHub
30 changed files with 5550 additions and 0 deletions

View File

@@ -0,0 +1,167 @@
# 브라우저 확장 프로젝트 파트 1: 브라우저에 대한 모든 것
![Browser sketchnote](images/sketchnote.jpg)
> Sketchnote by [Wassim Chegham](https://dev.to/wassimchegham/ever-wondered-what-happens-when-you-type-in-a-url-in-an-address-bar-in-a-browser-3dob)
## 강의 전 퀴즈
[Pre-lecture quiz](.github/pre-lecture-quiz.md)
### 소개
브라우저 확장은 브라우저에 추가적인 기능을 추가합니다. 그러나 빌드하기 전에, 브라우저가 작동하는 방식에 대해 약간 알아야 합니다.
### 브라우저에 대하여
이 강의의 시리즈에서는, Chrome, Firefox와 Edge 브라우저에서 작동하는 브라우저 확장을 빌드하는 방법을 배웁니다. 이 부분에서는, 브라우저가 작동하는 방식을 발견하고 브라우저 확장의 요소를 발판으로 딛습니다.
그러나 브라우저는 정확히 무엇일까요? 엔드 유저가 서버에서 콘텐츠에 접근하여 웹 페이지로 볼 수 있도록 해주는 소프트웨어 애플리케이션입니다.
✅ 약간의 역사: 첫번째 브라우저는 'WorldWideWeb'라고 불렸으며 Sir Timothy Berners-Lee가 1990년에 만들었습니다.
![early browsers](images/earlybrowsers.jpg)
> Some early browsers, via [Karen McGrane](https://www.slideshare.net/KMcGrane/week-4-ixd-history-personal-computing)
사용자가 URL(Uniform Resource Locator) 주소를 사용하여 인터넷에 연결하고, `http` 혹은 `https` 주소를 통해 Hypertext Transfer Protocol을 사용하면, 브라우저가 웹 서버와 통신하여 웹 페이지를 가져옵니다.
이 시점에서, 브라우저의 렌더링 엔진은 모바일 폰, 데스크톱 혹은 노트북과 같은 사용자의 장치에 출력합니다.
또한 브라우저는 콘텐츠를 캐시할 수 있으므로 매번 서버에서 찾을 필요가 없습니다. 브라우징 활동 기록을 기록할 때 필요한 정보가 포함된 작은 데이터인 'cookies'를 저장할 수 있습니다.
브라우저에 대해 알아야 할 중요한 점은 브라우저가 모두 같지 않다는 것입니다! 각 브라우저에는 장점과 단점이 있으며, 전문 웹 개발자는 웹 페이지가 크로스 브라우저로 잘 작동하도록 만드는 방법을 이해해야 합니다. 여기에는 모바일 폰과 같은 작은 뷰포트 제어와 오프라인 처리 작업을 포함합니다.
선호하는 브라우저에 책갈피를 추가한다면 정말 유용한 웹 사이트는 [caniuse.com](https://www.caniuse.com)입니다. 웹 페이지를 만들 때, caniuse의 지원 기술 목록을 사용하면 사용자의 브라우저를 가장 잘 지원할 수 있습니다.
✅ 웹 사이트의 사용자 층에서 가장 인기있는 브라우저가 어떤 것인지 어떻게 알 수 있나요? analytics를 확인해보세요 - 웹 개발 프로세스의 일부로 다양한 분석 패키지를 설치할 수 있으며, 다양한 인기 브라우저에서 가장 많이 사용되는 브라우저를 알려줍니다.
## 브라우저 확장
브라우저 확장을 만드려는 이유는 무엇입니까? 반복 작업을 빠르게 할 때 브라우저로 연결하면 편리합니다. 예를 들어, 상호 작용하는 다양한 웹 페이지에서 색상을 확인하는 경우에는, color-picker 브라우저 확장을 설치할 수 있습니다. 비밀번호를 기억할 때 어려운 경우에는, password-management 브라우저 확장을 설치할 수 있습니다.
브라우저 확장도 재미있게 개발할 수 있습니다. 제한된 수의 작업을 잘 관리하는 경향이 있습니다.
✅ 가장 좋아하는 브라우저 확장은 무엇입니까? 어떤 작업을 수행하나요?
### 확장 설치하기
만들기 전에, 브라우저 확장을 작성하고 배포하는 프로세스를 찾아보세요. 브라우저마다 이 작업을 관리하는 방법이 다소 다르지만, 프로세스는 Chrome과 Firefox와 같이 Edge의 예제와 유사합니다:
![install a browser extension](images/install-on-edge.png)
본질적으로, 프로세스는 다음과 같습니다:
- `npm build`를 사용하여 확장을 빌드합니다
- 우측 상단의 `...` 아이콘을 사용하여 브라우저에서 extensions 패널로 이동합니다
- 새로 설치하는 경우, `load unpacked`를 선택하여 build 폴더(이 경우에는 `/dist`)에서 새 확장을 올립니다
- 또는, 이미 설치된 확장 프로그램을 다시 불러오는 경우에 `reload`를 클릭합니다
✅ 이 설명서는 직접 만든 확장과 관련이 있습니다; 각 브라우저와 관련된 브라우저 확장 저장소에 출시된 확장을 설치하려면, 해당 [stores](https://microsoftedge.microsoft.com/addons/Microsoft-Edge-Extensions-Home)로 이동하여 원하는 확장을 설치해야 합니다.
### 시작하기
지역 탄소 발자국을 표시하는 브라우저 확장을 만들어서 지역의 에너지 사용량과 소스를 표시합니다. 확장에는 CO2 Signal의 API에 접근할 수 있도록 API 키를 모으는 폼이 있습니다.
**필요합니다:**
- [an API key](https://www.co2signal.com/); 이 페이지의 상자에 이메일을 입력하면 이메일이 전송됩니다.
- [Electricity Map](https://www.electricitymap.org/map)에 해당하는 [code for your region](http://api.electricitymap.org/v3/zones) (보스턴에서 예시를 들면, 'US-NEISO'를 사용합니다).
- [starter code](../start). `start` 폴더를 다운로드하세요; 이 폴더에서 코드를 완성하게됩니다.
- [NPM](https://www.npmjs.com) - NPM은 패키지 관리 도구입니다. 로컬에 설치하고 `package.json` 파일에 나열된 패키지를 웹 어셋에서 사용하도록 설치합니다.
✅ 이 [excellent Learn module](https://docs.microsoft.com/en-us/learn/modules/create-nodejs-project-dependencies/)에서 패키지 관리에 대해 자세히 알아보세요
잠시 시간을 내어 코드베이스를 보세요:
dist
-|manifest.json (defaults set here)
-|index.html (front-end HTML markup here)
-|background.js (background JS here)
-|main.js (built JS)
src
-|index.js (your JS code goes here)
✅ API 키와 지역 코드를 가지고 있다면, 나중에 다시 사용할 수 있도록 메모하세요.
### 확장을 위한 HTML 제작하기
이 확장은 두 화면을 가집니다. 한 화면에는 API 키와 지역 코드를 수집합니다:
![extension form](images/1.png)
그리고 두번째 화면에는 지역의 탄소 사용량을 출력합니다:
![carbon usage](images/2.png)
이제 HTML 폼을 작성하고 CSS 스타일을 지정하는 것으로 시작하겠습니다.
`/dist` 폴더에서, 폼과 결과 영역을 작성합니다. `index.html` 파일에서, 구분된 폼 영역을 채웁니다:
```HTML
<form class="form-data" autocomplete="on">
<div>
<h2>New? Add your Information</h2>
</div>
<div>
<label>Region Name</label>
<input type="text" required class="region-name" />
</div>
<div>
<label>Your API Key from tmrow</label>
<input type="text" required class="api-key" />
</div>
<button class="search-btn">Submit</button>
</form>
```
저장된 정보를 입력하고 로컬 저장소에 저장하는 양식입니다.
다음, 결과 영역을 만듭니다; 마지막 폼 태그 아래에 약간의 div를 추가합니다:
```HTML
<div class="result">
<div class="loading">loading...</div>
<div class="errors"></div>
<div class="data"></div>
<div class="result-container">
<p><strong>Region: </strong><span class="my-region"></span></p>
<p><strong>Carbon Usage: </strong><span class="carbon-usage"></span></p>
<p><strong>Fossil Fuel Percentage: </strong><span class="fossil-fuel"></span></p>
</div>
<button class="clear-btn">Change region</button>
</div>
```
이 시점에서 다시 빌드할 수 있습니다. 이 확장의 패키지 의존성을 설치해야 합니다:
```
npm install
```
이 명령은 Node 패키지 관리자인 npm을 사용하여, 확장의 빌드 프로세스를 위한 webpack을 설치합니다. Webpack은 컴파일 코드를 제어하는 bundler입니다. 이 프로세스의 출력은 `/dist/main.js`에서 볼 수 있습니다. - 코드가 번들로 제공됨을 알 수 있습니다.
지금은, 확장이 빌드되어 확장으로 Edge에 배포된다면, 폼은 깔끔하게 출력됩니다.
축하합니다, 브라우저 확장을 만들기 위한 첫 단계를 수행했습니다. 이어지는 강의에서, 더 기능적이고 유용하게 만들 것입니다.
---
## 🚀 도전
브라우저 확장 저장소를 살펴보고 브라우저에 하나 설치하세요. 흥미로운 방식으로 파일을 뜯어볼 수 있습니다. 무엇을 발견할 수 있나요?
## 강의 후 퀴즈
[Post-lecture quiz](.github/post-lecture-quiz.md)
## 리뷰 & 자기주도 학습
이 강의에서는 웹 브라우저의 역사에 대해 조금 배웠습니다; 이 기회에 역사를 더 많이 읽어보면서 World Wide Web의 탐험가들이 어떻게 사용했는지에 대해 알아보십시오. 유용한 사이트는 다음과 같습니다:
[The History of Web Browsers](https://www.mozilla.org/en-US/firefox/browsers/browser-history/)
[History of the Web](https://webfoundation.org/about/vision/history-of-the-web/)
[An interview with Tim Berners-Lee](https://www.theguardian.com/technology/2019/mar/12/tim-berners-lee-on-30-years-of-the-web-if-we-dream-a-little-we-can-get-the-web-we-want)
## 과제
[Restyle your extension](assignment.md)

View File

@@ -0,0 +1,222 @@
# 브라우저 확장 프로젝트 파트 2: 로컬 저장소를 사용한, API 호출
## 강의 전 퀴즈
[Pre-lecture quiz](.github/pre-lecture-quiz.md)
### 소개
이 강의에서는, 브라우저 확장의 폼을 제출하여 API를 호출하고 브라우저 확장에 결과를 출력합니다. 또한, 나중에 참조하고 사용하도록 브라우저의 로컬 저장소에 데이터를 저장하는 방법에 대해 알아봅니다.
✅ 적절한 파일 번호가 매겨진 세그먼트를 따라서 코드를 둘 위치를 알아봅니다.
### 확장에서 조작할 요소를 설정합니다:
지금까지 HTML 폼과 브라우저 확장에 대한 결과 `<div>`를 작성했습니다. 이제부터, `/src/index.js` 파일에서 작업하고 확장을 조금씩 빌드해야 합니다. 프로젝트 설정 및 빌드 프로세스에 대해서는 [이전 강의](../about-browsers/README.md)를 참조하세요.
`index.js` 파일에서 작업하면서, 다양한 필드에 값을 저장할 `const` 변수를 만드는 것으로 시작합니다:
```JavaScript
// form fields
const form = document.querySelector('.form-data');
const region = document.querySelector('.region-name');
const apiKey = document.querySelector('.api-key');
// results
const errors = document.querySelector('.errors');
const loading = document.querySelector('.loading');
const results = document.querySelector('.result-container');
const usage = document.querySelector('.carbon-usage');
const fossilfuel = document.querySelector('.fossil-fuel');
const myregion = document.querySelector('.my-region');
const clearBtn = document.querySelector('.clear-btn');
```
모든 필드는 이전 강의에서 HTML을 설정한 것처럼 CSS 클래스에서 참조됩니다.
### 리스너 추가하기
다음으로, 폼에 이벤트 리스너를 추가하고 폼을 리셋해주는 clear 버튼을 추가하여, 폼을 제출하거나 reset 버튼을 클릭하면 실행되도록, 파일 하단에 앱 초기화를 호출하도록 추가합니다:
```JavaScript
form.addEventListener('submit', (e) => handleSubmit(e));
clearBtn.addEventListener('click', (e) => reset(e));
init();
```
✅ submit 또는 click 이벤트를 받을 때 사용되는 약칭과, 이벤트가 handleSubmit 또는 reset 함수에 전달되는 방법에 유의하십시오. 이 약칭에 관련된 것을 더 긴 형식으로 바꿔 작성할 수 있나요? 어느 쪽을 선호하나요?
### init() 함수와 reset() 함수 작성하기:
이제 init()라고 불리는 확장 초기화하는 함수를 만드려고 합니다:
```JavaScript
function init() {
//if anything is in localStorage, pick it up
const storedApiKey = localStorage.getItem('apiKey');
const storedRegion = localStorage.getItem('regionName');
//set icon to be generic green
//todo
if (storedApiKey === null || storedRegion === null) {
//if we don't have the keys, show the form
form.style.display = 'block';
results.style.display = 'none';
loading.style.display = 'none';
clearBtn.style.display = 'none';
errors.textContent = '';
} else {
//if we have saved keys/regions in localStorage, show results when they load
displayCarbonUsage(storedApiKey, storedRegion);
results.style.display = 'none';
form.style.display = 'none';
clearBtn.style.display = 'block';
}
};
function reset(e) {
e.preventDefault();
//clear local storage for region only
localStorage.removeItem('regionName');
init();
}
```
함수에는, 약간의 흥미로운 로직이 있습니다. 이것을 읽어보면, 어떤 것이 보이나요?
- 사용자가 로컬 저장소에 APIKey 및 지역 코드를 저장했는지 확인하기 위해 두 'const'가 설정됩니다.
- 둘 중 하나가 null이면, 'block'으로 출력되도록 스타일을 변경하여 폼을 나타냅니다.
- 결과를 숨기거나, 불러오고, 또한 clearBtn을 숨기며 오류 텍스트를 빈 문자열로 설정합니다
- 키와 지역이 존재하는 경우에는, 다음 루틴이 시작됩니다:
- 탄소 사용량 데이터를 얻기 위한 API 호출
- 결과 영역 숨기기
- 폼 숨기기
- 리셋 버튼 보이기
계속 진행하기 전, 브라우저에서 사용할 수 있는 매우 중요한 개념: [LocalStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage)에 대해 알아 보는 것이 좋습니다. LocalStorage는 브라우저에 문자열을 `key-value` 쌍으로 저장하는 유용한 방법입니다. 이런 타입의 웹 저장소는 브라우저에서 데이터를 관리하기 위해 JavaScript로 제어할 수 있습니다. LocalStorage는 만료되지 않지만, 다른 종류의 웹 저장소인 SessionStorage는 브라우저를 닫는 즉시 지워집니다. 다양한 타입의 저장소를 사용하는 것은 장점과 단점이 존재합니다.
> Note - 이 브라우저 확장은 로컬 저장소를 가집니다; 주요 브라우저 창은 각자 다른 객체이며 별도로 동작합니다.
APIKey를 문자열 값으로 설정한다고 하면, 예를 들어 웹 페이지를 "inspecting" 하고 (브라우저를 우측 클릭하여 검사할 수 있습니다) 애플리케이션 탭으로 이동하여 저장소를 확인했을 때 Edge에 설정되어 있다는 것을 볼 수 있습니다.
![Local storage pane](images/localstorage.png)
✅ LocalStorage에 일부 데이터를 저장하기 꺼리는 상황을 생각해보세요. 일반적으로 API 키를 LocalStorage에 배치하는 것은 좋지 않은 생각입니다! 알 수 있나요? 우리 경우, 앱은 순수하게 학습을 위함이고, 앱 스토어에도 배포하지 않으므로 이 방법을 사용합니다.
Web API로 `getItem()`, `setItem()` 또는 `removeItem()`을 사용하여 LocalStorage를 제어합니다. 대부분 브라우저에서 광범위하게 지원됩니다.
`init()`에서 호출되는 `displayCarbonUsage()` 함수를 만들기 전에 초기 폼 제출을 하는 기능을 만들어 보겠습니다.
### 양식 제출 제어하기
이벤트 인자 `(e)`를 받는 `handleSubmit` 함수를 만듭니다. 이벤트 전달을 중단하고(브라우저 새로 고침을 중단) `apiKey.value``region.value` 인자를 전달하는 새로운 함수 `setUpUser` 를 호출합니다. 이런 방식으로, 적절한 필드가 채워지는 순간 초기 폼을 통해 가져온 두 값을 사용합니다.
```JavaScript
function handleSubmit(e) {
e.preventDefault();
setUpUser(apiKey.value, region.value);
}
```
✅ 메모리를 초기화합니다 - 지난 강의에서 설정한 HTML에는 파일 상단에 지정한 `const`를 통해 `values`이 잡히는 두 입력 필드가 있으며, 둘 다 `required`이므로 브라우저에서 사용자가 null 값을 입력하지 못하도록 합니다.
### 사용자 설정하기
`setUpUser` 함수로 이동하고, 여기에 apiKey와 regionName에 대한 로컬 저장소 값을 설정합니다. 새로운 함수를 추가합니다:
```JavaScript
function setUpUser(apiKey, regionName) {
localStorage.setItem('apiKey', apiKey);
localStorage.setItem('regionName', regionName);
loading.style.display = 'block';
errors.textContent = '';
clearBtn.style.display = 'block';
//make initial call
displayCarbonUsage(apiKey, regionName);
}
```
이 함수는 API가 호출되는 동안 로딩 메시지를 설정하게 합니다. 핵심으로, 이 브라우저 확장의 가장 중요한 함수를 만드는 데 도달했습니다!
### 탄소 사용량 출력하기
마지막으로 API 쿼리할 시간입니다!
계속 진행하기 전에, API에 대해 논의해야 합니다. API, 또는 [Application Programming Interfaces](https://www.webopedia.com/TERM/A/API.html)는 웹 개발자의 툴박스에서 중요한 요소입니다. 프로그램이 상호 작용하거나 할 수 있게 도와주는 표준 방법을 제공합니다. 예시로, 데이터베이스를 쿼리할 웹 사이트를 구축하는 경우, 누군가 사용할 API를 만들었을 수 있습니다. 다양한 유형의 API가 있지만 가장 인기있는 API 중 하나는 [REST API](https://www.smashingmagazine.com/2018/01/understanding-using-rest-api/)입니다.
✅ 'REST'라는 용어는 'Representational State Transfer'를 의미하고 데이터를 가져오기 위해서 다양하게-구성된 URL을 쓰는 기능입니다. 개발자가 사용할 수 있는 다양한 타입의 API에 대해 약간 알아보십시오. 어떤 포맷이 좋습니까?
이 함수에 대해 유의해야 할 중요 사항이 있습니다. 먼저 [`async` keyword](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function)를 확인합니다. 비동기로 실행되도록 함수를 작성한다는 것은 수행되기 전 데이터 반환 작업이 완료될 때를 기다린다는 점을 의미합니다.
다음은 `async`에 대한 간단한 영상입니다 :
[![Async and Await for managing promises](https://img.youtube.com/vi/YwmlRkrxvkk/0.jpg)](https://youtube.com/watch?v=YwmlRkrxvkk "Async and Await for managing promises")
C02Signal API를 쿼리할 새로운 함수를 만듭니다:
```JavaScript
import axios from '../node_modules/axios';
async function displayCarbonUsage(apiKey, region) {
try {
await axios
.get('https://api.co2signal.com/v1/latest', {
params: {
countryCode: region,
},
headers: {
'auth-token': apiKey,
},
})
.then((response) => {
let CO2 = Math.floor(response.data.data.carbonIntensity);
//calculateColor(CO2);
loading.style.display = 'none';
form.style.display = 'none';
myregion.textContent = region;
usage.textContent =
Math.round(response.data.data.carbonIntensity) + ' grams (grams C02 emitted per kilowatt hour)';
fossilfuel.textContent =
response.data.data.fossilFuelPercentage.toFixed(2) +
'% (percentage of fossil fuels used to generate electricity)';
results.style.display = 'block';
});
} catch (error) {
console.log(error);
loading.style.display = 'none';
results.style.display = 'none';
errors.textContent = 'Sorry, we have no data for the region you have requested.';
}
}
```
이는 큰 함수입니다. 여기에 어떤 일이 일어나고 있나요?
- 좋은 사례에 따라, `async` 키워드를 사용하여 이 함수가 비동기로 동작하도록 합니다. 이 함수는 API가 데이터를 반환할 때 promise를 반환하므로 `try/catch` 블록을 포함합니다. API 응답 속도를 제어할 수 없기 때문에 (전혀 응답을 못 받을 수 있습니다!) 확실하지 않은 일은 비동기로 호출하여 처리해야 합니다.
- API 키를 사용해서, 지역의 데이터를 얻기 위해 co2signal API를 쿼리하고 있습니다. 이 키를 사용하려면, 헤더 파라미터에 인증 타입을 사용해야 합니다.
- API가 응답하면, 이 데이터를 출력하도록 설정한 화면에 응답 데이터의 다양한 요소를 할당합니다.
- 오류가 있거나, 결과가 없는 경우에는, 오류 메시지가 출력됩니다.
✅ 비동기 프로그래밍 패턴을 사용하는 것은 툴박스의 다른 매우 유용한 도구입니다. [about the various ways](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function)를 읽고 이런 타입의 코드를 구성할 수 있습니다.
축하합니다! 확장을 빌드하고 (`npm run build`) 확장 패널에서 새로 고치면, 작동하는 확장이 있습니다! 아이콘만 작동하지 않으며 다음 강의에서 수정할 예정입니다.
---
## 🚀 도전
지금까지 이 강의에서 여러 타입의 API에 대해 논의했습니다. 웹 API를 선택하고 제공하는 내용에 대해 자세히 알아보세요. 예시로, [HTML Drag and Drop API](https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API)와 같은 브라우저에서 쓸 수 있는 API를 보세요. 당신의 의견에 비추어 볼 때 좋은 API를 만드는 방법은 무엇일까요?
## 강의 후 퀴즈
[Post-lecture quiz](.github/post-lecture-quiz.md)
## 리뷰 & 자기주도 학습
이 강의에서는 전문 웹 개발자에게 매우 유용한, LocalStorage와 API에 대해 학습했습니다. 어떻게 두 가지가 같이 작동하는지 생각해볼 수 있나요? API에서 사용할 아이템을 저장하는 웹 사이트를 어떻게 설계할지 생각해보세요.
## 과제
[Adopt an API](assignment.md)

View File

@@ -0,0 +1,161 @@
# 브라우저 확장 프로젝트 파트 3: 백그라운드 작업과 성능 학습
## 강의 전 퀴즈
[Pre-lecture quiz](.github/pre-lecture-quiz.md)
### 소개
이 모듈의 마지막 두 강의에서는, API에서 가져온 데이터에 대한 폼과 출력 영역을 만드는 방법을 배웠습니다. 웹에서 웹 프레즌스를 만드는 매우 표준적인 방법입니다. 비동기로 데이터를 가져와서 처리하는 방법도 배웠습니다. 브라우저 확장이 거의 완성되었습니다.
확장의 아이콘 색상을 새로 고치는 것부터 포함하여, 일부 백그라운드 작업을 관리하는 것도 남아있으므로, 브라우저가 이러한 종류의 작업을 관리하는 방법에 대해 이야기해 볼 수 있는 시간입니다. 웹 어셋을 구축하며 성능과 관련한 브라우저 작업에 대해 생각합시다.
## 웹 성능 기초
> "Website performance is about two things: how fast the page loads, and how fast the code on it runs." -- [Zack Grossbart](https://www.smashingmagazine.com/2012/06/javascript-profiling-chrome-developer-tools/)
모든 종류의 사용자와 상황에서의 모든 장치에서, 웹 사이트를 매우 빠르게 작동하도록 만드는 방법은 놀랍지 않을 정도로 많습니다. 표준 웹 프로젝트 혹은 브라우저 확장을 만들 때 알아두어야 할 몇 가지 사항이 있습니다.
사이트가 효율적으로 실행되는지 확인하기 위해 가장 먼저 할 일은 성능 데이터를 모으는 것입니다. 첫 번째 장소는 웹 브라우저의 개발자 도구입니다. Edge에서는, 브라우저 우측 상단에 존재하는 세 개 점을 선택한 다음, More Tools > Developer Tools로 이동하여 Performance 탭을 열 수 있습니다.
Performance 탭에는 Profiling 도구가 있습니다. 웹 사이트를 열고 (예를 들어, https://www.microsoft.com) 'Record' 버튼을 클릭한 뒤에, 사이트를 새로 고칩니다. 언제든 recording을 중단하면, 사이트를 'script', 'render', 그리고 'paint' 하려고 만든 루틴을 볼 수 있습니다:
![Edge profiler](./images/profiler.png)
✅ Edge에서 Performance 패널에서 [Microsoft Documentation](https://docs.microsoft.com/en-us/microsoft-edge/devtools-guide/performance)를 방문하세요
> Tip: 웹 사이트의 시작 시간을 순수하게 보려면, 브라우저의 캐시를 지우세요
프로필 타임라인의 요소를 선택하여 페이지가 불러지는 동안에 발생하는 이벤트를 확대합니다.
프로필 타임라인의 일부를 선택하고 요약 패널을 보게된 뒤 페이지 performance의 snapshot을 가져옵니다:
![Edge profiler snapshot](./images/snapshot.png)
이벤트 로그 패널을 확인하여 15ms 이상 넘긴 이벤트가 있는지 확인합니다:
![Edge event log](./images/log.png)
✅ 프로파일러에 대해 알아보세요! 이 사이트에서 개발자 도구를 열고 병목 현상이 있는지 확인하세요. 불러오는 속도가 가장 느린 어셋은 무엇인가요? 가장 빠른가요?
## 프로파일링 점검
일반적으로 모든 웹 개발자가 사이트를 만들 때는 주의해야 하는 몇 가지 "problem areas"가 있습니다, 따라서 프로덕션으로 배포할 때 깜짝 놀라는 것을 피할 수 있습니다.
**어셋 크기**: 웹은 지난 몇 년 동안 '무거워'지고 느려졌습니다. 이렇게 무거워지는 일부 원인은 이미지를 사용하는 것과 관련이 있습니다.
✅ 페이지 무게 등의 역사적 관점을 보려면 [Internet Archive](https://httparchive.org/reports/page-weight) 를 살펴보세요.
이미지가 최적화되어 사용자에게 적당한 크기와 해상도로 제공하고 있는지, 확인해보는 것이 좋습니다.
**DOM 순회**: 브라우저는 작성한 코드를 기반으로 Document Object Model을 작성하므로, 페이지에 필요한 것만 사용하며 스타일을 지정하고, 태그도 적게 사용하는 것이 좋은 페이지 성능을 위해 필요합니다. 이 시점에서, 페이지와 관련되어 많은 CSS를 최적화할 수 있습니다: 예를 들면, 한 페이지에서만 사용할 스타일은 main style sheet에 포함할 필요가 없습니다.
**JavaScript**: 모든 JavaScript 개발자는 나머지 DOM을 탐색하는 과정을 브라우저에 그리기 전에 불러와야 한다면 'render-blocking' 스크립트를 봐야 합니다. inline 스크립트와 (Terrarium 모듈에서 한 것처럼) `defer` 사용을 고려해보세요.
✅ [Site Speed Test website](https://www.webpagetest.org/)에서 일부 사이트를 시도해보고 사이트 성능을 결정하기 위해 수행되는 일반적인 확인 사항에 대해 알아보세요.
이제 브라우저가 전송한 어셋을 렌더링하는 방법에 대한 아이디어를 얻었으므로, 확장을 완료하고자 하는 마지막 몇 작업을 봅시다:
### 색상 계산하는 함수 생성하기
`/src/index.js`에서 작업하면서, DOM에 접근하기 위해 설정한 `const` 변수 뒤에 `calculateColor()`라는 함수를 추가합니다:
```JavaScript
function calculateColor(value) {
let co2Scale = [0, 150, 600, 750, 800];
let colors = ['#2AA364', '#F5EB4D', '#9E4229', '#381D02', '#381D02'];
let closestNum = co2Scale.sort((a, b) => {
return Math.abs(a - value) - Math.abs(b - value);
})[0];
console.log(value + ' is closest to ' + closestNum);
let num = (element) => element > closestNum;
let scaleIndex = co2Scale.findIndex(num);
let closestColor = colors[scaleIndex];
console.log(scaleIndex, closestColor);
chrome.runtime.sendMessage({ action: 'updateIcon', value: { color: closestColor } });
}
```
여기에 어떤 일이 일어나고 있나요? 지난 강의에서 완료한 API 호출에서 값(탄소 강도)을 전달한 다음에, 값이 colors 배열에 표시된 인덱스에서 얼마나 가까운 지 계산합니다. 그러고 가장 가까운 색상 값을 chrome 런타임으로 보냅니다.
hrome.runtime은 [API](https://developer.chrome.com/extensions/runtime)는 모든 종류의 백그라운드 작업을 제어하며, 확장은 다음을 활용합니다:
> "Use the chrome.runtime API to retrieve the background page, return details about the manifest, and listen for and respond to events in the app or extension lifecycle. You can also use this API to convert the relative path of URLs to fully-qualified URLs."
✅ Edge 용 브라우저 확장을 개발하고 있다면, chrome API를 사용하고 있다는 점에 놀랄 수 있습니다. 최신 Edge 브라우저 버전은 Chromium 브라우저 엔진에서 실행되므로, 이 도구를 활용할 수 있습니다.
> 참고로 브라우저 확장을 프로파일링하려면, 이는 분리된 브라우저 인스턴스이므로 확장 자체적으로 dev tools를 시작합니다.
### 기본 아이콘 색상 지정하기
이제, `init()` 함수에서, chrome의 `updateIcon` 액션을 다시 호출하여 시작할 때의 아이콘을 평범한 녹색으로 설정합니다:
```JavaScript
chrome.runtime.sendMessage({
action: 'updateIcon',
value: {
color: 'green',
},
});
```
### 함수 호출하고, call 실행하기
다음, 방금 전에 만든 함수를 C02Signal API가 반환한 promise에 추가하여 호출합니다:
```JavaScript
//let CO2...
calculateColor(CO2);
```
그리고 마지막으로, `/dist/background.js` 에서, 백그라운드 엑션 호출하는 리스너를 추가합니다:
```JavaScript
chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) {
if (msg.action === 'updateIcon') {
chrome.browserAction.setIcon({ imageData: drawIcon(msg.value) });
}
});
//borrowed from energy lollipop extension, nice feature!
function drawIcon(value) {
let canvas = document.createElement('canvas');
let context = canvas.getContext('2d');
context.beginPath();
context.fillStyle = value.color;
context.arc(100, 100, 50, 0, 2 * Math.PI);
context.fill();
return context.getImageData(50, 50, 100, 100);
}
```
코드에서, 백엔드 작업 매니저로 들어오는 모든 메시지 리스너를 추가합니다. 'updateIcon' 이라고 불리면, 다음 코드가 수행되고, Canvas API를 사용해서 적절한 색상의 아이콘을 그립니다.
✅ [Space Game lessons](../../space-game/drawing-to-canvas/README.md)에서 Canvas API에 대해 더 배울 것 입니다.
이제, 확장을 (`npm run build`)로 다시 빌드합니다, 확장을 새로 고치고 시작한 뒤, 색상이 변하는 것을 봅니다. 심부름을 하거나 설거지를 하기에 좋을 때 인가요? 이제 압니다!
축하합니다, 유용한 브라우저 확장을 만들었고 브라우저 작동 방식과 성능 프로파일링 방식에 대해 더 배웠습니다.
---
## 🚀 도전
일부 오픈소스 웹 사이트가 옛날에도 있었는지 알아보고, GitHub 히스토리를 바탕으로, 몇 년 동안 성능을 위해 최적화되고 있었는가에 대해 확인하세요. 가장 일반적인 문제점은 무엇일까요?
## 강의 후 퀴즈
[Post-lecture quiz](.github/post-lecture-quiz.md)
## 리뷰 & 자기주도 학습
[performance newsletter](https://perf.email/) 가입을 고려해보세요
웹 도구의 performance 탭을 통하여 브라우저에서 웹 성능을 측정하는 방식이 어떤 것인지 알아보세요. 큰 차이점을 찾을 수 있나요?
## 과제
[Analyze a site for performance](assignment.md)

View File

@@ -0,0 +1,28 @@
# 브라우저 확장 만들기
브라우저 확장을 만드는 것은 다른 타입의 웹 어셋을 빌드하면서 앱의 성능에 대해 생각할 수 있는 재미있고 흥미로운 방법입니다. 이 모듈에는 브라우저의 작동 방식과 브라우저 확장을 배포하는 방법, 폼을 만들고 API를 호출하며 로컬 저장소를 사용하는 방법과 웹 사이트의 성능을 측정하고 개선하는 방법에 대한 강의가 포함되어 있습니다.
Edge, Chrome과 Firefox에서 작동하는 브라우저 확장을 만듭니다. 매우 특정한 작업에 맞춰진 작은 웹 사이트와 같은 확장은 특정 지역의 전기 사용량과 탄소 강도에 대한 [C02 Signal API](https://www.co2signal.com)를 확인하고, 해당 지역의 탄소 발자국에 대한 판독 값을 반환합니다.
이 확장 기능은 API 키와 지역 코드를 양식에 입력하여 지역 전기 사용량을 결정하고 사용자의 전기 결정에 영향을 줄 수 있는 데이터를 제공하면 사용자가 임시로 호출할 수 있습니다. 예로 들면, 해당 지역에서 전기 사용량이 많은 기간에는 의류 건조기(a carbon-intense activity) 작동을 연기하는 것이 좋습니다.
### 주제
1. [브라우저에 대하여](1-about-browsers/README.md)
2. [폼과 로컬 저장소](2-forms-browsers-local-storage/README.md)
3. [백그라운드 작업과 성능](3-background-tasks-and-performance/README.md)
### 크레딧
![a green browser extension](extension-screenshot.png)
## 크레딧
The idea for this web carbon trigger was offered by Asim Hussain, lead at Microsoft of the Green Cloud Advocacy team and author of the [Green Principles](https://principles.green/). It was originally a [web site project](https://github.com/jlooper/green).
The structure of the browser extension was influenced by [Adebola Adeniran's COVID extension](https://github.com/onedebos/covtension).
The concept behind the 'dot' icon system was suggested by the icon structure of the [Energy Lollipop](https://energylollipop.com/) browser extension for California emissions.
These lessons were written with ♥️ by [Jen Looper](https://www.twitter.com/jenlooper)