[버그] 간헐적 TypeError: fs.readFileSync is not a function 오류

Ko Seoyoung·2022년 1월 18일
1

몇일간 이 에러때문에 고생을 했다 😭

왜냐하면 특정한 상황에서만 에러가 나는데 정확한 원인을 모르겠기 때문이다.

에러는 서버사이드에서 readFileSync로 파일을 읽을 때 발생했다.

TypeError: fs.readFileSync is not a function

하지만 서버사이드는 "node환경이니 에러가 나지 않아야 되는거 아닌가!?"라는 생각에 삽질을 했다.


파일을 읽는 위치는 _app.tsx 파일의 App.getInitialProps 부분에서 발생했다. 처음에는 마크업 파일을 파싱하는 matter.read 함수를 사용했지만 이함수가 내부적으로 readFileSync를 호출하는 바람에 에러가 나서 matter 라이브러리 잘못인줄 알았다😂

아니면 웹팩과 fs 모듈을 같이 사용할때 발생하는 에러와 관련된 글을 읽고 이 문제인가 싶었다.

하지만 문제는 getInitialProps에서 브라우저는 제공하지 않는 fs를 호출했기 때문이다.


사실 주요 원인은 getInitialProps에 대한 확실한 개념 부족이다;;

내가 알고있던 내용은 getInitialProps은 getStaticProps 또는 getServerSideProps가 나오기 전에 사전 렌더링을 위해 사용되었던 개념인데, 이제 getStaticProps와 getServerSideProps로 대체된다. 하지만 _app.js에선 아직 getStaticProps와 getServerSideProps를 사용할 수 없기 때문에 getInitialProps를 사용해야한다.

그리고 서버사이드에서 실행되는 코드이다!! -> 이것이 잘못된 개념이였다.

For the initial page load, getInitialProps will run on the server only. getInitialProps will then run on the client when navigating to a different route via the next/link component or by using next/router.

공식문서를 다시 읽어보자. 페이지가 처음 로딩될 때 getInitialProps는 서버에서만 실행된다.

하지만, next/link또는 next/router를 사용해 페이지 전환을 하는 경우 getInitialProps는 client에서 실행된다.

이제 드디어 원인을 발견했으니 해결해야지...


해결방법: client에서 fs.readFileSync를 대체할 수있는것?

dynamic import를 사용한다. 이때 default로 파일 내용을 반환한다. (파일 내용이 마크다운 텍스트라 markdown으로 rename)

const file = fs.readFileSync(path); // 이 코드를 

const { default: markdown } = await import(`src/contents/blog/${path}`); // 이걸로 대체

Refs

https://github.com/vercel/next.js/discussions/12124

profile
Web Frontend Developer 👩🏻‍💻 #React #Nextjs #ApolloClient

0개의 댓글