[programmers] TIL_DAY-02

2022.03.22(화)

🗒 목차

  1. 함수형 프로그래밍

  2. 프로토타입

  3. 이벤트 루프

  4. 모듈

  5. 정규표현식

  6. 쿠키와 세션, 웹 스토리지

✅ 1. 함수형 프로그래밍

패러다임은 무엇을 해야 할지를 말하기보다 무엇을 해서는 안 되는지를 말해준다. - Robert C. Martin

 이번에 공부하면서 완전히 잘못 알고 있었던 내용 중 하나가 프로그래밍 언어마다 하나의 패러다임만을 사용할 수 있다고 생각했던 것이다. C++은 객체지향 프로그래밍 C는 절차지향 프로그래밍, GO와 같은 언어는 함수형프로그래밍만 사용가능한 언어라고 생각했었다.

 또한 시대적으로 절차지향 언어에서 객체지향 언어로 넘어왔고 현재는 함수형 언어가 떠오름에 따라 함수형 프로그래밍이 가장 좋은 패러다임이라는 잘못된 생각을 갖고 있었다.

 하지만 패러다임이라는 것은 프로그램의 (순차, 분기, 반복, 참조) 4가지 요소를 어떻게 이용할 것인가에 의해 결정되고 상황에 따라 적절한 패러다임이 있을뿐 패러다임간 우위는 없다는 것을 알게 되었다.

 함수형 프로그래밍은 기존의 명령형 프로그래밍이 아닌 선언형 프로그래밍에 가까운 패러다임으로 문제를 어떻게 해결해야 하는지에 초점을 맞추기 보다 무엇을 해결해야 할지에 집중하고 해결 방법은 컴퓨터에게 위임하는 방법이라는 것도 알게 되었다. 이 문장이 잘 이해하지 못해서 구글에 검색해본 결과 좋은 예시가 있었다.

나는 회사에서 열심히 일하고 퇴근을 한 뒤 Red Lobster에서 가족과 즐거운 외식을 하기로 결정했습니다. 그리고 Red Lobster에 도착한 뒤 안내 데스크에 다가가서 말합니다.

명령형 방식 (HOW) : "12번 테이블 자리가 비어있습니다. 나와 우리 가족은 저 자리로 걸어가 앉을 것입니다."
선언형 방식 (WHAT) : "네 명 앉을자리를 부탁해요"

위의 예시를 보면 알겠지만 명령형 방식은 내가 실제로 자리에 "어떻게" 자리에 앉을지 에 관심이 있습니다. 
따라서 "어떻게" 자리에 앉을지에 대한 단계를 하나하나 나열해야 합니다. 
그와 반대로 선언형 방식은 내가 "무엇을" 원하는지에 더 집중되어 있습니다.

출처: https://boxfoxs.tistory.com/430 [박스여우 - BoxFox]

c결론적으로 지금 배우고 있는 자바스크립트는 멀티 패러다임이 가능한 언어로 객체지향 또는 함수형으로 구분지을 필요 없이 필요한 상황에 맞춰 적절한 패러다임을 사용할 수 있는 능력을 키워야 겠다.

✅ 2. 프로토타입

자바스크립트의 객체만으로 객체지향 프로그래밍이 가능한데 프로토타입은 왜 필요하지?

 JavaScript는 클래스라는 개념이 없다. 그래서 기존의 객체를 복사하여 새로운 객체를 생성하는 프로토타입 기반 언어다. 프로토타입 기반 언어는 객체 원형인 프로토타입을 이용하여 새로운 객체를 만들어 낸다. 이렇게 생성된 객체 역시 또 다른 객체의 원형이 될 수 있다. 프로토타입은 객체를 확장하고 객체지향적인 프로그래밍을 할 수 있게 해준다.

 프로토타입은 크게 두 가지로 해석된다. 프로토타입 객체를 참조하는prototype 속성과 객체 멤버인 proto 속성이 참조하는 숨은 링크가 있다. 이 둘의 차이점을 이해하기 위해서는 JavaScript 함수와 객체의 내부적인 구조를 이해해야 한다.

const user = {
	name: "Minki",
}

 위와 같은 객체에서 user.name을 출력하면 Minki라는 값이 나온다. 객체가 property를 갖고 있는지 확인하는 함수 hasProperty를 사용하면

console.log(user.hasOwnProperty("name"); // true
console.log(user.hasOwnProperty("age"); // false

여기서 사용한 hasOwnProperty는 어디에 있는가? 객체를 만들때 저런 함수를 추가한 적이 없었는데 오류없이 사용가능한 이유는?

객체 내부에 __proto__ 라는 객체가 생성되어 있다.
우선 적으로 user객체 내부에서 hasOwnProperty 메소드를 찾고 없을 경우 proto에서 찾는다. 만약 hasOwnProperty 메소드를 user 객체내부에 만든다면 객체 내부에 있는 메소드가 사용된다. 객체 내부에 메소드가 있을 경우 탐색을 멈추기 때문에 proto에 있는 메소드는 사용되지 않는다.

const cat = {
  legs: 4,
  cute: true,
  color: "brown",
  eat() {
    console.log("eat!")
  }
}

const dog = {
  legs: 4,
  cute: true,
  age: 3,
  eat() {
    console.log("eat!")
  }
}

위 객체에서 legs, cute, eat은 중복되는 속성이다. 이 때 prototype을 사용하면 중복을 막을 수 있다.

const animal = {
  legs: 4,
  cute: true,
  color: "white",
  eat() {
  	console.log("eat!");
  }
}
// animal 상위 개념의 객체를 만들고
const cat = {
  color: "brown",
}

const dog = {
  color: "white",
}
// cat, dog 객체의 proto에 상위 객체 animal을 추가한다.
cat.__proto__ = animal; 
dog.__proto__ = animal;

dog, cat은 animal을 상속 받는다. 따라서 cat.cute를 사용해도 정상적으로 true 가 출력된다. 이러한 상속 관계는 계속 이어질 수 있다. (Prototype Chain)

const Animal = function (color) {
  this.color = color;
};

// ** 방법 1 **
Animal.prototype.legs = 4;
Animal.prototype.cute = true;
Animal.prototype.eat = function() {
  console.log("eat!");
}
// ** 방법 2 **
Animal.prototype = {
  legs: 4,
  cute: true,
  eat() {
    console.log("eat!")
  }
};

const cat = new Animal("Brwon");
const dog = new Animal("White");

위와 같은 방법으로 사용해도 된다. __proto__ 와 모습이 다르다. Animal.prototype을 사용하는 방법은 생성자 함수가 생성하는 객체의 __proto__ 를 위와 같이 설정한다는 의미다. 주의할 점은 방법2를 사용할 경우 constructor가 사라진다. 따라서 방법1을 사용하는 것이 좋다.아니면 방법2에서 constructor를 수동으로 추가해야 한다.

const Animal = function(color) {
  const c = color;
  this.getColor = function() {
    console.log(c);
  }
}

const dog = new Animal("white");

cat,dog는 색상을 아무나 변경할 수 있다. 이 때 클로저를 사용해서 외부에서 변경하는 것을 막을 수 있다. 클로저를 사용하면 초기에 설정한 색상을 읽어 올수만 있고 외부에서 변경할 수 없다.

✅ 3. 이벤트 루프

자바스크립트는 Single Thread로 동작한다?!

  자바스크립트 엔진은 콜 스택 하나만 존재한다. 따라서 실제로 Single Thread로 동작한다. 하지만 실제로 브라우저를 보면 비동기적으로 데이터를 불러오거나 애니메이션을 실행시킨다.
📍 브라우저의 이벤트 루프 시스템 떄문에 Muti Thread 처럼 동작할 수 있다.
이벤트 루프는 자바스크립트 엔진에 포함되어 있지 않다. 브라우저나 Node.js에서 자체적으로 관리하고 있다.
 Web API는 브라우저에서 제공하는 API다. 클릭과 같은 DOM 이벤트나 네트워크 호출 타이머 등은 실행시킬 경우 브라우저에 위임된다. 보통 이런 Web API는 콜백함수를 넘기게 되는데 이 콜백함수는 비동기 작업이 끝나면 테스크 큐에 넣어져 순차적으로 꺼내 콜스택에 푸시가 된다. 그래서 이런 과정들은 결국 멀티 스레드로 동작한다.

자바스크립트 엔진이 싱글스레드 일 뿐 브라우저는 멀티스레드로 동작하기에 이런과정들이 가능해진다.

✏️ Microstack Queue, Animation frames 찾아보기

✅ 4. 모듈

웹 사이트는 여러 개의 자바스크립트 파일들로 구성되어 있다. 자바스크립트는 각 파일들을 하나의 프로그램으로 취급한다.

 예전 자바스크립트에서는 스크립트 파일간 통신을 위해 전역 스코프에 존재하는 변수와 함수를 사용해야 했다.이 방법은 스크립트 파일간 의존도를 확인하기 힘들고 실행 순서를 제어해 한다.
이런 한계점을 극복하기 위해 모듈이 탄생했다. 모듈을 사용하면 자바스크립트간 의존도를 파악할 수 있고 실행 순서를 쉽게 제어할수 있게 된다.

 프로그래밍을 하다보면 자주 듣지만 헷갈리는 용어가 모듈과 컴포넌트다.모듈은 설계시점에 의미있는 요소이고 컴포넌트는 런타임 시점에 의미있는 요다. 즉 모듈은 우리가 의식적으로 나누어 놓은 요고 컴포넌트는 나누어 놓은 요소에 포함되어 실행되는 요소다.

일반 자바스크립트와 달리 모듈 자바스크립트는 몇 가지 규칙이 있다.

  1. script 태그 내부에 type="module"을 추가해야 한다.
  2. 항상 엄격 모드로 실행된다. 변수의 타입을 생략하는 것은 전역스코프에 변수가 저장되기 때문에 일반적으로 가능하지만 모듈에서는 오류가 발생한다.
  3. 모듈 레벨 스코프를 갖는다. 각 모듈에 사용된 변수는 모듈 레벨에서만 사용가능하다. 다른 스크립트에서 사용할 수 없다.
  4. 모듈 스크립트는 한 번만 평가된다. 모듈 스크립트를 여러 번 추가하더라도 한번만 평가된다.
  5. 지연 실행된다. 모듈 스크립트는 모든 DOM이 만들어진 후에 생성된다.

✅ 5. 정규표현식

정규표현식은 성능은 느리지만 매우 편하고 가독성이 좋기 때문에 성능상 큰 이슈가 없다면 많이 사용한다.

 정규표현식 문법은 간단하다. / / 내부에 패턴을 작성하고 / /i 마지막으로 플래그를 설정한다. 다양한 패턴과 플래그는 필요할 때마다 찾아보면서 배워야 한다.
정규표현식을 연습해 볼 수 있는 다양한 사이트가 있다. 한번 들어가서 연습해보는것도 좋을거 같다.

 자바스크립트는 RegExp객체로 정규표현식 기능을 제공한다. RegExp 객체는 정규표현식을 위해 다양한 함수들을 제공하는데, test, exec, math, replace, search, capture 함수가 있다.
✏️ 개미 수열 문제

✅ 6. 쿠키와 세션, 웹 스토리지

HTTP는 단발성 통신이다.

 HTTP 통신은 stateless 통신으로 상태가 존재하지 않는다. 일반적인 socket 통신처럼 연결되어 있는 것이 아니라 통신을 할때만 연결되고 통신이 끝나면 연결이 사라진다. 따라서 서버는 브라우저로부터 받은 request를 보고 어떤 브라우저에서 보낸 것인지 알 수 있는 방법이 없다.

 이런 문제를 해결하기 위해 서버는 헤더에 set-cookie를 담아 request에 응답한다. 이제 브라우저는 다시 서버에 request할 때 cookie를 같이 보내서 서버가 어떤 브라우저인지 인식할 수 있도록 만든다. cookie는 해커에 의해 탈취당할 가능성이 있기 때문에 암호화한 후 보내야 한다.

쿠키만으로 서버는 어떤 브라우저인지 알지 못한다.

 쿠키의 주인을 알 수 있게 하려면 세션을 사용해야 한다.HTTP Session ID를 식별자로 사용자를 구분한다. Session은 서버 자체적으로 기록하고 관리한다. 브라우저에서 요청이 발생하면 Session을 생성하고 유지한다. 브라우저에서 다시 요청이 발생하면 Session 저장소에서 Session을 읽고 요청한 브라우저를 찾은 다음 응답을 보낸다.

 세션은 서버에 파일로 저장되기 때문에 사용자가 많아질 경우 서버에 부담이 크다. 또한 서버가 여러대일 경우에도 문제가 발생한다. 이런 문제를 해결하기 위해 이제 서버와 클라이언트간 인증은 별도 토큰을 사용하고 쿠키는 클라이언트 자체적인 지속적인 데이터 관리용도로 많이 사용한다.

Cookie 대신 로컬 데이터를 관리하는 웹 스토리지

웹 스토리지는 클라이언트에 데이터를 저장하기 위한 새로운 방법이다. 쿠키에서 하기 힘든 것들을 지원하기 위해서 등장했다. 웹 스토리지는 로컬 스토리지와 세션 스토리지가 있다.
로컬 스토리지

  1. 데이터를 저장하면 반영구적으로 데이터가 저장된다.
  2. 브라우저를 종료해도 계속해서 데이터가 남는다.
  3. 저장했던 도메인과 이용하는 도메인이 다른 경우엔 접근할 수 없다.
  4. 쿠키와 마찬가지로 Key-Value 형태로 저장한다.

세션 스토리지

  1. 새 창을 생성할 때마다 개별적으로 저장되는 데이터를 관리한다.
  2. 브라우저를 닫는 순간 사라진다.
  3. 같은 도메인이어도 세션이 다르면 데이터에 접근할 수 없다.
  4. 쿠키와 마찬가지로 Key-Value 형태로 저장한다.

자바스크립트에서 쿠키와 스토리지 사용하기

document.cookie = "Name=Minki;"

localStorage.setItem("Name", "Minki");
console.log(localStorage.getItem("Name"));

sessionStorage.setItem("Name", "Minki");
console.log(sessionStorage.getItem("Name"));

// removeItem, clear

쿠키는 document 객체를 통해 관리할 수 있다. 하지만 String으로 관리되기 때문에 값을 추가하고 제거하는 것이 불편하다. 따라서 별도 로직을 파싱하거나 라이브러리를 이용하는 것이 좋다.
로컬과 세션의 경우 같은 인터페이스를 갖기 때문에 사용하기 쉽다.

좋은 웹페이지 즐겨찾기