React Virtual DOM이란?

카테고리 React

Virtual DOM이란?

Virtual DOM은 Real DOM을 효율적으로 조작하기 위해 가상으로 DOM 구조를 흉내낸 자바스크립트 객체이다.

가상적인 표현을 메모리에 저장하고 React 같은 프레임워크를 통해 Real DOM과 동기화 하기 위해 사용된다.

Virtual DOM 사용하는 이유는?

Real DOM을 조작하여 DOM Tree의 배치가 바뀌면 Real DOM의 재렌더링이 발생하기 때문에 컴퓨터에 부담이 되고 속도가 느려지게 될 것이다.

그래서 Real DOM과 구조가 똑같은 Virtual DOM을 만들고 DOM 조작이 가해진 요소만 찾아 Real DOM에 변화를 가하는 방법을 사용하여 메모리 상에서만 동작하고 실제 렌더링을 하지 않아 연산 비용을 최소화 할 수 있다.

React에서 Virtual DOM 작동원리

  1. 우리가 UI를 조작하면 React는 Virtual DOM을 생성한다.
  2. diffing 알고리즘을 통해 이전 Virtual DOM과 변경사항을 비교한다.
  3. 이 때 변경된 부분을 파악하여 Real DOM에 반영하여 변경된 부분만 재렌더링이 발생한다.

댓글 공유

실행 컨텍스트란?

자바스크립트에서 실행 컨텍스트는 모든 코드의 동작원리를 담고 있는 핵심 개념이다.

다음 예시를 실행 컨텍스트 관점으로 설명해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var outer = () => {
const a = 3;

const inner = () => {
const b = 5;
return a + b;
};

return inner;
};

const closure = outer();

closure();

소스코드 평가와 실행

1. 전역 코드 평가

실행컨텍스트1

  1. 전역 실행 컨텍스트 생성
  2. var 키워드로 선언된 전역변수 outer는 전역 객체에 등록
  3. const 키워드로 선언된 전역변수 closure는 선언적 환경 레코드에 등록
  4. this는 전역 객체 바인딩

2. 전역 코드 실행 단계

실행컨텍스트2

  1. outer 우항의 함수를 평가한 뒤, 메모리에 저장한 뒤 전역 객체에서 outer 식별자에 할당
  2. closure 우항의 outer 함수를 전역 객체에서 찾아 호출

3. outer 함수 평가 단계

실행컨텍스트3

  1. outer 함수 실행 컨텍스트 생성
  2. outer 함수에서 선언된 변수 a, inner를 환경 레코드에 등록
  3. outer 함수의 외부 렉시컬 환경 참조는 outer 변수에 할당된 익명함수 객체의 내부슬롯 [[Environment]]가 가리키는 외부 렉시컬 환경을 가리킨다.

4. outer 함수 실행 단계

실행컨텍스트4

  1. outer 함수 환경 레코드의 변수 a에 값 3이 할당된다.
  2. 변수 inner에 익명 함수 객체의 참조값이 할당되고, 익명 함수 객체의 내부 슬롯 [[Environment]]은 정의된 outer 렉시컬 환경을 가리킨다.

5. 전역 코드 실행 단계 복귀

실행컨텍스트5

  1. 전역 렉시컬 환경의 선언적 환경 레코드에서 closure를 찾는다.
  2. inner 함수 객체가 closure라는 식별자에 할당된다.

6. closure 함수 평가 단계

실행컨텍스트6

  1. closure() 문이 실행되면서 closure의 실행 컨텍스트가 생성된다.
  2. closure를 실행하기 위해 inner 함수 객체를 평가한다.

    즉, closure() 평가단계 === inner() 평가단계

  3. const로 선언된 변수 b가 closure 환경 레코드에 등록된다.
  4. 화살표 함수의 this는 함수가 정의될 때 상위 스코프의 this로 정적으로 결정된다.

7. closure 함수 실행 단계

실행컨텍스트7

  1. closure 즉, inner 함수 내부 코드가 실행
  2. b에 값 5가 할당되고 a+b를 수행하기 위해 스코프 체인에서 a를 찾는다.
  3. closure 환경 레코드에는 a가 존재하지 않기 때문에 외부 렉시컬 환경 참조를 따라 익명함수 객체로 이동하고, 익명함수 객체의 [[Environment]]내부 슬롯이 가리키는 outer 함수 렉시컬 환경으로 이동된다. 결국 outer 환경 레코드에서 a를 찾을 수 있다.
  4. a+b 연산을 수행하고 연산값을 반환한다.

8. closure 실행 컨텍스트 소멸

실행컨텍스트8

  • closure 함수 코드가 실행을 마치고 closure의 실행 컨텍스트가 pop 되어 더 이상 참조되지 않는 객체들은 Garbage Collector에 의해 메모리가 해제된다.

9. 전역 실행 컨텍스트 소멸

실행컨텍스트9

  • 마지막으로 전역 실행컨텍스트가 pop 되어 참조될 수 있는 객체가 없기 때문에 모든 객체가 Garbage Collector에 의해 메모리가 해제된다.

댓글 공유

스코프는 무엇인가요?

카테고리 CS

스코프

스코프란, 식별자가 참조할 수 있는 범위(유효범위)를 말한다. 자바스크립트 엔진이 식별자를 찾기 위해 사용하는 규칙이다.

  • 모든 식별자는 자신이 선언된 위치에 의해 상위 스코프를 결정한다.
  • 식별자는 어떤 값을 구별하기 위해 유일 해야하므로 중복될 수 없다. 단, 스코프가 다르면 중복될 수 있다.

지역 스코프

자바스크립트는 함수 레벨 스코프를 갖는다. 그러므로 지역이란, 함수 몸체 내부를 말한다.

즉, 지역 스코프는 함수에 의해서 생성된다.

let, const가 나오면서 블록 레벨 스코프를 갖는 식별자를 선언할 수 있다. 여기서 지역 스코프는 코드 블록에 의해 생성된다.

1
2
3
4
5
6
7
var x = 1;

if (true) {
var x = 10;
}

console.log(x);

var 키워드는 함수 레벨 스코프를 갖는다. 즉, 함수 몸체 내부에서 var 키워드로 선언된 변수는 지역 스코프 범위를 참조할 수 있다. 함수 몸체 이외에서 선언된 변수는 모드 전역 스코프 범위로 본다.

스코프 체인

스코프는 함수의 중첩에 의해 계층적 구조를 갖는다. 모든 스코프는 하나의 계층적 구조로 연결된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
var x = 10; // 전역 스코프

function outer() {
var x = 100;
function inner() {
var x = -100;
console.log(x);
}
console.log(x); // 100
inner(); // -100
}
console.log(x); // 10
outer();
  1. 전역 스코프 (최상위 스코프)

  2. outer 지역 스코프

  3. inner 지역 스코프

자바스크립트 엔진은 변수를 참조하는 스코프에서 시작하여 상위 스코프 방향으로 이동하며 변수를 검색한다.

실제 자바스크립트 엔진은 코드를 실행하기 전 렉시컬 환경이라는 자료구조를 생성한다. 변수 선언이 실행되면 변수 식별자가 자료구조의 key로 등록되고 변수 할당이 일어나면 변수 식별자에 해당하는 값을 변경한다.

렉시컬 스코프

렉시컬 스코프란, 함수 정의가 평가되는 시점에 상위 스코프가 정적으로 결정된다.

함수 호출이 아닌 함수 정의(함수 선언문, 함수 표현식)가 실행되어 생성된 함수 객체는 자신이 정의된 스코프인 상위 스코프를 기억한다.

즉, 내가(함수가) 정의된 스코프가 자신의 상위 스코드이다.


전역변수와 var 키워드

변수는 생명주기가 있어 선언에 의해 생성되고 언젠가 소멸한다. 소멸하는 시점은 스코프에 따라 다르다.

  • 전역변수 : 런타임 이전에 자바스크립트 엔진에 의해 선언되고 애플리케이션이 종료되면 소멸한다.

  • 지역변수 : 함수가 호출될 때 생성되고 함수가 종료하면 소멸한다. 함수가 호출되는 순간 함수 몸체에 있는 선언들이 호이스팅 된다.

전역변수의 문제점

  1. 암묵적 결합
    어디서든 참조하고 변경할 수 있어 의도치 않게 변경될 수 있다.

  2. 긴 생명주기

메모리 자원도 오랜 기간 소비한다. 1번의 위험이 오래 지속되어 오류의 기회가 많아진다.

  1. 네임 스페이스 오염

자바스크립트는 파일을 분리해도 전역 스코프를 공유한다는 점에서 다른 파일에서 동일한 이름의 전역 변수끼리 충돌이 일어날 수 있다.

그러므로 전역변수를 꼭 써야하는 상황이 아니라면 사용하지 말자.

전역변수 사용 억제 방법

  1. 즉시실행함수
    즉시실행함수를만들어 함수 종료 시 변수도 사라져 메모리 해제도 빨리 되고 지역 스코프를 가져 충돌의 위험을 줄일 수 있다.

  2. 모듈패턴
    클래스를 모방하여 관련이 있는 변수와 함수를 모아 즉시실행함수로 감싸 하나의 모듈로 만든다.

전역변수 억제와 캡슐화까지 가능하다.

캡슐화란, 객체의 상태를 나타내는 프로퍼티와 프로퍼티를 참조하고 조작할 수 있는 메서드를 하나로 묶는 것을 말한다. 객체의 특정 프로퍼티나 메서드를 감출 목적으로 사용하기도 한다.(정보은닉)

var 키워드

var 키워드는 함수 레벨 스코프를 따른다. 함수 몸체 외부에서 var 키워드로 선언시 전역 변수로 선언되고 전역 스코프를 갖는다.

1
2
3
var x = 10;

console.log(window.x); // 10;

var 키워드는 전역에서 선언시 전역 객체의 프로퍼티로 등록된다.

1
2
3
4
5
6
7
y = 100;

function foo() {
z = 20;
}

foo();

키워드로 선언되지 않은 변수는 어디에서든지 항상 전역 변수이다.

선언되지 않은 변수는 해당 코드가 실행되어야 존재한다.

키워드 없이 선언하는 것은 옳지 않다.

러버덕하면서 알게된 내용

1
2
3
4
5
6
7
8
var x = 1;

function foo() {
y = 2;
}

Object.getOwnPropertyDescriptor(window, "x"); // {value: 100, writable: true, enumerable: true, configurable: false}
Object.getOwnPropertyDescriptor(window, "y"); // {value: 50, writable: true, enumerable: true, configurable: true}

var 키워드로 선언된 변수와 암묵적 선언으로 선언된 변수 모두 전역 객체의 프로퍼티로 등록된다.

하지만, 객체의 프로퍼티를 보면 configurable 값이 다른 것을 볼 수 있는데, 이것이 true이면 재정의(삭제, 변경)가 가능하다는 의미이다.

따라서 암묵적 선언으로 전역 객체의 프로퍼티로 등록이 되면 재정의가 가능하므로 암묵적 선언은 사용하지 않는 것이 좋다.


let, const 키워드

let, const 키워드는 블록 레벨 스코프를 따른다. 그러므로 var 키워드의 함수 레벨 스코프보다 더 한정적인 스코프를 지원하여 작은 범위의 스코프를 다룰 수 있어 유용하다.

let

var 키워드와 비교하여 let 키워드를 알아보자.

  1. 변수 중복 선언 금지

  2. 블록 레벨 스코프

let 키워드로 선언한 전역변수는 전역객체의 프로퍼티가 아니다. 전역 객체의 프로퍼티가 되는 것들은 var 키워드로 선언한 전역변수 및 전역함수, 그리고 선언하지 않는 변수에 값을 할당한 암묵적 전역이 있다. 이에 대해서는 실행 컨텍스트에 대해 배울 때 자세히 배우자.

  1. 변수 호이스팅

var 키워드로 선언한 변수는 선언단계와 초기화 단계가 동시에 진행된다. 하지만 let 키워드로 선언한 변수는 선언단계와 초기화 단계가 분리되어 진행된다.

선언단계가 자바스크립트 엔진에 의해 실행되고 초기화 단계는 변수 선언문에 도달했을 때, 실행된다.

1
2
3
4
5
6
7
let a;
console.log(a); // undefined
a = 10;
console.log(a); // 10

console.log(b); // Uncaught ReferenceError: b is not defined
let b;

언뜻보면 let 키워드는 호이스팅이 일어나지 않는 것처럼 보이지만, 선언단계는 호이스팅이 되어 최상단에서 먼저 실행되었고 초기화 단계는 선언문에 도달했을 경우 진행되기 때문에 위와 같은 현상이 발생하는 것이다.

const

let 키워드와 비교해서 알아보자

  1. 선언과 초기화

const 키워드로 선언한 변수는 개발자가 선언과 초기화를 동시에 해야한다.

1
2
3
const foo = 1; // 1

const baz; // Uncaught SyntaxError : Unexpected identifier

이전에 선언을 하면 선언단계와 초기화 단계가 진행된다 그랬었는데, 이것도 초기화가 맞지만 const를 사용하기 위해서는 개발자가 직접 초기화를 해줘야한다. 만약 초기화를 해주지 않고 나중에 값을 할당한다는 것이 재할당으로 해석되기 때문이다.

  1. 재할당 금지

const 키워드로 선언한 변수에 원시값을 할당하면 값을 변경할 수 없다. 하지만 객체를 할당한 경우 값을 변경할 수 있다. 재할당 금지라는 말이 불변을 의미하지는 않는다. 왜냐하면 식별자가 가리키는 메모리 주소 공간은 참조값이 저장되어 있고 객체를 변경하여도 참조값은 변하지 않기 때문이다.

  1. 상수

변하지 않는 값을 사용하기 위해 우리는 상수를 사용한다.

주로 상수의 이름은 대문자로 사용한다. 원시값을 할당한 경우 원시값은 변경 불가능한 값이고 재할당이 금지되므로 할당된 값을 변경할 방법은 없다.

댓글 공유

프로세스와 스레드는 무엇인가요?

프로세스란? 작업의 단위로써, 작업을 관리하는 주체는 OS이다. 프로세스는 최소 1개의 스레드(thread)를 가진다.

컴퓨터가 명령을 받게되면 명령을 실행하면서 연산코드의 흐름이 생겨난다. 이 때의 흐름을 스레드라고 한다.

즉, 스레드가 실질적으로 연산을 하는 주체가 된다.

기본적으로 프로세스 흐름(스레드)은 1개이다. 그런데 흐름이 n개 일 수 있는데, 이런 경우를 멀티 스레딩(Multi-threading)라고 한다.

멀티 스레딩은 동시성과 동기화라는 특징이 있는데 이는 아래 예시를 통해 설명할 수 있다.

만약 프로세스가 여러 개라면 멀티 태스킹(Multi-tasking)이라고 한다.

프로세스와 스레드 비유 설명

프로세스와 스레드 비유 설명

한 가구(Process)가 있다고 하자. 해당 가구는 집(Virtual Memory)이라는 공간에 살게된다. 한 가구안에 세대원(Thread) 3명이 있다고 하자.

집 안에는 세대원들이 각자 방(Thread Local Storage)을 하나씩 사용한다. 뿐만 아니라 Thread마다 Stack 자료구조로 관리되는 메모리 공간이 따로 있다.

각자 방은 본인만 사용 가능하고 거실, 화장실, 부엌은 공용공간(Heap)이다.

프로세스와 스레드 작동원리

프로세스와 스레드 작동원리

  1. Process가 Thread를 처리하기 위해서는 CPU와 메모리(연습장)가 필요하는데 이를 관리해주는 것이 바로 OS가 하는 일이다.

  2. 이 때 Process는 실제 메모리를 사용하지 않고 RAM(1차 메모리)과 HDD(2차 메모리)를 추상화한 Virtual Memory를 사용한다.

  3. Virtual Memory는 RAM과 연결된 부분이 있을 수도 있고 HDD와 연결된 부분이 있을 수도 있다. RAM이 부족해서 연결하지 못하는 것보단 HDD라도 연결해주는 것이 낫기 때문이다.

OS가 Virtual Memory를 Process에게 할당해준다. 때문에 Process 내부의 Thread는 작동범위가 Virtual Memory로 제한된다.

참고

유튜브 널널한 개발자 - Process와 Thread 차이

댓글 공유

0.1은 우리 눈에 보이는 0.1이 아니다?

컴퓨터는 데이터를 RAM이라는 곳에 임시 저장한 뒤 CPU가 꺼내와서 데이터를 연산한다.

RAM에 데이터를 저장할 때 2진수로 저장을 하는데, 정수가 아닌 소수를 저장할 때는 다음과 같은 방식으로 저장한다.

ex) 5.125 -> 101.001 -> 1.01001 * 2^2

컴퓨터가 소수 저장하는 원리

  1. 32칸의 공간을 마련한 뒤 첫칸에 부호를 나타내는 숫자를 적어둔다. (양수:0, 음수:1)
  2. 소수점 우측 부분을 mantissa 부분으로, 정수부분 8칸 공간 뒤에 23칸에 넣어준다.
  3. 지수에다가 127을 더한 뒤 2진법으로 만들고(2+127 -> 10000001) 이를 맨 앞 8칸에다가 넣어준다.

순환소수

하지만 0.1같은 소수는 32칸으로 표현할 수 없는 무한한 소수점 이하의 값을 가진다. 그러므로 컴퓨터는 32칸까지만 표시를 해주고 뒤의 값은 무시한다.

1
2
3
4
const a = 1.1;
const b = 0.1;

a + b === 1.2; // false

32칸뒤에 잘려나간 부분때문에 오차가 발생하여 위 비교식이 false가 판단된다.

정리

정확히 계산하기 위해서는 정수를 사용하자.

1m를 표시하는데, 1.2m를 표시하는 것을 변수에 그대로 담지 말고, mm로 단위를 통일하고 1200를 변수에 담자.

댓글 공유

REST API란 무엇인가요?

카테고리 CS

REST API란 무엇인가요?

자원의 이름으로 구분하여 해당 자원의 상태(정보)를 주고 받는 것을 의미한다. REST API는 HTTP 프로토콜을 의도에 맞게 디자인 하도록 유도하고 있다.

즉, REST는 HTTP를 기반으로 클라이언트가 서버의 리소스에 접근하는 방식을 규정한 아키텍처이고 REST API는 REST를 기반으로 서비스 API를 구현한 것이다.

REST API의 구성

  • 자원 : 모든 자원에는 고유한 ID가 존재하고 ID는 /store/:store_ID와 같은 HTTP URI이다.
  • 행위 : 자원에 대한 행위 (HTTP 요청 메서드)
  • 표현 : 자원에 대한 행위의 구체적 내용 (페이로드, JSON)

REST API 설계 규칙

1. URI는 리소스를 표현하는데 집중하고 마지막에 슬래시 포함하지 않는다.

1
2
3
4
5
6
7
# bad
GET /getTodos/1
GET /todos/show/1
GET /todos/1/

# good
GET /todos/1

2. 행위에 대한 정의는 HTTP 요청 메서드를 통해 정의한다.

HTTP 요청 메서드 종류 목적 페이로드
GET index/retrieve 모든/특정 리소스 취득 X
POST create 리소스 생성 O
PUT replace 리소스 전체 교체 O
PATCH modify 리소스 일부 수정 O
DELETE delete 모든/특정 리소스 삭제 X
  • 리소스에 대한 행위는 HTTP 요청 메서드를 통해 표현하며 URI에 표현하지 않는다.
1
2
3
4
5
# bad
GET /todos/delete/1

# good
DELETE /todos/1

3. 슬래시 구분자(/)는 계층 관계를 표현

1
http://example.com/stores/restaurant

4. 불가피하게 긴 URI인 경우 하이픈(-) 사용

1
http://example.com/stores/very-long-store

단 밑줄(_)은 포함하지 않는다.

5. 파일 확장자는 URI에 포함하지 않는다.

1
2
3
4
5
# bad
http://example.com/stores/restaurant/:1/logo.png

# good
GET /stores/restaurant/:1/logo HTTP/1.1 HOST: example.com Accept: image/png
  • 대신 Accept header를 사용한다.

RESTful한 REST API 설계하기

RESTful은 이해하기 쉽고 사용하기 쉬운 REST API를 만들고, 일관적인 컨벤션을 통해 API의 이해도를 높이는 것을 말한다.

REST API 설계 예시

CRUD HTTP verbs Route
resource 목록 표시 GET /resource
resource 하나 내용 표시 GET /resource/:id
resource 생성 POST /resource
resource 수정 PUT /resource/:id
resource 삭제 DELETE /resource/:id

응답상태 코드

상태코드 설명
1xx 전송 프로토콜 수준의 정보 교환
2xx 클라이언트 요청 성공
3xx 클라이언트 요청 완료하기 위해 추가 행동 필요
4xx 클라이언트의 잘못된 요청
5xx 서버쪽 오류

댓글 공유

OOP에 대해 설명하세요

카테고리 CS

OOP란 무엇인가요?

OOP(Obeject-Oriented-Programming)는 객체지향 프로그래밍을 말한다.

객체지향 프로그래밍이란, 실세계에 존재하고 우리가 인지하는 객체라는 대상을 추상화하여 프로그래밍에 접목 시킨 방식으로,

프로그래밍 관점에서 데이터를 추상화할 때, 상태와 행동을 가진 객체를 만들고 이 객체들간의 유기적인 상호작용을 통해 로직을 구성하는 프로그래밍 방식을 객체지향 프로그래밍이라 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const TV = {
name: "Samsung UHD Ultra",
price: "1,000,000원",
state: "off",
volume: 10,
turnOn() {
this.state = "on";
},
turnOff() {
this.state = "off";
},
volumeUp(num = 10) {
this.volume += num;
},
volumeDown(num = 10) {
this.volume -= num;
},
};

위는 TV라는 데이터를 상태와 행동으로 추상화한 객체로 표현한 것이다.

OOP의 특징은 무엇인가요?

1. 캡슐화

캡슐화란 객체를 특정한 목적을 위해 변수 혹은 메서드 하나로 묶는 것을 말한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const counter = (() => {
let count = 0;

return {
getCount() {
return count;
},
increase() {
count += 1;
},
decrease() {
count -= 1;
},
};
})();

위 예시는 counter를 캡슐화한 예시이다. 이렇게 캡슐화를 하게되면 count라는 변수에 대해 참조하거나 변경하는 함수를 통해서만 간접적으로 접근이 가능하도록 하여 해당 데이터를 은닉하고 안전하게 보존하기 위해 사용한다.

2. 추상화

우리는 앞서 TV라는 데이터를 추상화하였다. 하지만 추상화는 예시처럼 간단하지만은 않다. 추상적으로 큰 틀에 공통적인 요소나 필수적인 요소를 담는 것을 말한다.

다시 TV의 예를 들어보겠다. 우리가 실생활의 모든 데이터(TV, 냉장고, 인덕션, 청소기 등)를 모두 개별적으로 만드는 것보단 이들의 공통적인 특성을 가진 큰 틀의 객체를 만들고 해당 객체의 상속을 받고 본인만의 특별한 기능을 추가하는 방법으로 객체를 생성해나가는 것이 중복을 줄이고 확장성의 장점을 살려 추상화를 할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class HomeAppliance {
constructor(name, price) {
this.state = "off";
this.name = name;
this.price = price;
}
turnOn() {
this.state = "on";
}
turnOff() {
this.state = "off";
}
...
}

const TV = new HomeAppliance("Samsung UHD Smart TV", 1000000);
const Refrigerator = new HomeAppliance("Samsung BSpoke", 2000000);
const vacuumCleaner = new HomeAppliance("Dyson", 800000);

위 예시처럼 가전제품이라는 데이터를 추상화하여 객체로 생성한 뒤, 해당 객체의 상속을 받아 공통적인 행동을 할 수 있는 객체를 생성하여 TV, 냉장고, 청소기 데이터를 추상화하였다.

3. 상속 및 다형성

다형성은 같은 동작이지만 다른 결과물을 반환하는 특징을 말한다.

상속과 다형성을 통해 기능을 확장하거나 변경하는 것이 가능하다. 그렇게 되면 코드의 재사용 및 코드 길이 감소되고 유지보수가 용이해지는 장점이 있다.

1
2
3
4
5
6
7
// 숫자를 문자열로 바꾸는 경우
const number = 100;
const string1 = number.toString();

// 날짜를 문자열로 바꾸는 경우
const date = new Date();
const string2 = date.toString();

위 예시는 다형성의 예시이다. toString()이라는 메서드를 사용하여 타입에 따라 적절한 변환 방식을 정의해둠으로써 객체의 종류와 상관없는 추상도가 높은 변환 형식을 구현할 수 있다는 장점이 있다.

이러한 다형성의 개념을 녹여내는 방법은 오버라이딩(Overriding), 오버로딩(Overloading) 두가지가 있다.

오버라이딩(Overriding)

자식 클래스가 부모 클래스에게 상속받은 메서드를 특정 형태로 구현하는 것을 말한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Animal {
constructor(name, legs) {
this.name = name;
this.legs = legs;
}
move() {
console.log("move forward faster!!");
}
eat() {
console.log("eat food");
}
}

class Dog extends Animal {
move() {
console.log("move like a dog!");
}
bark() {
console.log("Wal! Wal!");
}
}

const animal = new Animal("eagle", 2);
const dog = new Dog("seechu", 4);

dog.move(); // move like a dog!
animal.move(); // move forward faster!!

위 예시에서 자식 클래스는 부모 클래스에게 상속받은 move 메서드를 새롭게 정의하였다. 그리고 자식 클래스의 인스턴스와 부모 클래스의 인스턴스에서 각각 move 메서드를 사용했을 때, 각자 클래스에 정의된 move 메서드가 동작하는 것을 알 수 있다.

오버로딩(Overloading)

하나의 클래스안에서 같은 이름의 메서드를 사용하지만 매개변수, Return Type 등의 특징에 따라 다른 용도로 사용되도록 구현하는 것을 말한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Animal {
constructor(name, legs) {
this.name = name;
this.legs = legs;
}

move(direction, distance) {
if (!direction || !distance) {
console.log("move forward faster!!");
} else {
console.log(`move ${direction} for ${distance}`);
}
}

eat() {
console.log("eat food");
}
}

const pig = new Animal("kong-e", 4);

pig.move(); // move forward faster!!
pig.move("right", "10m"); // move right for 10m

위 예시는 자바스크립트에서 오버로딩을 구현한 예시이다. move라는 메서드를 사용할 때, 매개변수가 있고 없고에 따라 다르게 동작하도록 구현하였다.

댓글 공유

SSR과 CSR에 대해 설명하라

카테고리 CS

🐥 SSR과 CSR에 대해 설명하라

SSR은 서버 사이드 렌더링의 줄임말로, 클라이언트가 서버에 요청을 보낼 때 서버에서 HTML,JS 등을 렌더링하고 클라이언트에게 완성된 HTML 파일을 응답해주는 방식이다.

CSR은 서버에 요청을 보내면 서버에서 HTML,JS 리소스 파일등을 받은 이후 브라우저에서 렌더링을 진행하는 것이다. 이후 클라이언트는 서버에게 데이터만 요청하면서 브라우저가 렌더링한 페이지에 서버의 응답으로 받은 데이터만 패칭해주면 된다.

😃 특징

✈️ 초기 로딩 속도

SSR은 클라이언트가 요청한 부분의 페이지만 렌더링해서 보내주면 되므로 초기 로딩 속도가 CSR에 비해서 빠른 반면, CSR은 HTML,JS, 모든 리소스를 한번에 로드하기 때문에 초기 로드 속도가 느리다.

❗️ 서버 부하

SSR은 View가 바뀔 때마다 서버에 요청을 보내고 서버는 그 때마다 응답해줘야하므로 서버의 부하가 높고 UX 측면에서는 깜빡임 현상이 있는 단점이 있다. 반면, CSR은 데이터 요청이 있을 때만 서버에 요청을 하기 때문에 서버 부하가 적다.

📚 SEO

SSR은 서버가 렌더링을 하고 완성된 페이지를 클라이언트에게 보내주는데, 그 안에는 SEO에 사용되는 meta 태그 등이 미리 정의 되어 있어 SEO 측면에서 유리하다. 반면 CSR은 초기에 비어있는 HTML 파일을 보내주고 JS를 다운로드하여 브라우저에서 렌더링이 완료되기 전까지는 빈 파일로 남아있기 때문에, SEO 측면에서 불리하다.

Next.js에서 SSR,CSR

이번 과제에서 Next.js를 사용하면서 새롭게 배우게 된 사실을 정리해본다. Next.js는 기본적으로 SSR을 지원한다. SSR을 지원하는 방법으로는 2가지 방법이 있는데,

첫번째, 클라이언트가 요청할 때마다 서버에서 렌더링을 해주는 진짜 SSR 방식

두번째, 미리 렌더링을 끝내놓은 페이지를 클라이언트가 요청할 때마다 캐싱하여 보여주는 SSG 방식

그리고 CSR까지 지원해준다.

Next.js를 사용하다보니 SSR, CSR, SSG에 대한 이해가 더 잘되는 것 같아서 마무리로 적어보았다.

댓글 공유

Next.js는 왜 사용하나요?

카테고리 CS

Next.js를 왜 사용하나요?

Next.js는 빠르게 웹 애플리케이션을 만들기 위한 React 프레임워크이다.

우리가 웹 애플리케이션을 만들기 위해서는 단순히 React로 코드만 짜서는 만들 수 없다.

UI는 물론, 라우팅, 데이터 패칭, 렌더링, 성능 최적화, 확장성, DX 까지도 고려하여 웹 애플리케이션을 만들어야한다.

그렇기 때문에 우리는 각 부분을 직접 구현할 지 아니면 라이브러리나 프레임워크와 같은 도구를 사용할지 결정해야한다.

즉, 우리는 React로 UI를 구축한 뒤 Next.js의 기능을 점진적으로 도입하여 라우팅, 데이터 가져오기 등 애플레이케이션 요구사항을 해결함과 동시에 UX, DX까지 개선할 수 있다.

Next.js 특징

👍 장점

  • SWR을 사용하여 컴파일, 축소, 코드분할, 번들링 작업을 하고 Babel보다 17배 빠른 컴파일 속도를 갖는다.
  • 페이지 별 SSR, CSR, SSG를 사용할 수 있다. 이를 통해 SEO 최적화 가능
  • React 프로젝트에서 Next.js로 점진적 마이그레이션 용이

👎 단점

  • SSR을 사용하여 서버 부하가 있을 수 있다.
  • 페이지 이동 시 깜빡거림

댓글 공유

객체 불변성에 대해 설명하라.

자바스크립트에서 데이터는 변경 불가능한 원시값, 변경 가능한 참조값으로 구성된다.

변경 가능한 참조값이 바로 객체를 말하는데, 객체는 값을 참조값으로 전달하고 전달 받으므로 객체가 참조를 통해 공유되어 있다면 하나를 바꿨을 때, 다른 것들도 바뀔 위험이 있다.

1
2
3
4
5
6
7
const a = { a: 10, b: 200 };
const c = a;

c.a = 30;

console.log(c); // {a: 30, b: 200}
console.log(a); // {a: 30, b: 200}

위와 같은 문제를 해결하기 위한 방법으로 객체를 불변객체로 만들거나, 참조값을 복사하는 것이 아닌 객체의 값을 복사하여 새로운 객체를 생성하는 방법이 있다.

객체를 불변 객체로 만드는 방법은 Object.freeze메서드와 Object.seal 메서드를 사용하는 방법이 있다. 두 메서드는 직속 프로퍼티에만 적용된다(얕은 방지).

Object.freeze(), Object.seal()의 차이는 Object.freeze()는 해당 객체에 속성 추가, 기존 속성 변경, 삭제가 모두 불가능하지만 Object.seal()은 새로운 속성 추가및 삭제가 불가능하고 기존 속성 변경은 가능하다.

객체의 값을 복사하는 방법으로는 Object.assign()를 사용하는 방법, ES6 Spread 문법이 있다. 이 두가지 방법 역시 얕은 복사이므로, 깊은 복사를 하려면 라이브러리를 사용하거나 새로 추가된 structedClone() 메서드를 사용하는 방법이 있다.

structedClone() 메서드는 Function 객체, DOM Node, 객체들의 몇몇 파라미터 일부 기능에 제한이 있다.

리액트에서 Props, State를 불변객체로 다루는 이유는?

리액트에서는 Props와 State의 변경을 불변성을 이용해 감지하고 리렌더링을 발생시킨다.

만약 불변 객체를 사용하지 않는다면, 객체의 값이 어디에서 바뀌게 되었는지 예상하기 어렵고 해당 객체도 엉망이 될 것이다.

setState는 비동기적으로 State를 변경시키는데, 불변 객체로 다루지 않고 직접 State를 변경시킨다면 이전의 값이 반환될 수 있다.

댓글 공유

loco9939

author.bio


author.job