트랜지션과 애니메이션을 다루면서 나는 요소를 옮기고 키우고 돌리는 변형을 계속 써왔다. 그런데 정작 그 변형 자체를 제대로 파고든 적은 없었다. 왜 위치 속성 대신 변형으로 옮기면 성능이 좋은지, 회전의 기준점을 어떻게 바꾸는지, 나아가 평면을 넘어 입체적으로 요소를 뒤집는 건 어떻게 하는지 궁금했다. 변형은 알수록 화면에 깊이를 더하는 강력한 도구였다.


이번 편은 요소를 변형하는 기능을 깊이 다룬다. 변형이 레이아웃과 어떤 관계인지, 이동과 확대와 회전과 기울임 같은 이차원 변형 함수들, 변형의 기준점을 옮기는 법, 그리고 평면을 넘어선 삼차원 변형까지 살펴본다. 마지막으로 변형이 조용히 일으키는 부작용도 짚는다. 변형을 손에 쥐면 화면에 움직임과 입체감을 자유롭게 불어넣을 수 있다.

1. 레이아웃을 건드리지 않는 변형

변형의 가장 중요한 성질은 요소의 실제 배치를 바꾸지 않는다는 것이다. 요소를 오른쪽으로 옮기거나 크게 키워도, 주변 요소들은 그 요소가 원래 있던 자리를 기준으로 배치를 유지한다. 나는 이 성질을 이해하고 나서, 변형이 왜 움직임에 그토록 적합한지 알게 되었다. 변형은 그려진 결과만 시각적으로 조정할 뿐, 문서의 구조는 그대로 두기 때문이다.


이 성질이 성능의 비결이기도 하다. 요소의 위치나 크기 속성을 직접 바꾸면 주변 배치를 다시 계산해야 하지만, 변형은 배치 계산을 유발하지 않는다. 이미 그려진 요소를 마지막 합성 단계에서 옮기거나 키우는 것에 가깝기 때문이다. 나는 애니메이션에서 위치 대신 변형을 쓰라고 배운 이유가 바로 여기에 있다는 걸 확실히 이해했다.


변형은 주변에 영향을 주지 않으므로, 다른 요소를 밀어내지 않고 겹쳐서 움직인다. 나는 요소를 살짝 확대하거나 이동시켜 강조할 때, 주변 배치가 흔들리지 않는다는 점이 특히 편하다. 위치 속성으로 같은 효과를 내려 하면 주변이 함께 밀려 화면이 출렁이는데, 변형은 그 요소만 깔끔하게 움직인다.


변형은 여러 함수를 한꺼번에 적용할 수 있다. 이동과 회전과 확대를 함께 걸면, 요소가 옮겨지면서 동시에 돌고 커진다. 다만 이때 함수를 적는 순서가 결과에 영향을 준다는 점을 알아야 한다. 나는 회전 후 이동과 이동 후 회전의 결과가 다르다는 걸 모르고 헤맨 적이 있다. 변형은 적힌 순서대로 차례로 적용되므로 순서가 곧 의미다.


변형된 요소는 시각적으로만 이동할 뿐, 문서 흐름상의 위치는 그대로다. 그래서 변형으로 옮긴 요소를 클릭하려면 원래 자리가 아니라 옮겨진 자리를 눌러야 한다. 나는 이 점을 잊고 변형으로 크게 옮긴 요소가 엉뚱한 반응을 하는 걸 겪었다. 겉모습과 실제 배치가 분리된다는 사실은 편리하면서도 가끔 혼란의 원인이 된다.


변형은 애니메이션 없이 정적인 상태에서도 유용하다. 요소를 살짝 회전시켜 기울인 배지를 만들거나, 미세하게 이동시켜 위치를 미세 조정할 때도 쓴다. 나는 배치 자체를 흔들지 않으면서 시각적인 위치만 다듬고 싶을 때 변형을 즐겨 쓴다. 레이아웃과 표현을 분리해 다룰 수 있다는 점이 변형의 근본적인 매력이다.

2. 이차원 변형의 함수들

평면에서 쓰는 변형 함수는 크게 네 가지다. 이동, 확대와 축소, 회전, 그리고 기울임이다. 이 네 가지를 조합하면 평면 위에서 표현할 수 있는 거의 모든 변형이 가능하다. 나는 이 함수들을 하나씩 익히며, 각각이 요소에 어떤 변화를 주는지 몸으로 감을 잡았다. 기본 함수들의 성격을 알면 조합의 결과를 예측할 수 있다.


이동 함수는 요소를 가로세로로 옮긴다. 위치 속성과 달리 배치 계산을 유발하지 않으므로, 애니메이션에서 요소를 옮길 때 가장 많이 쓴다. 나는 요소를 위로 살짝 띄우는 강조 효과나, 화면 밖에서 안으로 미끄러져 들어오는 효과에 이 함수를 쓴다. 옮기는 값을 상대 단위로 주면 요소 자기 크기에 비례해 이동하게 만들 수도 있다.


확대와 축소 함수는 요소의 크기를 배율로 조절한다. 값이 일보다 크면 커지고 작으면 줄어든다. 너비나 높이 속성을 바꾸는 것과 달리 배치를 흔들지 않으므로, 마우스를 올렸을 때 요소가 살짝 커지는 효과에 잘 어울린다. 나는 카드나 버튼에 마우스를 올리면 미세하게 확대되도록 해서, 반응하고 있다는 느낌을 준다. 작은 확대 하나로 요소가 살아난다.


회전 함수는 요소를 기준점을 중심으로 돌린다. 각도를 지정해 시계 방향이나 반시계 방향으로 회전시킬 수 있다. 나는 로딩 표시를 무한히 회전시키거나, 펼침 표시 화살표를 뒤집을 때 이 함수를 쓴다. 회전은 특히 상태를 시각적으로 표현하기 좋아서, 접힌 상태와 펼친 상태를 화살표의 회전으로 나타내는 데 자주 활용한다.


기울임 함수는 요소를 비스듬히 눕힌다. 다른 함수들에 비해 쓸 일이 적지만, 역동적인 배경 무늬나 특정한 디자인 효과를 낼 때 쓴다. 나는 기울임을 단독으로 쓰기보다, 다른 변형과 조합해 미묘한 원근감이나 개성을 줄 때 가끔 활용한다. 자주 쓰지는 않아도 표현의 선택지로 알아두면 필요할 때 요긴하다.


이 함수들은 값을 세밀하게 조절해 미묘한 효과부터 과감한 효과까지 낼 수 있다. 나는 대부분의 상호작용에는 아주 작은 값을 써서 은은하게 반응하도록 하고, 진입 효과처럼 존재감이 필요한 곳에만 큰 값을 쓴다. 같은 함수라도 값의 크기에 따라 느낌이 완전히 달라지므로, 상황에 맞는 절제된 값을 찾는 감각이 중요하다.

3. 기준점과 개별 변환 속성

변형에는 기준점이 있다. 요소를 회전시키거나 확대할 때, 그 변형이 어느 지점을 중심으로 일어나는지를 정하는 것이 기준점이다. 기본적으로는 요소의 한가운데가 기준이 되지만, 이 기준점을 다른 곳으로 옮길 수 있다. 나는 기준점을 조절하는 법을 알고 나서, 회전과 확대의 표현이 훨씬 다채로워졌다.


기준점을 바꾸면 같은 회전이라도 전혀 다른 움직임이 된다. 한가운데를 중심으로 도는 것과 한쪽 모서리를 중심으로 도는 것은 완전히 다르다. 나는 펼쳐지는 메뉴가 위쪽 모서리를 축으로 열리도록 기준점을 위로 옮긴다. 그러면 메뉴가 문이 열리듯 자연스럽게 펼쳐진다. 기준점 하나로 움직임의 성격이 결정되는 것이다.


확대에서도 기준점은 중요하다. 한가운데를 기준으로 커지면 사방으로 퍼지지만, 아래쪽을 기준으로 커지면 위로만 자란다. 나는 말풍선이나 툴팁이 특정 방향에서 솟아나는 효과를 만들 때 기준점을 그 방향에 맞춰 조절한다. 요소가 어디에서 비롯되는지를 기준점으로 표현하면 움직임에 논리가 생긴다.


변형을 개별 속성으로 나눠 쓸 수도 있다. 이동과 회전과 확대를 각각 별도의 속성으로 지정할 수 있게 된 것이다. 예전에는 이 셋을 하나의 변형 안에 몰아 적어야 해서, 그중 하나만 애니메이션하기가 까다로웠다. 나는 개별 속성이 생긴 뒤로, 회전은 그대로 두고 확대만 부드럽게 바꾸는 식의 세밀한 제어가 훨씬 쉬워졌다.


개별 변환 속성의 장점은 조합과 애니메이션이 독립적이라는 데 있다. 각 변형을 따로 다루니, 서로 다른 상호작용에 서로 다른 변형을 걸어도 충돌하지 않는다. 나는 마우스를 올리면 확대하고, 눌리면 이동하는 것처럼 여러 상태에 각기 다른 변형을 줄 때 개별 속성을 쓴다. 하나의 변형 안에서 값이 서로를 덮어쓰던 문제가 사라진다.


다만 하나의 변형에 몰아 적는 방식과 개별 속성을 섞어 쓸 때는 주의가 필요하다. 둘이 함께 적용될 때 어떤 순서로 처리되는지를 알아야 예상한 결과를 얻는다. 나는 되도록 한 요소에서는 한 방식으로 통일해서 혼란을 줄인다. 도구가 늘어난 만큼 규칙도 늘어나므로, 일관된 방식을 정해 두는 것이 안전하다.

4. 평면을 넘어선 삼차원

변형은 평면을 넘어 삼차원 공간으로 확장된다. 요소를 화면 앞뒤 축을 중심으로 돌려 실제로 뒤집거나, 가로축과 세로축을 중심으로 회전시켜 입체적으로 기울일 수 있다. 나는 처음 삼차원 변형을 접했을 때, 평면인 화면에서 깊이가 느껴지는 효과를 낼 수 있다는 사실에 흥미를 느꼈다. 카드를 뒤집는 효과가 대표적이다.


삼차원 변형에는 원근감이 필요하다. 원근을 설정하지 않으면 삼차원 회전이 밋밋하게 눌린 것처럼 보인다. 원근값은 보는 사람이 화면에서 얼마나 떨어져 있는지를 정하는데, 값이 작을수록 원근이 과장되어 극적으로 보이고 클수록 완만해진다. 나는 카드 뒤집기 같은 효과에 적당한 원근을 줘서, 입체감이 자연스럽게 살아나도록 조절한다.


가로축을 중심으로 회전하면 요소가 위아래로 넘어가고, 세로축을 중심으로 회전하면 좌우로 뒤집힌다. 나는 카드의 앞면과 뒷면을 만들고, 마우스를 올리면 세로축으로 반 바퀴 회전시켜 뒷면을 보여주는 효과를 만든다. 앞면이 돌아가며 사라지고 뒷면이 나타나는 이 움직임은 삼차원 회전이 아니면 표현할 수 없다.


여러 요소를 하나의 삼차원 공간에서 다루려면, 그 요소들이 입체 공간을 공유하도록 설정해야 한다. 이 설정이 없으면 자식 요소들이 각자 납작하게 평면으로 처리되어 입체감이 사라진다. 나는 카드 뒤집기에서 앞면과 뒷면이 같은 입체 공간에 놓이도록 부모에 이 설정을 준다. 그래야 두 면이 하나의 카드처럼 함께 돈다.


요소의 뒷면을 감출지 보일지도 정할 수 있다. 요소가 삼차원으로 뒤집혀 뒷면이 화면을 향할 때, 그 뒷면을 보이지 않게 하면 카드 뒤집기가 자연스러워진다. 나는 앞면이 뒤집혀 사라질 때 그 뒷면이 비쳐 보이지 않도록 이 설정을 쓴다. 이 세밀한 조정이 있어야 앞뒤가 깔끔하게 교체되는 완성도 높은 효과가 나온다.


삼차원 변형은 화려하지만 남용하면 어지럽고 산만하다. 나는 삼차원 효과를 정말 의미 있는 순간에만 아껴 쓴다. 카드의 양면을 보여주거나, 요소가 공간에서 회전하며 등장하는 것처럼 입체감이 정보 전달에 도움이 될 때만이다. 기술이 가능하다고 모든 곳에 쓰면, 오히려 사용자를 피로하게 만든다는 걸 경험으로 배웠다.

5. 변형이 남기는 부작용

변형은 편리하지만 조용한 부작용을 남긴다. 그중 하나는 변형이 걸린 요소가 새로운 쌓임 맥락을 만든다는 것이다. 이는 요소들이 앞뒤로 겹치는 순서에 영향을 주는데, 나는 변형을 걸었더니 갑자기 겹침 순서가 예상과 달라지는 걸 겪은 적이 있다. 변형이 단순히 겉모습만 바꾸는 게 아니라는 걸 그때 알았다.


더 흔하고 까다로운 부작용은 고정 위치 자식에 대한 것이다. 어떤 요소에 변형을 걸면, 그 안에 있는 화면 고정 요소가 화면이 아니라 변형된 조상을 기준으로 삼게 된다. 나는 화면에 고정해 둔 요소가 스크롤을 따라 엉뚱하게 움직이는 문제로 오래 고생했는데, 원인은 조상 어딘가에 걸린 변형이었다. 이건 정말 찾기 어려운 함정이다.


이 함정은 변형뿐 아니라 몇몇 다른 속성에서도 똑같이 일어난다. 그래서 화면 고정 요소가 이상하게 동작하면, 나는 가장 먼저 조상들 중에 변형이나 유사한 속성이 걸린 게 있는지 살핀다. 원인을 알고 나면 해결은 간단하지만, 모르면 며칠을 헤맬 수 있는 종류의 문제다. 부작용을 아는 것이 곧 디버깅 능력이다.


변형은 요소를 별도의 층으로 분리해 처리하게 만들기도 한다. 이는 애니메이션 성능에는 이롭지만, 남발하면 층이 너무 많아져 메모리를 낭비한다. 나는 성능을 위해 일부러 변형을 걸어 층을 분리하는 기법을 쓰기도 하지만, 꼭 필요한 곳에만 절제해서 적용한다. 최적화 기법도 지나치면 오히려 부담이 된다.


변형된 요소는 흐릿하게 보일 때가 있다. 특히 삼차원 변형이나 미세한 확대에서 요소의 가장자리나 글자가 살짝 번지는 현상이 생긴다. 나는 이런 흐릿함이 거슬릴 때 변형의 값을 조정하거나 다른 방식을 찾는다. 변형이 픽셀 단위의 정밀함을 항상 보장하지는 않는다는 점을 염두에 두면, 결과가 기대와 다를 때 당황하지 않는다.


정리하면 변형은 레이아웃을 건드리지 않고 요소의 겉모습만 이동, 확대, 회전, 기울임으로 바꾸며, 삼차원으로 확장해 입체감까지 표현한다. 다만 쌓임 맥락과 고정 위치 자식에 대한 부작용을 반드시 알고 써야 한다. 나는 이 부작용까지 이해한 뒤에야 변형을 온전히 다룰 수 있게 되었다. 다음 편에서는 이런 값들을 이름으로 관리해 재사용하는 CSS 변수를 다룬다.