개발자 노트

[Javascript]Transition 작동문제(infinite sliding window...) 본문

Web

[Javascript]Transition 작동문제(infinite sliding window...)

jurogrammer 2020. 6. 15. 18:27

Infinite Sliding 구현시 transition 문제

무한 슬라이딩 윈도우 구현시 애니메이션 효과가 정상적으로 작동하지 않는 문제가 발생했습니다.

분명 부드러운 이동 효과를 준 후 이동했는데도 순간이동 한다던지,

부드러운 이동 효과를 제거하여 순간이동 해야함에도, 부드러운 이동 효과로 이동하였습니다. (부드러운 이동 효과 제거 -> 이동 -> 부드러운 효과 켜기) 따라서 이를 해결하기 위한 과정을 적어보려 합니다.

순간이동 표현이 묘하지만; 슬라이딩 윈도우에서 이미지가 부드럽게 넘어가는 효과의 반의어로 순간이동이란 표현을 사용했습니다.

참고자료

상황

슬라이드가 1,2,3 이 있다고 할 때, 무한 슬라이딩 윈도우를 구현하기 위해 다음과 같이 프로세스를 세웠습니다.

  1. s1,s2,s3,s`1으로 설정 (이때 s`1은 s1을 복사하여 생성한 이미지입니다.)
  2. 애니메이션 효과 키기 (즉, 부드러운 이동 효과 ON)
  3. s3->s`1으로 이동 했을 때, s`1에서 애니메이션 효과 끄기 (이미지를 순간이동 시키기 위해)
  4. s`1에서 s1으로 이동 (순간이동!)
  5. s1에서 애니메이션 효과 키기

이와 같이 구성하려 했습니다.

허나 문제는 절차 3->4->5에서 발생했습니다.

문제

문제1.

  1. 아래의 [코드1]의 실행 부분을 1번째 실행 시 : 슬라이딩 효과가 미적용된 채 정상 작동합니다.

  2. 아래의 [코드1]의 실행 부분을 2번째 실행 시 : 슬라이딩 효과가 적용 된 채 작동됩니다.

이에 따라서 문제는 다음과 같이 가설을 세워보았습니다.
가설 1: "프로세스에서 3이 적용 되지 않은 채 4가 실행된다."

이를 검증하기 위해 다음과 같이 코드를 작성해보았습니다.

[코드2 - 검증하기 위한 코드]

turnOn();
//일정 시간이 지난 후에 아래 코드 실행
shift(100);
turnOff();

결과는 놀랍게도 애니메이션 효과가 미적용된 채 이미지가 이동합니다!!! 분명 애니메이션 효과를 먼저 준 후 한참 뒤에 이동 후 애니메이션 효과를 껏음에도 불구하구요. 이렇다면, 가설이 이상하게 됩니다.

위 [코드 2-검증코드]에서는 프로세스 3번은 적용됬다고 볼 수 있습니다. 실행 후 한참을 기다렸으니까요. 그런데 그 아랫줄의 shift(100)과 turnOff()를 실행하니 turnOff가 나중에 적혀 있음에도 애니메이션이 꺼진채로 이동합니다. 

브라우저는 어떻게 작용하길래 위와 같은 문제가 발생했을까요?

[코드1 - 전체 코드]

var img = document.querySelector("#logo-default");
var curPos = 0;

function turnOn() {
    img.style.position = "relative";
    img.style.transition = 2000+"ms";
    img.style.transform = "all";
}

function turnOff() {
    img.style.transition = "";
    img.style.transform = "";
}

function shift(dev) {
    curPos += dev;
    img.style.left = curPos + "px";
}
/*실행 부분*/
turnOff(); //transition 기능 중지.
shift(200); //transition 없는 상태 +200이동
turnOn(); //그리고나서 transition키기
//이 코드의 문제점 : +200 이동할 때 21번째줄 turnOff()가 적용되지 않은 채 transition 적용이 됩니다.

문제2. 왜 turnOff를 안 썻는데도 순간이동하지??

[코드3]

turnOn();
setTimeout(() => {
    shift(200);
},5000)

초기시작 시에 turnOn() 이후 5초후 200만큼 이동했음에도 순간이동합니다.

이건 또 도대체 뭐가 문제일까요...

결론적으로 이 두 문제는 다른 원인으로부터 파생된 문제입니다. 그런데 전 처음에 이 두 문제를 동일한 원인으로 봐서 문제 해결에 아주 골머리를 앓았습니다.. 해결 과정을 설명드리겠습니다.

문제 분석

분석 툴

google dev tools에서 performance의 timeline을 보고 해결하기로 정했습니다.

실험

목적

작성하려한 대로 실행하면 브라우저에서 어떤 일이 일어나는지 확인.

[실험1]init turnOff - shift - turnOn
결과 : 순간이동

  • 예상은 turnOff를 하고 이동했으니 순간이동할 것이라고 생각했습니다. 그리고 결과도 순간이동으로 잘 나왔습니다.! 
  • 허나 위 결과는 turnOff를 하여 순간이동한 것이 아니라 [실험2], [실험3]에서 나온 원인과 동일합니다. 즉, 위 내용은 잘못된 판단입니다. img의 위치를 브라우저가 모르기 때문에 순간이동한 것이죠. 이 부분을 잘못 해석하여 아주 골머리를 앓았던 겁니다.. 그래서 이 실험을 통해 알아낸 결과는 아래 내용입니다.
  • 그런데 여기서 주목하실 점이 있습니다. turnOff와 shift, 그리고 turnOn이 한 호흡에 다 실행된 후에 스타일 렌더일이 발생하는 것을 볼 수 있습니다. 뭐가 문제인지 머리를 팍! 스쳐지나가네요. 이에 따르면 순간이동 후 다시 슬라이드 효과를 주려면 슬라이드 효과를 주는 코드는 다음 호흡에서 실행되도록 해야 함을 알 수 있습니다.

 

[실험2]init turnOn- setTimeout(shift)
결과 : 순간이동

목적

처음 애니메이션 적용시, 설마 turnOn이 적용되지 않은 채 이동했나 싶어 위와 같은 실험을 해보았습니다.

  • 보시는 바와 같이 turnOn에서 정상적으로 렌더링 한 후에, shift에서 또 다시 렌더링을 하죠. 즉, 정상적으로 turnOn이 적용되었다고 볼 수 있습니다. (위 프로세스 3번은 정상 작동했단 이야기입니다.)
  • 한편으로, 생각해보면 turnOn이 정상작동되지 않았다면, 페이지 이동조차 되지 않았을 겁니다. position : relative효과는 turnOn에서 실행된것이니까요. 설마 코드의 맨 윗줄만 실행되고 말았나 싶어 위치를 바꾸어보았습니다. 하지만 결과는 동일하게 순간이동 되었습니다.
  • 다른 문제가 있다고 보고 다음 실험으로 넘어갔습니다.

[실험3] init turnOn-shift(0)-setTimeout(shift(200))

결과 : 부드러운 이동

목적

turnOn의 transition 효과가 한번이라도 적용되어 발생해야만 애니메이션 효과로 이동하나 싶어 shift를 2번 적용해보았습니다.

/*실행 코드*/
setTimeout(function(){
    turnOn();
    shift(0);
    setTimeout(function(){
    shift(200);
    },500)
       }, 6000);  //performance 녹화를 위해 6초 후 실행하도록 설정.

(turnOn의 stack trace를 보면 shift도 실행됬는데, log activity에는 안찍히네요..)

  • 위 결과는 부드럽게 잘 이동합니다. shift()를 한번이라도 적용한 후에는 잘 작동되었습니다.
  • 도대체 무엇이 문제일까 싶어서 인터넷에서 찾아보던 결과... 이미지의 초기 left값이 셋팅이 되지 않아서였습니다. 분명 이전 슬라이딩 윈도우짤 때도 이 부분 때문에 애먹었었는데 또 같은 실수를 반복했네요..

문제 결론

결론적으로 2가지 관점에서 예상한 대로 움직이지 않은 원인을 알 수 있었습니다.

  1. browser의 schedule

    브라우져의 스케줄에 의해 Js가 먼저 모두 실행된 다음 rendering으로 넘어갔기 때문에 turnOff-shift-turnOn에서 부드러운 이동 효과가 적용된것입니다.

  2. 초기 위치 지정

    이미지의 절대 위치를 지정해주지 않는 이상 브라우저는 이미지의 위치를 모릅니다. 따라서 이를 지정해주지 않았기 때문에 처음에 순간이동 하였고, 그 뒤엔 브라우저가 위치를 알고 있으므로 정상적으로 작동하였습니다.

...반성

명확히 알아서 불분명함을 극복하자!

Js를 통해 브라우저를 조작하다보면 예상치 못한 결과가 꽤나 발생합니다. 그런데 이번에 브라우저가 어떻게 작동하는지 살펴봄으로써 Js에 대한 두려움을 한 번 넘어서는 계기가 되었습니다.

chrome browser 공식문서는 어디에..?

한편으로 chrome 작동방식에 관한 문서를 못찾았는데... 네이버 D2 를 보니 브라우저 표준안이 있다고 하더군요. 어쩐지 Firefox랑 Chrome이 동일한 결과를 내주었었는데 이런 이유같습니다.

앞으로 문제 원인 분석을 위한 방법은 체계적으로!

앞으로 분석할 땐 위처럼 문제 원인을 진단하기 위해 어떤 신뢰성있는 툴을 이용할 것이고, 어떤 가설을 세우고, 어떤 실험을 하여 증명할지 지금보다 구체적으로 정해야겠습니다. 위와 같이 실험한 것은 주먹구구식으로 하다가 정리하게 된 것 입니다..

파이팅!

 

※ 2020.06.21 수정

- 당시 논리적으로 접근한 것이 아닌, 의식의 흐름대로 위 문제를 해결했습니다. 그걸 그대로 글로 옮기다보니 잘못된 내용 및 이해되지 않는 부분이 많아서 내용을 수정하였습니다.

- 이미지가 첨부되지 않아서 올렸습니다.

반응형

'Web' 카테고리의 다른 글

dataTable 구현  (0) 2021.06.01
[Browser] 크롬에서 console.log가 안되는 경우  (0) 2020.06.16
[Javascript] 함수에 bind()가 안 묶인 경우  (0) 2020.06.09
[Junit]testCode 참고자료  (0) 2020.06.05
[Spring]Spring 문서 주소  (0) 2020.06.04
Comments