Server Component
의 경우, onClick
, onChange
와 같은 API들을 사용하면 오류 발생!사용자와 상호작용 하지 않는 부분은 Server Component
로 개발하는 게 유리함!
예를 들어, 위 그림처럼 Button
만 사용자와 상호작용 할 필요가 있으면, 해당 부분만 따로 Client Component
로 만드는 게 유리
사용자와 상호작용 → Client Component
정보를 단순히 디스플레이 → Server Component
강의에서는 먼저 Client Component
로 개발하여 비효율을 확인하고, Server Component
로 전환하는 식으로 진행
const [topics, setTopics] = useState([]);
useEffect(() => {
fetch('http://localhost:9999/topics')
.then(resp=>resp.json())
.then(result => {
setTopics(result);
});
}, []);
이렇게 코드를 짜면,
Client Component
에서만 사용할 수 있다는 오류가 발생함Client Component
가 되었는데, metadata
는 Server Component
에서만 사용되는 거라 나타나는 오류로, metadata
부분을 주석 처리 해주면 해결된다.📍Client Component
를 사용할 때의 단점
=> Server Component
로 바꿔 보자
useState
, useEffect
hook 제거하고 비동기 호출fetch()
메소드가 호출되고, 그 다음 json()
을 실행시켜 topics
데이터를 가져옴metadata
도 다시 사용 가능✔️ 클라이언트로 JavaScript를 전송하지 않으니까 용량이 절약됨
✔️ fetch()
로 호출하는 서버와 현재 파일이 동작하는 서버가 같은 서버거나 가까이 있는 서버라면, 굉장히 속도가 빠름
✔️ 서버 쪽에서 렌더링을 끝내고 보내기 때문에, 리로드를 시켜도 똑같이 동작함
+) 서버와 클라이언트를 동시에 켜는 방법은, 터미널을 2개 열어서 실행
Server Component
로 만들자export default async function Read(props) {
const resp = await fetch(`http://localhost:9999/topics/${props.params.id}`);
const topic = await resp.json();
return(
<>
<h2>{topic.title}</h2>
{topic.body}
</>
)
}
+) 나는 오류가 생기지 않았지만, 영상에서 오류가 나타난다면 단순히 .next
폴더를 지웠다가 다시 실행시켜 보는 게 일차적인 방법이 될 수 있다고 함!
onSubmit
이벤트는 사용자와 "상호작용"하는 부분이기 때문에, Client Component
로 구현할 필요가 있음Client Component
로 하고 어떤 걸 Server Component
로 할지 구분하는 게 중요할 듯."use client"
import { useRouter } from "next/navigation";
export default function Create() {
const router = useRouter();
return (
<form onSubmit={(e) => {
e.preventDefault();
const title = e.target.title.value;
const body = e.target.body.value;
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({title, body})
}
fetch(`http://localhost:9999/topics`, options)
.then(res => res.json())
.then(result => {
console.log(result);
const lastid = result.id;
router.push(`/read/${lastid}`);
})
}}>
<p>
<input type="text" name="title" placeholder="title" />
</p>
<p>
<textarea name="body" placeholder="body"></textarea>
</p>
<p>
<input type="submit" value="create" />
</p>
</form>
)
}
useRouter()
는 next/router
가 아닌 next/navigation
에서 import 해야 한다는 점에 유의하자!rm -rf .next
npm run dev
를 실행시키면 위와 같은 과정이 실행됨✔️ 데이터를 가져온 후에 그것을 cache로 만들지 않으면, 성능은 다소 희생되겠지만, 강의에서는 단순한 진행을 위해 그렇게 진행함👀
revalidate
: cache가 유지되는 시간 지정(ex. 10으로 지정하면 10초가 지나면 cache는 유지되지 않고 다시 만들어진다는 의미)→ 이걸 '0'으로 지정하면, cache를 사용하지 않겠다는 의미와 동일
no-store
: cache 옵션을 no-store
로 지정해주면 cache를 사용하지 않는다는 의미⭐ cache를 잘 활용하면 성능을 아주 좋게 만들 수 있기 때문에, 추후에 꼭 공부하는 것을 권장👀
useParams()
를 사용하기 위해서, layout.js 전체를 Client Component
로 바꿀 수도 있겠지만, 이렇게 하면 Server Component
의 장점을 잃어버림(기본적으로 Server Component
가 가능하다면 Server Component
로 사용하려고 노력하는 것이 좋다)
⭐
Client Component
로 사용하고 싶은 부분만Client Component
화 해서 사용하자!!
→ 이 스킬이 되게 중요할듯...
"use client"
import Link from "next/link";
import { useParams } from "next/navigation";
export function Control() {
const params = useParams();
const id = params.id;
return (
<ul>
<li><Link href='/create'>Create</Link></li>
{id ? <>
<li><Link href={"/update/"+id}>Update</Link></li>
<li><input type="button" value="delete" /></li>
</> : null}
</ul>
);
}
Client Component
로 동작할 필요가 있는 부분만 분리하여 사용하자!Update
는 Create
와 Read
가 가능한 느낌POST
가 아닌 PATCH
메소드 사용!DELETE
메소드 사용dotenv
를 설치하지 않아도 환경변수 사용이 가능한듯?.env.local
파일 생성process.env.
)⭐ 환경변수에 저장될 수 있는 기밀 정보들은, 클라이언트 사이드에 노출되지 않는 것이 좋기 때문에 Server Component
에서만 접속 가능!
NEXT_PUBLIC_
접두사로 붙이자!