이전 포스팅에서 상품을 보여주는 과정에서 약간의 시간과 자연스럽지 못한 퍼포먼스를 보였는데요. 이것을 개선하기 위해 크게 두가지 방법을 생각했습니다.
1.로딩 페이지 삽입!
2. SSR ( 😄 왜 SSR이 방법인지 궁금한 사람은 클릭!)
로딩 페이지 제작은 아주 기본적이고 간단한 방법입니다. 대부분의 외부 디자인 라이브러리의 경우 (bootstrap, semantic-ui-react 등... ) 은 Loading 과 관련된 페이지를 제공하기 때문에 각자 쓰시는 것에서 불러온 후, 데이터를 저장한 후에 loading
의 논리 구조를 반대로 설정해주면 됩니다.
#index.js
import { Divider, Header, Loader } from 'semantic-ui-react'
export default function Home() {
const API_URL = "http://makeup-api.herokuapp.com/api/v1/products.json?brand=maybelline"
const [list,setList] = useState([]);
const [isLoading, setIsLoading] = useState(true); # 로딩값 초기 설정.
useEffect(() => {
axios.get(API_URL)
.then((res) =>{
setList(res.data) // 데이터 입력, 설정
console.log(res.data)
setIsLoading(false); // 이후에 로딩 값 변경
})
}, [])
return (
<div>
<Head>
<title>HOME | JUSER</title>
</Head>
{
isLoading && (<div style= {{padding : "300px 0"}}>
<Loader inline="centered" active> // 로딩 중일때......
Loading
</Loader>
</div>)
}
{
!isLoading &&(
<>
{로딩이 끝나면 보여주고 싶은 구조}
</>
)
}
</div>
)
}
위와 같이 대충 저런 논리 구조로 작성하면 됩니다. 그런데 조금 너무 간단하고 굳이 NextJs 가 아니라도 할 수 있는 해결법입니다.
NextJs의 특성을 이용한 솔루션을 한번 보시죠.
SSR 을 사용한 솔루션을 사용하기 위해서는 getServerSideProps
함수를 사용하는 방법입니다.
getServerSideProps
는 빌드와 상관없이, 매 요청마다 데이터를 서버로부터 가져옵니다.
작동 포멧 ,논리는 👇
function Page({ data }) {
console.log(this.props.data)
//res.json()이 찍힙니다
}
export async function getServerSideProps() {
const res = await fetch(`https://.../data`)
const data = await res.json()
return { props: { data: data } }
}
export default Page
위의 로직은 fetch api를 통해 data값을 가져오고 data를 Page component에서 this.props.data로 접근이 가능한 형식입니다.
이 로직을 제 코드에 적용해보도록 하겠습니다.
Before 👇
const Post = () => {
const [item, setItem] = useState({})
const router = useRouter()
const { id } = router.query
const [isLoading, setIsLoading] = useState(true);
const API_URL = `http://makeup-api.herokuapp.com/api/v1/products/${id}.json`
useEffect(() => {
if (id&& id >0){
axios.get(API_URL)
.then(res =>{
setItem(res.data);
setIsLoading(false);
})
}
}, [id])
return <>{ isLoading ? (<div style= {{padding : "300px 0"}}>
<Loader inline="centered" active>
Loading
</Loader>
</div>) : <Item item ={item}/>}</>
}
export default Post;
After 👇
const Post = ({item}) => {
return <>{ item && <Item item ={item}/>}</>
}
export default Post;
export async function getServerSideProps(context) {
const id = context.params.id;
const apiUrl = `http://makeup-api.herokuapp.com/api/v1/products/${id}.json`
const res = await axios.get(apiUrl);
const data= res.data
return {
props: {
item : data
}
}
}
네 아주 놀라운 변화가 있었는데요. 코드가 훨씬 간편해진게 보이시나요?! 🔥
🙋 파라미터로 받는 context는 뭔가욥?!
🤖 context 에는 여러가지 정보가 들어있습니다. params, 요청 등과 같은 데이터들이 들어있죠.
context 하위 키👉
params: 이전에 나온 내용과 동일
req: The HTTP request object.
res: The HTTP response object.
query: The query string.
preview: 나중에
previewData: 나중에
🙋 근데 이러면 대체 뭐가 더 좋나요??
🤖 최신상태유지 , SEO 향상
이전에는 그저 pre - rendering 된 상태일 뿐입니다. 소스를 보시면 메타테그에 관련된 내용이 없었지만,
이후에는 아래와 같이 메타 테그로 인한 상품 설명 부분이 들어가게 되었습니다. 만약 배포하게 된다면 저 내용에 관련된 검색어를 검색하면 저 상품이 딱 나오겠죠?
또한 요청 받으면 거기에 대해서 렌더링을 그때그때 진행하기 때문에 퍼포먼스 적으로 더이상 기다리지도, 로딩창을 보지도 않아 체감상 훨씬 자연스럽고 빠른 속도를 체감할 수 있습니다. ( 실제로는 요청 자체가 늘어나기 때문에 퍼포먼스는 낮아질 수 있지만..😅 )
아! 그리고 실시간 데이터를 호출하기 때문에 가격 변동이나, 다이나믹하게 변하는 데이터를 즉각 반영할 수 있다는 장점도 있죠! 😄
아니 그런데 자꾸 콘솔창에 저렇게 시뻘건 글씨로 에러가 뜨는 것을 볼 수 있습니다. Ref말고 딴거 써라!!!!라고 하는데....
아래는 NextJS 공식 문서에 나와있는 문구입니다. 직역하자면,
이전까지는 원래 Link 에 as 써줬음!
'as'는 브라우저 주소창에 나오는 주소를 의미하는데요. 즉, 실제 사용자가 보는 주소를 의미합니다.
<Link href="/post/[pid]" as="/post/abc">
<a>First Post</a>
</Link>
href는 넥스트 JS 가 실제로 가는 경로이고 , as 는 사용자에게 보여줄 경로를 의미합니다.
# itemList.js
...
<Link href={`/view/${item.id}`}>
...
위의 코드를...
...
<Link href="/view/[id]" as={`/view/${item.id}`}>
...
요렇게 바꿔주면
에러가 시원하게 사라졌습니다!!😄