30개의 프로젝트로 배우는 프론트엔드 with VanillaJS (2-3) 이미지슬라이더

productuidev·2022년 9월 7일
0

FE Study

목록 보기
51/67
post-thumbnail

[fastcampus] 30개의 프로젝트로 배우는 프론트엔드 with VanillaJS (2-3)

(2) 바닐라 자바스크립트로 만드는 이미지 슬라이더

jQuery 라이브러리를 사용하지 않고 만드는 슬라이더

setTimeout, setInterval에 대한 이해

autoplay 기능을 구현하기 위한 setTimeout, setInterval을 이해해본다.

자바스크립트 주기적인 실행(setInterval, setTimeout)

  • setInterval() : 일정한 시간 간격으로 작업을 수행하기 위해서 사용
  • setTimeout() : 일정한 시간 후에 작업을 한번 실행한다. 보통 재귀적 호출을 사용하여 작업을 반복. 지정된 시간을 기다린후 작업을 수행하고, 다시 일정한 시간을 기다린후 작업을 수행하는 방식. 지정된 시간 사이에 작업 시간이 추가 되는 것. clearTimeout() 을 사용해서 작업을 중지한다.
  • clearInterval(), clearTimeout() : 지정된 작업은 모두 실행되고 다음 작업 스케쥴이 중지 되는 것

=> 차이점 : 반복되냐 한번만 실행하느냐에 차이이므로 적절한 상황에 맞춰서 메서드를 선택해서 사용

예제

간단 Test : JSBin

function test(a,b) {
	console.log(a,b);
}

setTimeout(test, 2000, "hi", "billy")

let id = setTimeout(()=>{console.log("hi")},3000)
console.log(id)

const btn = document.getElementById("btn")
btn.addEventListener("click",()=>{
	clearTimeout(id)
})
// 전달 파라미터를 1초마다 계속 나타나게

let i=0;

const test = (a,b) => {
  console.log(a,b)
  console.log(i++)
}

const id = setInterval(test,1000,"a","b")

예를 들어 const test = () => {} 라는 함수가 있다고 할 때

setInterval("함수","시간")
setTimeout("함수","시간")

아래와 같이 이렇게 함수를 넣으면 되는데

setInterval(test,1000)
setTimeout(test,1000)

이런 식으로 함수를 실행시켜서 넣는 실수

setInteval(test(),1000)
setTimeout(test(),1000)

이럴 경우 함수를 실행시켜서 리턴되는 값이 들어가게 됨
(리턴되는 값이 의도하지 않는 경우라면 오류)

유의사항 : 그냥 함수를 넣으면 되지 함수를 실행시켜서 넣는 것이 아니다

autoplay 기능 구현

위에서 알아본 setInterval, setTimeout을 통해 autoplay 기능을 추가해보자.
slider가 실행 시 기본적으로 autoplay가 되도록 만들 것인데, pause 버튼을 누르면 일시정지되고 play 버튼으로 변경되도록 추가한다.

index.html

      <div class="control-wrap" id="control-wrap">
        <i class="fa fa-pause" id="pause" data-status="pause"></i>
        <i class="fa fa-play" id="play" data-status="play"></i>
      </div>

css/style.css

.control-wrap {top: 350px;right: 35px;width: auto;position: absolute;}
.control-wrap i {color: white;cursor: pointer;margin-right: 20px;}
.play .fa-play {display: none;}
.play .fa-pause {display: block;}
.pause .fa-play {display: block;}
.pause .fa-pause {display: none;}

control-wrap 클래스에 버튼 클릭에 따라 play/pause 클래스가 추가되어 재생/멈춤이 되도록 구현한다. (css styling 확인)

src/js/ImageSlider.js

// Instance 생성
export default class ImageSlider {

  // Private Field 
  #intervalId;
  #autoPlay = true; // 초기 자동재생이 기본값이므로 true

  // Public Field
  controlWrapEl;

  // 초기화해줄 element들을 constructor에 넣어서
  // class에서 instance를 생성할 때 실행시키도록 함
  constructor() {
    this.initAutoplay();
  }

  // 요소 탐색
  assignElement() {
    this.controlWrapEl = this.sliderWrapEl.querySelector('#control-wrap');
  }

  // 초기화 : 3초 간격 자동재생
  initAutoplay() {
    // setInterval(this.moveToRight.bind(this), 3000);
    // setInterval 함수는 interval id를 리턴한다.
    // 자동재생을 멈추기 위해 interval id를 클래스의 private field에 저장해둔다.

    this.#intervalId = setInterval(this.moveToRight.bind(this), 3000);
  }

  // 버튼 이벤트 : 클릭 시 오른쪽으로 이동 실행
  addEvent() {
    this.controlWrapEl.addEventListener('click', this.togglePlay.bind(this));
  }

  // control-wrap i에 data-status (pause/play)를 가지고 멈춤/재생되도록 조건 걸기
  togglePlay(event) {
    if (event.target.dataset.status === 'play') {
      this.#autoPlay = true;
      this.controlWrapEl.classList.add('play');
      this.controlWrapEl.classList.remove('pause');
      this.initAutoplay();
    } else if (event.target.dataset.status === 'pause') {
      this.#autoPlay = false;
      this.controlWrapEl.classList.add('pause');
      this.controlWrapEl.classList.remove('play');
      clearInterval(this.#intervalId);
    }
  }

  // 좌우 이동 
  moveToRight() {
    // 재생/멈춤 중 이전/다음버튼을 누르면 슬라이드 간에
    // 변경되는 간격이 3초가 아닐 수 있어 해당 부분에 대해
    // moveToRight와 moveToLeft에 추가
    // autoplay 상태인지 아닌지도 조건에 추가
    if (this.#autoPlay) {
      clearInterval(this.#intervalId);
      this.#intervalId = setInterval(this.moveToRight.bind(this), 3000);
    }

    this.setIndicator(); // 다음버튼 눌렀을 때 indicator 활성화
  }

  moveToLeft() {
    // 재생/멈춤 중 이전/다음버튼을 누르면 슬라이드 간에
    // 변경되는 간격이 3초가 아닐 수 있어 해당 부분에 대해
    // moveToRight와 moveToLeft에 추가
    // autoplay 상태인지 아닌지도 조건에 추가
    if (this.#autoPlay) {
      clearInterval(this.#intervalId);
      this.#intervalId = setInterval(this.moveToLeft.bind(this), 3000);
    }

    this.setIndicator(); // 이전버튼 눌렀을 때 indicator 활성화
  }

}

setTimeout() 함수와 setInterval() 함수를 사용한 후에는 반드시 clearTimeout() 함수와 clearInterval() 함수를 사용해서 타이머를 청소해주는 습관을 들이시라고 말씀드리고 싶습니다. 특히, SPA(Single Page Application)을 개발할 때는 이 부분이 메모리 누수(memory leak)로 이어질 수 있기 때문에 각별히 주의가 필요합니다.
출처 - 자바스크립트의 setTimeout()과 setInterval() 함수

💡 조언 : 클래스에서 어떤 변수가 쓰이는지 상단에 미리 써놓으면 코드 리팩토링할 때나 협업할 때 class 내에서는 이런 변수들이 있구나 하고 알아보기 쉬워서 작성함. 본인이 짠 코드여도 시간이 지나면 기억하지 못할 수 있다. 코드를 잘 짜는 것만큼 정리를 잘하는 것도 좋은 프로그래머의 기본 중 하나

Result


짬짬히 공부 재개..

profile
필요한 내용을 공부하고 저장합니다.

0개의 댓글