일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- 코테
- 백준
- HTML5
- 프로그래머스
- 자바스크립트
- 백준구현문제
- 포이마웹
- CSS
- 익스프레스
- css기초
- 코딩테스트
- 리액트커뮤니티
- 백준골드
- HTML
- 리액트댓글기능
- 프로그래머스코테
- 리액트
- dp알고리즘
- 백준js
- 안드로이드 스튜디오
- 다이나믹프로그래밍
- 프로그래머스JS
- 알고리즘
- JS프로그래머스
- 백준알고리즘
- 백준nodejs
- 몽고DB
- 백준구현
- js코테
- JS
- Today
- Total
개발새발 로그
NextJS 14 - App Router 본문
1. App 라우터 경로
src/app에서 url에대한 경로에 맞는 페이지를 출력하려면 아래와 같이 만든다.
i/flow/login
동적 파라미터
일론머스크의 게시글을 들어간 url이다.
페이지는 아래와 같이 page.tsx로 만들면 된다.
이때 usename 경로만 갔을 때의 페이지가 필요하다면 아래와 같이 구성하게 된다.
404페이지 만드는법
layout 계층
home페이지에서 또 다른 layout을 구성하고 싶을 때는 위와 같이 구성한다.
이때 최상위 레이아웃안에 home의 layout이 포함되는 것이다.
라우트 그룹
예를 들어 로그인헸을 때의 레이아웃과 하지않았을 때의 레이아웃이 달라야한다,
이럴 때 어떻게 해야할까?
예전 page router일때는 이 부분이 복잡했는데
app router에서는 간단하게 해결할 수 있다.
afterLogin과 beforeLogin이라는 라우트 그룹을 만들었다.
이는 URL에 영향을 주지 않는다.
이를 통해서 afterLogin과 beforeLogin만의 레이아웃을 만들 수 있다.
레이아웃은 페이지가 바뀌어도 리렌더링이 되지않는다
만약 페이지가 바뀔 때 레이아웃도 리렌더링을 하고 싶다면 template.tsx를 사용하면된다.
리렌더링보다는 매번 새롭게 마운트된다고 보면된다,
Link
redirect
해당되는 페이지로 이동시킨다.
Next에서 제공하는 Image 태그 사용
알아서 최적화를 해줌
css module?
- styled-component가 된다고 우기는 블로그들은 다 ssr의 이점을 버리고 사용중인 거라고 보면될까요?
- 채용공고에서 next와 styled-component를 동시에 요구하는 공고는 두 개를 같이 쓰고 있는 곳일까요?
- 현실적으로 next와 함께 쓰일만한 라이브러리는 유명한 라이브러리 중에서 postCSS, SASS 가 전부인가요?
- 애초에 css를 굳이 필수적으로 ssr 할 필요가 없으니 그냥 쓰는 겁니다. ssr의 목적으로 SEO만을 생각하는 경우에는 css는 그냥 포기하는 거죠.
- next-app-router를 쓰는 곳보다 next-page-router를 쓰는 회사가 더 많습니다. page-router는 styled-components도 ssr 되니까요.
- vanilla-extract나 tailwind가 제일 현실적인 것 같네요. vanilla-extract는 Window 지원 x
next-app-router는 실무에 적용하기 아직 이릅니다. 대부분의 회사가 page router에서 안 넘어가고 있는 이유가 있어요
.
Parallel Routes
만약 i/flow/login이라는 경로에 있는 page.tsx를 출력하되
백그라운드에는 메인의 page.tsx가 출력되게하고싶다면 어떻게해야할까?
이때 패러렐 라우트를 사용한다.
패러랠 라우트는 위와 같이 Layout에서 modal이라는 매개변수를 호출해서 사용하고 아래와 같이 @modal 폴더를 만든다.
이 때 @modal 폴더와 layout.tsx가 폴더구조에서 동일선상에 있어야 modal을 호출할 수 있다.
아니면 오류가 발생한다.
클라이너트 컴포넌트로 전환하기
useState를 사용하려고하면 오류가 뜬다.
useState는 클라이언트 컴포넌트에서만 사용할 수 있는데
현재 서버 컴포넌트를 사용하고 있다는 뜻이다.
서버 컴포넌트
- 서버 컴포넌트는 NextJS 서버에서 동작된다.
- 리액트 18버전에서 새로 생긴 것인데 원래 리액으는 프론트엔드 라이브러리이다.
그래서 컴포넌트는 클라이언트에서 동작해야한다.
- 근데 서버컴포넌트는 서버에서 동작하기 때문에 컴포넌트에 async와 같이 비동기도 가능하다.
- 아무튼 서버컴포넌트를 사용하면 리액트 훅을 못쓰게 된다.
그래서 리액트 훅을 사용하려면 클라이언트 컴포넌트로 바꿔줘야하는데 아래와 같이 page.tsx에 작성하면된다.
'use client'를 작성하면 된다.
클라이언트 사이드 렌더링, 서버 사이드 렌더링이 클라이언트 컴포넌트 서버 컴포넌트인가요?
예전에 사용한 getserversideprops() 이거는 이젠 안쓰는건가요?
그러면 use client를 선언하면 csr 이고 사용하지 않으면 ssr인가요?
->
아뇨 클라이언트/서버 컴포넌트는 ssr과 관련 없습니다. 둘 다 ssr 되고요. 서버 데이터에 직접 접근 가능하냐의 차이뿐입니다. 'use client'를 하면 클라이언트 컴포넌트인 것일뿐 ssr과 관련 없습니다.
getServerSideProps는 page router에서만 씁니다.
default.tsx
현재 @modal 폴더를 만들고 해당 모달을 열면 url이 원하는 대로 나오지 않는다.
i/flow/login이 @modal안에 없기 떄문이다.
그래서 아래와 같이 바꿔주면 또 문제가 생기게된다.
뭔가 i/flow/login이 모달에 떠야할 것 같지만 뜨지 않는다.
위 로그아웃 상태에서의 page.tsx는 메인 페이지이다.
메인 페이지의 layout에서 modal을 찾으려고하면 찾을 수 없는것이다.
왜냐하면 위 같은 구조에서 @modal의 page.tsx를 찾지 못하는 것이기 때문이다.
하지만 page.tsx를 만들면 넣어줄 내용이 없다.
왜냐하면 @modal띄워지지 않은 메인페이지의 url에서는 아무내용을 띄우지 않기 때문이다.
이때 default.tsx를 사용한다.
이는 패러랠 라우트에 대한 기본값을 뜻하는데
보통 패러랠라우트가 사용되지않을 때 사용한다.
그럼 메인페이지의 layout에서는 (localhost:3000 일 때)
children에서는 메인 page.tsx를 출력하고,
modal에서는 @modal/default.tsx를 출력한다.
그럼 만약 url이 localhost:3000/i/flow/login 일 때는
children은 i/flow/login/page.tsx를 출력하고,
modal은 @modal/i/flow/login/page.tsx를 출력한다.
이때 주의점
만약 폴더를 바꾸다가 이런 오류가 뜨면 캐싱이 되어있어서 꼬인 것이기 때문에 서버를 재시작해주면 된다.
인터셉팅 라우트
위와같이 완료하게되면 예상되는 문제가 있을 것이다.
children은 i/flow/login/page.tsx를 출력하고,
modal은 @modal/i/flow/login/page.tsx를 출력한다.
이 부분이다.
위 부분의 말대로 화면은 아래와 같이뜨게된다.
그래서 필요한 것이 인터셉팅 라우트이다.
일단 @modal에 있는 것은 메인의 layout의 modal에서 출력하는 것이고,
아래 i와 login,page.tsx는 layout의 children에서 출력하는 것이다.
그럼 우리가 원하는 것은 @modal의 i/flow/login에 있는 page.tsx를 띄우면서]
메인의 page.tsx를 띄울 수 있냐인데 그게 인터셉팅 라우트이다.
인터셉팅 라우트는 아래와같이 바꿔주면 된다.
@modal에 있는 i를
beforeLogin에 있는 i로 대체하려고 하는 것이다.
그러면 layout의 children은 메인의 page.tsx가 되고,
modal은 @modal/i/flow/login을 띄울 수 있는 것이다.
이때 일단 아래와 같이 로그인하기 버튼을 클릭했을 때 i/flow/login으로 가도록 한다.
이 문제는 뒤에서 다룰 예정 (redirect가 문제가 있음)
쉽게말하면
아래 그림과 같이 원래 (beforeLogin)에 있는 i로 가야하는데
그걸 인터셉팅 라우트를 해서 @modal에 있는 i로 간 것이다.
근데 인터셉팅한 i는 패러랠 라우트이다.
그래서 layout에서 {children}에 그려지는 것이 아닌 {modal}에 그려지는 것이다.
그럼 여기서 궁금한 것이 생긴다.
가로채기 당한 (beforeLogin)의 i는 필요없는 것이 아닌가?
하지만 필요하다.
(beforeLogin)의 i는 새로고침 되었을 때 실행되는 것이다.
즉 브라우저를 통해서 i/flow/login을 들어오면 beforeLogin의 i가 실행되는 것이다.
근데 Link를 통해서 i/flow/login을 들어온다면 인터셉팅되어 @modal의 (.)i가 실행되는 것이다.
-> 그래서 (beforeLogin)의 i와 @modal의 (.)i는 똑같은 내용의 파일로 구성해야한다!
-> 그래야 모달이 뜨니까
여기까지와서 다시 리마인드!
지금 트위터의 url방식을 완전히 따라하고 있기 떄문에위와 같은 방식이 되었다.
일반적인 방식은 아니지만 위와 같은 상황일 때 이용하는 것이다.
private folder( _폴더 )
위에서 말했듯이 @modal의 i와 (beforeLogin)의 i가 똑같은 내용의 파일로 구성된다.
즉 완벽하게 중복된 것이다. 그래서 정리해줄 필요가 있다.
중복되는 파일을 하나로 통합해서 출력하려고 한다.
위와 같이 구성하면 하나로 통합된 컴포넌트를 동시에 사용 가능하게 된다.
이때 폴더명을 ' _component '를 하게되면 브라우저 주소창에서 인식하지 않게 된다.
이때 궁금한 것이 생길텐데
본래 LoginModal.tsx는 클라이언트 컴포넌트로 바꿔줘서 'use client'를 작성해줬었다,
하지만 위와 같이 구성하면 page.tsx에 'useClient'를 사용하지 않아도 된다.
서버컴포넌트는 클라이언트 컴포넌트를 import 해도 되지만
클라이언트 컴포넌트는 서버컴포넌트를 import 하면 안된다.
원래는 클라이언트 컴포넌트가 서버 컴포넌트를 import 해올 수 있지만
그렇게 되면 서버 컴포넌트는 클라이언트 컴포넌트로 바뀌게 된다.
이 부분은 이후에 다시 설명하겠다.
Link에서 /login 경로로가면 자동으로 i/flow/login으로 보내주던 redirect 문제 해결
트위터의 방식을 클론하기 위해 로그인 하기 버튼을 클릭하면
/login경로로 갔다가 i/flow/login으로 간다.
위 로직을 통해 가능하게 했는데
redirect를 쓰면 인터셉팅 라우트가 제대로 작동이 되지않았다.
어떤 문제였냐면
로그인 하기 버튼을 누르면 뒤에 메인 page.tsx가 출력이 되지않고, modal만 출력되는 것이었다.
왜 이렇게 됐냐면
login/page.tsx가 서버컴포넌트이기 때문에 redirect가 서버의 redirect 기능을 한 것 이었다.
서버의 redirect를 하게되면 인터셉팅 라우트가 정상적으로 작동하지 않는다.
클라이언트에서 Link를 통한 redirect가 되어야만 인터셉팅 라우트가 정상적으로 작동한다.
그러면 client의 redirect로 바꿔줘야한다.
이때 Link를 통해 /login 경로로 갔다가 (.)i/flow/login으로 가는 것이기 때문에
배경이 login의 page.tsx가 된다.
그래서 login의 page.tsx도 일단 메인의 page.tsx를 띄워주게 했다.
router.push는
i/flow/login으로 이동한 다음 뒤로가기를 눌렀을 때 바로 이전경로인 /login으로 가게된다.
router.replace는
i/flow/login으로 이동한 다음 뒤로가기를 눌렀을 때 이전경로에서 이전경로로 가게된다.
하지만 page.tsx는 서버컴포넌트인 것이 좋기 때문에 나중에 다시 바꿀 예정이다.
아래와 같이 다른 방식도 쓰는 것 같다.
만약 한 번에모달을 두 개이상 쓰고 싶을 때는 어떻게하나요??
사용하고 싶은 @modal을 위와같이 추가해서 사용한다.
그리고 메인 layout에서 아래와 같이 등록해주면 된다.