카카오 웹툰, 안드로이드에서만 제공하는 인터렉션은 무엇일까?
웹툰 플랫폼 중 단연 가장 이쁘다고 할 수 있는 <카카오웹툰>
이번 포스트에서는 해당 앱 속 인터렉션에 대해 작성하려한다.
개발할 내용은 웹툰 뷰어 내부에서 해당 웹툰의 목록을 볼 수 있게 해주는 기능이다.
위와 같이 동작하는 기능인데 처음 접했을 때 와우했던 포인트 중 하나이다.
디자인 대격변을 하면서 다른 디자인들은 과하다. 라고 생각할 수 있지만 이 기능은 디자인뿐만 아니라 사용성 또한 높다.
(UX를 배운적은 없어 옳은 UX 방향인지는 모르겠다. 다만, 고객의 입장에서 사용했을 때 충분히 만족했다.)
하지만, 이 인터렉션은 독특하게도 Android에서만 제공하는 기능이다.
어떠한 사유인지는 모르겠으나 Web과 iOS에서는 개발을 하지 않은 부분인데 플랫폼별 기획이 달랐던 것인지, A/B테스트를 하는 중인지, 어떤 의도로 다른 경험을 제공하는지는 의문이다.
Web에서는 웹툰 뷰어가 좌우로 펼쳐지지 않고, 위에 오버레이 효과가 나타난다.
< 카카오웹툰 > 아비무쌍 188화 中
<네이버웹툰 > 초인의시대 2부 10화 中
애니메이션과 함께 보면 정말 좋은 인터렉션인 것 같은데,
뒤에 있는 웹툰 속 캐릭터가 절반으로 나뉘어 살짝 거부감이 있을 수 있어보인다. 원작을 해치는 느낌 또한 받을 수 있기 때문에 안드로이드서만 적용했나 싶기도 하다.
아무튼 Android에서만 제공하는 이 인터렉션을 모든 플랫폼에서 느낄 수 있게 Flutter로 개발해보려한다.
클라이언트 개발자라면 읽기전에 어떻게 만들지 한 번쯤 생각해보는 것도 좋을 것 같다.
사실 이번 인터렉션 개발의 난이도가 상당히 높아보인다.
"위젯이 좌우로 분할된다니...기존에 개발하던 방식처럼 위젯들만 이용해서는 개발하기 힘들어보이는데? 도대체 어떻게 하는거지?"
라는 의문이 들 수 있다.
하지만, 말로만 표현한다면 굉장히 쉬워질 수 있다.
여기서 할 수 있는 것들을 제외하고 생각해보자.
이벤트를 발생시키는 트리거(카카오웹툰에서는 버튼)는 어려울 게 없다. GesutureDetector, InkWell, Button, ... 등 이벤트 감지 위젯을 사용하면 된다.
화면의 가운데를 찾는 것도 어렵지 않다. MediaQuery 에서 화면에 대한 정보를 가져올 수 있으니..
왼쪽/오른쪽으로 움직이는 애니메이션도 AnimatedBuilder를 이용하면 된다.
웹툰 목록도 Fade효과를 부여하면된다..
다 쉬워보이는데 그렇지 않은게 하나 있다...
처음 보고 할 수 있을까? 라고 생각되던 것은!!
위젯을 반으로 나누는 것이다.
어떻게 해야 화면에 이미 그려진 위젯을 반으로 나눌 수 있을까?
화면에 있는 것을 그려본 사람은 많아도, 나눠볼 생각을 한 사람은 적을 것 같다.
나 또한, 이 앱을 보기 전까지는 그러했다.
아무튼 이번 인터렉션은 위젯을 반으로 나누기만하면 끝난다.
첫 번째 생각은
두 번째 생각은
첫 번째 방법과 두 번째 방법의 장단이 있을 것 같다.
결과적으로는 두 가지 방법으로 구현을 해보았는데,
첫 번째 아이디어는 구현하기는 훨씬 간단하지만, 스크롤의 미세한 이슈가 있었다.
두 번째 아이디어는 구현 난이도가 높았지만, 좀 더 완성도가 높은 모습을 보였다.
각각의 방법을 좀 더 자세히 설명하자면, 다음과 같다.
<네이버웹툰 > 초인의시대 2부 10화 中
먼저 ClipPath
위젯을 사용하여 기준이 되는 위젯을 절반으로 나눈다. clipper는 화면의 절반을 자르기 위해 Rect를 사용하였다.
getClip(Size size) {
Path path = Path()..addRect(Rect.fromLTRB(0, 0, size.width / 2, size.height));
return path;
}
Path
이렇게 두 번 반복하면 하나의 위젯(이미지)처럼 보이게 된다.
<네이버웹툰 > 초인의시대 2부 10화 中
이 방법은 두 개의 위젯을 절반씩 보여줘 하나의 위젯처럼 보이게 하는 방식이다.
하지만 스크롤 컨트롤러를 동기화 해주지 않으면 양쪽이 각각 따로 노는 문제가 발생한다...
<네이버웹툰 > 초인의시대 2부 10화 中
ScrollController
를 동기화 해주자!
단일 스크롤 컨트롤러를 사용해도 되고, 2개의 스크롤컨트롤러를 사용해도 된다.
leftSC.addListener((){
rightSC.moveTo(leftSC.offest);
});
스크롤까지 동기화하였다면 이제 쉬운 일들만 남았다.
AnimatedBuilder(
animation: _animationController,
builder: (context, child) {
return Transform.translate(
offset: Offset(-gap * _animationController.value, 0),
child: child,
);
},
child: ClipPath(
clipper: const CustomClipper(),
child: MyWebToonViewer(),
),
),
애니메이션을 만들어주고,... fade 효과를 적용하면 된다.
<네이버웹툰 > 초인의시대 2부 10화 中
첫 번째 방법은 화면에 렌더링할 대상이 이미지였기에 이런 방식으로 가능했다.
또한 웹툰의 확대, 축소 기능을 넣을거면 부적합하다.
빠르게 개발을 하기 위해서는 위의 첫 번째 방법 혹은 본인이 생각한 쉬운 방법으로 진행하면 될 것 같다.
...
하나의 위젯을 둘로 나누는 방법을 사용하기 위해서는 RenderRepaintBoundary
을 사용하여 화면에 렌더링 되어있는 것을 이미지로 바꾸고, 해당 이미지를 x좌표의 중점을 기준으로 절반을 나누어 다시 위젯으로 변경하면 된다.
...
이번 포스트에서는 카카오웹툰에 사용된 인터렉션 중 일부를 구현해보았다.
하나의 개발을 할 때, 여러가지의 방법을 생각하는 과정에서 얻는 재미가 상당하다.
좀 더 나은 방법을 모색하고, 현재 상황에서 좋은 결과를 내기 위해 노력하는 과정에서 오는..
나는 두 가지 정도의 방식을 생각했는데, 과연 Android 카카오웹툰에서는 어떤 방식을 사용해서 구현했을지 궁금하다.
아래는 두 번째 방법으로 만든 결과이다.
애니메이션은
Duration
과Curve
,Interval
을 조절하여 좀 더 자연스럽고 부드럽게 할 수 있다.
<네이버웹툰 > 초인의시대 2부 10화 中
좀 더 궁금하시다면, 댓글을 남겨주세요.
안녕하세요..! 게시물 잘 보고있습니다. Flutter로 개발을 해오면서 UI는 자신 있다고 생각했건만.. 갈 길이 멀었다는 걸 씨게 느끼네요.. 굉장합니다..! 궁금한거 있을 때 여쭤봐도 될까요!?
안녕하세요! 주니어 개발자 입니다! 여러가지 애니메이션 관련 글들 잘 보고 있습니다 :) 다름이 아니라 해당 글의 인터렉션을 따라해보면서 화면을 이미지로 만들고, 애니메이션을 주는 것 까진 구현했는데, 혹시 몇 가지 키워드를 조금 더 알려주실 수 있는지 해서 여쭤봅니다! 현재 변수를 하나 두고, 처음 리스트뷰에서 버튼을 누르면 false->true로 변수를 바꾸면서 이미지로 전환하고, 애니메이션 되게 구현했습니다. 예시 동작 화면처럼 조금 더 부드럽게 처리하고 싶은데, 혹시 찾아 볼만한 키워드를 주시면 감사하겠습니다! (인스타 좋아요 인터렉션도 꽤 어렵게 따라했는데 이건 더하네요 ㅎㅎ...)
오 flutter 관련 글 읽다가 여기까지 왔는데요 내용이 알차네요ㅎ 좋은글 감사합니다. ^^
추가적으로 보통 이런 인터렉션 구현 솔루션 기획이랑 구현까지 어느 정도 시간이 걸리는지 궁금합니다^^
안녕하세요! 플러터 주니어 개발자입니다~! 항상 LOCKED님 게시물들 보면서 감탄과 함께 열심히 공부중에 있습니다. 흥미롭고 유익한 게시물들을 올려주셔서 감사합니다! 공부하고난 이후에 해당 게시물들 관련해서 개인 블로그나 개인 프로젝트에 적용해도 될까요? 출처는 당연히 남겨 놓겠습니다!