닥터마틴, 기억하고 싶은 코드 1 - 캐러셀(이미지 슬라이드)

Seokho·2021년 12월 28일
1

Dr.martens Project

목록 보기
3/4
post-thumbnail

2주간 빠르기 진행되었던 닥터마틴 클론 코딩 프로젝트 과정에서 꼭 기억하고 싶은 코드를 정리해보자!

Carousel(캐러셀)

이미지를 슬라이드 형식으로 바꾸기로 결정했지만, 정작 방법은 모르고 있었다. 무작정 구글링을 하기 보다 고민하며 구조를 잡기 위해 노트를 작성하며 정리했다.

내가 생각한 슬라이더 구조

❓ 첫번째 방법

이미지를 전부 같은 위치에 배치 후, 하나만 보여주고 나머지는 가려놓기!
처음 생각했던 구조.. 이미지를 한곳에 모아놓고 하나씩만 보여주면되지? 라고 아주 1차원적으로 접근했다.

  1. 5장의 이미지를 전부 같은 위치에 놓고
  2. 보여줄 이미지 opacity:1 나머지 이미지 opacity:0

하지만 이 방식은 아주 비효율적인 코드가 작성되었고, 애당초 슬라이드 가능이 구현되지 못했다.

❓ 두번째 방법

position으로 이미지를 나열한 후 하나씩 이동하기!
이미지를 안보이게 나열하고 보여주고 싶은 이미지 하나씩 움직이며 보여주면 될까? 라고 생각했다. 그럼 움직이는 거리를 어떻게 계산하지? posotion으로 하나씩 움직여볼까..? 라고 고민하던 찰나에 극단적으로 생각할 필요가 있다고 깨달았다!
이미지가 5장이라면 괜찮을지 모른다. 하지만 만약 이미지가 500장, 5000장이라면? 거리를 전부 계산한다고..? 아니면 자동으로 계산되는 로직을 짜야하는건가..?

💡 해결 방법

유래카!! 내가 고민했던 구조가 맞았다! 방법을 몰랐을뿐..!

  1. 이미지 배열하기
  2. 보여주고 싶은 사이즈의 화면 구현 & 보여주고 싶지 않은 이미지는 가려주기
  3. 버튼 구현 & 이미지 이동하기

1. 이미지 배열하기

map 메서드 사용하여 이미지 배열

{detailData.imageUrls &&
    detailData.imageUrls.map((img, idx) => {
      return (
        <li key={idx} className="slideContent">
          <img src={img} alt="drmartens" />
        </li>
      );
    })}

2. 보여주고 싶은 사이즈의 화면 구현 & 보여주고 싶지 않은 이미지는 가려주기

overflow: hidden 가장 핵심 포인트였다.

.slideShow {
  width: 560px;
  height: 700px;
  margin-right: 60px;
  overflow: hidden;
  }

overflow 에 사용할 수 있는 값은 네가지가 있다.

  • visible : 기본 값입이다. 넘칠 경우 컨텐츠가 상자 밖으로 보여진다.
  • hidden : 넘치는 부분은 잘려서 보여지지 않는다.
  • scroll : 스크롤바가 추가되어 스크롤할 수 있다.(가로, 세로 모두 추가)
  • auto : 컨텐츠 양에 따라 스크롤바를 추가할지 자동으로 결정된다.( 필요에 따라 가로, 세로 별도로 추가 가능)

3. 버튼 구현 & 이미지 이동하기

const [slidePosition, setSlidePosition] = useState(0);

const movePrev = () => {
    slidePosition > 0
      ? setSlidePosition(slidePosition - 1)
      : setSlidePosition(4)};

const moveNext = () => {
    slidePosition < 4
      ? setSlidePosition(slidePosition + 1)
      : setSlidePosition(0)};


<ul 
    className="slides" 
    style={{ transform: `translateX(-${slidePosition * 560}px)` }}>
</ul>

<div className="slideButton">
    <button className="prev" onClick={movePrev}>
          &lang;
    </button>
    <button className="next" onClick={moveNext}>
          &rang;
    </button>
</div>
이미지 slidePosition에 대입 이해하기

img = [
{
  id :0,
  imgpath:'images/0.jpg'
},
{
  id :1,
  imgpath:'images/1.jpg'
},
{
  id :2,
  imgpath:'images/2.jpg'
},
]

img.map((item,index) =>{
  return (
    <li>
      <img name={item.id} src={item.imgpath}/>
    </li>)
});
  
[img, img, img]

[0]
[1]
[2]

슬라이드 구조 파악하기
div는 고정되어있고, transform이 쓰여진 img를 묶고 있는 ul이 움직인다. img들은 단순 나열되어 있는 것이므로 신경쓰지 않아도 된다.

<div>  <- 고정된영역, overflow:hidden
 <ul style={transform}>  <- transform
 	<li></li>  <- 단순 나열 img
 	<li></li>
 </ul>
</div>

참고 https://im-developer.tistory.com/97

🌐 브라우저 렌더링 성능 최적화

position 속성을 활용해서 이미지의 움직임을 구현하려고 하던 찰나에 Reflow와 Repaint라는 개념을 알게되었다. 쉽게 말해 브라우저의 렌더링 과정에서 Reflow와 Repaint를 최대한 일어나지 않게 구현해야 렌더링 속도가 개선되고, 이를 통해 애니메이션이 깔끔하고 부드럽게 보여질 수 있다.
position 값을 수정할 경우 Reflow가 생기기 때문에, 나는 transform속성의 translate를 사용하며 보다 높은 성능의 애니메이션을 구현할 수 있었다.

Reflow

어떤 액션 혹은 이벤트에 따라 html요소의 크기나 위치 등 레이아웃 수치를 수정하면 그에 영향을 받는 자식과 부모를 포함하여 레이아웃 과정을 다시 수행, 계산을 하게 되는데 이 과정을 Reflow라고 한다.

Reflow가 일어나는 대표적인 경우는 아래와 같다.

  • 페이지 초기 렌더링 시(최초 Layout 과정)
  • 윈도우 리사이징 시 (Viewport 크기 변경시)
  • 노드 추가 또는 제거
  • 요소의 위치, 크기 변경 (left, top, margin, padding, border, width, height, 등..)
  • 폰트 변경 과(텍스트 내용) 이미지 크기 변경(크기가 다른 이미지로 변경 시)

Repaint

Reflow만 수행되면 실제 화면에 반영되지 않는다. 렌더링 과정에서 화면을 다시 그려주는 과정이 필요하다. 결국 paint 단계가 다시 수행되는 것이며, 이를 Repaint라고 한다!
하지만 무조건 Reflow가 일어나야 Repaint가 일어나는 것은 아니다. 레이아웃에 영향을 주지않는 스타일 속성(background-color, visibility)이 변경되었을때는 Reapaint만 수행하게 된다.

Reflow, Repaint 가 발생하는 속성 사용 피하기

아래는 각각 Reflow, Repaint가 일어나는 CSS 속성들 이다. Reflow가 일어나면 Repaint는 필연적으로 일어나야 하기 때문에 가능하다면 Reflow가 발생하는 속성보다 Repaint 만 발생하는 속성을 사용하는것이 좋다.
또한, Reflow와 Repaint가 일어나지 않는 transform, opacitiy와 같은 속성도 있다. 따라서 left, right, width, height 보다 transform을, visibility/display 보다 opacitiy를 사용하는 것이 성능 개선에 도움된다.

참고: https://boxfoxs.tistory.com/409

profile
같이의 가치를 소중하게 생각하는, 프론트엔드 개발자 이석호 입니다.

0개의 댓글