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
에 내려오나봄
강의에서는 axios
를 사용하지만 Next v14에서는 WebAPI인 fetch
를 확장해놓아서 그냥 fetch
를 사용하면된다.
getServerSideProps()
메서드도 fetch
로 그냥 사용할수 있다고한다.
그런데, 아주 커다란 의문점이 생겼다.
getServerSideProps()
만 사용했는데 어떻게 서버에서 렌더링해서 내려주는걸까? 서버에서도 준비가 되어있어야 할텐데 말이다..!
이를 이해하려면 NextJS의 서버와 NextJS의 hydration에 대해 알아야한다...!
NextJS에는 사실 서버코드가 내장되어있음. next start, next dev
를 실행하면 자체 서버도 실행된다
=> 서버에서 HTML을 렌더링해서 보내주는게 가능한 이유다.
NextJs의 기능인줄 알았는데, 놀랍게도 React의 기능이었다. V18로 넘어오면서 정확히는 hydrate => hydrateRoot가 되었다.
이 기능은 서버에서 렌더링된 HTML에 JS를 붙이는거다. 즉, SSR에 필요한 기술이다.
저번에 사용했던 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...
등이 올 수 있으니 광범위하게)
.type
프로퍼티로 타입을 얻어낼수있다. 이때 얻어내는 타입은 ReactElement
의 프로퍼티다.
{
type: T;
props: P;
key: string | null;
}
요부분...
콘솔로 찍어보니 컴포넌트 함수 자체를 반환한다😎.
필요한 프롭스가 없다고 오류 But, React.cloneLement로 생성하여 프롭스 전달.
https://blog.cristiana.tech/react-children-map-and-cloneelement-using-typescript
일단 밖에서 직접 주입하는 타입을 제외한 타입은 옵셔널 타입으로 지정하여 해결...!
안티패턴일까 유심히 고민중이다. 리액트의 상태업데이트는 동기적이지 않을 수 있어서...
깊게 찾아봐야겠다.
css
프로퍼티 사용시
요래나옴. 타입스크립트가 emotion의 타입을 몰라서 그런것.
//tsconfig.json
"compilerOptions": {
...
"types": ["@emotion/react/types/css-prop"],
}
요래 추가해주면 인식