RN으로 앱 개발 위주의 삶을 살아온지 어언 1년하고도 8개월...
웹 개발은 간헐적으로 어드민페이지 혹은 회사 홈페이지 위주의 개발만을 하고 있던 어느날 웹개발 프로젝트가 하나 똑 떨어졌다.
두근거리는 맘으로 시작한 오랜만의 웹개발, 그 과정에서 내가 겪는 갈등과 고민 그리고 선택에 대한 기록을 적을 계획이다.
병원에서 종합 검진을 받은 고객은 결과를 책자형태로 받게된다.
허나 우리가 제공해주는 서비스를 이용한다면 종합 검진 결과를 카카오톡을 통해 링크를 전달받은 후,
웹페이지를 통해 자세한 결과를 더욱 보기 쉬운 형태로 확인할 수 있다.
또한 종합검진 결과에 대해 기존 책자형태에서는 제공하지 않던 AI 해석이 추가적으로 첨부된다.
기술적으로 현재 프로젝트의 특징은 아래와 같다.
뭔가 SSR을 사용하면 좋은 퍼포먼스를 낼 수 있을것같다는 느낌이 강하게 온다.
각각의 종합 검진 결과에 해당하는 설명 페이지로 들어갈 때 SSR을 통해 더욱 빠르게 렌더링해줄 수 있을것같은 그런 강한 유혹이 생긴다.
어차피 모든 검진 데이터는 고정되어있으니 각각의 모든 검진 결과 페이지를 들어갈 때 서버에서 렌더링해준다면 훨씬 빠른속도로 모든 페이지를 쾌적하게 제공해줄 수 있을것만 같은 그런 핑크빛 미래가 그려진다.
Framework는 NEXT.js로 결정
해당 프로젝트의 페이지 구성의 큰 줄기는 아래와 같다.
종합검진, 일반검진 중 하나의 항목을 선택함
선택한 검진에 따른 검진 항목 목록을 볼 수 있는 페이지
목록 중 선택한 항목의 상세정보를 볼 수 있는 페이지
종합검진 항목들의 목록을 볼 수 있는 페이지에서 각 항목을 클릭하여 상세 페이지로 들어갈 시
각 상세 항목의 정보를 네트워크 요청을 통해 받아와 서버사이드 렌더링해주는것이 첫 의도였다.
허나 이후 지속적으로 고민해본 결과 위와같은 설계는 불필요한 네트워크 요청을 여러번 발생시킨다고 판단하였다.
즉, 네트워크 요청 방법 설계를 두고 아래의 두가지 방법을 고민하였고 2번째 방법을 채택하였다.
렌더링 속도: 모든 데이터를 처음에 한 번에 가져오고 zustand에 저장하면 이후 페이지 전환 시 네트워크 요청 없이 빠르게 클라이언트 측 렌더링을 할 수 있다. 따라서 항목 간 전환이 빈번한 경우에는 이 방식이 훨씬 더 빠르고 부드럽게 느껴질 것이라 판단하였다.
네트워크 요청의 최소화: 페이지 전환 시마다 네트워크 요청을 보내는 대신 한 번에 가져오기 때문에 네트워크 요청 수가 적다. 이는 네트워크 요청이 적을수록 성능이 더 좋다는 관점에서 확실한 장점이다.
현재 데이터 규모와 사용 패턴을 고려할 때, 두 번째 방법은 충분히 합리적인 선택이라고 판단된다. 데이터가 작고 변화가 적다면 한 번에 데이터를 가져와서 클라이언트 상태로 관리하는 방식이 빠르고 효율적이기 때문이다.
만일 데이터가 증가하거나 실시간으로 변경되는 경우가 많다면 첫 번째 방법을 채택하였을 것이다.
초기 로딩 시간 : 모든 데이터를 한 번에 가져오기 때문에 초기 로딩 시간이 상대적으로 길어질 수 있다. 특히 데이터 양이 늘어날 경우, 사용자가 첫 화면을 볼 때까지의 대기 시간이 길어질 수 있다. 현재 검진 정보의 데이터가 작다고 판단 헀지만 이후 데이터 양이 커지거나 확장될 가능성을 항상 고려해야 한다.
서버사이드에서 네트워크 요청을 통해 검진결과데이터를 받아온 후 클라이언트 컴포넌트로 검진결과 데이터를 전달.
import { cookies } from "next/headers";
import ComprehensiveCheckup from "./comprehensiveCheckup";
export default async function ServerSideComponent({
searchParams,
}: {
searchParams: { [key: string]: string | string[] | undefined };
}) {
const checkupId = searchParams.checkupId;
const cookieStore = cookies();
const accessToken = cookieStore.get("accessToken")?.value;
if (typeof checkupId === "string" && accessToken) {
const [comprehensiveCheckupResponse, generalCheckupResponse] =
await Promise.all([
fetch(`${API_URL}/v1/checkup/comp/${checkupId}`, {
credentials: "include",
headers: {
Cookie: `accessToken=${accessToken}`,
},
}),
fetch(`${API_URL}/v1/checkup/general/${checkupId}`, {
credentials: "include",
headers: {
Cookie: `accessToken=${accessToken}`,
},
}),
]);
const comprehensiveData = await comprehensiveCheckupResponse.json();
const generalData = await generalCheckupResponse.json();
if (comprehensiveData?.statusCode === 404) {
return <ClientSideRootComponent />;
}
return (
<ClientSideRootComponent
comprehensiveData={comprehensiveData.data}
generalData={generalData.data}
/>
);
}
return <ClientSideRootComponent />;
}
네트워크 요청 시점의 차이:
빠른 첫 번째 렌더링 (FCP: First Contentful Paint): SSR을 통해 페이지가 로드되면 초기 렌더링 속도가 빨라지고, 사용자가 페이지에 도달했을 때 이미 데이터가 채워진 상태이므로 콘텐츠의 빈틈이나 지연이 거의 없을것으로 기대됨.
네트워크 환경에 대한 이점: 만약 사용자가 느린 네트워크 환경에서 페이지에 접근할 경우, 클라이언트 측 네트워크 요청보다 서버사이드에서 데이터를 미리 가져와 렌더링하는 것이 훨씬 더 유리할 수 있다고 기대됨.