티스토리 뷰

서론

프로젝트를 진행하다가 삽질한 내용을 공유합니다. Next.js에서는 getInitialProps라는 메소드가 있습니다. 이 메소드를 사용하면 화면이 렌더링 되기 전에 필요한 데이터를 미리 준비해 놓을 수 있습니다.

 

getInitialProps는 다음과 같은 상황에서 트리거 됩니다.

 

1. 주소창에 직접 URL을 치고 들어온 경우 SSR(Server Side Rendering)이 일어납니다. 이때 getInitialProps가 실행됩니다.

2. next/link나 next/router를 사용해서 클라이언트 사이드 라우팅(CSR)을 한 경우. 이 경우에도 getInitialProps가 실행됩니다.

 

이슈

제가 만들고 있는 프로젝트는 SNS라서 메인페이지에 진입했을때 피드의 리스트가 쭉 출력되어야 합니다. 그래서 메인페이지에 진입했을때 getInitialProps를 통해 서버사이드 렌더링을 하면서 필요한 데이터를 관련 액션을 dispatch해서 스토어가 업데이트 되면 그 업데이트 된 값을 다시 가져와서 컴포넌트로 내려주려고 했습니다. 아래와 같이 말이죠.

Index.getInitialProps = async ctx => {
	await ctx.store.dispatch(createGetFeedsAction());
	const feedState = ctx.store.getState();
	
	return { feedState };
};

 

여기서 문제가 발생했습니다.

 

액션이 dispatch되고 나서 api호출을 통해 데이터를 가져와야 하는데 그 api 호출이 종료될때까지 await에서 블럭되는게 아니라 바로 다음줄로 넘어갑니다. 무슨 소리냐면

Index.getInitialProps = async ctx => {
	console.log(1);
	await ctx.store.dispatch(createGetFeedsAction());
    	console.log(2);
	const feedState = ctx.store.getState();
	
	return { feedState };
};

이런식으로 콘솔을 찍었을때 1이 출력되고나서 액션이 dispatch되서 스토어에 api 호출 결과가 담긴 다음에 2가 출력되어야 하는데 그게 아니라 1이 출력된다음에 바로 2가 출력되었습니다. await에서 제대로 블럭되지 않은거죠.

 

이 문제는 이렇게 해결했습니다.

const fetchAndWait = (
	store: Store,
	actionCreator: (...params: any[]) => ActionWithPayload,
	params = [],
) =>
	new Promise(resolve => {
		store.dispatch(actionCreator(...params));
		const unsubscribe = store.subscribe(() => {
			const state = store.getState();
			unsubscribe();

			return resolve(state);
		});
	});

문제는 dispatch 함수의 호출 결과로 Promise를 리턴하지 않은거였습니다. await는 promise가 resolve될때까지 블럭 시키는 역할을 하는 키워드인데 제가 잠깐 그 사실을 망각하고 있었습니다. 그래서 fetchAndWait라는 유틸성 함수를 만들어서 액션을 dispatch하고 스토어에 상태가 업데이트 될떄까지 기다리고 업데이트된 상태를 resolve를 통해 promise 바깥으로 전달해줬습니다. 이제 다음과 같이 업데이트 된 상태를 getInitialProps에서 가져올 수 있게 되었습니다.

Index.getInitialProps = async ctx => {
	const updatedStore = (await fetchAndWait(ctx.store, createGetFeedsAction)) as RootState;
	const feedState = updatedStore.feed;

	console.log(feedState);
	return { feedState };
};

콘솔 출력 결과

자 이제 업데이트 된 상태를 제대로 가져올 수 있게 되었습니다.

 

 

 

오픈소스가 아니어서 소스는 따로 공개하지 않습니다. 질문이 있으시면 댓글로 남겨주세요.

 

 

 

 

 

댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
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
글 보관함