프론트엔드 데브코스 5기 TIL 57 - Next.js, React + TS, emotion + TS 오류해결

김영현·2023년 12월 14일
1

TIL

목록 보기
66/129

Next.js

SSR : 서버로부터 파일을 받아 렌더링

왜 SSR을 해야하는가?
=> SEO최적화, 더 빠른 초기 렌더링 속도. 첫 렌더링은 SSR이후 CSR하면 사용자 경험 향상
But, 기존 SSR의 문제점은 코드를 두배로 짜야했음.
Isommorphic(동형 사상)이라는 기능이 생겨서 하나의 언어로 둘 다사용 가능함.
=> 둘 다 JS사용하자(node.js)

설치

CRA처럼 Create Next APP이 존재함. 이거로 뚝딱하면 바로 완성된다.


폴더구조가 강의와 많이 다르다.
v13.4부터 PageRouter => AppRouter로 바뀌었다.
참고로 현재 버전은 14다. 차이가 많이난다 ㅋㅋ

라우팅

기존에는 pages/about.tsx or pages/about/index.tsx이런식으로 생성했고 이제는 src/app/about/page.tsx 이렇게 만들어야 한다 ㅎㅎ

동적 라우팅

원래는 파일 이름을 브라켓으로 감싸서 [id].tsx이렇게 만들어야했지만 이제는 폴더이름을 감싼다 /posts/[id]/page.tsx

//src/app/post/[id]/page.tsx

const Post = ({ params }: { params: { id: string } }) => {
  return <div style={{ fontSize: 100 }}>{params.id}</div>;
};

export default Post;

강의에서는 useRouter를 이용하여 params를 가죠왔는데, 공식문서에서는 이렇게 구조분해할당으로 가져온다. 아마 자동으로 props에 내려오나봄

getServerSideProps로 서버 사이드에서 데이터 불러오기

강의에서는 axios를 사용하지만 Next v14에서는 WebAPI인 fetch를 확장해놓아서 그냥 fetch를 사용하면된다.

getServerSideProps()메서드도 fetch로 그냥 사용할수 있다고한다.

그런데, 아주 커다란 의문점이 생겼다.
getServerSideProps()만 사용했는데 어떻게 서버에서 렌더링해서 내려주는걸까? 서버에서도 준비가 되어있어야 할텐데 말이다..!

이를 이해하려면 NextJS의 서버와 NextJS의 hydration에 대해 알아야한다...!

NextJs 서버

NextJS에는 사실 서버코드가 내장되어있음. next start, next dev를 실행하면 자체 서버도 실행된다
=> 서버에서 HTML을 렌더링해서 보내주는게 가능한 이유다.

hydration

NextJs의 기능인줄 알았는데, 놀랍게도 React의 기능이었다. V18로 넘어오면서 정확히는 hydrate => hydrateRoot가 되었다.
이 기능은 서버에서 렌더링된 HTML에 JS를 붙이는거다. 즉, SSR에 필요한 기술이다.

NextJs API제작

저번에 사용했던 vercel의 serverless함수와 굉장히 비슷하다.

// api/foldername/route.js
export async function GET(req){
	return Response.json(res)
}

단, HTTP메서드가 함수 이름이 되어야한다. 파일 위치또한 app/foldername/route.js가 되어야한다.


리액트 컴포넌트 타입

react-typescript-cheatsheet를 참고하였다

다른 라이브러리, 프레임워크처럼 기본 타입 지원 잘함. 특히 리액트라 더 잘하는듯ㅎㅎ
컴포넌트를 정의한 타입을 알아보자

  • ReactElement React.createElement의 리턴타입중하나.
 interface ReactElement<
        P = any,
        T extends string | JSXElementConstructor<any> = string | JSXElementConstructor<any>,
    > {
        type: T;
        props: P;
        key: string | null;
    }

이렇게 제네릭을 받아 타입과 프롭스의 타입도 지정할 수 있다...!

  • React.FC : 뭔 축구구단같다. 사실 Function Component의 준말임. 잘 안쓰인다. 일단 이렇게만 알고 넘어간다.

  • React.JSX.Element : Return value of React.createElement.

namespace JSX {
 interface Element extends React.ReactElement<any, any> {}
}

사실 얘도 ReactElement의 한 종류다.type, props의 타입을 둘 다 any로 갖다넣은 녀석임

  • React.ReactNode : Return value of a component. 그냥 리액트쪽의 any타입이다.
    type ReactNode =
        | ReactElement
        | string
        | number
        | Iterable<ReactNode>
        | ReactPortal
        | boolean
        | null
        | undefined
        | DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_REACT_NODES[
            keyof DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_REACT_NODES
        ];

특히 children프롭스의 타입으로 얘를 많이쓴다. 뭐가 올지 모르니까!

자식의 타입


공식문서에서 추천하는 방식이다.

프롭스 타입 지정

구조분해할당으로 많이 가져오니까, 결국 interafce{...}로 하면됨.
children의 타입은 ReactNode가 좋다!(컴포넌트, string, null...
등이 올 수 있으니 광범위하게)

ReactElement.type

.type 프로퍼티로 타입을 얻어낼수있다. 이때 얻어내는 타입은 ReactElement의 프로퍼티다.

    {
        type: T;
        props: P;
        key: string | null;
    }

요부분...
콘솔로 찍어보니 컴포넌트 함수 자체를 반환한다😎.


과제중 트러블 슈팅

react clonelement type인식못함

필요한 프롭스가 없다고 오류 But, React.cloneLement로 생성하여 프롭스 전달.

https://blog.cristiana.tech/react-children-map-and-cloneelement-using-typescript

일단 밖에서 직접 주입하는 타입을 제외한 타입은 옵셔널 타입으로 지정하여 해결...!

state끼리 값 의존

안티패턴일까 유심히 고민중이다. 리액트의 상태업데이트는 동기적이지 않을 수 있어서...
깊게 찾아봐야겠다.

emotion + TS오류해결

css프로퍼티 사용시

요래나옴. 타입스크립트가 emotion의 타입을 몰라서 그런것.

//tsconfig.json
"compilerOptions": {
  	...
	"types": ["@emotion/react/types/css-prop"],
}

요래 추가해주면 인식

profile
모르는 것을 모른다고 하기

0개의 댓글