Skip to content

Commit b541784

Browse files
committed
feat: Hydration 및 서버상태와 클라이언트상태 동기화'
1 parent eef713f commit b541784

File tree

3 files changed

+38
-13
lines changed

3 files changed

+38
-13
lines changed

packages/vanilla/server.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ if (!prod) {
3232
}
3333

3434
// Serve HTML
35-
app.use("*all", async (req, res) => {
35+
app.get("*all", async (req, res) => {
3636
try {
3737
const url = req.originalUrl.replace(base, "");
3838

packages/vanilla/src/main.js

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,47 @@ import { registerAllEvents } from "./events";
44
import { loadCartFromStorage } from "./services";
55
import { router } from "./router";
66
import { BASE_URL } from "./constants.js";
7+
import { productStore } from "./stores/productStore.js";
8+
import { PRODUCT_ACTIONS } from "./stores/actionTypes.js";
79

810
const enableMocking = () =>
911
import("./mocks/browser.js").then(({ worker }) =>
1012
worker.start({
1113
serviceWorker: {
1214
url: `${BASE_URL}mockServiceWorker.js`,
1315
},
14-
onUnhandledRequest: "bypass",
16+
onUnhandledRequest: "warn",
1517
}),
1618
);
1719

1820
function main() {
21+
// SSR에서 주입된 초기 데이터 확인 및 hydration
22+
const initialData = window.__INITIAL_DATA__;
23+
if (initialData) {
24+
console.log("Hydrating with initial data:", initialData);
25+
26+
productStore.dispatch({
27+
type: PRODUCT_ACTIONS.SETUP,
28+
payload: {
29+
products: initialData.products || [],
30+
totalCount: initialData.totalCount || 0,
31+
categories: initialData.categories || {},
32+
currentProduct: initialData.product || null,
33+
relatedProducts: initialData.relatedProducts || [],
34+
loading: false,
35+
status: "done",
36+
},
37+
});
38+
}
39+
1940
registerAllEvents();
2041
registerGlobalEvents();
2142
loadCartFromStorage();
2243
initRender();
2344
router.start();
2445
}
2546

26-
if (import.meta.env.MODE !== "test") {
27-
enableMocking().then(main);
28-
} else {
29-
main();
30-
}
47+
// 현재 node, test, browser환경에서 모두 msw를 사용하므로 분기처리하지 않음.
48+
enableMocking().then(main);
49+
50+
// enableMocking().then(main);

packages/vanilla/src/services/productService.js

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@ import { initialProductState, productStore, PRODUCT_ACTIONS } from "../stores";
33
import { router } from "../router";
44

55
export const loadProductsAndCategories = async () => {
6+
const currentState = productStore.getState();
7+
8+
// 이미 상품 목록과 카테고리 데이터가 있으면 API 호출 스킵 (SSR hydration)
9+
if (currentState.products.length > 0 && Object.keys(currentState.categories).length > 0 && !currentState.loading) {
10+
console.log("이미 상품 목록 데이터가 있어서 API 호출 스킵");
11+
return;
12+
}
13+
614
router.query = { current: undefined }; // 항상 첫 페이지로 초기화
715
productStore.dispatch({
816
type: PRODUCT_ACTIONS.SETUP,
@@ -120,14 +128,11 @@ export const setLimit = (limit) => {
120128
*/
121129
export const loadProductDetailForPage = async (productId) => {
122130
try {
123-
const currentProduct = productStore.getState().currentProduct;
124-
if (productId === currentProduct?.productId) {
125-
// 관련 상품 로드 (같은 category2 기준)
126-
if (currentProduct.category2) {
127-
await loadRelatedProducts(currentProduct.category2, productId);
128-
}
131+
// 이미 해당 상품 데이터가 있고, 관련 상품도 있으면 API 호출 스킵
132+
if (import.meta.env.SSR) {
129133
return;
130134
}
135+
131136
// 현재 상품 클리어
132137
productStore.dispatch({
133138
type: PRODUCT_ACTIONS.SETUP,

0 commit comments

Comments
 (0)