yamoo9 / likelion-FEQA

질문/답변 — 프론트엔드 스쿨, 멋사
29 stars 9 forks source link

[LAB-4] user를 불러오다가 생긴 궁금증에 대해 질문있습니다..!! #275

Closed SeoMiYoung closed 1 year ago

SeoMiYoung commented 1 year ago

질문 작성자

서미영

문제 상황

마켓칼리의 피그마 시안에서 상품문의, 상품 후기 작성하기 버튼을 눌렀을 때 뜨는 팝업창을 ProductDetailPopUp이라는 폴더안에서 구현하였습니다. 저는 ProductDetailPopUp.jsx에서 로그인한 user의 정보를 받아오고 싶었습니다.

// 현재 로그인된 사용자의 사용자명 불러오기
const { user } = useAuthState();

그래서 이렇게 useAuthState()를 통해서 user의 정보를 받아오고, user안에 displayName에 사용자의 이름을 담아두었기 때문에, user.displayName을 출력해보고 싶었습니다.

그래서 ProductDetailPopUp.jsx에서 displayName을 출력하기 위한 여러 시도들을 했습니다.

[1차시도] 그냥 user를 불러오고, console.log로 찍어보기

// 현재 로그인된 사용자의 사용자명 불러오기
  const { user } = useAuthState();

  console.log('user dpN', user.displayName);

=> 결과) displayName을 읽을수가 없음 에러 image

[2차시도] useEffect로 감싸기

// 현재 로그인된 사용자의 사용자명 불러오기
  const { user } = useAuthState();

  useEffect(() => {
    console.log('user dpN', user.displayName);
  }, [user]);

=> 결과) 1차 시도와 같은 에러가 뜸 (displayName을 읽을수가 없다)

[3차 시도] useEffect로 감싸고, 그 안에서 if문으로 user를 한번 확인하고, user.displayName에 접근하게 하기

// 현재 로그인된 사용자의 사용자명 불러오기
  const { user } = useAuthState();

  useEffect(() => {
    if (user) {
      console.log('user', user);
      console.log('user dpN', user.displayName);
    }
  }, [user]);

=> 결과) user.displayName을 불러오는데 성공!! image 제가 로그인한 이름이 '태태'여서 위 사진은 옳바르게 로그인한 사용자의 이름을 가져온 걸 확인할 수 있었습니다.

세번째 시도가 성공한 이유를 팀원들과 논의를 해본 결과, if문 없이, 바로 user.displayName이나 user를 출력하려고 한다면, 아직 user의 정보를 가져오지 않았는데 콘솔로 출력을 하니 user에 대한 정보를 불러올 수 없는 것 같다는 얘기가 나왔습니다. 따라서 if(user)로 user가 있는지 확인하고, user.displayName에 접근해야 이제서야 user정보를 가져올 수 있어서 3차 시도 방법이 성공한 것이라고 판단했습니다.

혹시 저희의 생각이 맞을까요? 또한, 저희 팀원들 중 어떤분은 저렇게 if문으로 접근을 해서 해결하려는 방식이 옳은 방식인지에 대해서도 궁금하다고 합니다. 궁금증을 해결해주시면 감사하겠습니다 ㅠㅠ

프로젝트 저장소 URL

https://github.com/SeoMiYoung/project-repo branch: feat/https://github.com/yamoo9/likelion-FEQA/issues/96 상품문의 팝업에 접근 방법: npm start => 상품을 누른다 => 문의하기 버튼 누른다

환경 정보

운영체제 정보: 윈도우 Node.js 정보: v18.14.0

yamoo9 commented 1 year ago

질문

세번째 시도가 성공한 이유를 팀원들과 논의를 해본 결과, if문 없이, 바로 user.displayName이나 user를 출력하려고 한다면, 아직 user의 정보를 가져오지 않았는데 콘솔로 출력을 하니 user에 대한 정보를 불러올 수 없는 것 같다는 얘기가 나왔습니다.

따라서 if(user)로 user가 있는지 확인하고, user.displayName에 접근해야 이제서야 user정보를 가져올 수 있어서 3차 시도 방법이 성공한 것이라고 판단했습니다.

혹시 저희의 생각이 맞을까요? 또한, 저희 팀원들 중 어떤분은 저렇게 if문으로 접근을 해서 해결하려는 방식이 옳은 방식인지에 대해서도 궁금하다고 합니다. 궁금증을 해결해주시면 감사하겠습니다 ㅠㅠ

답변

정답입니다! 😊

user 상태의 초깃값이 null이고, Firebase에서 인증 요청/응답 받기 전까지는 null 값입니다. 그래서 user 상태가 변경 됨을 useEffect(또는 useLayoutEffect) 훅을 사용해 감지해 displayName 속성에 접근해야 합니다.

하지만 useEffect 훅은 상태 업데이트 외에도 마운트(mounted) 시점에 실행되기 때문에 user 상태 값이 아직 null일 때 displayName 속성에 접근하려 시도하면 오류(error) 메시지가 출력되는 것입니다. null은 객체(object)가 아니니까요.

그래서 useEffect 훅의 이펙트 콜백(callback) 함수 안에서 if 조건 처리하여 user 상태 값이 null이 아닐 때 displayName 속성에 접근하는 접근이 필요합니다.

const { user } = useAuthState();

useEffect(() => {
  if (user) {
    console.log('사용자 이름: ', user.displayName);
  }
}, [user]);

TypeScript 그리고 개발자 경험

만약 타입 검사하는 TypeScript와 VS Code를 사용했다면?

Code 에디터에서 바로 오류(빨간색 밑줄)가 표시 되었을 거에요. (ESLint 린팅 검사와 같은 경험) user 상태 값이 null일 가능성이 있는데 displayName 속성에 접근하려 시도했기 때문입니다.

const { user } = useAuthState();

useEffect(() => {

  // 🚨 TypeScript : Object is possibly 'null'. ts(2531)
  console.log('사용자 이름: ', user.displayName);

}, [user]);

이런 경우 타입 가드(Type Guard)하여 타입이 올바른 경우에만 코드가 실행되도록 구성해야 TypeScript가 오류 메시지를 출력하지 않습니다.

const { user } = useAuthState();

useEffect(() => {

  if (user) {
    // ✅ TypeScript : user가 null일 가능성 없음 (타입 검사 통과)
    console.log('사용자 이름: ', user.displayName);
  }

}, [user]);

TypeScript를 사용하는 이유가 여기에 있습니다. DX(Developer eXperience)가 향상되기 때문이죠. 😃

SeoMiYoung commented 1 year ago

와 타입스크립트를 쓰면 저런걸 캐치할 수 있겠군요..! 나중에 꼭 타입스크립트를 시도해봐야겠어요!! 정말 질문에 항상 신경써주시면서 답변해주셔서 항상 감사했습니다!! 감사합니당~~