next JS 강의 정리 - 2 (Layouts & Image Component & Routing )

도리쿠·2023년 1월 11일
0

nextjs

목록 보기
2/4
post-thumbnail

패스트컴퍼스 강의를 듣고 정리한 내용입니다.

Pages

pages/index.js => /
pages/ssg.js => /ssg
pages/products/[slug].js => /products/[slug]

Pre-rendering & SEO

  • Pre-rendering
    : next.js 는 모든 페이지를 Pre-rendering 함
    ( * Pre-renders : HTML와 같은 기초적인 UI요소들을 미리 그린다.)

    • SEO에 용이, 초기 로딩속도 빠름
  • NO Pre-rendering : 백지 상태에서 js가 실행이 된 후에 화면을 그린다.

  • SEO : 검색엔진 최적화
    Pre-rendering 를 하면 Client 처럼 동작하지 않는 검색엔진에게 필요한 데이터를 제공 할 수 있다.

    • CSR을 제공한다면 긁어갈 데이터가 없으니 검색엔진이 조회 불가하다.
    • SSG(빌드 타임에만) & SSR(요청 타임마다)

Layout

  • pages/_app.js 를 활용해서 페이지에 공통으로 사용되는 코드를 모듈화 해서 공통 적용할 수 있음
  • subLayou 을 추가해서 Layout안에 중첩할 수 있음.

Image Component & Image Optimization

: NextJs에서 제공하는 최적화 image component

npx create-next-app --example image-component image-app

참고 사이트 : https://github.com/vercel/next.js/tree/canary/examples/image-component , https://nextjs.org/docs/api-reference/next/image

Prettier 설정

.prettierignore 파일 추가

node_modules
.next
public

.prettierrc 파일 추가

{
  "semi": false,
  "singleQuote": true,
  "tabWidth": 2,
  "useTabs": false
}

package.json 파일

  • 상단 "scripts" 안 "start" 밑에 "prettier-fix": "prettier --write ." 추가
"scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "prettier-fix": "prettier --write ."
  },

절대 경로 설정

.jsconfig.json

  • src를 절대 경로 접근 가능
{
	"compilerOptions": {
 	 "baseUrl": "src"
}
}

Router

Q : pages/index.js & src/pages/index.js 둘 중 어떤게 우선순위가 높을까?
A : pages/index.js 가 더 높다. pages 폴더가 있으면 src/pages 폴더는 반영이 안된다.(무시됨)

pages/product/first-item.js => /product/first-item
pages/settings/my/info.js => /settings/my/info

/settings/my/ 에 접근 하고 싶다면 /pages/settings/my/index.js 를 생성
/settings/ 에 접근 할때도 /pages/settings/index.js 를 생성

[slug].js

pages/category/[slug].js => /category/[slug] (ex. /category/apple)
pages/[username]/info.js => /[username]/info (ex. /jimmy/info)

[...slug].js

pages/cart/[...slug].js => /cart/[...slug]
(ex. /cart/2022/06/24 , [slug].js의 여러 depth 버전)

[slug].js에서 [slug]값을 활용하는 방법

* useRouter 훅 사용

  • //localhost:3000/category/food

    import {useRouter} from "next/router";
    
    export default function CategorySlug() {
        const router = useRouter()
        const {slug} = router.query
    
        return (
            <>
                <h1 className="title"> SLUG : {slug}</h1>
            </>
        )
    }

    SLUG : food

  • //localhost:3000/category/food?from=event
    router.query 는 url 상 ? 뒤에 오는 값(쿼리 값) 도 사용 가능 함

    export default function CategorySlug() {
        const router = useRouter()
        const {slug, from} = router.query
    
        return (
            <>
                <h1 className="title"> SLUG : {slug} , FROM : {from}</h1>
            </>
        )
    }

    SLUG : food , FROM : event
    이렇게 url/? 뒤의 커리 값(from)도 받아올 수 있다.

  • //localhost:3000/category/food?from=

    SLUG : food , FROM :

    from값이 없을땐 undefined 로 처리 됨.


  • //localhost:3000/category/food?from=event&slug=book
    : 또 다른 예시 쿼리 안에 slug값이 있다면?

    SLUG : food , FROM : event

    페이지 구조 안에 있는 [slug] 값이 적용된다.

    즉 위 URL은 food 값이 적용 됨. book값은 무시

  • //localhost:3000/category/food?from=event&from=book
    : 또 다른 예시 쿼리 안에 from값이 중복으로 있다면?

    SLUG : food , FROM : eventbook

    쿼리 값은 둘다 갖고온다.



다중 [slug]

/pages/ [slug] / [slug].js 구조

  • //localhost:3000/dorikoo/food

    export default function UserNameInfo() {
        const router = useRouter()
        const {username,info} = router.query
    
        return (
            <>
                <h1 className="title"> {username}'s {info} Info</h1>
            </>
        )
    }

    dorikoo's food Info


다중 [...slug]

  • //localhost:3000/cart/1999/12/31

    export default function CartDateSlug() {
    
        const router = useRouter();
        const {date} = router.query
        return (
            <>
                <h1 className="title"> CartDateSlug{JSON.stringify(date)}</h1>
            </>
        )
    }

    CartDateSlug["1999","12","31"]
    : 배열로 데이터가 들어온다.

//localhost:3000/cart/ 로 접근할때, pages/cart/index.js 를 안 만들고 접근 할 수 있는 방법.

  • 파일 명을 pages/cart/[[... date]].js 로 생성 하면 date의 값이 없어도 CartDateSlug 만 노출


router.push

<Link href="/cart/2023/01/01"><a>2023년 1월 1일 로</a></Link> 
<button onClick={()=>{router.push('/cart/2023/01/01')}}>2023년 1월 1일로</button> 
2023년 1월 1일 로 와 2023년 1월 1일로 가 같은 개념 - button ui의 차이


Shallow Routing

: getServerSideProps / getStaticProps 등을 다시 실행시키지 않고, 현재 상태를 잃지 않고 url을 바꾸는 방법 (ex. 스크롤 이벤트시 페이지 번호를 주고 싶을때)

url을 바꾸는 3가지 방식

  • location.replace(“url”): 로컬 state 유지 안됨(리렌더)

    <button onClick={()=>{
       alert('edit');
       setClicked(true);
       location.replace('/settings/my/info?status=editing')
    }}>edit(replace)</button>
  • router.push(url): 로컬 state 유지 / data fetching은 일어남

    <button onClick={()=>{
       alert('edit');
       setClicked(true);
       router.push('/settings/my/info?status=editing')
    }}>edit(push)</button>
  • router.push(url, as, { shallow: true }): 로컬 state 유지 / data fetching

    <button onClick={()=>{
         alert('edit');
         setClicked(true);
         router.push('/settings/my/info?status=editing',undefined,
         {shallow : **true**})
    }}>edit(shallow)</button>

Shallow Routing 테스트

  • //localhost:3000/settings/my/info
export async function getServerSideProps() {
    console.log('server')

    return {
        props: { time: new Date().toISOString() },
    }
}

export default function MyInfo() {
    const router = useRouter()
    const [clicked, setClicked] = useState(false)
    const {status = 'initial'} = router.query
    return (
        <>
            <h1 className="title"> My Info</h1>
            <h1 className="title"> Clicked : {String(clicked)}</h1>
            <h1 className="title"> Status : {status}</h1>
            <button onClick={()=>{
                alert('edit');
                setClicked(true);
                location.replace('/settings/my/info?status=editing')
            }}>edit(replace)</button>
            <br/>
            <button onClick={()=>{
                alert('edit');
                setClicked(true);
                router.push('/settings/my/info?status=editing')
            }}>edit(push)</button>
            <br/>
            <button onClick={()=>{
                alert('edit');
                setClicked(true);
                router.push('/settings/my/info?status=editing',undefined,{shallow : true})
            }}>edit(shallow)</button>
        </>
    )
}

  • 첫번째 버튼 클릭시 (location.replace) : Clicked가 true로 변경 후 다시 false 로 돌아옴 Statuc 값은 변경 된 상태로 있음. getServerSideProps() 도 동작.

  • 두번째 버튼 클릭시(router.push) : Clicked = true , Status : editing 둘다 데이터 변경됨. getServerSideProps() 도 동작.

  • 세번째 버튼 클릭시(router.push {shallow : true}) : 두번째 버튼과 화번은 동일, Clicked = true , Status : editing 둘다 데이터 변경됨. 하지만 getServerSideProps() 가 동작하지 않음. (서버는 실행하지 않음)

profile
환영

0개의 댓글