문제링크: https://www.acmicpc.net/problem/11399

 

♣ 문제정리

사람의 수 N

i번째 사람이 돈을 인출하는 데 걸리는 시간 : 입력값 (1,2,3...N)

순서를 아무렇게나 할 수 있음

각 사람이 돈을 인출하는 데 걸리는 총 시간의 최소값: 출력값

 

 

♣ 코드 작성 전 생각할 거리

경우의 수: N!

총 시간이 최소인 경우의 순서를 알 필요는 없다.

가장 오래 걸리는 사람을 조금 더하고, 가장 적게 걸리는 사람을 가장 많이 더해야지 총 합이 최소

-> 정렬!

 

 

 

♣ 코드 작성

총 시간을 구하려면 배열에서 각 원소에 왔을 때 처음부터 그 순서까지를 계속 더해야 한다

i:0 -> 0

i:1 -> 0, 1

i:2 -> 0,1,2

i:3 -> 0,1,2,3

i:4 -> 0,1,2,3,4

 

이것에 충실하게 코드를 작성했다

n = int(input())

# fetch하는 time 넣을 리스트
f_times = list(map(int, input().split(' ')))

f_times.sort()

sum = 0
k=1

while(k <= n):
    for i in range(0, k):
        sum = sum + f_times[i]
    k += 1

print(sum)

 

 

하지만, 조금만 더 생각해 보면,

sum이나 k라는 변수를 따로 만들지 않아도 배열을 순차적으로 갱신해주는 방법도 있다!

우리가 구해야 하는 것은 소요시간들의 합이기 때문에 각 배열의 원소들을 이전 원소들을 더한 합으로 바꿔준다. 

=> 순차적으로 각 원소는 (자신의 값 + 이전 원소값)으로 바꿔준다.

그리고 바뀐 배열들의 합을 구해도 같은 답이 나오게 된다.

for i in range(1, n):
    f_times[i] += f_times[i-1]
print(sum(f_times))

코드길이도 많이 줄었고 시간은 거의 절반으로 줄어듬을 알수 있다!!!!!!

memoization을 사용한 방법

동일한 계산을 반복해야 할 때, 이전에 계산한 값을 메모리에 저장함으로써 동일한 계산의 반복 수행을 제거하여 프로그램 실행 속도를 빠르게 하는 기술! 동적 계획법의 핵심

 

 

코드를 작성하러 들어가기 전에 어떻게 작성할 건지를 확실하게 하는 게 시간을 절약하는 데 중요하다!

즉, 코드 작성보다는 문제를 분석하는 데에 시간을 더 투자하자

'알고리즘 공부 > coding test' 카테고리의 다른 글

백준 1931 [회의실 배정]  (0) 2022.05.20
백준 20115 [에너지 드링크]  (0) 2022.05.20
백준 2217[로프]  (0) 2022.05.17
백준 2358 [평행선]  (0) 2022.02.08
백준 2609 [최대공약수와 최소공배수]  (0) 2021.02.04

문제링크 : https://www.acmicpc.net/problem/2217

 

♣ 문제정리

k 개의 로프를 병렬로 연결

각 로프에는 모두 고르개 w/k 만큼의 중량이 걸린다

로프를 이용하여 들어올릴 수 있는 물체의 최대 중량(w)을 구하라

모든 로프를 사용할 필요는 없다 => 사용하는 로프가 1개, 2개, 3개 ,,,, k개

 

입력: 각 로프가 버틸 수 있는 최대 중량

출력: 로프를 이용하여 들어올릴 수 있는 물체의 최대 중량

 

♣ 코드 작성 전 생각할 거리

만약 모든 로프를 사용한다면 물체의 최대 중량은 

=> (로프가 버틸 수 있는 최대 중량 중 가장 최소 값) * k개 일 것이다.

 

하지만, 

모든 로프를 사용할 필요는 없기 때문에 케이스마다 사용하는 로프의 개수를 1개, 2개, 3개 ,,,, k개로 나눈다면,

(로프의 개수) * (해당하는 로프들 중 가장 최소 값) 으로 계산해서 가장 최대인 값이 출력돼야 한다!

 

그러려면  입력되는 로프들을 정렬을 해야한다. 최대중량이 제일 큰 로프 순으로 꺼내면서 순서대로 병렬을 해야 하기 때문이다.

 

♣ 코드 작성

k = int(input())

ropes = []
for i in range(k):
    ropes.append(int(input()))

ropes.sort(reverse=True) # 내림차순 정렬

weights = []
for i in range(k):
    w = (i+1) * ropes[i]
    weights.append(w)

print(max(weights))

참고: https://pangsblog.tistory.com/21

https://jitolit.tistory.com/134

'알고리즘 공부 > coding test' 카테고리의 다른 글

백준 20115 [에너지 드링크]  (0) 2022.05.20
백준 11399 [ATM]  (0) 2022.05.18
백준 2358 [평행선]  (0) 2022.02.08
백준 2609 [최대공약수와 최소공배수]  (0) 2021.02.04
백준 11022 [A+B-8]  (0) 2021.02.04

1. String.prototype.matchall

RegExp.prototype.exec()와 매우 유사하게 동작한다.

  • RegExp.prototype.exec()
    • 정규표현식과 첫번째로 일치하는 하위 문자열의 정보를 반환
    • index 속성은 텍스트와 일치하는 첫번째 문자위치
const regExp = /javascript/g;
const text = 'javascript1 is a very good javascript2';
let matches;

while ((matches = regExp.exec(text)) !== null) {
  console.log(matches);
}

  • String.prototype.matchall()
    • 모든 하위 문자열의 정보를 포함하고 있는 iterator를 반환한다.
const result2 = Array.from(text.matchAll(regExp));

console.log(result2);

 

2. Dynamic import

ES11 이전에 modules를 import하기 위해서는 아래와 같이 사용했다.

import * as TestModule from "./test-module.js";

하지만 위와 같이 사용하면 문제점이 있다.

  • 모든 모듈들이 처음 로드될 때 전부다 import가 된다면 프로그램 상에서 효율을 떨어뜨릴 수 있다.
  • 게다가 모듈 이름을 프로그램이 동작할 동안 동적으로 변경하지 못한다.

위 문제를 해결하기 위해 Dynamic import가 등장

const baseModulePath = "./baseModules";
const btnImportModule = document.getElementById("btnImportModule");
let userList = [];

btnImportModule.addEventListener("click", async e => {
  const userModule = await import(`${baseModulePath}/users.js`);
  
  userList = userModule.getUsers();
});

btnImportModule 버튼을 클릭하면 user.js 모듈이 동적으로 로드되고 getUsers() 메서드가 userList 리스트에 추가될 수 있다. 그리고 모듈명을 변수 형식으로 설정하면 모듈명을 동적으로 변경할 수도 있다.

 

import() 구문은 Promise 객체를 반환하기 때문에 async/awaitthen/catch 를 사용해서 비동기 처리를 해야 한다.

 

 

3. BigInt

Number 원시값이 표현할 수 있는 최대치인 2^53 - 1보다 큰 값을 표현하고 싶을 때 사용한다.

BigInt를 사용하려면 정수 리터럴 뒤에 n을 붙이거나, BigInt() 생성자 함수의 인자로 생성할 숫자를 전달합니다.

주의해야 할 점은 BigInt는 Math객체의 메서드와 함께 사용할 수 없고, 연산에서 Number 타입의 원시값과 같이 연산할 수 없습니다.

// 정수 리터럴 방식
const bigInt1 = 9007199254740999n
// 생성자 함수 방식
const bigInt2 = BigInt(9007199254740998)

console.log(bigInt1 > bigInt2) // true
console.log(bigInt1 > bigInt2 + 2n) // false

 

4. Promise.allSettled

Promise.allSettled 메서드는 인자로 받은 배열이나 iterable 객체를 통해 열거된 Promise 객체들이 모두 실행됐을 때 resolve하는 Promise 객체를 반환한다. 

Promise.allSettled 메서드는 Promise.all 메서드와 유사하지만, Promise.all 메서드는 열거된 Promise 객체들 중 하나라도 reject 되면 자신도 reject하지만 Promise.allSettled 메서드는 이행 여부와 상관없이 전부 다 실행되면 resolve한다는 차이가 있습니다.

Promise.allSettled([
    Promise.resolve(33),
    new Promise(resolve => setTimeout(() => resolve(66), 0)),
    99,
    Promise.reject(new Error('an error'))
])
.then(values => console.log(values));

Promise.all([
    Promise.resolve(33),
    new Promise(resolve => setTimeout(() => resolve(66), 0)),
    99,
    Promise.reject(new Error('an error'))
])
.then(values => console.log(values));

 

5. globalThis

globalThis는 어떠한 javascript 실행환경이라도 동일하게 전역객체를 반환한다.

기존의 javascript 환경에서는 실행환경에 따라서 접근하는 방법이 달랐다.

  • 브라우저 환경 -> window, sef, frames를 사용해서 접근,
  • node.js 환경   -> global 를 사용해서 접근,
  • web worker 환경 -> self를 통해 접근

=> 코드가 다양한 실행환경에서 작동하려면 별도의 예외 처리를 해줘야 했는데, 이제 globalThis를 이용하면 별도의 예외 처리를 하지 않고도 손쉽게 전역객체에 접근할 수 있다.

 

6. Optional Chaining (?.)

왼쪽 피연산자 값이 null이나 undefined일 경우 실행을 멈추고 undefined를 반환하는 연산자.

Optional Chaining 연산자를 사용하면, 존재하지 않을 수도 있는 값에 대해 예외 처리를 해야 할 때 손쉽게 처리할 수 있다.

const person1 = {
    name: 'jin',
    job: {
        title: 'singer',
    }
}
const person2 = {
    name: 'jhope'
}

function printJob(person){
    console.log(person.job.title)
}

printJob(person1) # singer
printJob(person2) # Uncaught TypeError: Cannot read properties of undefined (reading 'title')

Optional chaining 연산자 사용 !

function printJob(person){
    console.log(person?.job?.title) # undefined
}

 

7. Nullish coalescing operator ( ?? )

왼쪽 피연산자 값이 null 이나 undefined인 경우에 오른쪽 피연산자를 반환하고 그렇지 않으면 왼쪽 피연산자를 반환하는 연산자이다.

변수에 기본값을 할당할 때 유용해 보인다.

주로 기본값을 할당할 때 || 연산자( A가 false이면 B가 출력됨 )를 사용하는데 0, '' , NaN 같은 falsy 값들을 null이나 undefined를 할당한 것과 동일하게 처리할 수 있기 때문에 예기치 못한 결과가 발생할 수 있다. 

nullish coalescing 연산자를 사용하면 정확하게 null 이나 undefined인 경우에만 기본값을 할당해주기 때문에 좀 더 안전하게 코드작성가능합니다.


const data = {
  title: 'foo',
  count: 0
}

const description3 = data.count || 100    -> 100
// 0을 할당했지만 0을 falsy한 값으로 취급했기 때문에 null이나 undefined를 할당한 것과 동일하게 처리

const description1 = data.count ?? 100    -> 0
// data.count가 정확하게 null이나 undefined일 경우에만 100이 됩니다. 
// 예시에선 0이라는 값이 할당됐기 때문에 0이 출력된다

const description2 =
  data.count == undefined && data.count == null ? 100 : data.count  -> 0
// 위와 동일한 동작을 함

 

 

참고, 출처:

https://segmentfault.com/a/1190000040438879/en

https://john015.netlify.app/what-is-new-in-es-11

https://zerq.tistory.com/92

https://intrepidgeeks.com/tutorial/regular-expression-correlation-method

'엘리스 ai 트랙 > FE' 카테고리의 다른 글

this [모던 js 딥다이브]  (0) 2022.09.22
CI와 CD  (0) 2022.03.31
http 1.1 과 http 2 의 차이점  (0) 2022.03.31
HTTP  (0) 2022.03.13
기본값+rest+spread  (0) 2022.03.07

일단 요약

CI/CD는 애플리케이션 개발 단계를 자동화하여 애플리케이션을 보다 짧은 주기로 고객에게 제공하는 방법입니다.

CI/CD는 새로운 코드 통합으로 인해 개발 및 운영팀에 발생하는 문제를 해결하기 위한 솔루션입니다.

개발부터 배포까지 모든 단계를 자동화 하는 것

 

CI/CD 파이프라인

애플리케이션의 통합 및 테스트 단계에서부터 제공 및 배포에 이르는 애플리케이션의 라이프 사이클 전체에 걸쳐 지속적인 자동화와 지속적인 모니터링을 제공하는 구축 사례

 

-> 5줄 요약한다면,

 

  1. 개발자가 작은 단위로 코드를 짜고 메인 리포지토리에 merge를 하면,
  2. 자동으로 빌드되고,
  3. 자동으로 테스트되어,
  4. 릴리즈되고(배포준비완료),
  5. 배포된다.

 

CI/CD는 이 파이프라인으로 표현되는 실제 프로세스를 의미하고 지속적인 자동화 및 모니터링을 추가하는 것을 의미합니다.


CI (continuous Integration, 지속적 통합)

애플리케이션의 새로운 코드들이 자동으로 빌드 및 테스트 되어 레포지토리에 통합되는 것을 의미한다.

현상황: 

개발자들은 보통 동일한 애플리케이션의 각기 다른 기능을 동시에 작업합니다.

그러나 각자 작업한 코드를 merge day를 정해 모든 분기 소스 코드를 병합할 경우, 결과적으로 반복적인 수작업 많은 시간을 소모하게 됩니다ㅠ

왜냐면, 각자 작업하는 개발자가 애플리케이션에 변경사항을 적용할 때 다른 개발자가 동시에 적용하는 변경사항과 conflict가 일어날 가능성이 많기 때문입니다.

 

CI를 통해 개발자의 변경사항이 애플리케이션을 손상시키지 않도록 자동으로 구축하고 각기 다른 레벨의 자동화 테스트(단위테스트, 통합테스트) 실행을 통해 변경사항이 잘 적용됐는지를 확인합니다.

다시 말해, 클래스와 기능에서부터 서로 다른 모듈에 이르기까지 모든 것에 대한 테스트를 수행합니다.

이렇게 자동화된 테스트에서 기존 코드와 신규 코드 간의 충돌이 발견되면 CI를 통해 이러한 버그를 더욱 빠르게 자주 수정할 수 있게 됩니다.

 

CI의 예시 ( Jenkins )

1. 개발자는 자신의 로컬에서 코드를 수정하고 Github에 push를 한다.

2. CI 도구에서 변경된 코드에 대한  Build, Test, Merge를 진행하고 결과를 피드백해준다.

빌드 & 테스트에 이상이 있는 경우 -> 실패
빌드 & 테스트가 이상 없이 수행되는 경우 -> 성공!

 

CI 도구

Jenkins , TravisCI, Github Actions


CD (continuous Delivery/Delploy, 지속적 제공/배포)

CI의 빌드 자동화, 유닛 및 통합 테스트 수행 후 이어지는 CD.

효과적인 CD를 실현하기 위해서는 개발 파이프라인에 CI가 먼저 구축되어 있어야 합니다 !

 

개발, 통합, 배포, 릴리즈, 테스트를 자동화하여 지속적으로 배포하는 것을 뜻합니다.

 

continuous Delivery ( 지속적 제공 )

배포 단계에서 release할 준비 단계를 거치고 문제가 없는지 수정할 만한 것들이 없는지 개발자가 검증을 합니다.

그 후에 나온 결론이 "이제 사용자들에게 서비스를 제공해도 되겠다!" 라고 정해져서 배포를 수동적으로 진행하는 것을 말합니다. 수동 검토와 배포시간을 고려해야 합니다.

 

continuous Delploy ( 지속적 배포 )

배포 단계에서 배포할 준비가 되자마자 자동화를 통해 사용자들에게 배포를 진행하는 것을 말합니다.

승인 주기가 필요가 없으므로 개발자는 테스트 사이트의 효과와 안정성을 보장해야 합니다.

최소한의 수동 작업으로 매우 짧은 시간 안에 여러 앱 또는 업데이트를 배포할 수 있다는 것이 장점입니다.

 


마무리.

CI의 장점

하나의 소프트웨어에 대해 수많은 개발자들이 동시에 개발을 진행하고 이 소스코드를 정기적으로 통합하는 회사라면 소스코드의 병합은 상당히 많은 공수를 요구하는 일이 될 것입니다.

CI를 적용한다면 소스코드의 변동이 생길 때마다 지속적으로 개발자들의 코드를 병합하고 테스트를 진행합니다. 변경한 소스코드가 문제가 발생하지 않는지 테스트를 실행하고 일련의 과정 중 코드의 충돌, 테스트의 실패 등이 발생하면 즉각적으로 알림을 전송합니다.

이 과정을 통해 아래 장점을 얻을 수 있습니다.

  • 개발의 편의성이 증가합니다.
  • 변경된 코드에 대한 즉각적 피드백과 검증이 가능합니다.
  • 소스코드의 통합과 검증에 들어가는 시간을 단축합니다.

CD의 장점

  • CD의 장점은 실제 배포할 애플리케이션의 서버가 여러 대일 때, 배포할 작업물이 여러 개일 때 나타납니다. 수작업으로 여러 작업물을 여러 서버에 배포할 때 발생하기 쉬운 실수를 방지할 수 있습니다.
  • '원클릭으로 빌드, 테스트, 배포 자동화'를 진행할 수 있습니다. 즉 소스코드 변경부터 배포까지의 작업을 자동화할 수 있기 때문에 수작업으로 할 때의 불편함을 줄일 수 있습니다.
  • 개발자는 개발에만 집중할 수 있게 됩니다.

 

 

참고, 출처:

https://llshl.tistory.com/50

https://www.redhat.com/ko/topics/devops/what-is-ci-cd

https://deveric.tistory.com/106

https://jhleed.tistory.com/130

https://jud00.tistory.com/entry/CICD%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C

'엘리스 ai 트랙 > FE' 카테고리의 다른 글

this [모던 js 딥다이브]  (0) 2022.09.22
Javascript - ES11 ( ES2020 )의 특징들  (0) 2022.04.04
http 1.1 과 http 2 의 차이점  (0) 2022.03.31
HTTP  (0) 2022.03.13
기본값+rest+spread  (0) 2022.03.07

http 1.1의 문제점

1) HOLB (Head Of Line Blocking) - 특정 응답의 지연

HTTP/1.1의 경우 기본적으로 connection당 하나의 요청을 처리하도록 설계되어 있기 때문에 HOL Blocking이 발생할 수 있습니다. 

HOL (Head-Of-Line) 블로킹이란 네트워크에서 같은 큐에 있는 패킷이 첫 번째 패킷에 의해 지연될 때 발생하는 성능 저하 현상을 말합니다.

웹 환경에서의 HOL 블로킹은 패킷 처리 속도 지연 뿐만 아니라 최악의 경우 패킷 드랍까지 발생할 수 있습니다.

=> HTTP/1.1의 connection당 하나의 요청 처리를 개선할 수 있는 기법 중 pipelining(connection을 통해서 다수개의 파일을 요청/응답받을 수 있는 기법)이 존재

* 하지만, 이 또한 처음의 요청에 대한 응답이 오래 걸리는 경우, 그 다음 응답까지의 시간이 지연되는 현상이 발생합니다.

 

2) 무겁고 중복 많은 헤더 구조

HTTP/1.1의 헤더에는 많은 메타 정보들이 저장되어 있습니다. 클라이언트가 서버로 보내는 HTTP 요청은 매 요청마다 중중복된 헤더 값을 전송하게 되며 서버 도메인에 관련된 쿠키 정보도 헤더에 함께 포함되어 전송된다.

이러한 반복적인 헤더 전송, 쿠키정보로 인한 헤더 크기 증가가 HTTP/1.1의 단점입니다.

 


http 2가 나오기 전의 단점 극복 방법

1) Image spriting

웹 페이지를 구성하는 다양한 아이콘 이미지 파일의 요청 횟수를 줄이기 위해 아이콘을 하나의 큰 이미지로 만든 다음 CSS에서 해당 이미지의 좌표 값을 지정하여 표시

 

2) 도메인 샤딩

HTTP/1.1은 하나의 도메인에 하나의 connection만을 맺을 수 있습니다.

이런 단점을 극복하고자, 서버는 같지만, 도메인명을 여러개 설정해서 이를 리소스 주소로 내려주면, 한 브라우저에서 여러 개의 connection을 맺을 수 있게 됩니다. 이렇게 되면, 리소스를 병렬적으로, 동시다발적으로 받을 수 있게 됩니다.

하지만, 너무 많은 도메인을 연결하는 경우, DNS 검색과 TCP handshake에서 발생하는 시간 때문에 역효과가 날 수도 있다고 합니다.

 

3)css, javascript 이미지 압축

HTTP를 통해 전송되는 데이터의 용량을 줄이기 위해서 CSS, Javascript를 축소해서 적용합니다.

name.min.js , name.min.css 등이 그 예입니다.

 

4) data URI 스키마

// data url
<img src="data:image/png;base64, ....."/>

// image file
<img src="./1.png">

HTML 문서 내에 이미지 리소스를 Base64로 인코딩된 이미지 데이터로 직접 기술하는 방법으로 이를 이용하여 서버로의 요청을 줄이는 방식입니다.

 


 

http 2의 등장!

http 2의 주요 특징들

1) 멀티 플렉싱

HTTP/2는 multiplexed Streams를 이용하여 Connection 한 개로 동시에 여러 개의 메시지를 주고 받을 수 있으며 응답은 요청 순서에 상관없이 stream으로 주고 받을 수 있습니다. HTTP/1.1의 Connection Keep-Alive, Pipelining의 개선 버전으로 보면 됩니다.

 

2) steam priorization

클라이언트가 요청한 HTML문서 안에 CSS파일 1개와 Image파일 2개가 존재하고 이를 클라이언트가 각각 요청하고 난 후 Image파일보다 CSS파일의 수신이 늦어지는 경우 브라우저의 렌더링이 늦어지는 문제가 발생하는데 HTTP/2의 경우 리소스간 의존관계(우선순위)를 설정하여 이런 문제를 해결

* 각 스트림에 가중치를 할당해서 우선순위를 결정합니다.

 

3) 서버 푸시

클라이언트(브라우저)가 HTML문서를 요청하고 해당 HTML에 여러 개의 리소스(CSS, Image...) 가 포함되어 있는 경우 HTTP/1.1에서 클라이언트는 요청한 HTML문서를 수신한 후  HTML문서를 해석하면서 필요한 리소스를 재 요청하는 반면,

HTTP/2에서는 Server Push기법을 통해서 클라이언트가 요청하지 않은 (HTML문서에 포함된) 리소스도 Push 해주는 방법으로 클라이언트의 요청을 최소화 해서 성능 향상을 이끌어 냅니다.

 

4) 헤더 압축

HTTP/2는 헤더 정보를 압축하기 위해서 Header TableHuffman Encoding 기법을 사용해서 처리하는데 이를 HPACK 압축방식이라고 부르며 별도의 명세서(RFC 7531)로 관리하고 있습니다.

위 그림처럼 클라이언트가 두번의 요청을 보낸다고 가정할 때 HTTP/1.x의 경우 헤더 중복이 발생해도 중복 전송합니다. 하지만 HTTP/2에서는 헤더에 중복이 있는 경우 Static/Dynamic Header Table 개념을 이용해서 중복을 검출해내고 해당 테이블에서의 index 값 + 중복되지 않은 Header 정보를 Huffman Encoding 방식으로 인코딩한 데이터를 전송합니다.

 


 

마무리.

HTTP(Hypertext Transfer Protocol)는 월드 와이드 웹 (World Wide Web)의 데이터 통신의 기초가 되는 응용 프로그램 프로토콜입니다.

간단하고 추상적인 예는 레스토랑 손님과 웨이터가 될 것입니다. 게스트(클라이언트)가 웨이터에게(서버)에게 식사를 요청하면 (웨이터 (응용 프로그램 논리)) 식사를 게스트에게 가져옵니다.

HTTP1.x 대신 HTTP2.0만 사용해도 아래 그림과 같이 응답속도(식사를 게스트에게 가져오는 속도)가 15~50%정도 향상됩니다.

 

 

참고, 출처:

https://ijbgo.tistory.com/26

https://seokbeomkim.github.io/posts/http1-http2/

https://jaeho214.tistory.com/32

https://lalwr.blogspot.com/2019/01/http1-vs-http2.html

https://mygumi.tistory.com/282

https://yceffort.kr/2021/05/http1-vs-http2

https://kooku.netlify.app/web/http1.1-vs-http2/

'엘리스 ai 트랙 > FE' 카테고리의 다른 글

Javascript - ES11 ( ES2020 )의 특징들  (0) 2022.04.04
CI와 CD  (0) 2022.03.31
HTTP  (0) 2022.03.13
기본값+rest+spread  (0) 2022.03.07
구조분해할당  (0) 2022.03.07

HTTP (Hypertext Transfer Protocol) ?

  • 인터넷에서 데이터를 주고받을 수 있는 통신규약.
  • 서버-클라이언트 모델을 따르는 프로토콜로 TCP/IP 위에서 동작하며 well-known 포트인 80번 포트를 사용

 

  • 표준 버전은 HTTP/1.1 부터 HTTP/2 HTTP/3이 있다. 여기선 HTTP/1.1의 내용을 정리한다.

 

HTTP Request & Response

HTTP 프로토콜로 데이터를 주고받을 때, 클라이언트와 서버를 이해해야 한다.

클라이언트란 요청을 보내는 쪽, 웹 관점에서는 브라우저

서버란 요청을 받는 쪽, 일반적으로 데이터를 보내주는 원격지의 컴퓨터

 

URL (Uniform Resource Locators)

=> 서버에 자원을 요청하기 위한 영문 주소

 

 

HTTP 프로토콜 특징

1. 비연결성(Connectionless)

클라이언트와 서버가 한 번 연결을 맺은 후, 클라이언트 요청에 대해 서버가 응답을 마치면 맺었던 연결을 끊어버리는 성질을 말한다.

 

1) 비연결성의 장점

HTTP는 인터넷 상에서 불특정 다수의 통신환경을 기반으로 설계되었다.

만약 서버에서 다수의 클라이언트와 연결을 계속 유지한다면, 아주 많은 리소스가 발생하게 된다.

=> 연결을 유지하기 위한 리소스를 줄이면 더 많은 연결을 할 수 있으므로 비연결적인 특징을 갖는다

 

2) 비연결성의 단점

하지만, 서버는 클라이언트를 기억하고 있지 않으므로 동일한 클라이언트의 모든 요청에 대해, 

매번 새로운 연결을 시도/해제의 과정을 거쳐야 하므로 연결/해제에 대한 오버헤드가 발생한다는 단점이 있다.

 

3) KeepAlive

이에 대한 해결책으로 오버헤드를 줄이기 위해 KeepAlive 속성을 사용한다.

KeepAlive는 정된 시간동안 서버와 클라이언트 간 패킷 교환이 없을 경우, 상태방의 안부를 묻기 위해 패킷을 주기적으로 보내는 것.

이 때 패킷에 반응이 없으면 접속을 끊게 된다.

 

주기적으로 클라이언트의 상태를 체크한다는 점에서 KeepAlive도 비연결성의 단점을 완벽히 해결해주진 않는다.

KeepAlive 속성이 On 상태라 해도, 서버가 바쁜 환경에서는 프로세스 수가 기하급수적으로 늘어나기 때문에 Keep Alive로 상태를 유지하기 위한 메모리를 많이 사용하게 되므로 주의해야 한다.

 

 

2. 무상태 (Stateless)

1) 무상태란?

Connectionless로 인해 서버는 클라이언트를 식별할 수가 없는데, 이를 stateless라고 한다.

 

예를 들면,

  1. 쇼핑몰에 접속
  2. 로그인
  3. 상품 클릭 -> 상세화면으로 이동
  4. 로그인
  5. 주문
  6. 로그인
  7. ...

즉, 매번 새로운 인증을 해야하는 번거로움이 발생하게 된다.

 

2) 상태를 기억하는 방법-쿠키

서버가 클라이언트를 기억하는 방법! -> 브라우저 단에서 쿠키를 저장하기

( HTTP 헤더: set-cookie )

 

3) 상태를 기억하는 방법-세션

쿠키는 브라우저에 저장되기 때문에 공격자로부터 위변조의 가능성이 높다.

세션은 브라우저가 아닌 서버단에서 사용자 정보를 저장하는 구조이기 때문에 쿠키보다는 안전하다.

 

하지만 세션도 탈취가 가능하기 때문에 보안에 완벽하다고는 할 수 없다. 또한 서버의 메모리를 많이 차지하게 되고, 만약 동시 접속자가 많은 경우에는 서버 과부화의 원인이 된다.

 

4) 상태를 기억하는 방법- 토큰을 사용하는 Oath, JWT

쿠키와 세션의 문제점을 보완하기 위해 Token 기반의 인증방식이 도입!

핵심은 보호할 데이터를 토큰으로 치환해서 원본 데이터 대신 토큰을 사용하는 기술이다.

그래서 중간에 공격자로부터 토큰이 탈취당하더라도 데이터에 대한 정보를 알 수 없으므로, 보안성이 높은 기술이라고 할 수 있다!

 

대표적으로 Oath, JWT가 있다

 

하지만 꼭 토큰 기반의 인증이 반드시 좋다고는 할 수 없다.

서비스에 따라 기술의 특징을 잘 이해해서 때에 따라 쿠키, 세션, oAuth, JWT 등을 적절히 사용하는 것이 좋다.

 

 

3. HTTP 메서드

클라이언트가 서버로 요청을 할 때 어떠한 목적을 갖는 행위인지 HTTP 메서드에 명시한다.

  • GET: 자료를 요청할 때 사용
  • POST: 자료의 생성을 요청할 때 사용
  • PUT: 자료의 수정을 요청할 때 사용
  • DELETE: 자료의 삭제를 요청할 때 사용
  • HEAD: 정확히 GET과 같지만, 요청에서 헤더만 가져올 때 사용
  • TRACE: 클라이언트와 서버 사이의 모든 HTTP 요청/응답 연쇄를 따라가면서 자신이 보낸 메시지의 이상유무 파악
  • OPTIONS: 서버가 실제 요청을 보내기 전에 서버를 테스트해보는 용도, 서버가 어떤 메소드를 지원하는지 알아본다.

 

4. 응답 상태코드

클라이언트가 서버에 요청하면, 서버는 요청에 대한 처리 상태를 숫자로 변환하는데, 이를 응답 코드라 한다.

HTTP 응답의 헤더에 상태코드를 추가해서 응답한다.

  • 100 - 109
    • 메시지 정보
  • 200 - 206
    • 요청 성공
  • 300 - 305
    • 리다이렉션
  • 400 - 415
    • 클라이언트 에러
  • 500 - 505
    • 서버 에러

상태 코드에 대한 자세한 정보 : https://developer.mozilla.org/ko/docs/Web/HTTP/Status/100

 

API 개발 시 올바른 상태 코드를 응답하는 것은 매우 중요하다.

예를 들어, 사용자가 요청 파라미터를 잘못 입력한 경우 잘못된 파라미터로 인해 비즈니스 로직에서 에러가 발생했다고 하여 500 코드를 반환하면 안된다!

사용자가 잘못 입력한 경우므로 403 코드를 반환해야 한다!

 

5. 헤더

 

1) 요청 헤더

시작줄을 HTTP/1.1 표준 버전

다음 줄부터 요청 헤더 정보

 

크롬 주소창에 https://wjdalwjdal6951.tistory.com/ 이라고 치는 것

=> GET https://wjdalwjdal6951.tistory.com/ HTTP/1.1 요청을 보내는 것과 같다.

 

 

< CORS, Origin, Access-Control-Allow-Origin에 대한 문서>

 

읽을 사이트: https://ko.javascript.info/fetch-crossorigin#ref-2011

만약, https://javascript.info/page에서  https://anywhere.com/request 에 요청을 보낸다고 가정할 때, 헤더는 다음과 같은 형태가 된다.

GET /request
Host: anywhere.com
Origin: https://javascript.info
...

Host

서버의 도메인 네임

Host 헤더는 반드시 하나가 존재해야 한다.

Host: anywhere.com

 

Origin

요청이 어느 도메인에서 왔는지 명시, 출처

스킴 https , 도메인 javascript.info , 포트로 정의된다

응답 헤더의 Access-Control-Allow-Origin와 관련

요청을 보낸 주소와 받는 주소가 다르면 CORS 문제가 발생하기도 한다.

Origin: https://javascript.info

 

 

Content-type

컨텐츠의 타입(MIME 미디어 타입) 및 문자 인코딩 방식(EUC-KR, UTF-8 등)을 지정한다.

Content-Type: text/html; charset=utf-8

=> 현재 메시지 내용이 html 텍스트 문서이고 utf-8 문자 인코딩 방식으로 표현됨.

 

**참고) POST 혹은 PUT 처럼 클라이언트가 서버에게 폼을 통해서 파일을 업로드할 때는

컨텐츠 타입을 application/x-www-form-urlencoded 

Content-Type: application/x-www-form-urlencoded

컨텐츠 타입을 multipart/form-data로 작성 (바이너리 데이터)

-> input이 여러개일 때 하나는 텍스트타입이고, 하나는 이미지타입일 때 2가지 종류의 데이터를 구분해서 넣어주기 위해 multipart 타입이 등장했다.

 

 

If-Modified-Since

페이지가 수정되었으면 최신 버전 페이지 요청을 위한 필드

만약 요청한 파일이 이 필드에 지정된 시간 이후로 변경되지 않았다면,

서버로부터 데이터를 전송받지 않는다. 304 상태코드(리다이렉션)를 전송받게 된다.

If-Modified-Since: Sat, 29 Mar 2022 19:43:31 GMT

 

 

Cookie

웹서버가 클라이언트에 쿠키를 저장해 놨다면 해당 쿠키의 정보를 이름-값 쌍으로 웹서버에 전송함

 

 

2) 응답 헤더

 

Access-Control-*

Access-Control-Allow-Origin: *

이 응답이 주어진 origin으로부터의 요청 코드와 공유될 수 있는지 여부 확인

 

Ex) Access-Control-Allow-Origin: https://javascript.info 

  • 프로토콜, 도메인, 포트 중 하나만 달라도 CORS 에러가 발생

EX) Access-Control-Allow-Origin: *

  • 만약 주소를 일일이 지정하기 싫다면 * 으로 모든 주소에 CORS를 허용한다. 하지만 그만큼 보안에 취약해진다.

 

**관련 헤더

 - Access-Control-Request-Method : 실제로 보내려는 메서드
 - Access-Control-Request-Headers : 실제로 보내려는 헤더
 - Access-Control-Allow-Methods : 서버가 허용하는 메서드
 - Access-Control-Allow-Headers : 서버가 허용하는 헤더

 

**참고: CORS ( Cross Origin Resource Sharing )란? 

서로 다른 도메인 간에 리소스를 활용할 필요가 있을때, 어떤 규칙으로 누구에게 허용할 것인지를 정의하는 HTTP 표준의 일부
https://developer.mozilla.org/ko/docs/Web/HTTP/CORS

 

Set-Cookie

서버에서 클라이언트에게 세션 쿠키 정보를 설정

set-cookie: UserID=JohnDoe; path=/; expires=Mon, 14 Mar 2022 02:05:36 GMT; secure; HttpOnly; SameSite=Lax

자세한 정보: https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/Set-Cookie

 

 

Last-Modified 

서버가 알고있는 가장 마지막 수정날짜와 시각. 저장된 리소스가 이전과 같은지 유효성 검사자로 사용됨

Last-Modified: Tue, 15 Mar 2022 12:45:26 GMT

 

 

Location

3xx 상태코드(라다이렉션)일 때 어느 페이지로 이동할지 알려준다

HTTP/1.1 302 Found
Location: /login

=> 위와 같은 응답시 /login 주소로 리다이렉트 한다.

 

 

Allow

해당 엔터티에 대해 서버에서 지원 가능한 HTTP 메소드 리스트.

때론, HTTP 요청 메세지의 HTTP 메소드 OPTIONS에 대한 응답용 항목으로 사용

Allow: GET, HEAD

=> 서버에서 제공가능한 HTTP 메서드는 GET, HEAD 뿐임을 알린다.

 

 

 

 

 

 

참고:출처:

https://developer.mozilla.org/ko/docs/Web/HTTP/CORS

https://ko.javascript.info/fetch-crossorigin#ref-2011

 

https://goddaehee.tistory.com/169

https://www.zerocho.com/category/HTTP/post/5b4c4e3efc5052001b4f519b

https://joshua1988.github.io/web-development/http-part1/#http-%EC%9A%94%EC%B2%AD-%EB%A9%94%EC%84%9C%EB%93%9C

 

https://github.com/baeharam/Must-Know-About-Frontend/blob/main/Notes/network/http.md#%EC%9D%91%EB%8B%B5-%ED%97%A4%EB%8D%94

https://victorydntmd.tistory.com/286

https://gmlwjd9405.github.io/2019/01/28/http-header-types.html

'엘리스 ai 트랙 > FE' 카테고리의 다른 글

CI와 CD  (0) 2022.03.31
http 1.1 과 http 2 의 차이점  (0) 2022.03.31
기본값+rest+spread  (0) 2022.03.07
구조분해할당  (0) 2022.03.07
IIFE (즉시 호출 함수 표현식)  (0) 2022.02.28

위에서 오류가 났다. isQualified는 filter메서드에 넣어지는 함수이다.

 

해결법

1. {} 를 ()로 바꿔준다

2. {} 를 쓰고 싶다면, { return ~~~}로 작성해준다.

 

화살표 함수의 주의사항

const Button = () => (
  <button>Submit</button>
)

화살표 함수의 경우 ()로 감싸진 부분이 return으로 넘어간다

이 때에는 return을 작성해주지 않아도 된다.

 

const Button = () => {
  <button>Submit</button>
}
console.log(Button);	// undefined
}

반면에 {}로 감싸진 함수는 return이 없다면 반환하지 않는다.

 

const Button = () => {
    return <button>Submit</button>
}

따라서 {  }로 반환하고 싶다면 위처럼 작성해줘야 한다

 

 

참고, 출처: https://velog.io/@chayezo/%EC%97%90%EB%9F%AC-Expected-an-assignment-or-function-call-and-instead-saw-an-expression-no-unused-expressions

 react.dom.development.js:23803 Uncaught Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

 

onClick 같은 이벤트함수에서 아래와 같이 작성했을 때 위 오류가 나타나는 것 같다.

setIsEditing()을 부른다 -> 컴포넌트를 재렌더링한다 -> 다시 setIsEditing()을 부른다 => 반복

함수를 부른다? -> {} 안에 함수명+()를 쓰면 바로 호출이라는 의미이다

 

그래서 함수를 무한정으로 다시 부르고 싶지 않다면 아래와 같은 코드로 작성하거나, 매개변수가 없을 땐 ()는 붙이지 않고 함수명만 작성해놔야 한다.

 

++) React 이벤트의 특징: 이벤트에 실행할 코드를 전달 (x) => 함수 형태의 객체를 전달 (o)

이벤트에 실행할 코드를 전달한다면, 이벤트가 호출되는 것으로 간주하여 바로 실행되고, 제대로 연결이 되지 않는다.

화살표 함수를 이용한 콜백 함수의 형태로 전달해야 한다.

 

참고, 출처: https://kss7547.tistory.com/36

"내가 어떤 문제가 있었고, 이것을 해결하기 위해 이렇게 작성했다"

1. 매개변수 기본값 (Default Parameter value)

  • 함수를 호출할 때 인수를 전달하지 않은 경우에도 에러가 발생하지는 않는다.
  • 함수는 매개변수와 인수의 개수를 체크하지 않는다. 
  • 인수가 부족한 경우, 매개변수의 값은 undefined이다.
function sum(x, y) {
  // 매개변수의 값이 falsy value인 경우, 기본값을 할당한다.
  x = x || 0;
  y = y || 0;

  return x + y;
}

console.log(sum(1));    // 1
console.log(sum(1, 2)); // 3

ES6에서는 매개변수 기본값을 사용하여 함수 내에서 수행하던 인수 체크 및 초기화를 간소화할 수 있다.

( 매개변수 기본값은 매개변수에 인수를 전달하지 않았을 경우에만 유효하다. )

function sum(x = 0, y = 0) {
  return x + y;
}

console.log(sum(1));    // 1
console.log(sum(1, 2)); // 3

 

 

2. Rest 파라미터

  • Rest 파라미터는 함수에 전달된 인수들의 목록을 배열로 전달받는다.
  • 이름 그대로 먼저 선언된 파라미터에 할당된 인수를 제외한 나머지 인수들이 모두 배열에 담겨 할당된다
function foo(param, ...rest) {
  console.log(param); // 1
  console.log(rest);  // [ 2, 3, 4, 5 ]
}
foo(1, 2, 3, 4, 5);
  • rest 파라미터는 반드시 마지막 파라미터여야 한다.
function foo( ...rest, param1, param2) { }

foo(1, 2, 3, 4, 5);
// SyntaxError: Rest parameter must be last formal parameter
  • 함수 정의시 선언한 매개변수 개수를 나타내는 함수 객체의 length 프로퍼티에 영향을 주지 않는다
function foo(...rest) {}
console.log(foo.length); // 0

function bar(x, ...rest) {}
console.log(bar.length); // 1

function baz(x, y, ...rest) {}
console.log(baz.length); // 2

 

ES5에서는 인자의 개수를 사전에 알 수 없는 경우 arguments 객체를 통해서 인수를 확인한다.

**arguments 객체: 전달된 인수들의 정보를 담고 있는 순회가능한 유사배열 객체

// ES5
var foo = function () {
  console.log(arguments);
};

foo(1, 2); // { '0': 1, '1': 2 }

배열이 아닌 유사배열 객체이므로 배열메소드를 사용하려면 Function.prototype.call을 사용하는 번거로움이 있다

// ES5
function sum() {
  /*
  가변 인자 함수는 arguments 객체를 통해 인수를 전달받는다.
  유사 배열 객체인 arguments 객체를 배열로 변환한다.
  */
  var array = Array.prototype.slice.call(arguments);
  return array.reduce(function (pre, cur) {
    return pre + cur;
  });
}

console.log(sum(1, 2, 3, 4, 5)); // 15

 

ES6에서는 rest 파라미터를 사용해서 가변인자의 목록을 배열로 전달받을 수 있다.

유사배열객체를 배열로 변환하는 번거로움을 피할 수 있다!

/ ES6
function sum(...args) {
  console.log(arguments); // Arguments(5) [1, 2, 3, 4, 5, callee: (...), Symbol(Symbol.iterator): ƒ]
  console.log(Array.isArray(args)); // true
  return args.reduce((pre, cur) => pre + cur);
}
console.log(sum(1, 2, 3, 4, 5)); // 15

 

 

3. spread 문법

  • spread 연산자는 연산자의 대상 배열 또는 이터러블을 개별 요소로 분리한다.

**이터러블: Array, String, Map, Set, DOM구조,     for...of로 순회할 수 있는 자료구조.

// 문자열은 이터러블이다.
console.log(...'Hello');  // H e l l o

// Map과 Set은 이터러블이다.
console.log(...new Map([['a', '1'], ['b', '2']]));  // [ 'a', '1' ] [ 'b', '2' ]
console.log(...new Set([1, 2, 3]));  // 1 2 3

// 이터러블이 아닌 일반 객체는 Spread 문법의 대상이 될 수 없다.
console.log(...{ a: 1, b: 2 });
// TypeError: Found non-callable @@iterator

 

함수의 파라미터로 사용하는 방법

function foo(x, y, z) {
  console.log(x); // 1
  console.log(y); // 2
  console.log(z); // 3
}

const arr = [1,2,3]
/* ...[1, 2, 3]는 [1, 2, 3]을 개별 요소로 분리한다(→ 1, 2, 3)
   spread 문법에 의해 분리된 배열의 요소는 개별적인 인자로서 각각의 매개변수에 전달된다. */
foo(...arr);

 

Rest와 헷갈리지 않기!!
  • Rest 파라미터는 함수 선언문의 파라미터에 spread 연산자(...)를 이용해서 받으면 가변인자를 받아 배열로 만들어서 사용하는 것 즉, spread 문법을 사용해서 파라미터를 정의한 것.
  • 함수 호출문의 파라미터에 spread 연산자(...)를 이용해서 호출하면 배열이 해당 매개변수로 각각 매핑되는 것.      (= spread 문법을 사용한 배열을 인수로 함수에 전달하면 배열의 요소를 순차적으로 파라미터에 할당하는 것.)
  • 또한, Rest 파라미터는 반드시 마지막에 써야 하지만, spread 호출(spread 문법을 사용한 인수)에서는 자유롭게 사용할 수 있다.
//Rest
function foo(param, ...rest) {
  console.log(param); // 1
  console.log(rest);  // [ 2, 3 ]
}
foo(1, 2, 3);
 
//Spread호출
function bar(x, y, z) {
  console.log(x); // 1
  console.log(y); // 2
  console.log(z); // 3
}
bar(...[1, 2, 3]);

 

1. 배열에서 사용하기

//ES5
var arr = [1, 2, 3];
console.log(arr.concat([4, 5, 6])); // [ 1, 2, 3, 4, 5, 6 ]
 
// ES6
const arr = [1, 2, 3];
// ...arr은 [1, 2, 3]을 개별 요소로 분리한다
console.log([...arr, 4, 5, 6]); // [ 1, 2, 3, 4, 5, 6 ]

-> concat() 대신 가독성이 좋아졌다

 

// ES5
var arr1 = [1, 2, 3];
var arr2 = [4, 5, 6];
 
// apply 메소드의 2번째 인자는 배열. 이것은 개별 인자로 push 메소드에 전달된다.
Array.prototype.push.apply(arr1, arr2);
//arr1.push(4, 5, 6); 하는 것과 동일하다
console.log(arr1); // [ 1, 2, 3, 4, 5, 6 ]
 
// ES6
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
 
// ...arr2는 [4, 5, 6]을 개별 요소로 분리한다
arr1.push(...arr2); // == arr1.push(4, 5, 6);
 
console.log(arr1); // [ 1, 2, 3, 4, 5, 6 ]

-> push 를 개별 요소로 전달할 수 있으니 훨씬 간결하고 가독성 또한 좋아졌다.

 

const htmlCollection = document.getElementsByTagName('li');

// 유사 배열인 HTMLCollection을 배열로 변환한다.
const newArray = [...htmlCollection]; // Spread 문법

// ES6의 Array.from 메소드를 사용할 수도 있다.
// const newArray = Array.from(htmlCollection);

-> 유사 배열 객체(Array-like Object)를 배열로 손쉽게 변환할 수 있다.

 

 

2. 객체에서 사용하기

const o1 = { x: 1, y: 2 };
const o2 = { ...o1, z: 3 };
console.log(o2); // { x: 1, y: 2, z: 3 }
 
const target = { x: 1, y: 2 };
const source = { z: 3 };
// Object.assign를 사용하여도 동일한 작업을 할 수 있다.
// Object.assign은 타깃 객체를 반환한다
console.log(Object.assign(target, source)); // { x: 1, y: 2, z: 3 }

-> Object.assign을 대체할 수 있는 간편한 문법이다.

 

 

 

 

참고,출처

https://poiemaweb.com/es6-extended-parameter-handling

https://jeong-pro.tistory.com/117

'엘리스 ai 트랙 > FE' 카테고리의 다른 글

http 1.1 과 http 2 의 차이점  (0) 2022.03.31
HTTP  (0) 2022.03.13
구조분해할당  (0) 2022.03.07
IIFE (즉시 호출 함수 표현식)  (0) 2022.02.28
var vs let vs const  (0) 2022.02.21

Destructuring (비구조화, 파괴)

구조화된 배열 또는 객체를 Desturcturing하여 개별적인 변수에 할당하는 것.
배열 또는 객체 리터럴에서 필요한 값만을 추출하여 변수에 할당하거나 반환할 때 유용

 

1. 배열 Destructuring 

  • 배열의 각 요소를 추출하여 변수 리스트에 할당
  • 추출/할당 기준은 배열의 인덱스
const arr = [1, 2, 3];

// 배열의 인덱스를 기준으로 배열로부터 요소를 추출하여 변수에 할당
// 변수 one, two, three가 선언되고 arr(initializer(초기화자))가 Destructuring(비구조화, 파괴)되어 할당된다.
const [one, two, three] = arr;
// 디스트럭처링을 사용할 때는 반드시 initializer(초기화자)를 할당해야 한다.
// const [one, two, three]; // SyntaxError: Missing initializer in destructuring declaration

console.log(one, two, three); // 1 2 3

 

할당연산자(=) 왼쪽에 배열형태의 변수 리스트가 있고, 오른쪽의 배열은 인덱스를 기준으로 할당된다

let x, y, z;

[x, y] = [1, 2];
console.log(x, y); // 1 2

[x, y] = [1];
console.log(x, y); // 1 undefined

[x, y] = [1, 2, 3];
console.log(x, y); // 1 2

[x, , z] = [1, 2, 3];
console.log(x, z); // 1 3

// 기본값
[x, y, z = 3] = [1, 2];
console.log(x, y, z); // 1 2 3

[x, y = 10, z = 3] = [1, 2];
console.log(x, y, z); // 1 2 3

// spread 문법
[x, ...y] = [1, 2, 3];
console.log(x, y); // 1 [ 2, 3 ]

 

2. 객체 Destructuring 

  • ES6의 객체 destructuring은 각 프로퍼티를 객체로부터 추출하여 변수 리스트에 할당
  • 할당 기준은 프로퍼티 이름(키)
const obj = { firstName: 'Ungmo', lastName: 'Lee' };

// 프로퍼티 키를 기준으로 디스트럭처링 할당이 이루어진다. 순서는 의미가 없다.
// 변수 lastName, firstName가 선언되고 obj(initializer(초기화자))가 Destructuring(비구조화, 파괴)되어 할당된다.
const { lastName, firstName } = obj;

console.log(firstName, lastName); // Ungmo Lee

 

할당연산자(=) 왼쪽에 객체형태의 변수 리스트가 있고, 프로퍼티 이름으로 값을 추출한다

// 프로퍼티 키가 prop1인 프로퍼티의 값을 변수 p1에 할당
// 프로퍼티 키가 prop2인 프로퍼티의 값을 변수 p2에 할당
const { prop1, prop2 } = { prop1: 'a', prop2: 'b' };
console.log({ prop1, prop2 }); // { prop1: 'a', prop2: 'b' }

// default value
const { prop1, prop2, prop3 = 'c' } = { prop1: 'a', prop2: 'b' };
console.log({ prop1, prop2, prop3 }); // { prop1: 'a', prop2: 'b', prop3: 'c' }

 

객체 비구조화는 프로퍼티 이름으로 필요한 프로퍼티 값만을 추출할 수 있다.

const todos = [
  { id: 1, content: 'HTML', completed: true },
  { id: 2, content: 'CSS', completed: false },
  { id: 3, content: 'JS', completed: false }
];

// todos 배열의 요소인 객체로부터 completed 프로퍼티만을 추출한다.
const completedTodos = todos.filter(({ completed }) => completed);
console.log(completedTodos); // [ { id: 1, content: 'HTML', completed: true } ]

filter 메소드의 콜백함수는 todos배열을 순회하며 첫번째 인자로 대상배열의 요소를 받는다.

그래서 completed가 true인 객체만 반환한다

이때 필요한 프로퍼티만을 추출할 수 있다.

 

중첩객체의 경우는 아래와 같이 사용한다

const person = {
  name: 'Lee',
  address: {
    zipCode: '03068',
    city: 'Seoul'
  }
};

const { address: { city } } = person;
console.log(city); // 'Seoul'

 

fail-soft 비구조화는 값이 찾아지지 않더라도 오류가 생기지 않고 undefined를 반환하는 것을 의미한다.

// Fail-soft 비구조화 (Fail-soft는 고장이 나도 작동하도록 짠 프로그램을 말한다)
var [a] = [];
a === undefined;

// 기본 값이 있는 Fail-soft 비구조화
var [a = 1] = [];
a === 1;

하지만, 중첩된 객체에서의 프로퍼티는 fail-soft가 적용되지 않는다는 점에 유의해야 합니다.

let options = {},
  // `delay` would be `undefined`, but trying
  // to assign to `name` is an error
  // since `options.info` is already `undefined`
  {
    delay, 
    info: { name },
  } = options

options.info와 delay는 모두 undefined를 반환한다.

하지만, info안의 name은 error을 발생시킨다. ( name을 감싸고 있는 info가 이미 undefined이기 때문에 ) 

 

 

참고, 출처: 

https://www.benmvp.com/blog/learning-es6-destructuring/

https://poiemaweb.com/es6-destructuring

'엘리스 ai 트랙 > FE' 카테고리의 다른 글

HTTP  (0) 2022.03.13
기본값+rest+spread  (0) 2022.03.07
IIFE (즉시 호출 함수 표현식)  (0) 2022.02.28
var vs let vs const  (0) 2022.02.21
스코프  (0) 2022.02.14

+ Recent posts