본문 바로가기
프로젝트 기록

[CINEMATE] 실시간 인기 순위 영화 넘버링 구현하기 (ft. React + SCSS)

by dygreen 2023. 5. 14.

프로젝트 정보 : https://github.com/MovieApplication/cinemate

Tool : React + TypeScript + Next.js + SASS(SCSS)

 

GitHub - MovieApplication/cinemate

Contribute to MovieApplication/cinemate development by creating an account on GitHub.

github.com

 

여러 OTT 플랫폼에서 실시간 인기 순위 넘버링을 구현한 경우를 많이 접할 수 있었다.

지금 진행하고 있는 프로젝트에도 실시간 인기 순위 영화 데이터를 제공하므로 직접 구현해보면 좋을 것 같았다.

 

구현한 화면 미리보기


첫 시도 (따라하지 마세요😭)

{
    props.listItem.item.map((items, index) => (
      <SwiperSlide key={items.id} virtualIndex={index}>
        <div 
          className={!props.detailList ? home.popularItem : ''} 
          style={{'--idx': `'${index + 1}'`}}
        >
          <Image
            src={items.poster_path === 'https://image.tmdb.org/t/p/w500/null' ? '/images/none_poster.png' : items.poster_path}
            alt={items.title}
            width={props.width}
            height={props.height}
          />
        </div>
        <Link href={`/detail/${encodeURIComponent(items.id)}`}>
          <ul className={props.detailList ? detail.cover : home.cover}>
            <li><FontAwesomeIcon icon={faCircleInfo} /></li>
            <li>{items.title}</li>
            <li><span>평점</span> {items.vote_average?.toFixed(1)} / 10</li>
            <li>{items.overview}</li>
          </ul>
        </Link>
      </SwiperSlide>
    ))
}
.popularItem::before {
    content: var(--idx);
    display: block;
    position: absolute;
    bottom: -50px;
    left: -60px;
    color: rgba(0,0,0,0.5);
    font-size: 150px;
    font-weight: 700;
    font-style: italic;
    -webkit-text-stroke: 2px #bbb;
    letter-spacing: -10px;
}

→ 코드가 조금 복잡하니 아래 부분만 보면 됩니다

 

1. style={{'--idx': `'${index + 1}'`}}

: JSX에서 style 태그에 '--idx' 속성을 (실시간 인기 순으로 넘어온 데이터의 index 값에 1을 더해) string 값으로 보낸다.

 

2. content: var(--idx);

: CSS에서 var() 함수로 --idx 값을 받아서 스타일링 한다.

 

문제점

해당 프로젝트에서 typeScript를 사용하다보니, style 태그에는 '--idx' 속성이 들어갈 수가 없다는 에러가 발생하여 next build를 할 수 없었다.

 

두 번째 시도 ✨

{
    props.listItem.item.map((items, index) => (
      <SwiperSlide key={items.id} virtualIndex={index}>
        <div
          className={!props.detailList ? home.popularItem : ''}
          data-idx={index + 1}
        >
          <Image
            src={items.poster_path === 'https://image.tmdb.org/t/p/w500/null' ? '/images/none_poster.png' : items.poster_path}
            alt={items.title}
            width={props.width}
            height={props.height}
          />
        </div>
        <Link href={`/detail/${encodeURIComponent(items.id)}`}>
          <ul className={props.detailList ? detail.cover : home.cover}>
            <li><FontAwesomeIcon icon={faCircleInfo} /></li>
            <li>{items.title}</li>
            <li><span>평점</span> {items.vote_average?.toFixed(1)} / 10</li>
            <li>{items.overview}</li>
          </ul>
        </Link>
      </SwiperSlide>
    ))
}
.popularItem::before {
    content: attr(data-idx);
    display: block;
    position: absolute;
    bottom: -50px;
    left: -60px;
    color: rgba(0,0,0,0.5);
    font-size: 150px;
    font-weight: 700;
    font-style: italic;
    -webkit-text-stroke: 2px #bbb;
    letter-spacing: -10px;
}

1. data-idx={index + 1}

: dataset을 사용하여 DOM요소에 값을 저장한다.

 

2. attr(data-idx)

: CSS에서 attr() 함수로 dataset 값을 가져와 스타일링 한다.

참고로 CSS에서의 attr() 함수는 속성의 값을 문자열로 가져온다. 따라서 data-idx의 값은 문자열로 표현된다.

 

 


 

훨씬 깔끔해지고 에러도 안터지는 코드로 해결하니 뿌듯했다..

사실 이렇게 간단하게 정리되었지만, 수많은 삽질이 있었다...

그런만큼 더 정리해서 나중에 같은 기능을 구현할 때 참고해야겠다..!

728x90

댓글