[NextJS] Framework Overview

신치우·2023년 4월 24일
0

NextJS

목록 보기
2/11

library : 내가 원하는 것을 언제든지 가져다가 씀
framework : 정해진 틀이 있고 규칙만 지켜서 쓰면 편하게 쓰기 가능

creat-react-app 은 client side rendering

--> 만약 클라이언트 쪽에서 JS를 비활성화하면 동작하지 않음

create-next-app 은 server side rendering

--> 만약 클라이언트 쪽에서 JS를 비활성화해도 동작함
--> JS를 비활성화하면 버튼이나 이런건 동작하지 않음
--> 단점으로 API등을 가져올때 느릴 수 있음
--> 연결이 느려도 기다리면 확인 가능

export default function NavBar() {
  return (
    <nav>
        <a href="/">Home</a>
        <a href="/about">About</a>
    </nav>
  )
}

위와 같이 코드를 작성해도 동작은 한다
문제는 NavBar가 동작할때마다 전체 페이지를 새로고침을 한다
이는 속도를 느리게 만들 수 있다
그래서 우리는 <a> 말고 Link를 사용한다
이거는 React의 router link랑 동일한거니깐 잘 기억해야한다

그러면 위 코드는 아래와 같이 수정된다 (속도도 훨씨이이인 빠른다)
그리고 버전에 따라 <Link><a></a></Link> 를 쓰는 것도 있는거 같다 (노마드 코드는 그렇게 쓰고있음 - 근데 내꺼는 저렇게 쓰면 <a> 를 지우라는 에러가 뜬다)

import Link from "next/link"

export default function NavBar() {
  return (
    <nav>
        <Link href="/">
            Home
        </Link>
        <Link href="/about">
            About
        </Link>
    </nav>
  )
}

그런데 개발자모드에서 검사로 보면 아래와 같이 <a>로 표기되는 것을 알 수 있다.

근데 Link 안에 style, className 같은건 적용할 수 없다고 했는데..?

된다 지금은 됩니다.


Next.JS 공식 doc
주석 처리한 방법처럼 사용해도 되고, 아니면 그냥 써도 된다
오히려 <a> tag를 넣으면 에러를 띄운다

import Link from "next/link"

export default function NavBar() {
  return (
    <nav>
        {/* <Link legacyBehavior href="/">
            <a style={{color: 'red'}}>Home</a>
        </Link> */}
        <Link style={{color: 'red'}} href="/">
            Home
        </Link>
        <Link href="/about">
            About
        </Link>
    </nav>
  )
}

그럼 이제 Router를 만들어보자

NextJS는 React랑은 다르게 router를 따로 install 하지 않아도 된다
그냥 불러와서 쓰면된다
아래처럼

import Link from "next/link"
import { useRouter } from "next/router"

export default function NavBar() {
    const router = useRouter();
    
  return (
    <nav>
        {/* <Link legacyBehavior href="/">
            <a style={{color: 'red'}}>Home</a>
        </Link> */}
        <Link style={{color: router.pathname === "/"? "red":"blue"}} href="/">
            Home
        </Link>
        <Link style={{color: router.pathname === "/about"? "red":"blue"}} href="/about">
            About
        </Link>
    </nav>
  )
}

style을 수정해보자 - css module

아래 코드처럼 쓰면 동작하지 않는다

import Link from "next/link"
import { useRouter } from "next/router"
import styles from "./NavBar.module.css"

export default function NavBar() {
    const router = useRouter();
    
  return (
    <nav className="nav">
        {/* <Link legacyBehavior href="/">
            <a style={{color: 'red'}}>Home</a>
        </Link> */}
        <Link href="/">
            Home
        </Link>
        <Link href="/about">
            About
        </Link>
    </nav>
  )
}

아래와 같이 적어야 동작한다

import Link from "next/link"
import { useRouter } from "next/router"
import styles from "./NavBar.module.css"

export default function NavBar() {
    const router = useRouter();
    
  return (
    <nav className={styles.nav}>
        {/* <Link legacyBehavior href="/">
            <a style={{color: 'red'}}>Home</a>
        </Link> */}
        <Link href="/">
            Home
        </Link>
        <Link href="/about">
            About
        </Link>
    </nav>
  )
}

그건 그렇고 동작을 완료하니 아래처럼 이상한 말로 써진 class가 생성됐다
난 분명 코드에서 nav 를 썼는데..
이는 css module의 역할이라서 그런다. 이런식으로 만들게 되면 클래스 네임이 중복되는 현상을 막을 수 있다

그리고 class를 중복 적용하려면 아래와 같이 두가지 방법을 사용할 수 있다

import Link from "next/link"
import { useRouter } from "next/router"
import styles from "./NavBar.module.css"

export default function NavBar() {
    const router = useRouter();
    
  return (
    <nav >
        {/* <Link legacyBehavior href="/">
            <a style={{color: 'red'}}>Home</a>
        </Link> */}
        <Link className={`${styles.link} ${router.pathname === "/" ? styles.active : ""}`} href="/">
            Home
        </Link>
        <Link className={[
            styles.link,
            router.pathname === "/about" ? styles.active : "",
            ].join(" ")} href="/about">
            About
        </Link>
    </nav>
  )
}

그런데 노마드코더는 둘다 좋아하지 않는다고 했음
왜냐면
1. 파일을 두개 써야함 (js, module.css)
2. 조건부 연산자를 쓰는게 복잡함

이 두가지를 해결하는걸 이제 다음장에서 해보자

styles.jsx

아래처럼 직접 쓰면된다 style jsx 그리고 `` 백틱을 사용해서
그리고 이는 독립적으로 움직여서 다른 페이지에 영향을 주지 못한다

NavBar.js

import Link from "next/link"
import { useRouter } from "next/router"

export default function NavBar() {
    const router = useRouter();

    return (
        <nav>
            <Link legacyBehavior href="/">
                <a>Home</a>
            </Link>
            <Link legacyBehavior href="/about">
                <a>About</a>
            </Link>
            <style jsx>{`
                nav {
                    background-color: tomato;
                }
                a{
                    text-decoration: none;
                }
            `}</style>
        </nav>

    )
}

index.js

import NavBar from "@/components/NavBar";

export default function Home() {

  return (
    <div>
        <NavBar />
        <h1>Hello</h1>
        <style jsx>{`
        a{
            color: white;
        }
        `}</style>
    </div>
  );
}

위 처럼 두개의 <a> tag 에 적용될수 있는게 코드상으로 두개의 style이 있지만 아래 그림을 보면 실제는 NavBar.js만 적용된 것을 알 수 있다

위에서 말했던 css.module 사용시 발생한다고 느낀 2가지 단점이 다 없어진 것을 확인할 수 있다.

그러면 전역으로 Css를 어떻게 설정할 수 있을까??
그건 이제부터 해봅시다

전역으로 CSS 를 먹여보자 - Custom App

import NavBar from "@/components/NavBar";

export default function Home() {

  return (
    <div>
        <NavBar />
        <h1>Hello</h1>
        <style jsx global>{`
        a{
            color: white;
        }
        `}</style>
    </div>
  );
}

위에 처럼 style jsx global을 하는 것도 하나의 방법이다
하지만 위처럼 하게 될 경우 상속관계가 아닌 페이지 이동의 경우 적용이 되지 않는다

react는 page별로 생각하지 않아도 되지만 NextJS는 해줘야한다

이를 해결하기위해서 NextJS에는 pages 폴더 안에 _app.js를 사용할 수 있게 해놨다 (파일명은 무조건 _app.js를 써야한다 그래야 모든 파일중에 가장 먼저 rendering 이됨)

_app.js

import NavBar from "@/components/NavBar";

export default function App({ Component, pageProps }) {
    return (
        <>
            <NavBar />
            <Component {...pageProps} />
            <style jsx global>{`
        a{
            color: white;
        }
        `}</style>
            <span>hello</span>
        </>
    )
}

위 코드를 한줄씩 뜯어보면
import는 NavBar를 불러온거다 (@를 써서 절대경로로 불렀음)
Component 는 pages에 있는 index.js, about.js 등 각각의 page를 얘기한다
pageProps 는 page 안에 있는 properties 를 얘기한다
<Component {...pageProps} /> 는 각각의 page를 가져와서 rendering 하는 부분이다.

위에처럼 작성하면 NavBar, style jsx, span은 전부 global로 동작하게 된다

global.css는 각각의 page에서 불러올수 없다!!!
그런데 _app.js 는 예외임 불러올수 있어
왜냐고? 내가 global 이니깐!!

profile
하루에 집중을

0개의 댓글