요즘 부쩍 크로스 플랫폼을 사용하는 회사들이 많아졌다. 심지어 Native에서 크로스 플랫폼으로 전환하는 회사도 꽤 보인다. Android 개발만 해온 나는 크로스 플랫폼이 뭐가 좋은지 이유를 찾기 위해 RN으로 앱 하나를 만들었다.
뭘 만들까 고민하다 앱스토어를 보니 생산성 있는 어플이 꽤 순위가 높았다. 그 중에서도 공부 타이머 어플들이 많았는데, 마침 룸메가 AI 공부를 한 적이 있다. '머신러닝 모델을 통해서 사용자를 감지하고 실질적인 공부 시간을 측정해주는 기능을 만들자' 라는 이야기가 나와 시작하게 되었다.
이렇게 탄생한 바른공부는 카메라 촬영과 머신러닝 모델을 통해 공부 시간을 측정한다.
(스토어 출시 예정이니 많은 관심 부탁드립니다 🙇)
나는 가만히 앉아서 문법 공부만 주구장창 하는 걸 별로 좋아하지 않는다. 그래서 React Native 개발을 시작하기 전에 정말 간단하게 JS 문법, 동작원리만 훑어보고 개발을 시작했다.
(개인적으로 React Native를 시작하고 싶다면 어느정도 언어 공부를 하고 개발하기를 추천한다. 프론트엔드 개발자라면 상관 없겠지만, 이쪽에 무지한 나는 꽤 시행착오가 많았다. 🥲)
프로젝트 만들기도 쉽지 않다. Expo cli랑 rn cli 중에 하나를 또 고르란다.
더 자세한 설명이 필요없다. 초보인 나는 무조건 Expo를 선택했다. (Expo 선택한 내 자신이 너무 밉다)
Expo cli로 개발해서 그런 건지는 몰라도 충격먹었다. 진짜 별의별 거 다 라이브러리로 추가해서 써야한다. StatusBar, SVG, 날짜 포맷 등등. 이 때문에 체감상 공수가 두 배는 더 드는 것 같다.
말은 크로스 플랫폼이라고 하지만, 막상 개발하면 iOS, Android 따로 논다. 아래는 개발하면서 겪었던 문제들이다.
앱 기능이 그렇게 많지 않아 플랫폼 간 이슈는 이정도 밖에 없었지만, 찾아보면 끝도 없이 나올 것 같다.
대부분 개발하다보면 에러로그를 통해서 어디가 문제인지, 무엇이 문제인지 알 수 있다. 근데 Expo 이녀석은 에러로그는 장식이다. 어디가 문제인지 잘 알려주지도 않고, 뭐가 문제인지 잘 알려주지도 않는다. 그냥 이상하게 만들었다고 뻗기만 하는 용도다. 덕분에 삽질이 늘었다.
솔직히 용량 크고, 빌드 시간 오래 걸리는 등 단점은 많지만 넘어가자
그나마 쉬운 프로젝트 세팅..? (이거 말곤 없다)
혹시나 Expo를 개발하는 사람들을 위해 도움이 되고자 겪은 이슈 몇 가지를 정리했다.
useEffect로 setState 함수를 호출 -> useEffect 호출 -> setState 함수 호출 -> useEffect 호출 ...
위와 같이 useEffect 내부에 setState 함수 때문에 무한루프에 빠져버리는 이슈가 발생했다.
useEffect(() => {
setState(value)
...
}, [])
위에서도 언급한 적이 있지만, SVG 사용을 위해 Transformaer 라이브러리를 사용하게 된다. 하지만 무작정 라이브러리를 추가하게 되면 iOS는 정상적으로 SVG 파일이 표시되지만, Android에서는 에러가 발생한다.
'13.4.0' 버전 까지만 Android에서 정상적으로 동작한다. 라이브러리 제거 후 '13.4.0' 버전으로 추가하면 해결된다.
컴포넌트별로 StatusBar 색상을 변경하기 위해서는 별도의 Hook이 필요하다. (각 컴포넌트에서 StatusBar를 호출해서 속성으로 변경하는 것은 동작하지 않음)
import { StatusBar } from "react-native";
import { useFocusEffect } from "@react-navigation/native";
//custom hook
export const useStatusBar = (style) => {
useFocusEffect(() => {
StatusBar.setBarStyle(style, true);
});
};
// 컴포넌트에서 사용 시
...
useStatusBar("light-content");
useStatusBar("dark-content");
타이머 종료시 공부한 내용을 Local DB에 저장하고 메인페이지에 바로 반영해야하는 경우가 생겼다. 이를 해결하기 위해 다양한 선택지가 있었지만 가장 간단하게 해결할 수 있는 방법을 사용했다.
useEffect(() => {
db.transaction((tx) => {
tx.executeSql(query);
});
}, []);
const isFocused = useIsFocused();
useEffect(() => {
if (isFocused) {
db.transaction((tx) => {
tx.executeSql(
query
);
});
}
}, [isFocused]);
useIsFucused()으로 화면 전환시 포커싱 여부를 판단하고, 화면 포커싱이 될 때 DB에 접근하여 최신 데이터를 가져오는 방법이다.
Expo는 여기까지👋
Expo를 사용하면서 크로스 플랫폼이 가지는 이점인 빠른 개발속도를 경험할 수 있어서 좋았다. 하지만 처음으로 돌아가 Expo cli와 RN cli를 고르라면 나는 무조건 RN cli를 고를 것이다. Expo 안에서 개발하는데 제약 사항이 너무나도 많았으며, Expo가 가진 장점이 단점을 커버치지 못 하기 때문이다. 과거 Expo eject를 통해 Native 모듈을 사용하기도 했으나, Expo 핵심 철학이 '절대 Native layer까지 내려가지 않는다.' 이기 때문에 권장하지 않는 방법이었다.
최근에는 eject deprecated 되었고, Expo Prebuild를 통해 네이티브 코드를 생성할 수 있게 되었다. Expo가 지속적인 업데이트를 통해 개선시키고 발전시키고 있긴 하지만, 이 글을 읽는 사람이나 React Native를 시작하려는 사람이 있다면 Expo 사용을 적극적으로 말리고 싶다. 프로젝트 세팅 때문에 Expo를 선택한다면 영영 React Native 개발을 접을 수도 있다. 그러니 React Native CLI를 통해 개발하길 추천한다.
글 잘 봤습니다! 디자인은 직접 하시는 건가요?? 저는 디자인이 너무 어려워서 고민이네요...