일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 스택
- exception
- Pattern
- 프로그래머스
- 로버트마틴
- Java
- 파이썬
- Eclipse
- 겨울카카오인턴
- 자바
- Collections
- solid
- Collection
- Rails
- 람다 칼큘러스
- javscript
- 디자인패턴
- 함수형 프로그래밍
- JDBC
- 백준
- DesignPattern
- functional programming
- Network
- Spring
- JavaScript
- tcp
- lambda calculus
- Python
- design-pattern
- 큐
- Today
- Total
개발자 노트
[Javascript]Transition 작동문제(infinite sliding window...) 본문
Infinite Sliding 구현시 transition 문제
무한 슬라이딩 윈도우 구현시 애니메이션 효과가 정상적으로 작동하지 않는 문제가 발생했습니다.
분명 부드러운 이동 효과를 준 후 이동했는데도 순간이동 한다던지,
부드러운 이동 효과를 제거하여 순간이동 해야함에도, 부드러운 이동 효과로 이동하였습니다. (부드러운 이동 효과 제거 -> 이동 -> 부드러운 효과 켜기) 따라서 이를 해결하기 위한 과정을 적어보려 합니다.
순간이동 표현이 묘하지만; 슬라이딩 윈도우에서 이미지가 부드럽게 넘어가는 효과의 반의어로 순간이동이란 표현을 사용했습니다.
참고자료
- https://d2.naver.com/helloworld/59361 (Naver D2 브라우저는 어떻게 작동하는가)
- https://medium.com/@gneutzling/the-rendering-process-of-a-web-page-78e05a6749dc (The rendering process of a web page.)
- https://developers.google.com/web/tools/chrome-devtools/evaluate-performance?hl=ko (google performance tool 사용법)
상황
슬라이드가 1,2,3 이 있다고 할 때, 무한 슬라이딩 윈도우를 구현하기 위해 다음과 같이 프로세스를 세웠습니다.
- s1,s2,s3,s`1으로 설정 (이때 s`1은 s1을 복사하여 생성한 이미지입니다.)
- 애니메이션 효과 키기 (즉, 부드러운 이동 효과 ON)
- s3->s`1으로 이동 했을 때, s`1에서 애니메이션 효과 끄기 (이미지를 순간이동 시키기 위해)
- s`1에서 s1으로 이동 (순간이동!)
- s1에서 애니메이션 효과 키기
이와 같이 구성하려 했습니다.
허나 문제는 절차 3->4->5에서 발생했습니다.
문제
문제1.
-
아래의 [코드1]의 실행 부분을 1번째 실행 시 : 슬라이딩 효과가 미적용된 채 정상 작동합니다.
-
아래의 [코드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가지 관점에서 예상한 대로 움직이지 않은 원인을 알 수 있었습니다.
-
browser의 schedule
브라우져의 스케줄에 의해 Js가 먼저 모두 실행된 다음 rendering으로 넘어갔기 때문에 turnOff-shift-turnOn에서 부드러운 이동 효과가 적용된것입니다.
-
초기 위치 지정
이미지의 절대 위치를 지정해주지 않는 이상 브라우저는 이미지의 위치를 모릅니다. 따라서 이를 지정해주지 않았기 때문에 처음에 순간이동 하였고, 그 뒤엔 브라우저가 위치를 알고 있으므로 정상적으로 작동하였습니다.
...반성
명확히 알아서 불분명함을 극복하자!
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 |