항해99 TIL [10/9]

이지연·2021년 10월 9일
0

항해99 TIL

목록 보기
5/33

어제부(10/8)로 길다면 길고 짧다면 짧은 일주일의 과제 심화주차 기간이 끝나고 회고의 날이 찾아왔다. 아쉬움보다는 앞으로의 항해를 어떻게 이어갈지를 생각하며 내가 속한 팀인 23조 및 다른 팀의 항해원들이 남긴 Wrap-up Assignment (W.A.)을 질문별로 찬찬히 살펴보는 시간을 가져보았다.

각 팀당 두 가지 질문을 스스로 만들어서 답변해 보세요 :-)

[23조]

우리 팀은 DebounceThrottle의 차이 & Memoization에 대한 질문을 만들었음.

▶ Debounce

이벤트 요청을 받으면 정해진 시간 만큼 기다렸다가 실행.
단, 실행 전 새로운 수행 요청이 들어오면 이전 요청을 실행하지 않고 새로운 요청을 실행함.

▶ Throttle

정해진 시간동안 들어온 요청을 취합하여 실행하기를 반복함.

ex)

import _ from "lodash";

...

const debounce = _.debounce((e)=>{
	console.log("debounce:::", e.target.value);
},1000} //새로운 요청이 들어오지 않으면 1초후 input 안에 들어온 값을 출력 

const throttle = _.throttle((e)=>{
	console.log("throttle:::", e.target.value);
},1000} //1초마다 input에 들어온 값을 출력

const onchange = (e) => {
	debounce(e);
	throttle(e);
}

...

return <input type="text" onChange={onchange}/>

예를 들어 "감자는 맛있다." 라는 문구를 입력창에 입력하면 onChange로 인해 문자가 입력될때마다 요청이 발생함. 이 때 throttle은 1초마다 지금까지 입력된 값을 출력하고 debounce는 문장 입력이 끝나고 1초 후 출력함.

▶ Memoization

Memoization은 주어진 입력값에 대한 결과를 저장함으로써 같은 입력값에 대해 함수가 한 번만 실행되도록 함. 예를 들어 n번째 피보나치 수를 계산하는 아래의 간단한 재귀식을 보면, 입력값에 대해 여러 번 실행되는 것을 알 수 있음.

deffib(n):
if n< 0:
raise IndexError(
        	'Index was negative.'
            'No such thing as a negative index in a series.'
        )
elif nin [0, 1]:
# Base cases
return n

print("computing fib(%i)"% n)
return fib(n- 1)+ fib(n- 2)

위 함수의 재귀호출은 빠르게 가지를 뻗어가는 트리 형태로 상상해볼 수 있음. 노드의 두 자식들은 노드가 만들어내는 두 재귀호출이 됨.

그리고 이처럼 가지를 뻗어나감으로써 발생되는 반복 작업을 피하기 위해서는, 입력값을 출력값과 매핑해주는 memo 라는 속성을 가진 클래스로 함수를 감싸야함.

이러한 과정을 통해,

  1. memo를 체크함으로써 어떤 주어진 입력값에 대해 계산을 안 해도 되는지 확인가능함
  2. 계산 결과를 memo에 저장할 수 있음.
classFibber(object):

def__init__(self):
        self.memo= {}

deffib(self, n):
if n< 0:
raise IndexError(
                'Index was negative.'
                'No such thing as a negative index in a series.'
            )

# Base cases
elif nin [0, 1]:
return n

# 이미 계산한 값인지 아닌지 확인한다.
elif nin self.memo:
print ("grabbling memo[%i]"% n)
return self.memo[n]

print("computing fib(%i)"% n)
        result= self.fib(n- 1)+ self.fib(n- 2)

# Memoize
        self.memo[n]= result

return result

이제 아래의 재귀 트리에서, 노드는 두 번 이상 나타나지 않음.

Memoization(메모이제이션)은 dynamic programming(동적 계획법) 문제를 풀 때 흔히 쓰이는 방법임. 동적 계획법이란 문제의 정답이, 입력값의 더 작은 부분에 대해 동일한 문제의 정답으로 구성되어 있는(마치 위에서 설명한 피보나치 같은 문제) 문제를 의미함. 동적 계획법 문제를 풀기 위한 또다른 일반적인 방법은 Bottom-up이 있는데, 보통 이것이 더 깔끔하고 더 효율적임.

[18조]
▶ 파라미터란?

특정 id나 이름을 가지고 조회를 할 때 사용하게 되고, 쿼리의 경우는 어떤 키워드를 검색하거나 요청할 때 필요한 옵션을 전달 할 때 사용됨. 파라미터는 일반적으로 특정id나 이름을 가지고 조회할때 사용함. 그 방법으로는 리액트의 라우팅 라이브러리를 사용해 (react-router-dom) Match 객체 에 접근하여 URL 파라미터를 받아올 수 있음.

<Route path="/somepath/:someInfo" component={SomeComponent}/> 

이렇게 path에 파라미터를 추가할 수 있고, 여기에 http://localhost:3000/somepath/Hello와 같은 요청을 받게 된다면 param 값은 {someInfo: "Hello"} 가 됨. 이를 원하는 페이지 에서 match를 받아와 match.params.seomInfo를 출력하면 Hello가 나옴.

▶ 디바운스란?

이벤트가 일어나면 일정시간 기다렸다가 이벤트를 수행하는 것. onChange 이벤트에서 키값 하나하나를 입력할 때마다 api 콜을 날리면 서버부담을 줄 수 있으므로 그것을 막기위해 하는 것.

- 예시
    - ㄱ | 가 | 감 |1초| 감ㅅ | 감사 | 감샇 |2초|
    - 이렇게 검색한다고 했을때 이벤트에서 ㄱ, 가 이벤트는 삭제하고 미지막 이벤트를 실행함.
    
- 활용사례
    - 연관검색어
        - 감사합니다 검색한다고 했을 때 가나 감사합 검색어는 필요없음.
        - 이전 이벤트 삭제해도 괜찮은 예시가 적합함.
  • throttle이란?
    • 일정 기간(시간)동안 일어난 이벤트를 모아서 주기적으로 1번씩 실행.
    • 예시
      • ㄱ | 가 | 감 |1초| 감ㅅ | 감사 | 감샇 |2초|
      • 이렇게 검색한다고 했을때 이벤트에서 ㄱ, 가 이벤트는 삭제하지 않고 1초에 다다른 마지막 이벤트를 실행.
    • 활용사례
      • 스크롤 높이에 따라 게이지 채워주는 것.
      • 이전 이벤트 삭제하지 않고 천천히 실행해주는 게 좋음.

[22조]
▶ 옵셔널 체이닝이란?

Optional Chaining은 ES2020에서 등장한 새로운 연산자로서 '?.' 의 형태로 사용하며 체인으로 이루어진 각 참조가 유효한지 명시적으로 검증하지 않고 연결된 객체 체인 내에 깊숙히 위치한 속성 값을 읽을 수 있는 연산자임.

호이스팅에 대하여
https://endurable-existence-f23.notion.site/023f2e154d7148ffa7c9dfb9ed1f4ca7

s3 버킷에 배포한 뒤, 어떤도메인.com이 아닌 어떤도메인.com/login 등 페이지로 이동하면 왜 오류가 날까요?

▶ 참고
https://docs.aws.amazon.com/ko_kr/AmazonS3/latest/userguide/CustomErrorDocSupport.html

  • 특정 Virtual URL로 이동할 때에는 403 또는 404 오류가 발생함.
  • 403 오류의 경우 객체가 존재하지만 해당 객체에 대한 읽기 권한을 부여하지 않았을 경우 발생함.
  • 404 오류의 경우 URL이 존재하지 않는 객체를 요청할 경우 발생함.

[15조]
리액트는 SPA 이기 때문에, 배포하게되면 S3서버에서는 index.html파일 하나만 있다고 인식하여, /login 이렇게 direct로 접근하게 되면 Access denied가 뜨게됨. (따로 옵션을 해줘야..)

[18조]
아마존 S3에서 /login 페이지를 존재하지 않는 객체 키를 참조 한다고 판단하고 url에 지정된 버킷이 존재하지 않는 것으로 간주되어 생기는 문제.

[튜터님의 답변]

  • 리액트의 라우팅 방식이 전통적 링크 방식이 아니기 때문임. (전통적 링크 방식의 경우 주소창에 적힌대로 html 파일을 받아 보여준다면, SPA는 하나의 html을 두고 주소창에 적힌 대로 내용을 갈아끼우는 방식)
  • s3 버킷의 정적 웹사이트 호스팅은 /login 경로에 맞는 html을 찾는 거고, 해당 html파일이 없기 때문에 404 에러가 나는 것.
  • 에러 해결 방법은? s3가 어떤 상황이건 index.html을 보도록 설정해주는 것.

리액트에서 각 페이지 컨텐츠에 맞는 미리보기(사이트 이미지, 사이트 설명 등)를 띄워주려면 어떻게 해야할까요?

▶ FileReader 객체를 사용하여 해결가능

🌟 FileReader

생성자 객체를 생성함.

const reader = new FileReader()

이벤트 핸들러

reader.onload = () => {}

FileReader.readAsDataURL()특정 Blob이나 File에서 읽어 오는 역할을 함. 다 읽고 난후 result 속성에 결과가 담아짐. - readAsDataURL() MDN 참조

Blob객체란? 파일류의 불변하는 미가공 데이터를 의미함.

▶ 메타태그를 사용하여 해결가능

1) react-helmet 설치하기

yarn add react-helmet

2) helmat으로 메타 태그 바꾸기

//One.js
import React from "react";
import {Helmet} from "react-helmet";
const One = (props) => {
    return (
      <div>
        <Helmet>
          <title>page one</title>
          <meta property="og:title" content="page one" />
          <meta property="og:description" content="hi there :) page one" />
          <meta property="og:image" content="%PUBLIC_URL%/logo192.png" />
        </Helmet>
        <h2>Hi, there :) ! page one</h2>
        <button
          onClick={() => {
            props.history.push("/");
          }}
        >
          page one
        </button>
        <button
          onClick={() => {
            props.history.push("/two");
          }}
        >
          page two
        </button>
      </div>
    );
}

export default One;

3) 확인하기

빌드 후, post man에서 확인해보기

  • 빌드하기
    yarn build
  • post man에서 확인하기

티스토리, 카카오톡 등에 페이지의 링크를 올릴 때 meta태그의 property에 맞는 content가 노출됨.

ex)

  • 티스토리에서 다른 티스토리 글의 링크를 걸었을 때

https://www.notion.so/React-W-A-23-7aa86bba589f457bab8c5de7c90d36a4#e8cf5e87799c48bc962bb89e8fd1a511

  • 링크 걸린 페이지의 메타태그

[15조]
⚙️ SPA
한개의 페이지를 가진 어플리케이션
SPA는 클라이언트 사이드 렌더링이지만 SPA === CSR

<장점>
사용자 친화적
초기 렌더링 후 데이터만 받아오기 때문에, 상대적으로 서버 요청이 적음.

⚙️ CSR
최초 요청시 html을 비록해 CSS, Javascript 각종 리소스를 받아옴.
서버에 데이터만 요청하고, 자바스크립트로 뷰를 컨트롤함.
초기요청에서 SSR 보다 많은 리소스를 요청하기 때문에 SSR보다 느림.
하지만 이후 다른페이지로 이동시 SSR보다 빠른 전환속도로 더 나은 사용자 경험을 제공.

🔨 검색엔진
검색엔진들은 웹사이트의 올려진 html을 분석해서 (여기에는 이런 title과 이런 컨텐츠가 있으니깐 특정 검색어로 찾아질수 있는 사이트라고) 검색엔진에 올려놓음.

🔨 react-helmet 이란?
리액트 SPA방식이고 index.html 하나만 존재함.
크롤러가 그 페이지를 읽으면 빈 index.html(컨텐트가 없다고) 만 있다고 인식함. 이것을 해결하기 위해 react-helmet 라이브러리를 통해 meta-tag를 넣어줘서 검색엔진 최적화에 조금이나마 도움이 됨.

🔨 어떻게 해야할까요?
각 컴포넌트에 helmet을 이용해서 meta 태그를 넣어줌.

[튜터님의 답변]

  • 메타태그를 페이지에 맞게 조절해준다. 그리고 검색봇이 해당 메타태그를 미리 읽어갈 수 있도록 서버사이드 렌더링 처리 혹은 pre-rendering처리 해준다.
    • 더 알아보면 좋을 키워드 : SSR

리덕스에서 미들웨어 청크의 역할은 뭘까요?

미들웨어

  • 액션과 리듀서 사이의 중간자 역할.
  • 미들웨어의 종류 : redux-thunk, redux-saga, redux-promise

redux-thunk

  • 리덕스에서 비동기 처리를 할 때 가장 많이 사용되는 미들웨어로 액션객체가 아닌 함수를 디스패치 할 수 있음.

  • 일반 액션 생성자는 하나의 액션객체를 생성하는 반면, redux-thunk를 통해 만들어진 액션 생성자는 내부에서 여러가지 작업 가능.

  • thunk 함수를 만들어 dispatch 하면 미들웨어가 그 함수를 전달받아 dispatch와 getState를 파라미터로 넣어서 호출.

    • thunk란? 특정 작업을 나중에 할 수 있도록 미루기 위해 함수 형태로 감싼 것
  • redux-thunk 형태

const reduxTunck = () => (dispatch, getState) =>{ }
  • 액션 생성 함수에서 일반 액션 객체 대신 함수를 리턴.

[15조]
🔨 미들웨어란?
기본 리덕스만 쓰게되면 동기 작업밖에 안됨. 비동기 작업(서버에 요청 응답, 외부 API 연동)를 사용하기위해 middleware에서 처리함.

🔨 redux-thunk
redux-thunk 미들웨어의 한종류.
redux-thunk는 액션 creator가 액션 대신 thunk라는 함수를 반환함.
기존 리덕스에서는 객체만을 반환하는데, redux-thunk라는 미들웨어를 사용하면 함수를 반환하게되고 그 안에서 비동기작업을 할 수 있음.

[24조]
redux-thunk는 리덕스에서 비동기 작업을 처리 할 때 가장 많이 사용하는 미들웨어임. redux-thunk 라는 미들웨어를 사용하며 이 미들웨어를 사용하면 액션 객체가 아닌 함수를 디스패치 할 수 있음.

thunk는 특정 작업을 나중에 하도록 미루기 위해서 함수형태로 감싼것을 칭함. 코드가 실행 될 때 바로 이뤄지지 않고 foo() 가 호출 되어야만 이루어짐.

[튜터님의 답변]

  • 액션 객체를 dispatch하는 대신 함수를 dispatch할 수 있도록 해줌.
    dispatch한 함수는 dispatch, getState, 그 외의 직접 설정한 값을 받아 사용할 수 있음.

  • 비동기 처리 등에 사용할 수 있음.

프로미스는 정확히 말하면 비동기가 아닙니다. 비동기와 프로미스는 각각 무엇일까요?

비동기와 Promise의 가장 큰 차이점은 비동기는 데이터 처리 방식이고 Promise는 객체라는 점.

  • 비동기란 여러가지의 작업이 각자 끝나는 대로 바로 처리되는 병렬적 데이터 처리 방식. 따라서 작업을 요청하고 그 결과를 꼭 바로 받지 않고 다른 작업을 수행할 수 있음.

  • Promise란 비동기 작업의 결과를 나타내는 JavaScript 객체. 즉, JavaScript 상에서 비동기적으로 실행되는 작업의 결과 (성공 또는 실패)를 객체화하여 반환함.

  • Promise 상태값

    pending : 비동기 처리 수행 전
    fulfillde : 수행 성공
    rejected : 수행 실패
    settled : 성공 or 실패

[18조]
비동기는 동시에 여러 가지 작업을 할 수 있는 개념이고 Promise는 비동기 작업의 단위를 뜻하며 비동기 작업을 쉽게 관리할 수 있음.

[19조]
▶ 비동기 처리란?
어떤 작업을 요청했을 때 그 작업이 종료될때 까지 기다리지 않고 다른 작업을 하고 있다가, 요청했던 작업이 종료되면 그에 대한 추가 작업을 수행하는 방식.

▶ 프라미스란?
비동기 작업이 종료된 후 결과값이 어떠한지에 대해 반환을 약속해주는 객체.

[튜터님의 답변]

  • 비동기는 요청을 보내고 해당 요청에 대한 응답을 기다리는 대신 다음 동작을 실행하는 방식.
  • 프로미스는 비동기 처리에 사용되는 객체. (비동기 자체는 아님.)

TDZ(Temporal Dead Zone/일시적 사각지대)란?

▶ 스코프의 시작 지점부터 초기화 시작 지점까지의 구간

  • JavaScript에서의 변수 생성 단계
    • 선언 단계 - 초기화 단계 - 할당 단계
    • var 변수
      • 변수 선언전에 선언 단계와 초기화 단계를 동시에 진행
    • let 변수 & const 변수
      • 선언 단계와 초기화 단계가 분리 → 실행 컨텍스트에 변수를 등록 했지만 메모리 할당이 되지 않아 접근 불가능한 참조 에러 발생 (ReferenceError) → TDZ 구간에 의해 메모리 할당이 되지 않은 것 (할당되기 전까지 잠시 죽어있는 상태 )

let이나 const 선언후 초기화 전에 할당을 하는 코드

**// Temporal Dead Zone**
A; // ReferenceError
const A = 1;
A; // 1

[15조]
🔨 TDZ
스코프의 시작 지점부터 초기화 시작 지점까지의 구간을 TDZ(Temporal Dead Zone) 라고 함.

[14조]
일시적인 사각지대는 스코프의 시작 지점부터 초기화 시작 지점까지 구간을 TDZ(Temporal
Dead Zone)이라고함.

우리가 변수를 입력하면,

  • 선언 단계(Declaration phase) : 변수를 실행 컨텍스트의 변수 객체에 등록하는 단계를 의미함. 이 변수 객체는 스코프가 참조하는 대상이 됨.
  • 초기화 단계(Initialization phase) : 실행 컨텍스트에 존재 하는 변수 객체에 선언 단계의 변수를 위한 메모리를 만드는 단계임. 이 단계에서 할당된 메모리에는 undefined로 초기화 됨.
  • 할당 단계(Assignment phase) : 사용자가 undefined로 초기화된 메모리의 다른 값을 할당하는 단계임.

우리가 변수를 입력할때 var혹은 let/const를 그냥 사용하였지만사실은 위 3가지 단계를 거쳐서 생성되는 것.

[튜터님의 답변]
const, let을 선언할 때 선언 -> 초기화 단계를 거침. 런타임(파일을 한 줄 한 줄 실행하는 것) 이전에 선언되어 메모리에 한 자리를 차지하지만 초기화 단계가 아직 실행되지 않았기 때문에 해당 변수(상수)에 접근할 수는 없는 상태를 TDZ라고 함.

profile
개발하는 디자이너입니다.

0개의 댓글