230605.til

Universe·2023년 6월 5일
0

타입스크립트 핸드북 스터디

타입스크립트의 기본 타입

1. Primitive types

1. string
	let str:string = 'hi'
2. number
	let num:number = 1;
3. boolean
	let bool:boolean = true;

2. Array

let arr: number[] = [1,2,3]
let charArr: string[] = ['가','나','다']

3. Enum
열거형. 특정한 값 집합 중 하나의 값만을 가질 수 있는 타입을 정의.
enum 을 생성하면 자동으로 숫자 기반 열거형을 지원하며 문자열 기반의 열거형도 사용자가 정의해줄 수 있다.

enum Color {
	Red,
	Green,
	Blue
}

let myColor: Color = Color.Green;
console.log(myColor) // 1

enum 타입을 활용할 경우 정의한 집합을 일종의 바운더리로 설정할 수 있기 때문에,
변수의 값을 예측 가능하도록 명시할 수 있다. 이는 개발자의 의도를 조금 더 직관적으로 파악할 수 있으므로
가독성 측면에서 유리하다. 또한 VSCode 의 자동완성 기능으로 생산성도 증진시킬 수 있다.

컴파일 시 코드의 양이 증가하는 단점이 있다. Tree-shaking 또한 지원하지 않는다.
런타임이 실제로 존재하는 객체이므로 enum 을 난발한다면 무거운 코드가 될 수 있다.

3-1. const enum

const enum ConstColor {
    Red = 1,
    Green,
    Blue
}

let myConstColor: ConstColor = ConstColor.Green; // -> let myConstColor: number = 2;

In most cases, enums are a perfectly valid solution. However sometimes requirements are tighter. To avoid paying the cost of extra generated code and additional indirection when accessing enum values, it’s possible to use const enums. Const enums are defined using the const modifier on our enums.

대부분의 경우 enum 이 유효한 해결책이지만, 요구사항이 엄격할 경우 const enum 을 활용하면 좋다는 이야기.
enum 의 단점을 대부분 해결해줄 수 있다.

대비되는 장점으로는 컴파일 시점에 제거되어 사용되는 곳에 inlined 형태로 적용되므로 컴파일 후 JS 파일에
enum 객체를 추가적으로 생성하지 않는다. 따라서 런타임 비용이 없어 코드가 가볍다.

그러나, 이러한 장점이 const enum 이 반드시 권장된다는 뜻은 아니다.
const enum 타입은 컴파일 시 완전히 제거되기 때문에 enum 객체에 접근할 수 없으며,
값을 객체로 생성되는 것이 아니라 디버깅 시 enum의 이름을 볼 수 없으므로 에러를 추적하기 어렵다.
결적적으로 babel 환경에서 트랜스파일링을 할 수 없어 추가적으로 플러그인을 설치해야한다.

3-2. as const 를 명시해준 객체.

const COLORS = {
    Red: 'RED',
    Green: 'GREEN',
    Blue: 'BLUE'
} as const;

let myColor: keyof typeof COLORS = 'Red';

as const 키워드는 TypeScript 3.4 버전 이후에 도입된 문법으로,
리터럴 타입을 유지하며 ReadOnly 속성을 가진 enum 의 대용품을 만들 수 있다.
타입스크립트의 개발 모토가 “a typed superset of javascript” 인 만큼,
위의 예시처럼 객체 리터럴에 as const 키워드를 추가해 정의함으로써 보다 직관적인 정적 타이핑을 한다는 느낌.
자바스크립트 문법을 그대로 사용함으로써 빌드에 관한 이슈도 없고,
const 로 선언했으므로 수정 불가능한 객체를 생성할 수 있다.

단, enum 들과는 다르게 값으로 이름을 얻으려면 위와 같이 keyof typeof 같은 메소드를 이용해야 한다.

4. Any

let notSure: any = 4;
notSure = "string";
notSure = false;

모든 유형의 값을 허용하는 가장 유연한 타입.
TypeScript 의 의의는 컴파일 시점에 잠재적인 오류를 찾아내는 것이므로,
이를 사용하면 TypeScript 를 사용하는 의미가 없다.
JavaScript 파일을 TypeScript 로 점진적으로 전환하는 과정에서 사용할 수 있다.

Any 타입이 추론에 의해 할당되거나, 사용하지 않으려면 tsconfig.json 에서
”noImplicitAny” : ture 옵션을 이용할 수 있다.
이를 활성화하면 Any 타입을 사용하기 위해서는 명시적으로 타입을 선언해주어야만 한다.

5. void

function warnUser(): void {
    console.log("This is a warning message");
}

return 값을 가지지 않는 함수에 대한 타입.

6. never

함수가 영원히 끝나지 않거나 항상 오류를 던진다는 것을 명시해준 타입.
never 를 명시해준 함수는 절대로 값을 반환하지 않아야 한다.

  • 항상 오류를 반환하는 함수. 따라서 정상적으로 종료되지 않는 경우.
function throwError(message : string):never {
	throw new Error(message);
}
  • 무한히 반복되는 함수. 따라서 정상적으로 종료되지 않는 경우.
function infiniteLoop(): never{
	while (true){
	}
}

6-1. never 타입의 실 사용

일반적으로는 잘 사용되지 않지만 적절한 사용 사례가 가끔 있는데,

  1. switch, if-else 문의 모든 상황을 컨트롤한다.
    쉽게 생각해서 모든 상황에 대처할 수 있는 조건문 을 보장할 수 있다.
function unknownColor(x: never): never {
    throw new Error("unknown color");
}

type Color = 'red' | 'green' | 'blue'

function getColorName(c: Color): string {
    switch(c) {
        case 'red':
            return 'is red';
        case 'green':
            return 'is green';
        default:
            return unknownColor(c); // 'string' 타입은 'never' 타입에 할당할 수 없음
    }
}

아래의 링크에 예시가 더 있지만 잘 이해되지 않았다.
추가적인 학습 이후에 읽어볼 것.
https://ui.toast.com/posts/ko_20220323

타입스크립트에서의 함수

함수를 정적 타이핑할 때, 3가지 타입을 정의할 수 있다.

  • 함수의 파라미터
  • 함수의 반환
  • 함수의 구조
const multiply = (x: number, y: number): number => {
    return x * y;
}

const subtract: (a: number, b: number) => number = function(a, b) {
    return a - b;
}
// 화살표 함수에서의 함수 구조 타이핑

위의 minus 함수를 보면 함수의 타입을 (a: number, b:number) ⇒ number 로 명시해주고 있는데,

type BinaryFn = (a: number, b: number) => number;

const subtract: BinaryFn = function(a, b) {
    return a - b;
}

이런식으로 ‘함수의 구조’를 type alias 로 설정하여 따로 관리할 수도 있다.
이는 ‘두개의 숫자를 매개변수로 받고 숫자를 반환하는 함수’ 라는 구조 자체를 타입으로 지정하여
’어떠한 기능을 하는 함수’라는 것을 명확하게 직관적으로 표현할 수 있다.
또한 위의 BinaryFn 타입은 다른 함수에서 재사용 할 수 있어 코드의 중복 또한 줄일 수 있다.







Next js 공식문서 스터디

Route

이론

Next js 13버전의 app directory 는 폴더 기반 라우팅을 사용한 Tree 구조를 갖는다.

  • Tree: 계층 구조를 시각화하는 방법. 부모와 자식 컴포넌트로 구성된 컴포넌트 트리나 폴더 구조.
  • Subtree: 트리의 일부로, 새로운 루트(첫 번째)에서 시작하여 잎(마지막)에서 끝나는 부분.
  • Root: 트리나 서브트리의 첫 번째 노드. 루트 레이아웃과 같은 것을 말한다.
  • Leaf: 자식이 없는 서브트리의 노드. URL 경로의 마지막 세그먼트.

위의 Tree 구조와 같이 구성된 app directory 는 다음과 같은 URL 을 가지게 된다.

  • URL Segment: ‘/’ 로 구분된 URL 경로의 일부.
  • URL Path: 도메인 이후의 URL의 일부. URL Segment 로 구성.

App 디렉토리는 React Server Components 를 활용하여 공유 레아이웃, 중첩 라우팅, 로딩 상태 및 에러 처리를 효과적으로 지원한다.

app
├── [route-segment]
│   ├── layout.tsx
│   ├── loading.tsx
│   ├── not-found.tsx
│   ├── error.tsx
│   ├── page.tsx
│   └── route.ts
│   └── template.ts
│   └── default.ts
└── _error.tsx

route-segment 는 URL Segment 를 나타내며, 해당 폴더안에 특정 키워드를 갖는 파일을 생성하면
특별할 역할을 수행하는 컴포넌트를 구현할 수 있다.

  • layout.tsx: 해당 라우트 세그먼트와 그 자식들에 대한 공유 레이아웃을 정의한다.
  • page.tsx: 해당 라우트의 고유한 UI를 정의. 이 파일이 있어야 해당 라우트에 접근할 수 있다.
  • loading.tsx: 해당 라우트 세그먼트와 그 자식들에 React Suspense 를 형성하여 로딩 상태 UI를 정의.
  • not-found.tsx: 해당 라우트 세그먼트와 그 자식들에 대한 404 에러(페이지를 찾을 수 없음) UI를 정의.
  • error.tsx: 해당 라우트 세그먼트와 그 자식들에 대해 React error boundary 형성하여 에러 UI를 정의.
  • route.ts: 해당 라우트의 서버 측 API 엔드포인트를 정의합니다.
  • template.tsx: 해당 라우트 세그먼트와 그 자식에 대한 레아이웃을 정의한다는 점에서 layout 컴포넌트와 유사하지만, 각 자식에 대해 새로운 인스턴스를 만들어 상태를 유지하지 않고 새로 동기화 된다.
    CSS 또는 애니메이션 라이브러리를 시작/종료 하거나 useEffect, useState 에 의존하는 UI 라면
    layout 컴포넌트보다 template 컴포넌트를 사용하는 것이 보다 적절한 옵션일 수 있다.
  • default.ts: 병렬 route의 Fallback UI. 해당 컴포넌트는 공식문서에 아직 업데이트 되지 않음

App 디렉토리의 폴더 안에는 키워드를 갖는 특별한 역할을 수행하는 컴포넌트 이외에도
개발자가 정의한 컴포넌트를 위치시킬 수 있다.
폴더 기반 라우트를 사용하지만, ‘page.js’ 키워드로 반환되는 컨텐츠만 공개적으로 접근 가능하기 때문이다.

pages 디렉토리에서 app 디렉토리로 변경하게 된 이유

이전 버전의 Next js 에서는 pages 디렉토리가 주로 이용되었다.
pages 디렉토리는 파일 기반 라우팅을 사용한 직관적인 라우팅을 제공했지만,
어플리케이션의 복잡성이 증가하면서 문제점이 드러났다.

  1. nested route, layout : 파일 기반 디렉토리에서는 중첩 라우팅의 구현이나 공유된 레이아웃을 설정하는 방법이 까다로웠다. 반면 폴더 기반 디렉토리에서는 폴더 구조를 이용한 중첩 라우팅, layout 컴포넌트로 쉽고 직관적으로 구현이 가능하다.
  2. loading, error 컴포넌트 : 파일 기반 디렉토리에서는 로딩 및 에러상태 컴포넌트를 개별적으로 관리해야 하는 불편함이 있었지만 폴더 기반 디렉토리에서는 loading, error 컴포넌트를 활용하여 보다 쉽고 일관성 있게 관리할 수 있다.
  3. React Server Component 지원 : Next 13 버전, React 18 버전 이후에 도입된 서버 컴포넌트는 서버에서 컴포넌트를 렌더링하고 결과를 클라이언트로 전송하는 기능을 제공하여 초기 페이지 로드 성능을 향상시키고 자바스크립트 번들 크기를 줄여주는 등의 이점을 제공한다. app 디렉토리는 default 로 서버 컴포넌트로 구성되어 있으며 이러한 이점을 쉽게 활용할 수 있다.

요약 : 라우팅 구성의 유연성을 증가시키고, 로딩 및 에러 상태 관리를 간소화하며, 서버 컴포넌트를 보다 쉽게 적용할 수 있다.

경로 정의

폴더 기반 라우팅에서는 각 폴더의 중첩으로 Nested route를 구성 할 수 있다.
각 폴더 내에 page.tsx 파일을 구성하면 해당 페이지로 공개적으로 접근할 수 있다.

Page, Layout

page 는 하나의 URL Segment 에 고유하게 존재한다. 접근할 수 있는 URL에 고유한 UI를 구성하게 된다.
page.ts 컴포넌트를 만들지 않으면 해당 URL 은 공개적으로 접근할 수 없다.

layout 은 여러 페이지 간에 공유되는 UI를 구성할 수 있다.
상태를 유지하고 재렌더링 되지 않는다. page 컴포넌트와는 다르게 중첩이 가능하다.
최상위 layout 컴포넌트를 root layout 이라고 하며 html 및 body 태그가 필수적으로 포함되어야 한다.
layout 컴포넌트는 data fetch 가 가능한데, 부모와 자식간의 데이터 전송이 불가능 하다.
단, 동일한 데이터를 두번 이상 가져오더라도 중복된 요청을 자동으로 제거하여 성능에 영향을 주지 않는다.

profile
Always, we are friend 🧡

0개의 댓글