\(@^0^@)/

[TDL] 08/05 Today's-Done-List 본문

TDL

[TDL] 08/05 Today's-Done-List

minjuuu 2022. 8. 6. 00:11
728x90

- 제로베이스 TS 강의

Interface

  • JavaScript에서는 존재하지 않는다.
  • 객체의 타입을 정의하고 생김새를 가지도록 할 수 있다.
  • TypeScript에서의 클래스 기능은 C#에서 유래된 것이 많다.
  • 일부 기능은 TS에서만 존재하는 고유 문법으로 컴파일 후 사라진다.
  • extends가 아닌 implements 키워드로 구현한다.

위에서 말했던 것처럼, 인터페이스는 JS에서 존재하지 않는 것을 볼 수 있다.


Implements

interface Fruits {
    name: string
    price: number
    discount(): void
}

interface Meat {
    name: string
    price: number
    typeOf: string
}

/* 
- interface의 설계를 구현한다.
- 두개 이상의 interface를 구현할 수 있음.
*/

class Cart implements Fruits, Meat {
    constructor(public name: string, public price: number, public typeOf: string) {}

    discount() {
        return `할인받을 금액은 ${this.price}의 10% 입니다.`
    }
}

Interface Extends

interface Chicken {
    name: string
    price: number
    
}

/* Meat에 Chicken을 확장 */
interface Meat extends Chicken {
    discount(): number
}

const friedChicken: Meat = {
    name: 'friedChicken',
    price: 18000,
    discount() {
       return this.price * 0.1
    }
}

Type Guards (타입 좁히기 ) 

typeof : primitive types 비교할 때 주로 사용  (JS 문법)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof

/* 지양해야 하는 코드 */
function print(val: number | string): string | number {
    if (typeof val === 'string') {
        return val
    }
    return val
}

/* 올바른 코드 
함수자체에 유니온으로 타입을 확장시키기 보다는, 
해당하는 코드만 Number형식으로 바꿔주기
*/
function print(val: number | string): number {
    if (typeof val === 'string') {
        return Number(val)
    }
    return val
}

In : 객체 타입 비교할 때 주로 사용  (JS 문법)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in

interface Korean {
    name: string,
    annyeong(): '안녕'
}

interface Chinese {
    name: string,
    nihao(): '니하오'
}

function sayHi(person: Korean | Chinese) {
    if ('annyeong' in person) {
        person.annyeong()
    }

    if ('nihao' in person) {
        person.nihao()
    }

}

Instanceof : 객체 타입 비교할 때 주로 사용 (JS 문법)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof

/*
instanceof 연산자는 생성자의 prototype 속성이
객체의 프로토타입 체인 어딘가 존재하는지 판별한다.
*/

function getDate(date: Date | string): Date {
    /* Date type일 경우 바로 리턴 */
    if (date instanceof Date) {
        return  date
    }

    /* string일 경우 new Date에 할당 */
    return new Date(date)
}

사용자 정의 타입 가드

interface Korean {
    name: string,
    annyeong(): '안녕'
}

interface Chinese {
    name: string,
    nihao(): '니하오'
}

/* 사용자 정의 타입 가드를 사용한 코드
매개변수 is 타입 => person is Korean 을 적용.
*/
function isKorean(person: Korean | Chinese): person is Korean {
    return 'annyeong' in person
}

function sayHi(person: Korean | Chinese) {
    if (isKorean(person)) {
        person.annyeong()
    }

    if ('nihao' in person) {
        person.nihao()
    }

}

Enum

  • 의미 있는 상수 자료를 정의할 수 있다. (문서화)
  • 키를 값에 할당하며 순서가 없는 집합이자 자료구조이다.
  • enum 키워드 + PascalCase 조합으로 생성
  • 계산된 값을 사용할 수 있다.
    • 타입 스크립트가 알아서 추론
  • 열거형 종류
    • 숫자형 열거
    • 문자형 열거
    • 복합형 열거

 

닷 연산자를 사용해서 값을 나타낼 수 있음.


문자형 열거

  • 각 멤버의 값을 문자열로 초기화되어야 한다.
  • 숫자형 열거와 동작 방식이 다르다.
    • 값이 자동으로 증가하지 않는다.
    • 이외에 리버스 매필의 차이점도 존재

 

리버스 매핑 (역방향 찾기)

  • 숫자형 열거 같은 경우 키와 값을 역으로 매핑할 수 있다.
    • 문자형 열거는 지원되지 않음.


const 열거

  • 기본적으로 열거형은 불안전한 접근을 허용한다.
    • const enum은 이러한 점을 보완하기 위한 안전한 열거형
  • enum 앞에 const 키워드를 명시한다.
  • 컴파일 후 제거되기 때문에 JavaScript 코드를 생성하지 않는다.

js스크립트로 컴파일된 코드를 보면, 객체로 생성하는 것보다 훨씬 복잡한 것을 볼  수 있다.
그래서, 개발자들 사이에서도 enum을 사용해야 할지, 그냥 객체로 생성할지 의견이 분분하다고 한다.
각자의 팀에서 충분한 의논을 통해 컨벤션을 정하여 사용하는 것이 좋을 것 같다.

나는 enum에 대해 알게 된 지 얼마 되지 않아서, 아직까지는 enum의 장점을 잘 모르겠다.
굳이 없어도 될 것 같은 느낌이랄까..? 의미 있는 상수값들을 enum으로 묶어서 관리할 수 있는 것은 좋지만 객체 또는 nuion type을 사용해서 충분히 대체할 수 있을 거 같다는 생각이다.


열거형 활용

  • 런타임에 존재하는 실체 객체
  • keyof, keyof typeof와 조합하여 활용할 수 있다.

keyof typeof를 사용했을 경우, 아래의 union type을 쓰는 것과 같게 나오는 것을 볼 수 있음.

일반 enum을 사용했을 경우, JS로 컴파일한다면 이렇게 복잡한 코드가 생성된다.

enum 앞에 const를 붙여 준다면, 불필요한 코드들이 컴파일되지 않는 것을 볼 수 있음.

또는 const enum 대신 union types을 사용해서 깔끔한 코드를 컴파일되도록 할 수도 있다.

 

https://engineering.linecorp.com/ko/blog/typescript-enum-tree-shaking/

 

TypeScript enum을 사용하지 않는 게 좋은 이유를 Tree-shaking 관점에서 소개합니다.

2022-LINE-engineering-site

engineering.linecorp.com

https://www.typescriptlang.org/ko/docs/handbook/enums.html

 

Handbook - Enums

How TypeScript enums work

www.typescriptlang.org


오후 회고 (만족도: 6)

어제 분명 일찍 오자고 다짐했는데 스카에 늦게 도착해서 TS강의 목표치도 겨우 끝냈다... 휴
저녁 먹고 오후 스터디 전에 react 강의 쭉 듣다가, 목표 달성하고 시간이 남으면 알고리즘 또는 함수형 프로그래밍 책 읽자.
요새 계속 늦게 일어나서 알고리즘 문제와 함수형 프로그래밍 책을 보지 못했다...ㅠ 점점 게을러지는 기분...
어떻게 해야 정신을 차릴까? 고민 중이다.


- 제로베이스 REACT 강의

전역 상태 관리

  • 전역 상태 관리가 필요한 경우
    • 로그인한 유저 정보
    • theme style

Context Api

Provider 하위에서 context를 구독하는 모든 컴포넌트는 Provider의 value prop가 바뀔 때마다 다시 렌더링 된다.

https://reactjs.org/docs/context.html

 

Context – React

A JavaScript library for building user interfaces

reactjs.org


context api를  사용하기 위해서 store 폴더 안에 user라는 이름의 파일을 하나 생성하여 context api를 구현했다.

import React, { createContext, useState } from "react";

export const UserContext = createContext();

export default function UserStore(props) {
	const [pwd, setPwd] = useState(1234);

	const user = {
		name: "amy",
		pwd: 1234,
		age: "50",
		job: "bloger",
		changePwd: (updatedPwd) => setPwd(updatedPwd),
	};

	return (
		<UserContext.Provider value={user}>{props.children}</UserContext.Provider>
	);
}
  • import 한 createContext를 UserContext에 대입.
  • user 객체 안에 user의 정보를 넣어주고, 비밀번호 변경 함수 또한 넣어주어서 pwd의 업데이트된 값을 받아올 수 있도록 useState를 사용하였음.
  • UserContext.Provider를 사용하여 하위 컴포넌트인 props.children에게 데이터를 넘겨준다.
  • UserContext.Provider 태그 안에 있는 value안에 넘기고 싶은 데이터를 넣어준다. (내 경우에는 user 객체)

Provider 하위에서 context를 구독하는 모든 컴포넌트는 Provider의 value prop가 바뀔 때마다 다시 렌더링 된다.


App 컴포넌트에 가서 전역에서 상태 관리를 할 수 있도록 UserStore로 전체를 감싼다.


  • 데이터를 넘겨주고 싶은 컴포넌트 BlogPage에 가서
  • useContext 훅과 데이터를 넘겨받을 UserContext를 import 하고
  • useContext로 UserContext를 받아서 value에 할당해준 후,
  • 잘 들어왔는지 확인하기 위해 value를 콘솔로 찍어보자.


실행해보면 아래와 같이 나오는 것을 볼 수 있다.


useReducer

(전역은 아니고 상태 관리와 관련이 있음)

  • useState의 대체 함수
  • (state, action) => newState의 형태로 reducer를 받고
    dispatch 메서드와 짝의 형태로 현재 state를 반환한다.
  • 다수의 하윗값을 포함하는 복잡한 정적 로직을 만드는 경우 또는 다음 state가 이전 state에 의존적인 경우
    보통 useState보다 useReducer를 선호
React는 dispatch함수의 동일성이 안정적이고 리 렌더링 시에도 변경되지 않으리라는 것을 보장합니다.
이것이 useEffect나 useCallback 의존성 목록에 이 함수를 포함하지 않아도 괜찮은 이유입니다.

 context api를 적용했던 코드에 useReducer를 적용해보자.

  • 빨간 박스 : useReducer함수를 넣는다.
    (state, action) => newState의 형태로 reducer를 받고 dispatch 메서드와 짝의 형태로 현재 state를 반환
  • 초록 박스 : 초기화를 해준다. user 정보를 초기화하였음.
  • 주황 박스 : reducer함수를 추가해서
    action의 type이 changePwd일 경우에 action.text를 변경해주고
    action의 type이 changeAge일 경우에는 age의 상태에 1을 더해준다.
  • 파란 박스 : 초기화를 해주었기에, user의 객체와 useState를 주석처리.
  • 보라 박스 : UserContext의 하위 컴포넌트에 넘겨줄 데이터를 value안에 넣어준다.

context api에서 받아왔던 value 대신 이번에는 dispatch로 바꿔주고 (사실 이름은 딱히 상관은 없음)
button태그를 추가하여 클릭 핸들러에 dispatch를 넣어 실행시킨다.


처음 화면을 렌더 시켰을 때, console창에 넣어둔 user 값이 (user 상태) 변하는 것을 확인할 수 있다.

처음 렌더시

 

ChangePwd 버튼 클릭시

 

New Year 버튼 클릭시


https://ko.reactjs.org/docs/hooks-faq.html#how-to-avoid-passing-callbacks-down

 

Hook 자주 묻는 질문 – React

A JavaScript library for building user interfaces

ko.reactjs.org

https://reactjs.org/docs/hooks-reference.html#usereducer

 

Hooks API Reference – React

A JavaScript library for building user interfaces

reactjs.org


저녁 회고 (만족도: 7)

TIL 작성하고, context api를 따라 하느라 생각보다 시간이 오래 소요돼서 전역 상태 관리의 모든 강의를 다 듣진 못하였지만, 그래도 배우지 않았던 것들을 배워서 흥미롭고 재미있게 학습한 것 같다.


[ 출처 및 참고 : 제로베이스 TypeScript,
제로베이스 React 이론 ]

728x90

'TDL' 카테고리의 다른 글

[TDL] 08/08 Today's-Done-List  (0) 2022.08.08
[TDL] 08/06 Today's-Done-List  (0) 2022.08.08
[TDL] 08/04 Today's-Done-List  (0) 2022.08.04
[TDL] 08/03 Today's-Done-List  (0) 2022.08.03
[TDL] 08/02 Today's-Done-List  (0) 2022.08.02