내배캠 30일차

·2022년 12월 13일
0

내일배움캠프

목록 보기
32/142
post-thumbnail

TODO

  • 알고리즘문제
  • 노드입문강의

알고리즘 문제

배수만 뽑아내기

function solution(n, numlist) {
    let answer = [];
    for (let i in numlist) {
        if (numlist[i] % n === 0) {
            answer.push(numlist[i])
        }
    }
    return answer;
}

2차원 배열로 만들기

function solution(num_list, n) {
  let array_index = Math.ceil(num_list.length / n);
  let answer = [];

  for (i = 0; i < array_index; i++) {
    answer.push(num_list.splice(0, n));
  }

  return answer;
}

// function solution(num_list, n) {
//   let result = [];

//   for(let i = 0; i < num_list.length / n; i++){
//       result = [...result, num_list.slice(i * n, i * n + n)];
//   }

//   return result;
// }

console.log(solution([1, 2, 3, 4, 5, 6, 7, 8], 2));

01. Javascript

노드입문(1-1)

동기(Sync)/비동기(Async)

일반적으로 "동기로 실행된다" 라고 함은, 먼저 실행된 코드의 결과가 나올때까지 대기하는 것을 말함.
반대로 "비동기로 실행된다" 라고 함은, 실행된 순서와 관계 없이 결과가 나오는 것.

Blocking & Non-Blocking

Blocking Model이란, 코드의 실행이 끝나기 전까지 실행 제어권을 다른곳에 넘기지 않아 다른 작업을 하지 못하고 대기하는 것을 말함.
Non-Blocking Model이란, 코드의 실행이 끝나지 않아도 실행 제어권을 다른곳에 넘겨 다음 코드가 실행될 수 있는것을 말함.

  • 자바스크립트는 Async + Non-Blocking Model을 채용하여 현재 실행중인 코드의 실행이 끝나지 않아도 다음 코드를 호출.
  • 결론적으로 자바스크립트는 각 명령들이 순서대로 실행될 수 있게 구현되어 있지만, Non-Blocking Model에 의해 동기적 명령이 아닌 모든 함수는 비동기적으로 실행.

동기, 비동기와 뭐가 다른걸까?

  • 제어권을 넘기면(Non-blocking) 다른 코드도 실행될 수 있으므로 비동기 처리가 가능

  • 제어권을 넘기지 않으면(Blocking) 비동기 처리가 가능한 환경이어도 비동기 처리가 불가능.(JAVA,C)

  • javascript는 async + non-blocking model을 채용하여 현재 실행중인 코드의 실행이 끝나지 않아도 다음 코드를 호출.
    즉, 자바스크립트는 각 명령들이 순서대로 실행될 수 있게 구현되어 있지만, Non-blocking에 의해 명령이 아닌 모든 함수는 비동기적으로 실행됨.

프로미스(Promise)

자바스크립트에서 비동기 처리동기로 처리할 수 있게 돕는 Built-in(미리 내부적으로 정의된)객체 유형입니다.

단어 그대로 ‘언제 진행할지 약속’ 언제 진행할지란, 바로 비동기 명령의 실행이 완료된 이후를 말하는 것.

Promise 생성자 인터페이스

executor에는 함수만 올 수 있으며 인자로 resolve, reject가 주입됩니다.

  • executorPromise실행 함수라고 불리고, Promise가 만들어질 때 자동으로 실행됩니다.
    Promise가 연산을 언제 종료하는지 상관하지 않고, resolve(성공했을때), reject(실패했을때) 중 하나를 무조건 호출해야합니다.
new Promise(executor);

// 예제
new Promise((resolve, reject) => {
	// 명령문
});

생성자(Constructor)?

Javascript에서는 원시 타입(String, Boolean 등) 을 제외한 대부분의 타입들이 객체(Object) 로 구성되어 있음.

일반적으로 객체(Object)를 생성하는 함수를 생성자(Constructor) 함수라고 부르게 되는데, Promise 또한 객체로 구성되어 있기 때문에 생성자 함수를 이용해 Promise를 선언함.

function printFunc(data){
  console.log(data);
}

// 생성자 함수
const obj = new Object();
const promise = new Promise(printFunc); // 성공하면 printFunc실행

obj
// Print : {}

Promise 상태

Promise는 반드시 3가지 상태를 지니며, 대기(Pending) 상태가 아니라면 Promise의 연산이 이미 끝난 상태로 볼 수 있습니다.

  • 대기(Pending): 이행하거나 거부되지 않은 초기 상태.
  • 이행(Fulfilled): 연산이 성공적으로 완료됨.
  • 거부(Rejected): 연산이 실패함.

Fulfilled Promise

  • Promise가 만들어 질 때 executor가 실행되며, executor에서 resolve 함수가 호출되기 전까지 firstPromise.then(...) 안에 있는 코드를 실행하지 않습니다.

이렇게 executor 가 실행되어 resovle된 프로미스를 Fulfilled Promise라고도 부릅니다.

const timerPromise = new Promise((resolve, reject) => { // 이곳에 정의된 함수가 executor
  setTimeout(() => {
	  console.log('First');
		resolve();
	}, 1000);
});

// 이 시점에서 timerPromise는 Fulfilled Promise라고 부를 수 있다.

timerPromise.then(() => {
	console.log('Middle');
	console.log('Last');
});

// Print: First
// Middle
// Last

Promise.then

Promise 안에서 resolve가 실행 된 경우 then 메서드에 작성된 함수가 실행됩니다.

const resolvePromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    console.log('First');
    resolve('Resolve!'); // resolve를 실행할 때, 안에 데이터를 넣어줄 수 있습니다.
  }, 1000);
});

resolvePromise.then((data) => {
  console.log('Middle');
  console.log('Last');
  console.log(data);
})

// Print: First -> 1초 뒤에 출력됩니다.
// Middle
// Last
// Resolve!

Promise.catch

Promise 안에서 에러가 throw 되거나 reject가 실행되면 catch 메서드에 작성한 함수가 실행됩니다.

const errorPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
	  console.log('First');
		reject('Error!!'); // 직접 reject를 실행하면 프로미스에서 에러가 발생한것으로 간주됩니다.
	}, 1000);
});

errorPromise.then(() => {
	console.log('Middle');
	console.log('Last');
}).catch((error) => {
	console.log('에러 발생!', error);
});

// Print: First -> 1초 뒤에 출력됩니다.
// Print: '에러 발생! Error!!'

Promise.then 더 알아보기

  1. Promise에서 resolve 된 값 이용하는 방법
const firstPromise = new Promise((resolve, reject) => {
  resolve('First');
});

firstPromise.then((value) => {
	console.log(value);
});

// Print: 'First'
  1. Promise.resolve 함수 이용
const firstPromise = Promise.resolve('First');

firstPromise.then((value) => {
	console.log(value);
});

// Print: 'First'
  1. Promise.then`으로 함수형 프로그래밍 체험하기

이것이 가능한 이유는 console.log라는 함수 뒤에 괄호를 사용해서 함수를 호출하지 않고, 함수를 그대로 then에 넘겼기 때문입니다.

const firstPromise = Promise.resolve('First');

firstPromise.then(console.log);

// Print: 'First'
  1. Promise.then으로 함수형 프로그래밍 체험하기 2
const countPromise = Promise.resolve(0);

function increment(value) {
	return value + 1;
}

const resultPromise = countPromise.then(increment).then(increment).then(increment);
resultPromise.then(console.log);

// Print: 3

비동기 함수 (Async Function)

비동기 함수는 일반 함수나 화살표 함수와 아주 비슷하지만 딱 두가지만 다르다.

  1. 비동기 함수결과 값항상 Promise 객체로 resolve된다.
  2. 비동기 함수 안에서만 await 연산자를 사용할 수 있다.

이 두가지 특징을 제외하면 기존처럼 일반 함수나, 화살표 함수처럼 사용할 수 있음.

// 비동기 + 일반 함수
async function 함수이름() {
	// 명령문
}

// 비동기 + 익명 함수
async function() {
  // 명령문
}

// 비동기 + 화살표 함수
async () => {
	// 명령문
}

이러한 특징은 마치 아래처럼 작성하는것과 굉장히 비슷함.

function 함수이름() {
	return Promise.resolve('값');
}

// 위와 아래의 함수는 같은 동작을 보여준다.

async function 함수이름2() {
	return '값';
}

함수이름();
// Print: Promise { '값' }

함수이름2();
// Print: Promise { '값' }

그럼 비동기 함수는 왜 쓸까??

  1. 아래에서 배울 await 연산자를 비동기 함수 안에서만 사용할 수 있는데, 이를 활용하면 문법이 훨씬 간결해질 수 있기 떄문이다.
  2. new Promise(executor) 코드로 Promise를 직접 생성하면 executor가 바로 실행되는것과 달리, 비동기 함수는 함수가 실행되기 전까지 Promise를 생성하지 않는다.

await 연산자

  • await 연산자를 사용하면 Promisefulfill 상태가 되거나 rejected될 때 까지 함수의 실행을 중단하고 기다릴 수 있습니다.
    Promise의 연산이 끝나면 함수에서 반환한 값을 얻을 수 있습니다.
  • await 연산자는 async 함수 안에서만 사용할 수 있습니다.
const result = await;

아래처럼 "값" 에는 Promise가 아닌 다른 값도 들어갈 수 있습니다.
Promise가 아니라면 기다리지 않고 해당 값 자체를 그대로 반환합니다.

async function 함수이름() {
	const result = await 'Test!';
	console.log(result);
}

함수이름();
// Print: 'Test!';

await 활용예제

await 사용

await이 없었을때는 setTimeoutFunc가 1초가 지난 뒤 마지막에 실행되었지만,
await을 사용하면 setTimeoutFunc가 실행된 뒤 종료되었다는 console.log가 실행된다.

await 사용 결과

노드입문(1-2)

객체리터럴

리터럴(literal)은 사람이 이해할 수 있는 문자 또는 약속된 기호를 사용해 값을 생성하는 표기법입니다.

여기서 객체 리터럴은 객체를 생성하기 위한 표기법입니다.

객체 리터럴은 객체를 생성하기 위해 Class를 먼저 선언하고 new 연산자와 함께 생성자를 호출할 필요가 없이 일반적인 숫자, 문자열을 만드는것과 유사하게 객체를 생성할 수 있습니다.

객체 리터럴로 객체 생성하기

  • 객체 리터럴은 중괄호 {} 내에 0개 이상의 프로퍼티를 정의해서 선언합니다.
let objectLiteral = {
    key: 'Value',
    helloWorld: function () {
        return "Hello world";
    } // 2개의 프로퍼티
};

프로퍼티(Property) 란?

객체의 상태를 나타내는 (Data)입니다.

프로퍼티는 (Key)와 (Value)으로 구성되어 있습니다.

프로퍼티 키는 따옴표를 안써줘도 되지만 띄어쓰기가 있거나 변수로 할당될 수 없는 경우에는 따옴표를 사용함!

const human = {
  // 프로퍼티 키: 'name', 프로퍼티 값: '이용우' 
  name: '이용우',
  // 프로퍼티 키: 'human age', 프로퍼티 값: 28 
  'human age': 28
}

메서드(Method) 란?

프로퍼티를 참조하고 조작할 수 있는 동작(behavior)을 나타냅니다.

간단히, 객체의 프로퍼티 값이 함수로 구성되어 있을 경우 메서드(Method)라고 부릅니다.

let objectLiteral = {
    key: 'Value', // 프로퍼티
    helloWorld: function () { // 메서드
        return "Hello world";
    }
};

console.log(objectLiteral.helloWorld()); // Hello world

노드입문(1-3)

Error handling

에러 핸들링은 에러를 관리하는 방법이고, 예상치 못한 상황에 대처하는 방식

에러는 예상할 수 있는 에러예상치 못한 에러로 구분할 수 있는데, 일반적인 어플리케이션을 설계할 때에는 예상치 못한 에러 상황이 더욱 많이 일어날 것으로 가정해야한다.

프로그래머가 작성한 코드에서 예상치 못한 에러가 일어날 가능성은 언제나 존재하고, 이러한 에러 상황을 대비해 언제든지 처리할 수 있어야 합니다.

try / catch

서버에서 에러가 발생하지 않게 하기 위해서 저희는 예외 처리를 진행합니다.

예외 처리는 일반적으로 try … catch 문을 사용합니다.

users에 들어있는 이름들을 String.toUpperCase()를 이용하여 대문자로 변경하려할 때 문자열(String)이 아닌 데이터가 들어온다면 에러가 발생합니다.

이렇게 예상치 못한 에러에 대처하기 위해선 try … catch문으로 코드 전체를 감쌀 수 있습니다.

에러가 발생하더라도 프로그램이 멈추지 않고 에러를 기록할 수 있습니다.

const users = ["Lee", "Kim", "Park", 2];

try {
  for (const user of users) {
    console.log(user.toUpperCase());
  }
} catch (err) {
  console.error(`Error: ${err.message}`);
}

// LEE
// KIM
// PARK
// Error: user.toUpperCase is not a function

throw

throw를 호출하면 그 즉시 현재 실행되고 있는 함수는 실행을 멈추게 됩니다.

프로그래머의 입장에서 에러는 고의로 에러를 발생시키기도 해야한다.

예를 들어서 은행 어플리케이션의 현금 인출 서비스를 만든다고 할 때, 계좌의 잔고가 요청받은 금액보다 적다면 현금 인출을 막고 예외를 발생시켜야겠죠? 이럴때 사용하는 것이 throw입니다.

function withdraw(amount, account) {
  if (amount > account.balance) {
    throw new Error("잔고가 부족합니다.")
  };
  account.balance -= amount;
	console.log(`현재 잔고가 ${account.balance}남았습니다.`); // 출력되지 않음
}

const account = { balance: 1000 };
withdraw(2000, account);

// Error: 잔고가 부족합니다.

finally(try / catch)

finally는 에러가 발생했는지 여부와 상관없이 언제든지 실행됩니다.

try 에서는 HTTP연결이 되고 있거나 파일과 같은 특정한 ‘자원’을 가지고 처리할 때가 있습니다. 하지만 해당 ‘자원'을 계속 가지고 있으면, 무의미한 메모리를 차지하게 될 것 이므로 에러 여부와 상관없이 일정 시점에서는 해당 ‘자원'을 삭제 시켜야합니다.

그렇다면 이 ‘자원'을 삭제하는 시점은 언제가 되어야 할까요? 에러가 언제든지 발생할 수 있는 try? 아니면 에러가 일어났을 때 실행되는 catch? 이런 상황에서는 finally가 필요합니다.

function errorException(isThrow) {
  try {
    console.log('자원을 할당하였습니다.');
    if (isThrow) throw new Error();
  } catch (error) {
    console.log('에러가 발생했습니다.');
  } finally {
    console.log('자원을 제거하였습니다.');
  }
}

errorException(false);
// 자원을 할당하였습니다.
// 자원을 제거하였습니다.
errorException(true);
// 자원을 할당하였습니다.
// 에러가 발생했습니다.
// 자원을 제거하였습니다.

노드입문(1-4)

class

현실과 비슷한 개념(객체)을 나타내기 위한 도구를 클래스(Class)라고 부릅니다.

클래스는 미리 정의해놓으면 필요할 때마다 해당 클래스로 동일한 틀을 가진 객체를 만들 수 있습니다.

여기서 동일한 클래스를 이용해 생성한 객체를 인스턴스(Instance)라고 부릅니다.

class User { 
}

const user = new User();
user.name = "이용우";
user.age = 28;
user.tech = "Node.js";

console.log(user.name); // 이용우
console.log(user.age); // 28
console.log(user.tech); // Node.js

생성자

클래스 내부에서 constructor()로 정의한 메서드를 "생성자"라고 부릅니다.

미리 정의한 클래스를 기반으로 인스턴스를 생성할 때 Javascript 내부에서 호출되는 메서드

생성자의 바디에서 this 키워드를 사용 => this는 클래스를 사용해 만들어 질 객체 자신을 의미하고 this 뒤에 붙는 name, age, tech는 클래스를 이용해서 만들어질 객체의 속성(Propety)입니다.

class User {
  constructor(name, age, tech) { // User 클래스의 생성자
    this.name = name;
    this.age = age;
    this.tech = tech;
  }
}

const user = new User("이용우", 28, "Node.js"); // user 인스턴스 생성

console.log(user.name); // 이용우
console.log(user.age); // 28
console.log(user.tech); // Node.js

메서드(Method)

메서드는 객체(Object) 에 묶여 있는 함수를 의미합니다.

클래스에서도 데이터를 나타내는 속성뿐만아니라 함수와 같이 특정 코드를 실행할 수 있는 문법을 사용할 수 있다.

class User {
  constructor(name, age, tech) { // User 클래스의 생성자
    this.name = name;
    this.age = age;
    this.tech = tech;
  }

  getName() { return this.name; } // getName 메서드
  getAge() { return this.age; }.  // getAge 메서드
  getTech() { return this.tech; } // getTech 메서드
}

const user = new User("이용우", "28", "Node.js"); // user 인스턴스 생성
console.log(user.getName()); // 이용우
console.log(user.getAge()); // 28
console.log(user.getTech()); // Node.js

상속

일반적으로 클래스의 인스턴스는 선언한 클래스의 기능을 모두 상속합니다.

상속을 이용해 부모 클래스자식 클래스로 나뉠 수 있는데요. 부모 클래스의 경우 메서드, 내부 변수와 같은 정보를 자식 클래스에게 할당해줄 수 있습니다.

class User { // User 부모 클래스
  constructor(name, age, tech) { // 부모 클래스 생성자
    this.name = name;
    this.age = age;
    this.tech = tech;
  }
  getTech(){ return this.tech; } // 부모 클래스 getTech 메서드
}

class Employee extends User{ // Employee 자식 클래스
  constructor(name, age, tech) { // 자식 클래스 생성자
    super(name, age, tech);
  }
}

const employee = new Employee("이용우", "28", "Node.js");
console.log(employee.name); // 이용우
console.log(employee.age); // 28
console.log(employee.getTech()); // 부모 클래스의 getTech 메서드 호출: Node.js

우선 User 클래스를 정의하고, Employee라는 이름의 새로운 클래스가 User를 상속합니다. 생성자 내부의 super()는 생성자 내에서만, 그리고 this 키워드를 사용하기 전에만 쓸 수 있습니다.

  • EmployeeUser의 서브 클래스로 정의합니다.

  • User의 자식 클래스인 Employee에서 User.getTech() 메서드를 호출합니다.

  • ❓ super 키워드는 무엇인가요?

    super 키워드는 함수처럼 호출할 수도 있고, this와 같이 식별자처럼 참조할 수 있는 키워드입니다.

    super 키워드를 호출하면 부모 클래스생성자(constructor)를 호출합니다.

    super 키워드를 참조하면 부모 클래스메서드(Method)를 호출할 수 있습니다.

노드입문(quiz)

  • 요구 사항
    1. Unit 클래스를 만든다.
    2. 클래스 생성자에서 내부변수 name, hp를 정의한다.
    3. healing, damaged 메서드를 정의한다.
    4. healing 메서드는 hp를 올릴 수 있고 hp가 100이 넘을 경우 더이상 회복되지 않는다.
    5. damaged 메서드는 hp를 감소 시킬 수 있고 hp가 0이 넘을 경우 더이상 감소되지 않는다.
    6. hp가 0이 되었을 경우 더이상 healing 메서드와 damaged 메서드가 동작하지 않는다.
class Unit {
  constructor(name, hp) {
    this.name = name;
    this.hp = hp;
  }

  healing(heal) {
    if (this.hp === 0) {
      return;
    }
    this.hp += heal;
    if (this.hp >= 100) {
      this.hp = 100;
    }
    console.log(this.name, this.hp);
  }

  damaged(damage) {
    if (this.hp === 0) {
      return;
    }
    this.hp -= damage;
    if (this.hp <= 0) {
      this.hp = 0;
    }
    console.log(this.name, this.hp);
  }
}

const unit = new Unit("유닛", 100);
unit.damaged(70); // 30
unit.healing(10); // 40
unit.damaged(50); // 0
unit.healing(100); // 작동안함.

02. HTTP / WEB SERVER

03. Package Manager

04. Express.js

profile
개발자 꿈나무

0개의 댓글