주요 코드에 대한 설명 주요 로직과 그 이유 코드 내에서 고려한 특정 유저 행동과 그에 대한 대처 활용한 라이브러리와 그 이유 프로젝트를 진행할 때 어려웠던 점 / 고민했던 부분과 해결방법

기술스택


말랑카우

주요로직/ 코드 설명

  1. ShortFormPlayer/index.tsx

Youtube shorts, 인스타그램 릴스와 비슷한 방식으로 동작하는 VideoList 실행 컴포넌트이다.

const ShortFormPlayer: React.FC<Props> = ({
  query,
  preLoadedVideos,
  requestIndex = 4,
  isEditable = false,
}) => {
  ...
  const [inViewIndex, setInVewIndex] = useState(0);
  const videoListRef = useRef<HTMLDivElement>(null);
...

useEffect(() => {
    const observer = new IntersectionObserver(
      (entry) => {
        entry.forEach((entry) => {
          if (entry.isIntersecting) {
            const targetID = parseInt(entry.target.id.replace(/[^0-9.]/g, ''));
            setInVewIndex(targetID);
          }
        });
      },
      { rootMargin: '0px', threshold: [1.0] }
    );
    if (videoListRef.current?.childNodes) {
      videoListRef.current?.childNodes.forEach((el) => observer.observe(el as Element));
    }
    return () => {
      observer && observer.disconnect();
    };
  }, [videos, videoListRef]);

viewPort에 노출된 비디오 컴포넌트를 확인하기위해 intersection observer 를 사용했다. intersectionObserver 객체를 생성하고, Player 컴포넌트를 감싸는 div element를 참조하는 videoListRef 오브젝트를 통해 해당 videoListRef 의 childNodes를 사용해 모든 자식객체에 intersectionObserver를 붙였다. 그리고 observer의 callback 함수가 실행되면 해당 Player 컴포넌트의 id 값을 통해 현재 뷰에 있는 video의 index를 갱신한다.

<div className='VideoListWrapper' ref={videoListRef} onClick={onClickPlayer}>
        {videos.map((video, index) => {
          return (
            <Player
              key={index}
              playerID={`player_${index}`}
              inViewPort={index === inViewIndex}
              isPlaying={index === playVideo}
              isEditable={isEditable}
              video={video}
            />
          );
        })}

2. EmbedPlayer