웹 개발 실전 프로젝트 - 2주차
DOM, AJAX, API 등을 배우고 터미널 기초를 배워보자
276. Promise의 마법
- Promise는 then 안에서 Promise를 반환할 수 있다. ⇒ 이를 활용하면 중첩을 없앨 수 있다. (연쇄 가능)
fakeRequestPromise('yelp.com/api/coffee/page1')
.then((data) => {
console.log('PROMISE RESOLVED!');
console.log(data);
return fakeRequestPromise('yelp.com/api/coffee/page2')
})
.then((data) => {
console.log('PROMISE RESOLVED (2)!');
console.log(data);
return fakeRequestPromise('yelp.com/api/coffee/page3')
})
.then((data) => {
console.log('PROMISE RESOLVED (3)!');
console.log(data);
})
.catch((err) => {
console.log('PROMISE REJECTED!!!');
console.log(err);
});
catch
는 가장 마지막에 하나만 있으면 된다!
- 또한 Promise는 값으로 resolve 또는 reject 된다.
- data와 err
277. 자신만의 Promise 만들기
const fakeRequest = (url) => {
return new Promise((resolve, reject) => {
const rand = Math.random();
setTimeout(() => {
if (rand < 0.7) {
resolve('YOUR FAKE DATA HERE');
}
reject('Request ERROR!!');
}, 1000)
})
}
fakeRequest('/dogs/1')
.then((data) => {
console.log('DONE WITH REQUEST!');
console.log('data is: ', data);
})
.catch((err) => {
console.log('OH NO!', err);
})


const delayedColorChange = (color, delay) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
document.body.style.backgroundColor = color;
resolve();
}, delay)
})
}
delayedColorChange('red', 1000)
.then(() => delayedColorChange('orange', 1000))
.then(() => delayedColorChange('yellow', 1000))
.then(() => delayedColorChange('green', 1000))
.then(() => delayedColorChange('blue', 1000))
.then(() => delayedColorChange('indigo', 1000))
.then(() => delayedColorChange('violet', 1000))
278. 비동기 키워드
async
- 비동기 함수의 깔끔한 코드 작성을 돕는다.
- syntex sugar 혹은 syntext makeup
async
는 함수 선언 시 해당 함수를 비동기로 만들어주는 키워드- 해당 함수는 자동으로 Promise를 반환하게 된다.
- 비동기 함수에 오류가 있으면 Promise의 상태는 실패로 뜬다.
throw
로 에러 발생시키기 (아래 예시)
const sing = async () => {
throw 'OH NO, PROBLEM!';
return 'LA LA LA LA';
}
sing()
.then(data => {
console.log('PROMISE RESOLVED WITH: ', data);
})
.catch(err => {
console.log('OH, NO, PROMISE REJECTED');
console.log(err);
})


- 로그인은 서버의 데이터베이스에서 암호화된 정보를 확인하는 데 시간이 걸린다. 즉각적인 반응 X ⇒ 비동기 함수를 사용
const login = async (username, password) => {
if (!username || !password) throw 'Missing Credentials'
if (password === 'corgiffetarecute') return 'WELCOME!'
throw 'Invaild Password'
}
login('sdlkjfwe', 'corgiffetarecute')
.then(msg => {
console.log('LOGGED IN!');
console.log(msg);
})
.catch(err => {
console.log('ERROR!');
console.log(err);
})
async는 promise를 반환하고, promise는 값으로 반환된다.
내부에 값이 있느냐에 따라 성공, 실패가 결정된다.
반환 값이 있으면
resolved
,
오류가 있으면 오류 값과 함께 rejected
279. 대기 키워드
await
- await의 역할은 기다리게 하는 것
- Promise가 값을 반환할 때까지 기다리기 위해 비동기 함수의 실행을 일시 정지시킨다.
const delayedColorChange = (color, delay) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
document.body.style.backgroundColor = color;
resolve();
}, delay)
})
}
// delayedColorChange('red', 1000)
// .then(() => delayedColorChange('orange', 1000))
// .then(() => delayedColorChange('yellow', 1000))
// .then(() => delayedColorChange('green', 1000))
// .then(() => delayedColorChange('blue', 1000))
// .then(() => delayedColorChange('indigo', 1000))
// .then(() => delayedColorChange('violet', 1000))
async function rainbow() {
await delayedColorChange('red', 1000);
await delayedColorChange('orange', 1000));
await delayedColorChange('yellow', 1000));
await delayedColorChange('green', 1000));
await delayedColorChange('blue', 1000));
await delayedColorChange('indigo', 1000));
await delayedColorChange('violet', 1000));
return 'ALL DONE!';
}
// rainbow().then(() => console.log('END OF RAINBOW!'));
async function printRainbow() {
await rainbow();
console.log('END OF RAINBOW!');
}
280. 비동기 함수의 오류 처리하기
- 기다리고 있는 promise가 reject 되었을 경우, 상황을 처리하기 위해 try ... catch 문을 쓰자.
const fakeRequest = (url) => {
return new Promise((resolve, reject) => {
const delay = Math.floor(Math.random() * 4500) + 500;
setTimeout(() => {
if (delay > 2000) {
reject('Connection Timeout :(');
} else {
resolve(`Here is your fake data from ${url}`);
}
}, delay)
})
}
async function makeTwoRequests() {
try {
let data1 = await fakeRequest('/page1');
console.log(data1);
let data2 = await fakeRequest('/page2');
console.log(data2);
} catch(e) {
console.log('CAUGHT AN ERROR!');
console.log('error is: ', e);
}
}
281. 섹션 주제
- API 개념과 API 문서, 엔드포인트, JSON 알기
- XHR 객체
- XML HTTP Request - JavaScript 루트를 알 수 있다.
- 오래되고 투박한 객체지만 알아두면 유용하다.
- fetch API - 요청할 수 있는 최신 기능
- Axios 객체로 요청하기
282. AJAX 개요
- AJAX는 Asynchronous JavaScript and XML을 말한다.
- 요청(Request)
- 정보를 전송하거나 어떤 정보를 저장하려면 요청을 해야 한다.
- 웹사이트에서 혹은 앱에서 보이지 않게 요청
- 서버로 데이터를 원활하게 주고받을 수 있다.
- 개발자 도구의 네트워크 탭에서 확인 가능
- AJAX는 페이지에 데이터를 요청하는데, 페이지가 로딩이 된 후에도 데이터를 요청할 수 있다. 새로고침 필요X
- 실시간 검색도 가능 (새로고침 대신 JavaScript 타임아웃으로)
- AJAX 이전 방식은 URL을 클릭해서 요청한다거나, Enter를 쳐서 폼을 제출(submit)해서 데이터를 받았다. user가 서버에 요청 → 서버 어딘가로 데이터를 보내고 특정 리소스 정보를 요청 → 서버는 HTML/CSS, JavaScript로 데이터를 보낸다. → 웹 페이지 생성
- AJAX는 JavaScript를 사용해서 앱을 만드는 기술
283. APIs 개요
- JavaScript로 AJAX 요청을 할 때 HTML/CSS, JavaScript가 아닌 순수한 정보( ⇒ 데이터)를 원함 → 이 때 필요한 것이 API
- API는 Application Programming Interface를 말한다.
- API는 컴퓨터가 여러 소프트웨어와 상호 작용하거나 소통하는 모든 인터페이스를 의미하는 광범위한 용어다.
- 꼭 컴퓨터일 필요 X. 오히려 소프트웨어끼리 작용하는 인터페이스라고 할 수 있다. 일반적으로 웹과는 상관이 없다.
- 웹 개발자들이 API란 용어를 사용할 때는 대부분 WebAPI를 뜻한다.
- WebAPI는 웹, HTTP를 기반으로 하는 인터페이스
- WebAPI에서 제공되는 엔드포인트(특정 URL)는 사용되는 코드에 정보로 응답하거나, 다른 소프트웨어에 정보로 응답한다.
- 다른 애플리케이션이나 데이터베이스로 가는 입구
284. JSON이란?
- API가 (주로 정보 자체인) 데이터만을 전송할 때 쓰는 포맷
- 초기에 유명했던 포맷은 XML
- XML은 확장성이 있는 마크업 언어를 의미한다.
- 여전히 사람들은 AJAX라고 말하지만, 요즘 개발자들이 쓰는 포맷은 XML이 아니라 실제로는 JSON이다. (AJAJ가 안 익숙해서 AJAX라는 용어를 그대로 사용한다.)
- JSON은 JavaScript Object Notation을 말한다. (JS 객체 문법)

- JavaScript에서 사용 가능한 값 형식
- undefined는 없다.
- JSON과 JavaScript는 동일하지 않다.
- Python, Ruby 등 다른 언어에서도 JSON을 파싱해서 사용한다.
JSON.parse()
- JavaScript에서 JSON을 유효한 객체로 바꾸는 메서드
- 문자열을 전달하면 파싱되어 JavaScript 객체로 변환된다.
JSON.stringify()
- JavaScript 객체인 정보를 JSON으로 변환하는 메서드
- JSON 형식의 데이터를 받는 API에 정보를 보낼 때 유용
- undefined 값은 모두 null로 바뀐다.
- 미지원 데이터 타입을 감지하고 필요 시 큰따옴표를 붙인다.
285. Postman 사용하기
- HTTP 요청과 응답의 세부적인 내용 살펴보기
- 다양한 API에 요청을 보내는 방법, 요청이 어떻게 구조화되는지, 다양한 상태 코드, 헤더, 쿼리, 문자열의 의미 등

HTTP 동사들
- 보낼 수 있는 요청의 타입들
- GET 요청은 정보를 검색해서 가져올 때 사용한다.
- POST 요청은 DB에 저장 혹은 업데이트하기 위해 서버로 데이터를 보낼 때 사용한다.
HTTP 상태 코드
- 2로 시작하는 코드는 성공, 3으로 시작하는 코드는 리디렉션을 의미한다.
- 400번대 코드는 클라이언트 오류, 500번대 코드는 서버 오류를 의미한다.
- 포스트맨으로 요청을 보내고 우측 상단에서 상태 코드를 확인할 수 있다.

286. 문자열 및 헤더 쿼리

?q=:query
처럼 URL에 콜론이 있으면 변수라는 뜻. 사용자가 입력하는 정보, 얻는 결과에 영향을 준다. ⇒ 쿼리스트링
- 쿼리스트링은 요청(request) 시 추가 정보를 제공하는 방법이다.
- 쿼리스트링은 URL의 한 부분으로써, 없는 상태는 기본 URL
- 설정된 엔드포인트 방식대로 쿼리 매개변수를 입력
- 일반적으로는 URL 창이 아닌 검색창에 입력
(
<form>
태그 사용)
- Postman에서 쿼리스트링을 작성할 때 Params 탭을 이용해 쉽게 키-값을 넣어줄 수 있다.

- API 작동 방식에서 필요로 할 경우 요청에도 헤더를 포함해야 한다.


287. XHR 객체 만들기
- XMLHttpRequest를 사용해보고 최신 객체의 좋은 점을 알아보자.
- XHR은 Promise를 지원하지 않는다. ⇒ 콜백 함수 사용
const req = new XMLHttpRequest();
req.onload = function () {
console.log('ALL DONE WITH REQUEST!!!');
const data = JSON.parse(this.responseText);
console.log(data.ticker.price);
}
req.onerror = function () {
console.log('ERROR!!!');
console.log(this);
}
req.open('GET', 'https://api.cryptonator.com/api/ticker/btc-usd');
req.send();
288. Fetch API
- JavaScript를 사용해서 HTTP 요청을 만드는 최신 방식
- 비동기 요청 방식인 AJAX는 페이지에서 동적 화면을 만들 수 있고, 새로고침을 하지 않아도 되었기 때문에 등장 이후 점차 사용이 증가했다.
- XHR 방식의 단점이 부각되면서 Fetch API가 선호되었다.
fetch
구문으로 엔드포인트를 요청하면 Promise를 반환한다.
json
메서드를 사용하면 JSON 형식으로 데이터를 받고, 비동기식이어서 Promise를 반환한다. (필요한 데이터가 담긴 body를 받길 기다린다.)
fetch('https://api.cryptonator.com/api/ticker/btc-usd')
.then(res => {
console.log('RESPONSE, WAITING TO PARSE...', res);
return res.json();
})
.then(data => {
console.log('DATA PARSED...');
console.log(data.ticker.price);
})
.catch(e => {
console.log('OH NO! ERROR!', e);
})
- XHR에 비하면 fetch 방식이 훨씬 좋다.
- 다른 요청을 만들 때 콜백을 중첩할 필요 X. catch 사용하면 됨
- Promise 버전 말고 비동기 함수로 async, await을 사용해 똑같이 만들어보면 훨씬 간단해진다.
const fetchBitcoinPrice = async () => {
const res = await fetch('https://api.cryptonator.com/api/ticker/btc-usd');
const data = await res.json();
console.log(data.ticker.price);
}
Fetch API와 json메서드는 Promise를 반환하고,
await은 Promise가 값을 반환할 때까지 기다리기 위해
비동기 함수(async)의 실행을 일시 정지시키므로
위와 같은 코드를 사용할 수 있다.
- try...catch 문으로 에러 핸들링
const fetchBitcoinPrice = async () => {
try {
const res = await fetch('https://api.cryptonator.com/api/ticker/btc-usd');
const data = await res.json();
console.log(data.ticker.price);
} catch(e) {
console.log('SOMETHING WENT WRONG!', e);
}
}
- fetch가 훌륭하지만 완벽하진 않아서 Axios 같은 라이브러리를 사용한다.
289. Axios 개요
- fetch를 기반으로 하는 라이브러리
- post 요청 보내기, 쿼리 문자열 정보 포함하기, 헤더 변경하기 등의 작업들을 더 쉽게 만들어 준다.
- Axios 없이 fetch로만 작업할 때는 (1) 처음에 fetch 응답이 수신되어 첫 번째 Promise가 완료되고 나면, (2) 다시
res.json()
을 호출하여 모든 body를 파싱해서 두 번째 Promise를 반환해야 한다. ⇒ 두 단계를 별개로 처리
- ‣는 이 과정을 한 단계로 만들어줄 수 있다.

- 완전히 파싱된 응답 객체를 반환한다.
axios.get('https://api.cryptonator.com/api/ticker/btc-usd')
.then(res => {
console.log(res.data.ticker.price);
})
.catch(err => {
console.log('ERROR!', err);
})
const fetchBitcoinPrice = async () => {
try {
const res = axios.get('https://api.cryptonator.com/api/ticker/btc-usd');
console.log(res.data.ticker.price);
} catch (e) {
console.log('ERROR!', err);
}
}
290. Axios로 헤더 세팅하기
- axios의 두 번째 인수로 헤더 객체를 전달할 수 있다.
const getDadJoke = async () => {
const config = { headers: { Accept: 'application/json' } };
const res = await axios.get('https://icanhazdadjoke.com/', config);
console.log(res.data.joke);
};
getDadJoke();
- DOM 조작
const getDadJoke = async () => {
try {
const config = { headers: { Accept: 'application/json' } }; // 헤더 지정
const res = await axios.get('https://icanhazdadjoke.com/', config); // 두 번째 인수로 전달
return res.data.joke;
} catch(e) {
return 'NO JOKES AVAILABLE! SORRY :(';
}
};
const jokes = document.querySelector('#jokes');
const addNewJoke = async () => {
const jokeText = await getDadJoke(); // getDadJoke에서 리턴한 값(문자열)을 사용
const newLI = document.createElement('li');
newLI.append(jokeText); // append로 문자열을 전달할 수 있음
jokes.append(newLI);
}
const btn = document.querySelector('button');
btn.addEventListener('click', addNewJoke);
291. TV 프로그램 검색 앱
- 템플릿 리터럴을 사용해 사용자 입력값을 쿼리스트링으로 전달한다.
const form = document.querySelector('#searchForm');
form.addEventListener('submit', async (e) => {
e.preventDefault();
const searchTerm = form.elements.query.value;
const res = await axios.get(`https://api.tvmaze.com/search/shows?q=${searchTerm}`);
makeImages(res.data);
})
const makeImages = (shows) => {
for (let result of shows) {
if (result.show.image) {
const img = document.createElement('IMG');
img.src = result.show.image.medium;
document.body.append(img);
}
}
}
- Axios가 제공하는 방법을 이용해 쿼리스트링이 없는 URL을 쓰고, 매개변수인 params를 입력하는 별도의 객체를 추가해서 요청을 보낼 수 있다.
292. 섹션 주제
- 객체가 작동하는 방식
- 배열과 문자열이 여러 메서드에 엑세스하는 방식
- 새 배열을 만들 때마다 생기는 기능을 직접 복제하는 방법
- 다양한 메서드와 프로퍼티를 반복 및 재사용 가능하게 만드는 방법
- 객체 지향 프로그래밍 (OOP)
new
키워드가 생성자 함수에서 하는 역할
293. 프로토타입이란?
- JavaScript는 프로토타입 기반 객체 지향 언어
- 프로토타입은 JavaScript 객체가 서로 기능을 상속하는 방식의 메커니즘
- 객체는 템플릿 객체 역할을 하는 프로토타입 객체를 가질 수 있다.
- dunder(double underscore) 라고도 부른다.


[[prototype]]
(__proto__
)
- 프로토타입 객체라 불리는 프로퍼티(특성)를 공유한다.
- 청사진 객체에 대한 참조

실제 프로토타입 (템플릿 객체)
- 문자열 프로토타입에 메서드 추가하기

String.prototype.yell = function() {
console.log(this);
};
"hello".yell(); // String {"hello"}
- 배열 프로토타입에 메서드 추가하기

- 프로토타입 객체를 건드릴 일은 거의 없다. 실제 프로토타입에 접근하거나 조작하는 정도
294. 객체 지향 프로그래밍 개요
- 팩토리 함수, 생성자 함수,
new
클래스 키워드, 클래스 생성자, 상속의super
키워드 - 이들 모두 코드를 구성하고 디자인하고 애플리케이션의 구조를 다룬다.
- 확실한 패턴을 가진 객체로 분해 (객체의 패턴 ⇒ 객체의 제조법)
- 나중에 만들어 볼 Color 클래스 미리 살펴보기
- 쿠키 틀로 쿠키 찍기 🍪🍪🍪
- 프로퍼티나 메서드 정의를 포함하는 클래스와 객체 템플릿 생성을 하는 객체 지향 프로그래밍 개념에 익숙해져보자.



295. 팩토리 함수
- 객체를 만드는 함수
- 패턴이나 레시피를 기반으로 한 객체를 만드는 방법 중 하나 (자주 쓰이지 X)
- 비어 있는 상태
{}
로 시작하지만 주어진 인수를 기반으로 속성을 추가한다.
function makeColor(r, g, b) {
const color = {};
color.r = r;
color.g = g;
color.b = b;
color.rgb = function () {
const { r, g, b } = this;
return `rgb(${r}, ${g}, ${b})`;
};
color.hex = function () {
const { r, g, b } = this;
return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
};
return color;
}

296. 생성자 함수
- 팩토리 함수 대신 생성자 패턴(함수)이 많이 쓰인다.
- XMLHttpRequest 예시 (Fetch나 Axios X)
- 이 요청은 패턴에 따라 새로운 객체를 만든다.
new
키워드는 연산자다.
팩토리 함수의 단점
- 팩토리 함수는 새로운 객체를 만들 때마다 빈 객체로 시작한다.
- 인수를 전달해주면 재생성되어서 각 객체에 각각의 복사본이 추가된다.
- 하지만 함수 자체의 고유의 복사본을 각각 만들 필요가 없다.
팩토리 함수의 경우

vs

생성자 함수의 특징
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
- 팩토리 함수는 함수 안에 객체를 만든 뒤, 객체 내부에서 this를 참조하고, 그 객체를 반환한다.
- 생성자 함수(및 클래스) 이름은 대문자로 시작한다.
- 생성자 함수는 함수 내부에서 this를 참조하고, 반환값이 없다.
new
연산자
- 생성자 함수를 new 연산자로 호출하면 다음과 같은 일이 발생한다.
메서드를 생성자 함수 밖에서 프로토타입에 정의하기
function Color(r, g, b) {
this.r = r;
this.g = g;
this.b = b;
this.rgb = function() {
const {r, g, b} = this;
return `rgb(${r}, ${g}, ${b})`;
};
}
function Color(r, g, b) {
this.r = r;
this.g = g;
this.b = b;
}
Color.prototype.rgb = function() {
const {r, g, b} = this;
return `rgb(${r}, ${g}, ${b})`;
};


color1
과color2
인스턴스를 비교해보면color1
은rgb
메서드가 개별 객체에서 정의되고 프로토타입에서 정의되지 않았지만,color2
는r
,g
,b
가 있는 객체가 생긴 것뿐만 아니라rgb
메서드가 개별 객체가 아닌 프로토타입에서 정의된 것을 확인할 수 있다.
- 고유의 복사본이 생긴 것이 아니라서 배열이나 문자열처럼 프로토타입 객체에 엑세스할 수 있다. ⇒ 팩토리 함수보다 효율적

Color 생성자 함수 완성
function Color(r, g, b) {
this.r = r;
this.g = g;
this.b = b;
}
Color.prototype.rgb = function() {
const { r, g, b } = this;
return `rgb(${r}, ${g}, ${b})`;
};
Color.prototype.hex = function() {
const { r, g, b } = this;
return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
}
Color.prototype.rgba = function(a = 1.0) {
const { r, g, b } = this;
return `rgba(${r}, ${g}, ${b}, ${a})`;
}
⇒ 정리
- 생성자 함수 자체는 return이 없는 함수
- 생성자 함수를 실행할 때 앞에
new
키워드를 넣으면 특수한 방식으로 동작한다.
- 즉,
new
키워드는 생성자 함수의 패턴을 기반으로 새로운 객체를 생성하는 연산자
297. JavaScript 클래스
- 위의 Color 생성자 함수를 단독 클래스로 다시 작성해보기.
- 생성자 함수와 비교했을 때 장점은 생성자 함수를 해체해서 메서드를 프로토타입에 각각 추가하지 않아도 된다는 것이다.
class Color {
constructor(){
this.r = r;
this.g = g;
this.b = b;
this.name = name;
}
innerRGB() {
const { r, g, b } = this;
return `${r}, ${g}, ${b}`;
}
rgb() {
return `rgb(${this.innerRGB()})`;
}
rgba(a = 1.0) {
return `rgba(${this.innerRGB()}, ${a})`;
}
hex() {
const { r, g, b } = this;
return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
}
}
- 클래스는
class
키워드로 만들고, 언제나constructor
를 추가한다. 컨스트럭터는 새로운 인스턴스가 만들어질 때마다 즉시 실행된다.
- 클래스 안의 this는 항상 클래스의 인스턴스, 개별 객체를 참조한다.
new
키워드를 쓴다면 prototype이나 함수나 window를 참조하지 않는다.
298. 클래스 연습 더 알아보기
코드
class Color {
constructor(r, g, b, name) {
this.r = r;
this.g = g;
this.b = b;
this.name = name;
this.calcHSL();
}
innerRGB() {
const { r, g, b } = this;
return `${r}, ${g}, ${b}`;
}
rgb() {
return `rgb(${this.innerRGB()})`;
}
rgba(a = 1.0) {
return `rgba(${this.innerRGB()}, ${a})`;
}
hex() {
const { r, g, b } = this;
return (
'#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)
);
}
hsl() {
const { h, s, l } = this;
return `hsl(${h}, ${s}%, ${l}%)`;
}
fulllySaturated() {
const { h, l } = this;
return `hsl(${h},100%, ${l}%)`;
}
opposite() {
const { h, s, l } = this;
const newHue = (h + 180) % 360;
return `hsl(${newHue},${s}%, ${l}%)`;
}
calcHSL() {
let { r, g, b } = this;
// Make r, g, and b fractions of 1
r /= 255;
g /= 255;
b /= 255;
// Find greatest and smallest channel values
let cmin = Math.min(r, g, b),
cmax = Math.max(r, g, b),
delta = cmax - cmin,
h = 0,
s = 0,
l = 0;
if (delta == 0) h = 0;
else if (cmax == r)
// Red is max
h = ((g - b) / delta) % 6;
else if (cmax == g)
// Green is max
h = (b - r) / delta + 2;
else
// Blue is max
h = (r - g) / delta + 4;
h = Math.round(h * 60);
// Make negative hues positive behind 360°
if (h < 0) h += 360;
// Calculate lightness
l = (cmax + cmin) / 2;
// Calculate saturation
s = delta == 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
// Multiply l and s by 100
s = +(s * 100).toFixed(1);
l = +(l * 100).toFixed(1);
this.h = h;
this.s = s;
this.l = l;
}
}
const red = new Color(255, 67, 89, 'tomato');
red.hsl();
red.opposite();
red.rgba(0.3);
const white = new Color(255, 255, 255, 'white');
299. 확장 및 슈퍼 키워드
extend
class Cat {
constructor(name, age) {
this.name = name;
this.age = age;
}
eat() {
return `${this.name} is eating!`;
}
meow() {
return 'MEOWWWW!!';
}
}
class Dog {
constructor(name, age) {
this.name = name;
this.age = age;
}
eat() {
return `${this.name} is eating!`;
}
bark() {
return 'WOOOF!!';
}
}
- Cat과 Dog 클래스에서 복제된 공통의 코드들을 별개의 부모 클래스로 만든 후 자식 클래스로 확장하기
class Pet {
constructor(name, age) {
console.log('IN PET CONSTRUCTOR!');
this.name = name;
this.age = age;
}
eat() {
return `${this.name} is eating!`;
}
}
class Cat extends Pet {
meow() {
return 'MEOWWWW!!';
}
}
class Dog extends Pet {
bark() {
return 'WOOOF!!';
}
}

super
- 자식 클래스에서 상위(super) 클래스의 생성자에 추가 정보가 필요할 때
super
키워드를 쓰면 확장시킨 클래스를 참조할 수 있다.
class Pet {
constructor(name, age) {
console.log('IN PET CONSTRUCTOR!');
[this.name](http://this.name/) = name;
this.age = age;
}
eat() {
return `${this.name} is eating!`;
}
}
class Cat extends Pet {
constructor(name, age, livesLeft = 9) {
console.log('IN CAT CONSTRUCTOR!');
super(name, age);
this.livesLeft = livesLeft;
}
meow() {
return 'MEOWWWW!!';
}
}
300. 섹션 주제
- 백엔드 콘텐츠에는 Node.js, Express, DB, 인증 등 서버 측에서 일어나는 주제들을 포함
- Terminal로 설정을 하는 이유와 중요성
- Shell에서 실행할 수 있는 명령어들과 그 역할
- 상대(Relative) vs 절대(Absolute) 경로(Paths)
301. 백엔드(Backend) 개요
- 서버를 구축하고 데이터베이스에 연결해서 동적 애플리케이션 만들기
- 남은 강의들에서는 주로 Node.js와 데이터베이스로 작업하게 될 것
302. 터미널 명령이란?
- GUI(Graphical User Interface) 방식이 아닌 CLI(Command-line Interface) 방식을 사용하기
303. 터미널 명령을 알아야 하는 이유
- 속도
- 정확하게 작업을 이해하고, 충분히 연습하고, 명령어를 기억해두면 타이핑만으로 작업을 할 수 있기 때문에 속도 면에서 빠르고 효율적이다.
- 엑세스
- Terminal은 컴퓨터에 대한 모든 엑세스 권한 비슷한 걸 제공하는데, 보통은 접근이 완전히 금지되어 있는 다양한 설정이나 소프트웨어 및 운영 체제의 일부분에 대한 엑세스 권한을 가질 수 있다.
- 이 점이 중요한 이유는 특정 작업 능력이 필요한 순간이 있기 때문이다.
- 서버를 시작하거나 프로세스를 중단하기 위해서는 숨겨진 파일을 만들어서 수정하고 특정 설정을 해주어야 한다.
- Node.js , ...
- 사용해야 할 많은 기술과 도구들이 Terminal을 기반으로 한다.
- 탐색, 서버 시작, 노드 실행, DB 연결 및 검사 작업이 모두 Terminal에서 일어난다.
Terminal
- 원래 실체가 있는 물건인 실제 단자를 뜻했다.
- 지금은 실제 앱인 소프트웨어에 해당한다.
Shell
- Terminal에서 실행되는 소프트웨어
- 제일 흔히 쓰이는 것은 bash와 zsh (터미널 앱에서 바꿔 쓸 수 있음)
- bash는 Mac에서 표준으로 쓰여왔고, zsh이 더 최신이라 bash엔 없는 기능들이 있다.
304. Windows 터미널 설치법
- Git Bash 사용
305. 기본 터미널: LS와 PWD
- 새 창을 열면 홈 디렉터리 위치가 자동으로 나타난다.

ls
- list를 의미하며, terminal에 입력할 때마다 현재 있는 디렉터리의 콘텐츠를 나열한다.
~
- 홈 디렉터리를 표시한다.

pwd
- print working directory를 의미하며, 현재 있는 디렉터리의 전체 경로를 표시한다.

306. 디렉토리 변경하기
cd
- change directory를 의미하며, 바꾸고자 하는 디렉터리로 이동한다.

cd
입력 후폴더 이름
을 입력하면 그 폴더로 갈 수 있다.
- 한 디렉터리 뒤로 가려면
cd ..
을 입력하면 된다. (계층 구조 역탐색)
307. 상대 경로와 절대 경로
- 경로(path)는 특정 파일이나 리소스로의 경로를 말한다.
cd /
를 입력해 루트(최상위) 디렉터리로 이동하거나,cd ~
를 입력해 홈 디렉터리로 이동할 수 있다.

절대 경로
- 절대 경로는 루트 디렉터리에서 /로 시작한다.
cd 절대경로
를 입력해 어디서든 해당 위치로 이동할 수 있다.

상대 경로
- 상대 경로는 현재 위치에 따라 작동한다.
두 단계 뒤로 가려면
cd ../../
를 입력한다.

308. 디렉터리 생성하기
mkdir
- make directory를 의미하며, 만들고자 하는 디렉터리 이름을 입력하면 새 폴더를 생성

- 여러 폴더를 한꺼번에 만들 수 있다.

- 다른 위치에 폴더를 만들 수도 있다.


309. 맨(Man) 페이지와 플래그
man
(Mac)
- 매뉴얼을 뜻한다. 파일 시스템에는 영향을 주지 않는다. 정보를 주는 역할

- man 페이지에서
-
부호가 붙은 플래그들을 확인할 수 있다.
q
를 눌러 보고 있던 페이지를 나갈 수 있다.
플래그
- 플래그는 명령어의 동작을 바꾸기 위해 쓰는 문자
ls -l
은 업데이트 시간 정보 등 긴 포맷으로 파일 목록을 확인한다.ls -a
는 숨김 파일을 포함한 모든 내용을 출력한다.ls -la
두 플래그를 결합할 수도 있다.mkdir -v
는 어떤 폴더를 생성했는지 출력한다.


310. 터치 명령
touch
- 파일을 생성하는 명령어.
touch 파일명.확장자
를 입력해 만든다.
- 여러 파일을 동시에 만들 수도 있다.

- 이미 존재하는 파일일 경우 최종 수정된 시간을 간단하게 바꿀 수도 있다.

311. 파일 및 폴더 제거하기
rm
- remove를 의미하며, 파일을 삭제한다.

rmdir
- remove directory를 의미하며, 비어 있는 폴더를 삭제한다.

-rf
- 비어 있지 않은 디렉터리 및 중첩 디렉터리가 여러 개 있어도 삭제를 강행하는 플래그

Terminal은 탁월한 접근성만큼 조심성이 요구된다.
본 스터디는 Udemy의 <【한글자막】 The Web Developer 부트캠프 2022> 강의를 활용해 진행됐습니다. 강의에 대한 자세한 정보는 아래에서 확인하실 수 있습니다.
프밍 스터디는 Udemy Korea와 함께 합니다.