프레이머X 야매 코딩: if, else

“if, else”, what else?

Junhyuk Jang
hyuk
11 min readDec 11, 2018

--

애초에 여러 편을 올릴 생각은 아니었는데, 어찌하다보니 벌써 이렇게 세 편째 글을 쓰고 있다. 그래도 쓰다보니 어지러웠던 부분들이 조금은 정리되는 느낌이다. 얼마나 더 쓰게 될 지는 나도 모르겠다. 쉿. 🤫

필요 충분 조건 같은 녀석

간단한 플로우를 보여주는 경우라면 문제가 없겠지만, 마이크로 인터랙션의 경우는 조금 복잡해질 수 있다. 대표적인 경우가 콘텐츠 스크롤이다. 처음에는 UI가 함께 표시되다가 스크롤 하는 순간 사라지고, 다시 역방향으로 스크롤하면 나타나는 인터랙션을 자주 보게 된다.

이럴 때 흔히 조건문을 사용한다. 플래시에서는 gotoAndStop만 알면 된다는 말을 들은 적이 있는데, 프레이머에서도 마찬가지로 if, else만 알면 많은 문제가 해결되던 경험이 있다. 그 정도로 조건문은 인터랙션을 구현하는 데 있어서 필요 충분 조건 같은 녀석이었다.

프레이머X에서도 잘 써먹을 수 있을까? 다음웹툰앱의 목록 탐색 인터랙션을 만들면서 한 번 확인해보자.

스크롤 컴포넌트를 배치하고, 링크를 연결하여 콘텐츠를 채워준다. 그런 다음 프리뷰를 확인해보면 일단 스크롤은 간단히 구현된다.

다음웹툰앱을 사용해 보면 알겠지만 실제 인터랙션은 상당히 정교하고 복잡하므로, 나머지 동작들을 단위 인터랙션으로 쪼개보는 것이 필수적이다.

스크롤 하는 경우

1. 좌측 상단 타이틀이 올라가며 사라진다

2. 상단 이미지가 올라가며 점차 사라진다.

3. 탭 메뉴가 올라간다.

4. 좌측 요일 메뉴가 올라간다.

스크롤 하다가 일정 높이를 넘어간 경우

1. 좌측 상단 타이틀이 보이지 않는다.

2. 상단 이미지가 보이지 않는다.

3. 탭 메뉴가 고정된다.

4. 좌측 요일 메뉴가 고정된다.

목록의 처음 위치에서 아래로 당기는 경우

1. 좌측 상단 아이콘이 회전하며 모양이 변한다.

2. 좌측 상단 타이틀이 내려가며 사라진다.

3. 좌측 상단에 refresh 텍스트가 나타난다.

4. 상단 이미지가 내려간다.

아래로 당기다가 일정 높이를 넘어간 경우

1. 좌측 상단 아이콘의 회전과 모양이 변경된 상태로 고정된다.

2. 좌측 상단 타이틀이 보이지 않는다.

3. 좌측 상단에 refresh 텍스트가 고정되고, 색상이 변한다.

4. 상단 이미지가 계속 내려간다.

위에서 정리한대로 이 단위 인터랙션들은 특정 스크롤값을 기준으로 일정 범위 마다 동작이 달라지고 있다. 달라지는 범위는 처음부터 위로 일정 높이까지, 위로 일정 높이 초과, 처음부터 아래로 일정 높이까지, 아래로 일정 높이 초과, 이렇게 네 덩어리로 나눌 수 있다.

구현해야 할 요소들이 상당히 많아 보이지만, 하나씩 차근차근 생각해보면 된다. 결국 모든 건 if, else니까. 🤓

리액트에서 조건문 사용하기

하지만 혹시 또 무언가 굉장히 어렵고 복잡한 문법을 사용해야 하는 게 아닐까 하는 생각에 선뜻 시작하기는 어려웠다. 리액트도 어려운데 거기에다 조건문까지 써야 한다니.

구글신께 도움을 청했더니, 3가지 방법을 찾을 수 있었다.

  • {조건 && 결과} _ 조건이 참인 경우에 결과를 반환하고, 거짓인 경우에는 무시한다.
  • {조건 ? 결과A : 결과B} _ 조건이 참인 경우에 결과A를 반환하고, 거짓인 경우에 결과 B를 반환한다.
  • {if (조건A) {결과A} else if (조건B) {결과B} else {결과C)} _ 조건A를 만족하는 경우에 결과A를 반환하고, 조건B를 만족하는 경우에는 결과B를 반환하며, 나머지 모든 경우에 결과C를 반환한다.

우리가 만들 인터랙션은 여러 개의 조건이 필요하므로 마지막 방법을 사용하기로 한다. 괄호가 많아서 복잡해 보일 수 있지만, 괄호만 제외하면 결국 프레이머 클래식에서 사용하던 if, else와 똑같다. 안도의 한숨을 한 번 내쉬고, 이제 코드를 작성해 보자.

스크롤 하는 경우

우선 스크롤 하는 경우에 변하는 상태값과 관련하여 data 안에 초기값을 나열해 본다. 이미지, 타이틀, 탭 메뉴, 요일 메뉴에 대한 값이다.

초기값을 모두 입력했으면 이제 스크롤 값에 따른 상태값 변화를 계산한다. 이를 위해 스크롤 값을 확인하는 코드를 추가해야 한다. 프레이머 클래식에서는 print scrollY로 간단히 해결할 수 있었을텐데, 이번엔 조금 다르다.

여기서 또 새로운 것이 나타났다. let과 console.log는 무슨 뜻일까?

let과 const

위 코드 19행의 ‘let’은 15행의 ‘const’와 함께 ‘A = 무엇’ 이라고 선언할 때 사용한다.

  • let _ 유동적인 값일 때 사용한다.
  • const _ 한 번 선언한 이후, 고정적인 값일 때 사용한다.

위의 코드에서 y는 스크롤 컴포넌트의 움직임(이벤트)에 대한 y값이다. 이 값은 이벤트가 진행되는 동안 계속해서 변하는 값이므로 let을 사용한다.

print와 console.log()

프레이머 클래식에서는 ‘print 무엇무엇’으로 프리뷰 상에서 곧바로 값들을 확인할 수 있었지만, 일반적으로 값을 확인할 때에는 console.log(무엇무엇)을 사용한다. console.log는 브라우저나 에디터의 콘솔창에서 확인하게 되는데, 프레이머X에서는 프리뷰에서 콘솔을 확인할 수 있도록 편의를 제공하고 있다. (단축키 ⌘ i)

스크롤 값을 확인해 가면서 상태값이 변하는 범위를 찾아보자. 일정 범위를 넘어갔을 때의 상태값 고정 상태를 옆에 미리 만들어 놓고 비교해 보면 조금 더 수월하게 기준값을 찾을 수 있을 것이다.

확인한 기준값을 토대로 이제 드디어 조건문을 작성할 차례다. 괄호가 조금 더 많을 뿐, 프레이머 클래식에서의 조건문과 크게 다르지 않다. 오히려 고민해야 할 것은 스크롤과 연동하여 변경되는 상태값 계산이다.

스크롤에 따라 변하는 상태값 계산하기

프레이머 클래식에서 Utils.modulate()로 쉽게 만들 수 있었던 효과를 일일이 계산해 주려니 조금 복잡하기는 하다.

만약 이미지의 top(y값)이 초기 44였다가, -300만큼 스크롤 했을 때 -52가 된다면, 이런 식으로 계산할 수 있다. 스크롤에 따른 변수가 처음에는 0이었다가, 기준값인 -300일 때 1이 되도록 수식을 만드는 것이다.

  • 이미지 top = 초기값 44 - (스크롤 절대값 / 300) * (변경된 이후 고정값 -52 - 초기값 44)

이것을 다시 코드로 옮겨 보면 이렇게 된다. bgTop은 data에 초기값 입력 시 추가한 이름이고, Math.abs(y)에서 y는 아까 let y = Math.round(event.y)로 선언했던 그 y다.

  • data.bgTop = 44 - (Math.abs(y) / 300) * (-52 - 44)

약간 어렵게 느껴질 수 있지만, 이해하기에 앞서 일단 따라하고 잠시 멍때려 보자. 당장 이것을 이해한다고 부귀영화가 따라올 리 없고, 모른다고 패가망신 할 것도 아니니, 조급해 하지 말자. 🤗

조건문을 완성했으니 이제 각 요소별로 상태값을 매칭한다. 인터랙션이 복잡해서 매칭해야 할 요소들도 많다. 하나씩 차근차근 적어 보자.

많기도 하다. 하지만 이제 절반 정도 온 셈이다. 코드를 저장하고 돌아와서 상태값을 변경할 요소들에 Code Override를 하나씩 선택한다. 코드에서 추가한 이름들을 모두 선택하고 나서 프리뷰를 확인해 보면, 스크롤에 따라 각 요소들의 상태값이 변하다가 일정 높이에서 고정되는 것을 확인할 수 있다.

만약 예상했던대로 동작하지 않는다면, 상태값이 변경되는 레이어의 오토 레이아웃 설정이 원인인 경우도 있으니 한 번 살펴보는 것을 권장한다. 가끔 이 설정 때문에 위치나 크기 등이 어긋나기도 한다.

아래로 당기는 경우

목록의 처음에서 아래로 당겨 리프레시 하는 경우에도 스크롤 하는 경우와 마찬가지로 하나씩 차근차근 풀어나가면 된다. 여기서 가장 중요한 것은 아무래도 드라마틱하게 변하는 상단 아이콘 애니메이션 일 것이다. 일단 아이콘의 구조와 애니메이션을 살펴보도록 하자.

중간 과정을 보면 N 자의 가운데 획이 두 개로 갈라지면서 마름모의 두 변이 되는 것을 알 수 있다. 동작을 구분하자면 이렇다.

1. 아이콘이 45도 각도로 회전함

2. 아이콘의 세로 길이(높이)가 가로 길이(너비) 만큼 짧아짐

3. 가운데 획을 이루는 두 레이어가 -90도 각도로 회전함

4. 가운데 획을 이루는 두 레이어의 세로 길이(높이)가 나머지 획만큼 짧아짐

5. 가운데 획을 이루는 두 레이어의 가로 길이(너비)가 나머지 획만큼 두꺼워짐

이렇게 아이콘을 이루고 있는 각 레이어들의 초기 상태값을 data 안에 추가하고, 아래로 당길 때 변경되는 나머지 요소들의 초기값도 적어준다. 아이콘 이외에 추가해야 할 것은 리프레시 텍스트 관련 초기값들 뿐이지만, 애니메이션이 복잡한 관계로 data에는 비교적 많은 값들이 추가된다.

초기값을 모두 입력한 다음, 아래로 당기는 경우에 대한 조건을 추가한다. 스크롤의 경우와 마찬가지로 리프레시 효과의 마지막 상태를 옆에 미리 만들어 놓고 비교해 가면서 조건문을 완성한다.

미리 만들어 둔 프레임에서 수식에 넣을 변경될 상태값을 확인할 수 있다. 로딩 아이콘의 레이어를 하나씩 선택해 가면서 값을 참고해 보자.

드디어 모든 조건이 추가되었다. 이제 변경될 상태값들을 각 요소별로 매칭한다. 복잡한 아이콘 애니메이션 때문에 매칭해야 할 것들이 조금 많지만, 심호흡 한 번 하고 하나씩 순서대로 적어보자.

주석을 포함하여 대략 200줄 정도의 코드를 작성했다. 의도하지 않았지만 이렇게 깔끔하게 숫자가 떨어질 때 괜히 기분이 좋다. 😋

이 좋은 기분을 잘 유지하며 코드를 저장한 다음, 요소별로 Code Override를 선택한다. 특히 아이콘의 각 레이어에 Code Override를 선택할 때에는 더욱 신경 쓰도록 한다. 잘못 선택할 경우에는 매우 자유분방한 애니메이션이 눈 앞에 펼쳐지게 된다.

마지막으로 프리뷰를 확인해 보면 리프레시 애니메이션까지 적용된 것을 볼 수 있다. 이번에는 특히 아래 링크의 프레이머 파일을 열어서 코드를 직접 확인해 보는 것이 이해와 학습에 도움이 될 것이다.

https://github.com/jangjunhyuk/framerx/tree/master/ifElse

*프레이머 X 버전 업데이트 이후 프레이머 라이브러리 버전 호환 문제로 인해 정상적으로 작동하지 않는 이슈가 있습니다. 이 경우, File > Update Framer Library 혹은 Framer Library Version > Built-in 을 선택하시면 해결됩니다 :)

조건문에 대해서 간단히 설명한다는 계획이었는데, 괜히 복잡한 애니메이션을 만드느라 더욱 어렵게 느껴졌을지도 모르겠다. 이런저런 부연 설명이 길어졌지만, 결국 프레이머X에서 사용하게 될 조건문도 프레이머 클래식에서의 if/else와 다르지 않다는 점을 강조하고 싶다.

이렇게 이벤트에 조건문을 추가하고 수식과 애니메이션을 조합하면, 재미있는 것들을 많이 만들어 볼 수 있다. docs에서 이벤트나 애니메이션 관련 내용을 조금 더 설명해 준다면 지금보다 훨씬 자유롭게 활용할 수 있을텐데. 당분간은 구글신께 의지해야 할 것 같다.

많은 사용자들이 바라는대로 프레이머 팀에서도 무언가 열심히 준비하고 있으리라 기대해 본다. 제발. 🙏

--

--