ReactNative에서는 Animated라는 패키지를 제공하고 있다.
하지만 ReactNative에서 제공하는 Animated에는 단점이 있는데,
이는 ReactNative가 갖는 단점이 그대로 따라오고 있다.
Main Thread와 JS Thread의 통신을 해야한다는 점인데, 네이티브 영역과 JS 영역에 통신하기 위해서는 Bridge를 통해서 메세지를 전달받는 구조를 그대로 사용하고 있는데, 애니메이션의 경우에는 프레임 단위로 생각해야하기 때문에 JS가 많은 일을해서 병목현상이 생긴다면 애니메이션의 프레임드랍 현상은 피할수 없게될것이다.
react-native-reanimated는 위의 문제를 개선하고자 만들었는데, Thread간 메세지를 전달하지 않고 애니메이션과 관련된 로직은 모두 Main Thread에서 진행하도록 만든 것이다. 최초 실행되기전에 JS로직에서 실행이 필요한 것들은 worklet을 이용하여 JS Thread로 전달한다.
이렇게 애니메이션 관련된 작업은 Main Thread에서 하다보니까 JS Thread에서 부하가 생기더라도 애니메이션은 그대로 동작할 수 있게 된다.
worklet은 react-native-reanimated V2부터 생긴 개념이다. 간단하게 말하면 작은단위의 JS로직이라고 생각할 수 있다. worklet을 만들때 가장큰 목표는 View속성을 업데이트 하거나 Main Thread에서 이벤트에 반응할 때 만들어진 작은단위의 JS를 실행할 수 있도록 만드는 것이었다. worklet은 JS와 완전히 독립된 곳에서 동작하게 되어있는데 worklet은 JS로부터 파라미터를 받을수도있고 혹은 상태업데이트를 하기 위해서 JS Thread에 있는 상수들에게도 동일하게 접근 할 수 있다.
worklet을 사용하기위해서는 함수 맨 첫줄에 "worklet"을 적어주기만 하면 된다
const funcA = () => {
"worklet"
/* ..etc logic */
}
위와 같이 worklet을 붙이면 별도의 컴파일 과정을 거치게 된다. 이 컴파일 과정을 거친후에돋 Main Thread에서 실행이 되게 된다. 이때 만약에 함수 밖의 값을 참조한다고 하더라도 해당값을 복사하여 Main Thread로 가져가게 된다.
이름에서 알 수 있듯이 어딘가와 공유하는 값이란걸 알 수 있다. 이 값은 JS Thread와 Main Thread 두 곳에서 모두 쓸수도있고, 읽기도 가능한 변경가능한값이다. 양쪽 Thread에서 모두 접근할 수 있지만 이 값의 Read는 대부분 Main Thread에서 일어나다보니 읽어오는 작업이 Main Thread에 맞게 최적화 되어있다.
worklet 함수에서 어떤 값이 변경되게 된다면 해당함수 호출과 동시에 Main Thread에 있는 값이 먼저 변경되면서 제일 먼저 해당값이 변경되었는지 인지를 할 수 있다.
const scrollOffset = useSharedValue(0)
const scrollHandler = useAnimatedScrollHandler({
onScroll:(event) => {
scrollOffset.value = evnet.contentOffset.y
}
})
// 스크롤시 어디까지 스크롤되어있는지 알아볼 수 있다.
react-native-reanimated를 설치하기 위해 npm package에 추가를 해줘야하고, babel plugin을 설정해주어야 한다.