스터디 포스트 >  웹 개발 실전 프로젝트

Javascript 뿌시기 2-2

조재홍 멘토
이로운 개발자가 되고 싶은 조재홍입니다.

웹 개발 실전 프로젝트 - 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);
	})
notion image
notion image
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);
	})
notion image
notion image
 
  • 로그인은 서버의 데이터베이스에서 암호화된 정보를 확인하는 데 시간이 걸린다. 즉각적인 반응 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 객체 문법)
notion image
  • JavaScript에서 사용 가능한 값 형식
  • undefined는 없다.
  • JSON과 JavaScript는 동일하지 않다.
  • Python, Ruby 등 다른 언어에서도 JSON을 파싱해서 사용한다.

JSON.parse()

  • JavaScript에서 JSON을 유효한 객체로 바꾸는 메서드
  • 문자열을 전달하면 파싱되어 JavaScript 객체로 변환된다.

JSON.stringify()

  • JavaScript 객체인 정보를 JSON으로 변환하는 메서드
  • JSON 형식의 데이터를 받는 API에 정보를 보낼 때 유용
    • undefined 값은 모두 null로 바뀐다.
    • 미지원 데이터 타입을 감지하고 필요 시 큰따옴표를 붙인다.
 

285. Postman 사용하기

  • HTTP 요청과 응답의 세부적인 내용 살펴보기
    • 다양한 API에 요청을 보내는 방법, 요청이 어떻게 구조화되는지, 다양한 상태 코드, 헤더, 쿼리, 문자열의 의미 등
 
notion image

HTTP 동사들

  • 보낼 수 있는 요청의 타입들
  • GET 요청은 정보를 검색해서 가져올 때 사용한다.
  • POST 요청은 DB에 저장 혹은 업데이트하기 위해 서버로 데이터를 보낼 때 사용한다.
 

HTTP 상태 코드

  • 2로 시작하는 코드는 성공, 3으로 시작하는 코드는 리디렉션을 의미한다.
  • 400번대 코드는 클라이언트 오류, 500번대 코드는 서버 오류를 의미한다.
  • 포스트맨으로 요청을 보내고 우측 상단에서 상태 코드를 확인할 수 있다.
비트코인 API에 GET 요청을 보냈더니 Cloudflare가 DDoS 공격을 차단하고 있어 JSON 포맷 데이터 대신 HTML 데이터가 넘어오고 있다.
비트코인 API에 GET 요청을 보냈더니 Cloudflare가 DDoS 공격을 차단하고 있어 JSON 포맷 데이터 대신 HTML 데이터가 넘어오고 있다.
 

286. 문자열 및 헤더 쿼리

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

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를 사용하는 방법들 - 예시에서는 jsDelivr CDN 사용
axios를 사용하는 방법들 - 예시에서는 jsDelivr CDN 사용
  • 완전히 파싱된 응답 객체를 반환한다.
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) 라고도 부른다.
notion image
프로토타입 객체에서 정의된 배열의 내장 메서드들을 볼 수 있다.
프로토타입 객체에서 정의된 배열의 내장 메서드들을 볼 수 있다.

[[prototype]] (__proto__)

  • 프로토타입 객체라 불리는 프로퍼티(특성)를 공유한다.
    • 청사진 객체에 대한 참조
      • dog은 String을 참조한다.
        dog은 String을 참조한다.

실제 프로토타입 (템플릿 객체)

  • 문자열 프로토타입에 메서드 추가하기
    • 문자열 템플릿이 grumpus 프로퍼티를 갖게 되었다.
      문자열 템플릿이 grumpus 프로퍼티를 갖게 되었다.
      String.prototype.yell = function() { 
      	console.log(this);
      };
      
      "hello".yell(); // String {"hello"}
      💡 this는 메서드를 호출하는 문자열을 참조한다.
  • 배열 프로토타입에 메서드 추가하기
기존 pop 메서드를 수정했다.
기존 pop 메서드를 수정했다.
  • 프로토타입 객체를 건드릴 일은 거의 없다. 실제 프로토타입에 접근하거나 조작하는 정도
 

294. 객체 지향 프로그래밍 개요

  • 팩토리 함수, 생성자 함수, new 클래스 키워드, 클래스 생성자, 상속의 super 키워드
    • 이들 모두 코드를 구성하고 디자인하고 애플리케이션의 구조를 다룬다.
    • 확실한 패턴을 가진 객체로 분해 (객체의 패턴 ⇒ 객체의 제조법)
  • 나중에 만들어 볼 Color 클래스 미리 살펴보기
  • 쿠키 틀로 쿠키 찍기 🍪🍪🍪
  • 프로퍼티나 메서드 정의를 포함하는 클래스와 객체 템플릿 생성을 하는 객체 지향 프로그래밍 개념에 익숙해져보자.
 
XHR 생성 방법을 배울 때 사용했던 XMLHttpRequest
XHR 생성 방법을 배울 때 사용했던 XMLHttpRequest
notion image
 
HTMLHeadingElement는
h1 태그 객체를 생성하는 제조법
HTMLHeadingElement는 h1 태그 객체를 생성하는 제조법

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;
}
notion image

296. 생성자 함수

  • 팩토리 함수 대신 생성자 패턴(함수)이 많이 쓰인다.
  • XMLHttpRequest 예시 (Fetch나 Axios X)
    • 이 요청은 패턴에 따라 새로운 객체를 만든다.
  • new 키워드는 연산자다.
 

팩토리 함수의 단점

  • 팩토리 함수는 새로운 객체를 만들 때마다 빈 객체로 시작한다.
  • 인수를 전달해주면 재생성되어서 각 객체에 각각의 복사본이 추가된다.
  • 하지만 함수 자체의 고유의 복사본을 각각 만들 필요가 없다.
팩토리 함수의 경우
참조(reference)값을 비교하므로 false.
참조(reference)값을 비교하므로 false.
 

vs

프로토타입에 위치한 하나의 함수를 참조하므로 true
프로토타입에 위치한 하나의 함수를 참조하므로 true

생성자 함수의 특징

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})`;
};
notion image
notion image
  • color1color2 인스턴스를 비교해보면 color1rgb 메서드가 개별 객체에서 정의되고 프로토타입에서 정의되지 않았지만, color2r, g, b가 있는 객체가 생긴 것뿐만 아니라 rgb 메서드가 개별 객체가 아닌 프로토타입에서 정의된 것을 확인할 수 있다.
  • 고유의 복사본이 생긴 것이 아니라서 배열이나 문자열처럼 프로토타입 객체에 엑세스할 수 있다. ⇒ 팩토리 함수보다 효율적
같은 reference끼리의 비교이므로 true가 나온다.
같은 reference끼리의 비교이므로 true가 나온다.

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!!';
	}
}
 
Dog에 생성자가 없더라도 Pet에서 확장시킴
Dog에 생성자가 없더라도 Pet에서 확장시킴

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. 터미널 명령을 알아야 하는 이유

  1. 속도
      • 정확하게 작업을 이해하고, 충분히 연습하고, 명령어를 기억해두면 타이핑만으로 작업을 할 수 있기 때문에 속도 면에서 빠르고 효율적이다.
  1. 엑세스
      • Terminal은 컴퓨터에 대한 모든 엑세스 권한 비슷한 걸 제공하는데, 보통은 접근이 완전히 금지되어 있는 다양한 설정이나 소프트웨어 및 운영 체제의 일부분에 대한 엑세스 권한을 가질 수 있다.
      • 이 점이 중요한 이유는 특정 작업 능력이 필요한 순간이 있기 때문이다.
      • 서버를 시작하거나 프로세스를 중단하기 위해서는 숨겨진 파일을 만들어서 수정하고 특정 설정을 해주어야 한다.
  1. Node.js , ...
      • 사용해야 할 많은 기술과 도구들이 Terminal을 기반으로 한다.
      • 탐색, 서버 시작, 노드 실행, DB 연결 및 검사 작업이 모두 Terminal에서 일어난다.

Terminal

  • 원래 실체가 있는 물건인 실제 단자를 뜻했다.
  • 지금은 실제 앱인 소프트웨어에 해당한다.

Shell

  • Terminal에서 실행되는 소프트웨어
  • 제일 흔히 쓰이는 것은 bash와 zsh (터미널 앱에서 바꿔 쓸 수 있음)
  • bash는 Mac에서 표준으로 쓰여왔고, zsh이 더 최신이라 bash엔 없는 기능들이 있다.
 

304. Windows 터미널 설치법

  • Git Bash 사용

305. 기본 터미널: LS와 PWD

  • 새 창을 열면 홈 디렉터리 위치가 자동으로 나타난다.
    • notion image

ls

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

~

  • 홈 디렉터리를 표시한다.
    • notion image

pwd

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

306. 디렉토리 변경하기

cd

  • change directory를 의미하며, 바꾸고자 하는 디렉터리로 이동한다.
    • notion image
  • cd 입력 후 폴더 이름을 입력하면 그 폴더로 갈 수 있다.
  • 한 디렉터리 뒤로 가려면 cd .. 을 입력하면 된다. (계층 구조 역탐색)
 

307. 상대 경로와 절대 경로

  • 경로(path)는 특정 파일이나 리소스로의 경로를 말한다.
  • cd / 를 입력해 루트(최상위) 디렉터리로 이동하거나, cd ~ 를 입력해 홈 디렉터리로 이동할 수 있다.
    • notion image

절대 경로

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

상대 경로

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

308. 디렉터리 생성하기

mkdir

  • make directory를 의미하며, 만들고자 하는 디렉터리 이름을 입력하면 새 폴더를 생성
    • notion image
  • 여러 폴더를 한꺼번에 만들 수 있다.
    • notion image
  • 다른 위치에 폴더를 만들 수도 있다.
    • notion image
      notion image

309. 맨(Man) 페이지와 플래그

man(Mac)

  • 매뉴얼을 뜻한다. 파일 시스템에는 영향을 주지 않는다. 정보를 주는 역할
    • notion image
  • man 페이지에서 - 부호가 붙은 플래그들을 확인할 수 있다.
  • q 를 눌러 보고 있던 페이지를 나갈 수 있다.

플래그

  • 플래그는 명령어의 동작을 바꾸기 위해 쓰는 문자
    • ls -l 은 업데이트 시간 정보 등 긴 포맷으로 파일 목록을 확인한다.
      • notion image
    • ls -a 는 숨김 파일을 포함한 모든 내용을 출력한다.
    • ls -la 두 플래그를 결합할 수도 있다.
    • mkdir -v 는 어떤 폴더를 생성했는지 출력한다.
      • notion image
 

310. 터치 명령

touch

  • 파일을 생성하는 명령어. touch 파일명.확장자 를 입력해 만든다.
  • 여러 파일을 동시에 만들 수도 있다.
    • notion image
  • 이미 존재하는 파일일 경우 최종 수정된 시간을 간단하게 바꿀 수도 있다.
    • notion image
 

311. 파일 및 폴더 제거하기

rm

  • remove를 의미하며, 파일을 삭제한다.
    • notion image

rmdir

  • remove directory를 의미하며, 비어 있는 폴더를 삭제한다.
    • notion image

-rf

  • 비어 있지 않은 디렉터리 및 중첩 디렉터리가 여러 개 있어도 삭제를 강행하는 플래그
    • notion image
 
💡
Terminal은 탁월한 접근성만큼 조심성이 요구된다.
 
 
 
 
본 스터디는 Udemy의 <【한글자막】 The Web Developer 부트캠프 2022> 강의를 활용해 진행됐습니다. 강의에 대한 자세한 정보는 아래에서 확인하실 수 있습니다.
 
 
프밍 스터디는 Udemy Korea와 함께 합니다.
 
 
원하는 스터디가 없다면? 다른 스터디 개설 신청하기
누군가 아직 원하는 스터디를 개설하지 않았나요? 여러분이 직접 개설 신청 해 주세요!
이 포스트는
"웹 개발 실전 프로젝트" 스터디의 진행 결과입니다
진행중인 스터디
웹 개발 실전 프로젝트
JavaScript를 이용한 DOM 조작으로 프론트엔드 분야를 배우고, Node JS와 Express, DB, HTTP, REST API 등 백앤드 지식을 학습할수 있습니다. 이론만 공부하는 스터디가 아니라 13개 이상의 프로젝트로 이루어진 실습 위주의 커리큘럼으로 개인 프로젝트 결과물을 가져갈 수 있다는 메리트가 있습니다.
조재홍 멘토
이로운 개발자가 되고 싶은 조재홍입니다.