1. 문제
리엑트에서는 state를 이용해서 컴포넌트를 렌더링하거나 없애는 경우가 흔하다. 이 과정에 컴포넌트의 생성과 제거 애니메이션을 넣어주면 유저와의 상호작용이 더 매끄럽게 이뤄진다. 이는 framer-motion 같은 라이브러리를 이용하면 쉽게 해결되지만, 문제는 아래처럼 "주변의 다른 컴포넌트들이 레이아웃에 영향을 받는 경우"다.
이런 경우, 주변 컴포넌트는 매끄럽지 않게 레이아웃이 변경된다. 이런 문제는 어떻게 해결할 수 있을까.
아래처럼 3가지 방법이 있다.
2. height animation
제일 처음 문제 삼은 예시는 animation으로 transform: scaleY()를 조작했다. 따라서, 컴포넌트 마운트 시, 요소의 정상적인 height만큼 레이아웃이 즉시 변하고, scale에 따라 컴포넌트가 서서히 렌더링되었다. 이 문제는 height를 animation의 대상으로 삼으면 쉽게 해결된다.
문제는 이런 방식이 성능 저하를 일으킬 수 있다. 기본적으로 애니메이션을 넣을 때는 애니메이션 대상 이외 요소들의 레이아웃을 건드리지 않는 게 좋다. 이를 레이아웃을 건드렸을 때 이를 재계산하는 과정을 "리플로우"라고 하는데, transform은 리플로우를 발생시키지 않아서 연산 비용이 작은 반면, 실제 레이아웃을 바꾸는 height는 리플로우를 발생시켜 큰 연산비용이 발생한다. 전체 레이아웃이 크게 바뀐다면 상황은 더 악화된다.
3. position
두 번째 방법은 애니메이션 대상 컴포넌트에 position을 설정하는 것이다. position은 대상을 전체 레이아웃에서 독립된 요소로 배치한다. 따라서, 컴포넌트가 새로 생성되어도 전체 레이아웃에 영향을 끼치지 않고, 그 위에 배치된다. 이 방식은 일반적으로 가장 많이 사용되고 특히 모달창을 띄울 때 아주 유용하고 쉽다.
하지만 모달창을 띄울 경우가 아니라면 이 방법을 쓸 수가 없다. 전체 레이아웃에서 벗어나기 때문에, 반응형 페이지에서는 위치를 계산하기도 어렵다.
4. pseudo element: before
세 번째 방법은 약간의 트릭을 이용한다. 먼저 state로 컨트롤할 박스를 감싸준다. 이를 wrap box라고 할 때, wrap box에 의사 요소로 ::before을 설정하고 크기는 animate box와 동일하게, 그리고 background-color: transparent로 설정한다. 마지막으로 animate box는 position:absolute; top:0로 설정해준다. 이러면, 컴포넌트가 존재하든지 없든지 상관없이 항상 해당 자리가 레이아웃에 마련되어 있다.
이 방법은 요소를 전체 레이아웃 내에 배치하면서도 2번 방법처럼 다른 요소에게 영향을 주지 않는다. 다만, 요소가 없을 때에도 해당 자리를 비워놔야 해서 공간이 낭비된다.
'react' 카테고리의 다른 글
[React] 컴포넌트 외부에 변수 선언과 컴포넌트 내부에 변수 선언 간 차이 (0) | 2024.03.04 |
---|---|
[React] pagination: 무한 스크롤 구현하기(+SWR 라이브러리) (0) | 2024.02.19 |
[React] url에 특정한 쿼리스트링을 강제로 추가하기 (0) | 2024.02.18 |
[React] pagination 컴포넌트 만들기(라이브러리x) (0) | 2024.01.09 |
framer-motion 라이브러리, path-spacing, path-offset 기능은 뭘까(추측) (0) | 2023.10.27 |