인프런 커뮤니티 질문&답변

Eunwoo님의 프로필 이미지

작성한 질문수

기초부터 배우는 Next YTMusic 클론 코딩 (with next.js 14, UI 마스터)

12.10 Slider 노래 재생 연동 - 2

오류발생 문제입니다.

해결된 질문

24.08.11 11:01 작성

·

103

·

수정됨

1

import { IoPlaySkipBackSharp, IoPlaySkipForwardSharp } from "react-icons/io5";
import { PlayerSlider } from "../ui/PlayerSlider";
import { useAudio } from "react-use";
import { AiOutlinePause } from "react-icons/ai";
import { usePlayerState } from "@/hooks/usePlayerState";
import { ClipLoader } from "react-spinners";
import { RiPlayFill } from "react-icons/ri";

export default function PlayerContent() {
  const { activeSong } = usePlayerState();
  const [audio, state, controls, ref] = useAudio({
    src: activeSong?.src ?? "",
    autoPlay: true,
  });

  const isLoading = activeSong?.src && state.buffered?.length === 0;

  console.log("로딩상태:", isLoading);

  const onClickPreBtn = () => {};
  const onClickStartBtn = () => {
    controls.play();
    console.log("start일때 로딩상태:", isLoading);
  };
  const onClickPauseBtn = () => {
    controls.pause();
    console.log("pause일때 로딩상태:", isLoading);
  };
  const onClickNextBtn = () => {};

  return (
    <div className="w-full h-full relative">
      <div className="absolute top-[-16px] w-full">
        <PlayerSlider
          className="w-full"
          defaultValue={[0]}
          value={[state.time]}
          onValueChange={(value) => {
            controls.seek(value);
          }}
        />
      </div>
      {audio}
      <section className="flex flex-row justify-between items-center w-full h-full px-2 lg:px-6">
        <div className="flex flex-row items-center h-full gap-1 lg:gap-8">
          <IoPlaySkipBackSharp
            size={40}
            className="cursor-pointer"
            onClick={onClickPreBtn}
          />
          {isLoading ? (
            <ClipLoader color="#FFF" />
          ) : state.playing ? (
            <AiOutlinePause
              size={40}
              className="cursor-pointer"
              onClick={onClickPauseBtn}
            />
          ) : (
            <RiPlayFill
              size={40}
              className="cursor-pointer"
              onClick={onClickStartBtn}
            />
          )}
          <IoPlaySkipForwardSharp
            size={40}
            className="cursor-pointer"
            onClick={onClickNextBtn}
          />
        </div>
        <article></article>
        <div></div>
      </section>
    </div>
  );
}

playerContent.tsx 파일인데

무한로딩이 계속 생겨서 UI만 뱅글뱅글 돌아가네요..

 

그리고 thumb도 조절이 안되요.. 어디가 잘못된지 모르겠네요 1시간째 찾고있는데 ㅠㅠ

 

저는 모든 파일을 jsx가 아닌 tsx로 해서 어딘가에 문제가 있는것 같은데 못찾겠습니다.

 

 

답변 1

0

도도(코딩루팡)님의 프로필 이미지
도도(코딩루팡)
지식공유자

2024. 08. 11. 12:11

 

1.확실하게 해결될지는 모르겠으나, "use client"; 부분을 추가해보시겠어요?

  • "use client"; 가 없다면 초기 화면 랜더링 결과 ( 즉 로딩상태 ) 가 지속될 수 있어요.

  • ( 하지만 components/player/PlayerContent.tsx 을 import하는 상위 컴포넌트에 "use client"; 가 있다면 "use client"; 의 효과가 생길 수 있습니다. )

  • ( 그렇기 때문에 확실하게 "use client"; 을 붙이는것이 좋습니다. )

     

     

    2. 코드 비교해보기

     

https://github.com/dodokyo/yt-music-clone/blob/main/components/player/PlayerContent.jsx

 

  1. thumb도 조절 문제도 여러 이슈가 있을 수 있어서 단계적으로 풀어주세요.

     

3.1 저희는 public/music 폴더에 여러 음원파일들을 넣었습니다.

강의중에 해당 음원파일을 직접 넣는 부분이 있습니다. zustand의 상태관리에서가 아닌 audio 훅의 정상작동 여부를 보기 위해서죠.

3.1.1 음원 파일에 이슈가 발생한 경우 - 음원파일 교체, 확장자 확인, 경로 체크 등으로 해결해야 합니다.

3.1.2 정상작동하는 경우 3.2로 넘어감.

 

3.2 음원파일의 경로는 정상적이라는 가정하에, zustand의 상태관리 도구에서 경로관리에 문제가 있을 수 있습니다.

3.2.1 콜솔로그로 디버깅을 해본다. 정상적인 경로인지 확인한다.

 

Eunwoo님의 프로필 이미지
Eunwoo
질문자

2024. 08. 11. 18:28

감사합니다.

app-index.js:33 Warning: Prop srcSet did not match. Server: "/_next/image?url=%2Fimg%2FCattyBGM%20-%20%ED%9C%B4%ED%99%94%EC%82%B0.jpeg&w=640&q=75 640w, /_next/image?url=%2Fimg%2FCattyBGM%20-%20%ED%9C%B4%ED%99%94%EC%82%B0.jpeg&w=750&q=75 750w, /_next/image?url=%2Fimg%2FCattyBGM%20-%20%ED%9C%B4%ED%99%94%EC%82%B0.jpeg&w=828&q=75 828w, /_next/image?url=%2Fimg%2FCattyBGM%20-%20%ED%9C%B4%ED%99%94%EC%82%B0.jpeg&w=1080&q=75 1080w, /_next/image?url=%2Fimg%2FCattyBGM%20-%20%ED%9C%B4%ED%99%94%EC%82%B0.jpeg&w=1200&q=75 1200w, /_next/image?url=%2Fimg%2FCattyBGM%20-%20%ED%9C%B4%ED%99%94%EC%82%B0.jpeg&w=1920&q=75 1920w, /_next/image?url=%2Fimg%2FCattyBGM%20-%20%ED%9C%B4%ED%99%94%EC%82%B0.jpeg&w=2048&q=75 2048w, /_next/image?url=%2Fimg%2FCattyBGM%20-%20%ED%9C%B4%ED%99%94%EC%82%B0.jpeg&w=3840&q=75 3840w" Client: "/_next/image?url=%2Fimg%2Fdaldam%20music%20-%20%EB%AA%A9%EC%9A%95%EC%98%A4%EB%A6%AC.jpeg&w=640&q=75 640w, /_next/image?url=%2Fimg%2Fdaldam%20music%20-%20%EB%AA%A9%EC%9A%95%EC%98%A4%EB%A6%AC.jpeg&w=750&q=75 750w, /_next/image?url=%2Fimg%2Fdaldam%20music%20-%20%EB%AA%A9%EC%9A%95%EC%98%A4%EB%A6%AC.jpeg&w=828&q=75 828w, /_next/image?url=%2Fimg%2Fdaldam%20music%20-%20%EB%AA%A9%EC%9A%95%EC%98%A4%EB%A6%AC.jpeg&w=1080&q=75 1080w, /_next/image?url=%2Fimg%2Fdaldam%20music%20-%20%EB%AA%A9%EC%9A%95%EC%98%A4%EB%A6%AC.jpeg&w=1200&q=75 1200w, /_next/image?url=%2Fimg%2Fdaldam%20music%20-%20%EB%AA%A9%EC%9A%95%EC%98%A4%EB%A6%AC.jpeg&w=1920&q=75 1920w, /_next/image?url=%2Fimg%2Fdaldam%20music%20-%20%EB%AA%A9%EC%9A%95%EC%98%A4%EB%A6%AC.jpeg&w=2048&q=75 2048w, /_next/image?url=%2Fimg%2Fdaldam%20music%20-%20%EB%AA%A9%EC%9A%95%EC%98%A4%EB%A6%AC.jpeg&w=3840&q=75 3840w"

at img

at eval (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/image-component.js:133:11)

at eval (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/image-component.js:243:47)

at section

at article

at PlayListCard (webpack-internal:///(app-pages-browser)/./components/PlayListCard.tsx:21:11)

at section

at div

at PagePadding (Server)

at LibraryPage (Server)

at InnerLayoutRouter (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/layout-router.js:243:11)

at RedirectErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/redirect-boundary.js:74:9)

at RedirectBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/redirect-boundary.js:82:11)

at NotFoundBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/not-found-boundary.js:84:11)

at Suspense

at LoadingBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/layout-router.js:349:11)

at ErrorBoundaryHandler (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/error-boundary.js:113:9)

at ErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/error-boundary.js:160:11)

at InnerScrollAndFocusHandler (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/layout-router.js:153:9)

at ScrollAndFocusHandler (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/layout-router.js:228:11)

at RenderFromTemplateContext (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/render-from-template-context.js:16:44)

at OuterLayoutRouter (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/layout-router.js:370:11)

at section

at header

at Header (webpack-internal:///(app-pages-browser)/./components/Header.tsx:93:11)

at div

at Layout (Server)

at InnerLayoutRouter (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/layout-router.js:243:11)

at RedirectErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/redirect-boundary.js:74:9)

at RedirectBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/redirect-boundary.js:82:11)

at NotFoundErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/not-found-boundary.js:76:9)

at NotFoundBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/not-found-boundary.js:84:11)

at LoadingBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/layout-router.js:349:11)

at ErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/error-boundary.js:160:11)

at InnerScrollAndFocusHandler (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/layout-router.js:153:9)

at ScrollAndFocusHandler (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/layout-router.js:228:11)

at RenderFromTemplateContext (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/render-from-template-context.js:16:44)

at OuterLayoutRouter (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/layout-router.js:370:11)

at div

at div

at Sidebar (webpack-internal:///(app-pages-browser)/./components/Sidebar.tsx:17:11)

at O (webpack-internal:///(app-pages-browser)/./node_modules/next-themes/dist/index.mjs:28:24)

at z (webpack-internal:///(app-pages-browser)/./node_modules/next-themes/dist/index.mjs:21:47)

at ThemeProvider (webpack-internal:///(app-pages-browser)/./providers/themeProviders.tsx:13:11)

at body

at html

at RootLayout (Server)

at RedirectErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/redirect-boundary.js:74:9)

at RedirectBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/redirect-boundary.js:82:11)

at NotFoundErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/not-found-boundary.js:76:9)

at NotFoundBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/not-found-boundary.js:84:11)

at DevRootNotFoundBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/dev-root-not-found-boundary.js:33:11)

at ReactDevOverlay (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/react-dev-overlay/app/ReactDevOverlay.js:87:9)

at HotReload (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/react-dev-overlay/app/hot-reloader-client.js:321:11)

at Router (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/app-router.js:207:11)

at ErrorBoundaryHandler (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/error-boundary.js:113:9)

at ErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/error-boundary.js:160:11)

at AppRouter (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/app-router.js:585:13)

at ServerRoot (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/app-index.js:112:27)

at Root (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/app-index.js:117:11

이러한 오류는 왜뜨는걸까요? 브라우저 콘솔창에 뜹니다.

도도(코딩루팡)님의 프로필 이미지
도도(코딩루팡)
지식공유자

2024. 08. 11. 20:55

개발 단계에서 발생하는 오류로 추측됩니다.

Image 컴포넌트에서 랜덤 이미지를 가지고 오는 부분을 기억하실겁니다.

*서버에서 랜덤 이미지를 뽑은 결과랑, 클라이언트에서 랜덤이미지를 뽑은 결과가 달라 오류가 발생하는것 같네요.

*개발 환경에서는 핫모듈리플레이스 라는 컨셉을 사용하고 있어요. 이로인해 발생할 수 있습니다.

 

해결법.

1.랜덤이미지 대신 첫번째 이미지만 가져올 수 있도록 변경 합니다.

2.랜덤 이미지 대신 아이디를 기반으로 대표 이미지를 고르는 로직구현. (혹은 해시 함수)

 


참고) GPT 도움말 입니다.

 

이 경고 메시지는 Next.js 애플리케이션에서 서버에서 렌더링된 이미지와 클라이언트에서 렌더링된 이미지의 srcSet 속성이 일치하지 않을 때 발생합니다. 주로 다음과 같은 이유로 발생할 수 있습니다:

1. 서버와 클라이언트의 URL 불일치: 서버에서 렌더링된 이미지 URL과 클라이언트에서 다시 렌더링된 이미지 URL이 다를 수 있습니다. 현재 문제가 바로 이 경우로 보입니다. 서버에서 렌더링된 이미지 URL과 클라이언트에서 렌더링된 이미지 URL이 다릅니다.

2. 동적 데이터 페칭: 이미지 URL이 서버와 클라이언트에서 다르게 처리되거나 가져오는 경우(예: 환경 변수나 조건에 따라) 이 불일치가 발생할 수 있습니다.

3. 하이드레이션 문제: 서버에서 사용된 데이터가 클라이언트에서 하이드레이션 후 사용하는 데이터와 약간 다를 때 이러한 불일치가 발생할 수 있습니다.

### 해결 방법:

1. 일관성 확보: 서버와 클라이언트 간에 이미지 URL 생성 로직이 일관되도록 확인하세요. URL이 생성되는 방식과 위치를 점검하고, 동적 값이 일관되게 사용되고 있는지 확인하는 것이 중요합니다.

2. 정적 데이터 사용: 가능하다면 서버와 클라이언트 간에 변화가 없는 정적 데이터를 사용하여 이러한 불일치를 방지하세요.

3. 클라이언트 측에서 이미지 다시 확인: 경우에 따라 클라이언트가 이미지를 다시 확인하거나 다시 가져오도록 강제하면 문제가 해결될 수 있습니다. 하지만, 이는 콘텐츠가 잠시 비어 보이는 문제를 일으킬 수 있으므로 최선의 방법은 아닐 수 있습니다.

4. 환경 변수 확인: URL 생성에 영향을 미치는 환경 변수나 설정이 서버와 클라이언트에서 동일하게 사용되고 있는지 확인하세요.

위의 방법으로 문제가 해결되지 않는다면, 이미지가 처리되는 방식을 더 깊이 분석하거나 Next.js의 설정 파일(`next.config.js`)에서 불일치를 일으킬 수 있는 설정을 확인해보는 것이 좋습니다.

 


function getImageIndex(id, n) {

// id의 각 문자의 코드 값을 합산

let sum = 0;

for (let i = 0; i < id.length; i++) {

sum += id.charCodeAt(i);

}

// n으로 나눈 나머지를 반환하여 이미지 인덱스를 결정

return sum % n;

}

// 사용 예시

const id = "post123";

const n = 10; // 이미지의 개수

const imageIndex = getImageIndex(id, n);

console.log(imageIndex); // 0부터 n-1까지의 값 중 하나를 반환

 

Eunwoo님의 프로필 이미지

작성한 질문수

질문하기