React로 SNS 만들기 (8) - 서버사이드렌더링

SangBooom·2021년 6월 5일
0

서버사이드 렌더링

//pages/index.js

const Home = () => {
  ...
  
  useEffect(() => {
    dispatch({
      type: LOAD_USER_REQUEST,
    });
    dispatch({
      type: LOAD_POSTS_REQUEST,
    });
  }, []);
  
  ...
  return (
    <AppLayout>
      {me && <PostForm />}
      {mainPosts.map((post) => <PostCard key={post.id} post={post} />)}
    </AppLayout>
  );
};

export default Home;

메인페이지에서 화면이 로딩된 후에 useEffect를 통해 사용자 정보와 게시글 정보를 불러온다. 로딩된 후에 정보를 불러오기 때문에 잠깐동안은 화면에 데이터의 공백이 발생한다. 그럼 화면을 받아올 때 부터 먼저 데이터를 불러올 수 있다면? 데이터가 채워진채로 화면이 보여질 것이고 더 나은 사용자경험을 제공할 수 있을 것이다.

next 8버전에서는 getInitialProps를 썼었는데
next 9버전부터는 getStaticProps, getStaticPass, getServerSideProps 를 쓴다.

getServerSideProps

//pages/index.js
...
import wrapper from "../store/configureStore";

const Home = () => {
  ...
  
  return (
    <AppLayout>
      {me && <PostForm />}
      {mainPosts.map((post) => (
        <PostCard key={post.id} post={post} />
      ))}
    </AppLayout>
  );
};

export const getServerSideProps = wrapper.getServerSideProps((context) => {
  const cookie = context.req ? context.req.headers.cookie : '';
  axios.defaults.headers.Cookie = '';
  if(context.req && cookie) {
  	axios.defaults.headers.Cookie = cookie;
  }
  // 브라우저가 백엔드에 보낼때 쿠키를 자동으로 붙여줌
  // 프론트서버(next)에서 백엔드에 보낼때는 쿠키를 붙여줘야됨
  context.store.dispatch({
    type: LOAD_USER_REQUEST,
  });
  context.store.dispatch({
    type: LOAD_POSTS_REQUEST,
  });
  context.store.dispatch(END);
  await context.store.sagaTask.toPromise();
  // 페이지를 실행하기 전에 서버에서 먼저 데이터를 받아와서 가져다 놓는다.
  // context 안에 store가 있으니까 쓰면된다.
  // 이 부분이 실행된 결과를 HYDRATE로 보낸다.
});

export default Home;

getStaticProps

언제든지 접속해도 데이터가 바뀔일이 없으면 getStaticProps

블로그 게시글? 뉴스(이것도 좀 한정적인 컨텐츠들만)같은 것들에 적용, 빌드할 때 미리 서버사이드렌더링을 통해 html으로 만들고 바로바로 보여주도록 함, 커머스 사이트의 이벤트페이지? 쓸때만 씀.. 잘안씀 사실 너무 한정적임

접속한 상황에 따라 데이터가 바뀌어야 하면 getServerSideProps

대부분 이걸쓰게 됨

getStaticPaths

getStaticProps이랑 같이쓰고 다이나믹 라우팅일때 쓴다.
html으로 만들어도 되는 애들을 먼저 빌드시켜놓고 화면을 불러올때 같이 불러온다. 근데 문제될 것이 html으로 만들직한것들 몇개 정도 놓을 때만 사용하는게 좋다. 네트워크 통신으로 동적으로 많이 나올 수 있는 것들을 다 불러와서 html으로 만들어놓으면 좋지않은 판단이 될 것이다.

if (router.isFallback) {
  return <div>로딩중...</div>;
}

export async function getStaticPaths() {
  return {
    paths: [
      { params: { id: '1' } },
      { params: { id: '2' } },
      { params: { id: '3' } },
      { params: { id: '4' } },
    ],
    fallback: true,
  };
}

다이나믹 라우팅

만약, 여러개의 게시물 중에 하나의 게시물을 공유하고싶다. 인스타에서 하나의 게시물을 링크로 공유할 때를 예를 들어보자. 주소가 필요할 것이다.
pages 폴더에 [id].js로 만들자. post/[id].js 이런식으로 들어가고 post/1 post/2 등등에 대응되는 것이다.

next8버전에선 express에서 했어야됐다. 지금은 next에서 가능하다.

const Post = () => {
 	const router = useRouter();
  	const { id } = router.query;
  	const { singlePost } = useSelector((state) => state.post);
  return (
  	<AppLayout>
      <Head>
        <title>
          {singlePost.User.nickname}
          님의 글
        </title>
        <meta name="description" content={singlePost.content} />
        <meta property="og:title" content={`${singlePost.User.nickname}님의 게시글`} />
        <meta property="og:description" content={singlePost.content} />
        <meta property="og:image" content={singlePost.Images[0] ? singlePost.Images[0].src : 'https://nodebird.com/favicon.ico'} />
        <meta property="og:url" content={`https://nodebird.com/post/${id}`} />
      </Head>
      <PostCard post={singlePost} />
    </AppLayout>
  );
};

카톡 링크로 공유할떄 미리보기가 뜨고 이미지, 게시글제목, 설명을 보이도록 하는 코드이다.

CSS 서버사이드 렌더링

현재 개발하고있는 페이지를 들어가보면 내가 준 CSS가 적용되지 않은 페이지가 나타나고 다른 탭을 누르거나 새로고침하면 CSS가 적용된 채로 나오게 된다.

Next도 임의적으로 웹팩과 바벨이 돌아가는데, 우리가 어느정도 커스터마이징을 할 수있다.

polyfill

ie같은 쓰레기브라우저가 최신문법들을 호환을 하기위해서 바벨을 사용하는데 최신 객체들 (Promise, map, Set)등은 추가가 안돼서 babel-polyfill을 쓰는데 너무 무거워서 요즘 풀리필을 쓴다. 참고하자
https://polyfill.io/v3/

swr

지금까지 redux로 엄청나게 많은 상태관리를 했다. 액션과 리듀서를 수도 없이 만들어 놨기 때문에 조금은 복잡한데 여기서 get요청정도는 더욱 편하고 성능면으로 더 좋게 받아올 수 있도록 도와주는 라이브러리가 있다.

리팩토링 : fetcher는 따로 폴더로 빼서 관리하자

profile
끊임없이 떨어지는 물방울이 바위를 뚫는다

0개의 댓글