Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DEV] frame 페이지 이미지 불러오기 #39

Merged
merged 18 commits into from
Oct 15, 2024

Conversation

yugenius0213
Copy link
Collaborator

@yugenius0213 yugenius0213 commented Oct 13, 2024

Summary

  • list 뷰에서 선택한 이미지가 frame 페이지에 뜨도록 하였습니다.
  • ai가 생성한 이미지가 frame 페이지에 뜨도록 하였습니다.
  • waiting 페이지에서 이미지 생성 api를 통해 생성 완료가 되면 frame로 라우팅하게 하였습니다.

Description

  • frame 페이지 안의 이미지가 렌더링되는 case가 2가지가 있어서 이미지 list에서 이미지가 선택되었는지 안되었는지에 따라 이미지를 다르게 띄우게 하였습니다.

이미지가 선택되었다면 그 이미지가 frame페이지에, 아무것도 선택되지 않았다면 ai가 생성한 이미지를 보여주게 하였습니다.
그러기 위해 PreviousPage 버튼을 누를때 list 선택을 해제하게 하였습니다.

  • 위의 로직을 위해 frame페이지에서 새로고침을 했을때 useAtom을 이용해 list에서 선택된 이미지가 계속 유지되어야 하는데, useAtom은 새로고침시 초기화가 되는 이슈가 있었습니다. 그래서 useAtom 대신에 상태를 localStorage에 저장해주는 atomWithStorage를 사용하여 새로고침시에도 상태가 변하지 않도록 하였습니다.

  • ai가 생성한 이미지를 불러오기 위해 이미지 목록 페이지에서 목록의 0번째 인덱스(가장 최근에 만들어진 이미지)를 사용해야해서 여기서도 atomWithStorage를 사용하였습니다.

따라서 list페이지에서 목록 중 선택한 이미지와 list[0]을 저장하는 부분에서 atomWithStorage를 쓰게 되었습니다. @ldh019 님의 코드를 수정한 부분이라 확인부탁드립니다!

  • 또한 const storedToken = window.sessionStorage.getItem('accessToken') || '';이 부분이 useEffect 바깥에 있을때 500에러가 발생해서 useEffect안에 있게 수정하였습니다.

찾아보니 Next.js가 SSR 방식으로 동작하기 때문에 window 객체를 사용하려면 클라이언트 측에서만 접근해야하기 때문에 useEffect안에 존재해야한다고 하는데, 똑같은 코드로 login에는 에러 없이 잘 작동해서 의문입니다(?)

  • 이전에 더미값으로 두었던 예제 list로 코드를 테스트 해보았고, api 연결했을때도 에러 없이 잘 작동하는 것을 확인하였습니다.

waiting 페이지에서 404에러가 뜨기는 하지만, api 명세서에 적혀있는대로 유저의 최근 요청을 찾지 못했을 때인 것 같아서 일단 PR올렸습니다. 이 부분은 나중에 확인을 다시 해보겠습니다

@yugenius0213 yugenius0213 added the dev New feature or request label Oct 13, 2024
@yugenius0213 yugenius0213 self-assigned this Oct 13, 2024
@yugenius0213 yugenius0213 linked an issue Oct 13, 2024 that may be closed by this pull request
src/app/api/waiting/route.ts Outdated Show resolved Hide resolved
src/app/list/page.tsx Outdated Show resolved Hide resolved
Copy link
Member

@ldh019 ldh019 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생했어요~!~~ LGTM~~

Copy link
Member

@falconlee236 falconlee236 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

찾아보니 Next.js가 SSR 방식으로 동작하기 때문에 window 객체를 사용하려면 클라이언트 측에서만 접근해야하기 때문에 useEffect안에 존재해야한다고 하는데, 똑같은 코드로 login에는 에러 없이 잘 작동해서 의문입니다(?)

이 부분에 대해서 답변 드리겠습니다.

문제점

window객체는 브라우저에서 동작하는 친구이기 때문에 서버사이드 렌더링에서는 항상 undefined을 반환합니다.
이걸 막기 위해서 use clients를 사용한다고 해도 또 다른 문제가 남아있습니다.

  • use client는 서버 사이드 렌더링 컴포넌트가 아니라는 선언만 할 뿐이지 next의 기본 렌더링 방식인 일괄적으로 모든 페이지를 렌더링하는 방식은 막지 않습니다.
  • 서버에서 해당 파일을 일괄적으로 렌더링하기 때문에 사용자가 해당 페이지를 렌더링하는 시점에는 이미 window가 undefined라는 문제가 발생합니다.
  • 이 문제를 막기 위해서 웹 프레임워크는 lazy loading을 지원합니다. 기존 방식처럼 한번에 모든 페이지를 불러오는 것이 아닌 필요할 때 마다 페이지를 불러오는 방식입니다.
  • lazy loading을 사용한다면 사용자가 이 페이지를 필요로 할때 비로소 해당 페이지가 로딩되기 때문에 window 객체를 정상적으로 받아올 수 있습니다.

해결방안

똑같은 코드라고 말씀하셨지만 유진님 코드랑 제 코드랑 결정적인 차이점이 맨 마지막 줄에 있습니다.

export default dynamic(() => Promise.resolve(LoginView), {
  ssr: false,
});

VS

return (
    <div className="flex w-full flex-col justify-start bg-background">
      <PreviousPage target="/login" />
      <p className="mb-3 text-center font-cafe24 text-xl text-primary-darkblue">
        나의 프로필 목록
      </p>
      {list.length === 0 && <EmptyList />}
      {!loading && list.length !== 0 && <ImageList list={list} />}
    </div>
  );

next에서 lazyloading을 지원하는 방식은 여러가지가 있지만 저는 다음과 같이 ssr:false option을 가진 프라미스 객체를 반환하는 형식으로 lazyloading을 구현했습니다.

  • 그렇기 때문에 window객체를 useEffect 함수 안에 넣지 않더라도 사용할 수 있게 됩니다.
  • 리액트나 next를 개발할때 저는 왠만하면 useEffect를 사용하지 않으려고 노력합니다. 이 함수 때문에 버그가 너무 많이 발생하고 디버깅도 힘들어지기 때문입니다.
  • 그래서 저는 useEffect에 값을 넣지않고 어떻게 window객체 문제를 해결할지 고민하고 나온 결과가 lazy loading 입니다.

마무리

제가 window 객체의 값이 로딩되는 문제를 해결한 방법을 소개해드렸습니다.
물론 유진님이 문제를 해결한 방식이 더 마음에 드시면 그대로 머지하셔도 괜찮습니다. 저는 또 다른 해결 방안과 공부하면 좋을 토픽을 던져드린것 뿐입니다.

해당 문제 말고 다른 리뷰 밑에 남겨드렸으니까 확인해 주시면 좋을것 같습니다.

위 문제를 해결하기 위해서 필요한 참고 자료 링크 올려드리겠습니다.
next.js lazy loading

src/app/frame/page.tsx Outdated Show resolved Hide resolved
src/constants/errorMessages.ts Outdated Show resolved Hide resolved
src/app/waiting/page.tsx Outdated Show resolved Hide resolved
src/app/list/page.tsx Outdated Show resolved Hide resolved
src/app/waiting/page.tsx Outdated Show resolved Hide resolved
src/store/atoms/atomWithStorage.ts Show resolved Hide resolved
@falconlee236 falconlee236 added this to the 1.0.0 milestone Oct 14, 2024
Copy link
Member

@falconlee236 falconlee236 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

일단 지금까지 push한 내용 리뷰했습니다. 에러메시지관련 몇가지 코멘트 남겨드렸습니다.

window 객체 문제는 해결되었는지 궁금하네요 항상 고생이 많으십니다

src/app/list/page.tsx Show resolved Hide resolved
src/app/list/page.tsx Outdated Show resolved Hide resolved
Copy link
Member

@falconlee236 falconlee236 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

변경사항 모두 확인했습니다!
뭔가 리뷰를 너무 많이 남겨드린 것 같은데, 혹시라도 너무 많다고 느끼시면 말씀해주세요
항상 고생 많으십니다 승인 했습니다

@yugenius0213
Copy link
Collaborator Author

Member

왕 감사합니다~~
많기는 한데 많이 배우기도 하고 그만큼 시간 써주시는건데 감사하죠 ^.^
덕분에 코드 쓰면서도 한번 더 생각하게 되는 습관이 생겼어요 ㅎㅎ
고생하셨습니다 ~ 끝이 보이네요~!~!

@yugenius0213 yugenius0213 merged commit 3f4f0cf into GDSC-CAU:main Oct 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dev New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[DEV] Frame페이지 이미지 불러오기
4 participants