Next 스터디 d1

송은우·2022년 5월 5일
0

Next

목록 보기
1/2

Next 시작하기

npx create-next-app@latest nullable[--typescript]

라이브러리는 우리가 사용하는 것
프레임워크는 우리의 코드를 불러오는것
di(dependency injection)의 개념과 유사

커다란 차이 중에는 ReactDOM.render부분이 없다는 것
이런 과정을 절대로 커스터마이징 할 수 없음
우리가 할 수 있는 유일한 부분은 pages안에 만드는 것임

export default를 안 했을 경우 next가 예쁘게 에러 메세지를 만들어 줌

next의 장점

server side rendering

그냥 하나의 div로만 되어 있고, 나머지는 전부 다 js로 되어 있다는 것들이 조금 특이한 점

client side render : 아주 느린 네트워크로 보면 아주 천천히 다 받아서 아주 느린 흰 화면에서부터 하나하나 요청해서 채워나가는 부분이 있음. 브라우저가 js 코드가 있을 때만 ui를 만들 수 있음
server side render : 아주 느린 네트워크로 보면 바로 만들어짐 그런 차이가 있음
흰 화면이 보이는 부분이 문제가 되는 경우가 많음. 로딩중이라는 그 화면을 안 보여주는 문제가 있음

disable js 로 nextjs를 실행 전혀 차이가 없음. 실제로 html이 나오기 때문에 로딩 과정은 오래 걸릴 수 있어도 어떤 html은 볼 수 있기에 일단 흰 화면은 안 뜸

hydration : react.js를 frontend에서 실행하는 것을 hydration이라고 함.

next.js는 component를 렌더링 하고, 그 결과를 소스코드에 넣어서 준다. 그리고 그것에 리엑트 js를 새로 붙힌다
js가 없어도 일단 html자체는 볼 수는 있음

Link tag는 href만을 위한 것, a 태그에 다 붙히는 걸로 생각하기

style 적용은 inline도 가능은 하지만
.module.css 패턴
<nav className={styles.nav}>
이 부분이 조금 특이함.

모듈로 처리하기에 그냥 className="nav"로 적어도 작동하지 않음. 그냥 충돌을 막는 효과

style 적용하기

  1. inline style
  2. module패턴
className={`${styles.link} ${
            router.pathname === "/about" ? styles.active : ""
          }`}
//혹은
className=[styles.link,router.pathname === "/about" ? styles.active : ""].join(" ")

이런 식으로 보통 처리하게 됨

styled component느낌

  1. styled JSX
<style jsx>{`
        nav {
          background-color: tomato;
        }
        a {
          text-decoration: none;
        }
      `}</style>

이렇게 되어 있는 경우에는 그 페이지에 있는 모든 것들에 다 적용이 됨. 다른 페이지는 영향을 끼치지 못함

조금 특이한 점은 className을 {"classname"} 같은 부분으로 추가하는 윗 부분에 적은 그 이름을 밑에 .classname으로 추가해도 변하지 않음
클래스 명을 페이지 단위로 관리해주는 듯?

a{
color:${props.color}
}
같은 것들도 가능

global css

style jsx global 까지 붙히면 문제가 없이 되긴 함
page별로 고려해야 한다는 문제가 됨
이 부분은 한 페이지 단위로 글로벌 css가 됨.
그래서 이거를 전부 다 붙혀넣기 가능은 하지만 추천 하지 않음

App Component, App page

global css를 위한 장소가 있음 App component
_app.js 파일임

<style jsx global></style>

이렇게 된 것을 _app.js안에 넣는 방식으로 모든 문제가 해결됨

page 안에 있는 것들(_app제외) 에서는 무조건 모든 것들을 그냥 "../styles/glolbal" 불가능
app에서는 module.css만 불러낼 수 있음

_app에서만 import가능. 이러면 자동 적용

정리

그냥은 현재 딱 보이는 컴포넌트에서만 작동함
다른 컴포넌트를 불러오는 경우 못 함
global 이 붙으면 한 페이지 단위
_app안에 넣으면 모든 페이지 단위

api fetch

그냥 비슷하게 useeffect로 데이터 fetch가능

request에 mask를 씌우는 방법. request를 보는 것 만으로 apikey를 찾을 수 없도록 하는 것들

nextjs는 config부분이 있음

const API_KEY = process.env.API_KEY;

module.exports = {
  reactStrictMode: true,
}
  async redirects() {
    return [
      {
        source: "/old-blog/:path*",
        destination: "/new-sexy-blog/:path*",
        permanent: false,
      },
    ];
  },
  async rewrites() {
    return [
      {
        source: "/api/movies",
        destination: `https://api.themoviedb.org/3/movie/popular?api_key=${API_KEY}`,
      },
    ];
  },
};

이 부분이 되게 신기함
source에 도달했을 경우 destination으로 보내줌
permanent: false
이때는 restart server를 해야 함
destination:"https://google.com" 도 가능함

pattern matching도 지원함.
*
부분이 모든 부분 뒤를 다 해결해준다는 것
rerwrite 는redirect를 해주기는 하지만, 내부에서 어떤 식으로 진행되는지 알 수가 없도록 숨겨줌

/api/movies에 fetch를 날리면 next에서 자동으로 destination으로 목적지를 바꿔줌
신기...
단 쿼리나 parameter에 섞일 가능성이 있는 경우 EncodeURIComponent로 그 부분 감싸는거 잊지 말기

export async getServerSideProps(){}

이 부분은 서버에서 돌아감.
이러면 서버에서 알아서 다 한 다음에 완벽한 처리를 다 한 이후에 그 데이터를 보내는 것으로 처리를 함.
시간은 조금 더 걸릴 수 있겠지만 완벽한 apikey 숨기기가 가능함

import Seo from "../components/Seo";
import { GetServerSideProps, InferGetServerSidePropsType } from "next";

interface IMovieProps {
  id: number;
  backdrop_path: string;
  original_title: string;
  overview: string;
  poster_path: string;
  title: string;
  vote_average: number;
  genre_ids: [number];
}

function Home({ results }: InferGetServerSidePropsType<GetServerSideProps>) {
  return (
    <div className="container">
      <Seo title="Home" />
      {results?.map((movie: IMovieProps) => (
        <div className="movie" key={movie.id}>
          <img src={`https://image.tmdb.org/t/p/w500/${movie.poster_path}`} />
          <h4>{movie.original_title}</h4>
        </div>
      ))}
      <style jsx>{`
        .container {
          display: grid;
          grid-template-columns: 1fr 1fr;
          padding: 20px;
          gap: 20px;
        }
        .movie {
          cursor: pointer;
        }
        .movie img {
          max-width: 100%;
          border-radius: 12px;
          transition: transform 0.2s ease-in-out;
          box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;
        }
        .movie:hover img {
          transform: scale(1.05) translateY(-10px);
        }
        .movie h4 {
          font-size: 18px;
          text-align: center;
        }
      `}</style>
    </div>
  );
  ``;
}

/* export const getServerSideProps: GetServerSideProps = async () => {
  ...
}; */

export async function getServerSideProps({}: GetServerSideProps) {
  const { results } = await (
    await fetch(`http://localhost:3000/api/movies`)
  ).json();
  return {
    props: {
      results,
    },
  };
}

export default Home;

index page에 대한 것들인데
볼 거는 꽤 있는 듯
server side

url 에다가 param넣는것

[name] 이라는 파일 명을 이용해 적는 방법이 있음
이런 방법으로 처리도 가능함
/:name임

그 path는 router을 통해서 판단하는 것

const router = useRouter();

이 느낌임

근데 query로 적힌다? 는 독특한 점이 있음

신기하다...

router hook을 사용한다.
onClick={()=>onClick=(movie.id)}
이렇게 받는데,
router.push(movies/${id}) 딱 이느낌으로 처리되긴 함
대충 감은 잡을 수 있음
react-router-dom과 비슷함.
내부 url에서는 이거를 쓰고, 외부 url부분은 window.location쪽이 조금 더 적절하다고 함

push를 할 때 선택지가 있음. string도 가능하지만, 객체도 가능함

router.push({
	pathname:'asdf',
    query:{
    	id:'asdfasdf'
    }
},"what brouser can see")

이런 방식으로 실제와 다른 경로를 보게 만들 수도 있음

catch all 부분 : 없는 404페이지

https://github.com/FIN443/next-simple-movie-app/blob/main/pages/index.tsx

ts 코드는 요쪽으로 가면 된다

profile
학생의 마음가짐으로 최선을 다하자

0개의 댓글