[Front-end] 개발자 공부

[개발 공부 63일차] 트러블 슈팅, Hydration Error

MOLLY_ 2024. 4. 9. 01:32
728x90

< 목차 >
1. pathname과 split을 이용해 URL의 UUID 추출해 상세정보 가져옴
2. 작성된 댓글 데이터가 안 가져와짐 ➡️ 장소 정보를 가져오는 useEffect 안에 댓글 정보 받아오는 코드 넣음
3. 프로필 이미지와 닉네임만 수정이 안 됨 ➡️ Supabase 테이블 외래 key 참조 해제해 해결
4. Error: Hydration failed because the initial UI does not match what was rendered on the server.

5. 금일 소감

 

 

1. pathname과 split을 이용해 URL의 UUID 추출해 상세정보 가져옴

 

 

와 대체 이것 때문에 몇 시간을 삽질한 건지...

 

메인 페이지에서 공부 장소를 눌렀을 때, 동적 Routing을 통해 상세 페이지로 이동한다. 상세 페이지에선 Supabase study_place 테이블에 있는 공부 장소 정보를 모두 갖고 와서 url에 있는 장소 uuid랑 맞는지 확인하고, 맞는 것을 브라우저에서 보여지게 하려 했다. 근데 어떻게 보여줘야 할지 모르겠었다.

 

심화 프로젝트 때의 다른 팀원이 작성한 코드를 봤는데 prop으로 갖고 와서 detail에서 뿌려주던데 난 그렇게 하고 싶지 않았다. 그래서 엄청 고민하고 삽질하다가

 

 

 

 

Next.js 공식 문서를 봤고, 그중에서도 pathname을 활용하자! 하는 생각으로 이어졌다. 위 사진처럼 console로 하나하나 확인해가며

 

 

 

 

마참내 답을 찾았다. split 메서드를 활용하여 /로 구분한 것을 잘라서 사용했다. data도 console로 확인해 보니 정보가 잘 들어와서 정말 감격했다. 내 이 정보를 갖고 오기까지 얼마나 긴 시간을 삽질했는가... 한 6시간은 족히 한 것 같다. 너무 긴 시간을 잡아버린... 분발하자

 

 

 

2. 작성된 댓글 데이터가 안 가져와짐 ➡️ 장소 정보를 가져오는 useEffect 안에 댓글 정보 받아오는 코드 넣음

왼쪽: 에러 메시지, 오른쪽: 에러 뜰 당시 작성된 코드

 

 

Error: Rendered more hooks than during the previous render. 라는 에러 메시지가 뜨며 작성된 댓글 정보가 가져와지지 않았다. 렌더링 간에 호출되는 Hook의 수가 일치하지 않을 때 발생하는 에러다. 그때 당시 작성된 코드는 오른쪽과 같은데 정말 뭐가 문제인지 모르겠어서 이것저것 시도하면서 시간을 꽤 보냈다. 이게 해결돼야 다른 기능으로 넘어가는데 되지 않아서 ZEP 들어가서 다른 동기분들과 상의하며 코드를 봤다.

 

 

 

 

주석으로 해둔 것도 시도한 흔적이다 ㅋㅋㅋㅋㅋㅋㅋ

 

흠.. 확실치는 않지만 중첩해서 useEffect를 사용해서 그런가 하고, 다른 시도를 하였다. 장소 정보를 받아오고 나서 댓글 정보를 받아오면 되는 것이니 장소 정보를 가져오는 useEffect 함수 안에 댓글 정보를 받아오는 코드를 넣었다. 장소 정보 data가 있으면 실행되게 하였다. 그랬더니 장소 정보가 받아와졌다!

 

이렇게 받아오는 데에는 성공했지만 장소 정보 가져오는 함수 내에서 댓글 정보까지 받아왔기 때문에, 댓글이 작성하고 제출한 즉시 댓글을 보여지게 하려니 어떻게 해야 할지 모르겠다. 좀 고민하다가 지금 당장 급한 건 아니니까 다른 페이지 구현하고 다시 와서 구현하려고 한다. 우선순위... 우선순위...

 

 

 

3. 프로필 이미지와 닉네임만 수정이 안 됨 ➡️ Supabase 테이블 외래 key 참조 해제해 해결

 

 

"insert or update on table "comments" violates foreign key constraint "public_comments_nickname_fkey"" ("테이블 "comments"에 대한 삽입 또는 업데이트가 외래 키 제약 조건 "public_comments_nickname_fkey"를 위반합니다.") 라는 에러 메시지가 뜨며 아까까지만 해도 분명 됐던 프로필 수정 기능이 안 됐다.

 

 

 

 

위 코드도 작성해가며 comments 테이블 정보를 가져오는데 nickname이 변경되지 않아서 그런 건가? 하며 잘못 추측한 것 같지만 일단 다른 좋은 방안은 떠오르진 않아서 한 번 시도는 해봐야겠다 싶었다. 코드 작성한 뒤 바로 테스트해봤다.

 

 

Error Message

 

시도 결과, 사진처럼 똑같이 에러 떴다.

 

 

우선적으론, 프로필 이미지와 닉네임만 수정이 안 돼서 일단 에러 코드와 에러 메시지 의미부터 확실히 이해해야겠다 싶었다. 저 오류는 'comments' 테이블의 nickname 필드와 'user_profiles' 테이블의 user_uid 필드가 데이터 타입이 서로 다르기 때문에 외래 키로 설정할 수 없음을 의미한다.

 

그래서 참조하는 게 문제라면, 해제하면 해결되지 않을까? 싶어서 위 사진과 같이 'comments' 테이블의 nickname과 'user_profiles' 테이블의 nickname을 연결시켜준 것을 해제했다. 어차피 댓글 등록할 때 'comments' 테이블의 nickname에도 함께 값을 넣어주기 때문에 괜찮을 것 같았다.

 

그렇게 하니 프로필 이미지와 닉네임이 잘 수정되었다. 휴 이렇게 잘 되다가 갑자기 안 되면 약간 당황스럽다. 언제부터 안 된지 모르니 어느 로직에 문제가 있는 것인지 가늠하기 어려워서 그런 것 같다. 하지만 해결! 히히

 

 

 

4. Error: Hydration failed because the initial UI does not match what was rendered on the server.

 

 

처음에 렌더링 시, 위 에러가 계속 떴다. 메인 페이지에서 뜨고, 다른 페이지에 가도 떠서 root layout에서 생긴 문제구나 싶었다. 그래서 해당 파일로 가서 코드 보면서 에러 메시지를 함께 봤다. 에러 메시지를 해석해 보자.

 

Error: Hydration failed because the initial UI does not match what was rendered on the server. Warning: Expected server HTML to contain a matching <div> in <html>. See more info here: https://nextjs.org/docs/messages/react-hydration-error

 

"Error: 초기 UI가 서버에서 렌더링된 것과 일치하지 않아 하이드레이션에 실패했다. 경고: 서버 HTML이 <html> 내에 일치하는 <div>를 포함하고 있을 것으로 예상했다. 여기에서 더 많은 정보를 확인해라: https://nextjs.org/docs/messages/react-hydration-error

 

 

Error: There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.

 

Error: 하이드레이션 중에 오류가 발생했다. 오류가 Suspense 경계 외부에서 발생했기 때문에 전체 루트가 클라이언트 렌더링으로 전환될 것이다."

이 메시지는 클라이언트 측에서의 React 하이드레이션 과정에서 문제가 발생했음을 나타낸다. 하이드레이션은 서버에서 렌더링된 HTML을 클라이언트에서 React 컴포넌트와 동기화하는 과정을 의미한다. 이 오류는 서버에서 생성된 HTML과 클라이언트에서 기대하는 HTML 사이에 불일치가 있을 때 발생한다. 종종 서버와 클라이언트 코드 사이의 불일치 또는 초기 렌더링 시 예상치 못한 변경으로 인해 발생할 수 있다. 이 문제를 해결하기 위해서는 클라이언트와 서버 사이에서 일관된 렌더링 결과를 보장해야 한다.

 

 

에러가 발생된 당시의 코드

 

 

오류 메시지와 위 코드를 보며 뭔가 알 것 같으면서도 모르겠어서 튜터님께 찾아가서 여쭤보았다. 답은 왼쪽 사진처럼 코드에서 QueryClientProvider가 body 태그를 감싸고 있기 때문에 발생한 오류다. QueryClientProvider를 타고 들어가면, 오른쪽 사진과 같이 'use client'로 돼있는 것을 확인할 수 있다.

 

에러가 발생한 명확한 이유는 바로 "Next.js는 기본값이 server 컴포넌트인데, QueryClientProvider로 body를 감쌈으로써 프로젝트 내 모든 컴포넌트를 client 컴포넌트로 만들어주었기 때문"이다.

 

 

해결된 코드

 

 그래서 위와 같이 이 두 개의 순서를 바꿔주니까 오류가 말끔하게 해결되었다.

 

 

 

5. 금일 소감

전엔 에러가 뜨면 당황스럽기도 하고 되게 싫었는데 이젠 종종 재밌기도 하다. 하나씩 풀다 보면 또 풀리는 게 은근 짜릿하기도 하다. 그리고 오류가 분명 뜨는데 에러 메시지는 안 나오는 상황이 가장 난해하기 때문에 에러 메시지가 나오는 상황은 감사하게 느껴진다.

 

트러블 슈팅을 위해 시간을 은근 소모했거나 해당 문제를 통해 내가 몰랐던 내용을 새로 알게 되었거나 기록하고 싶으면, 문제가 해결되었어도 이전으로 세팅을 다시 맞추고 이슈가 있었던 내용을 기록하곤 하는데 이러면서 한 번 더 복습이 돼서 되게 좋다. 개인 프로젝트 열심히 분발하며 구현 중이지만 트러블 슈팅과 기록! 늘어지지 않고 꼭 챙기자! 이번 주도 파이팅!!!

728x90