원래는 react-native cli를 통해 개발해보려고했는데
사내에서 expo를 이용하고 계신 개발자분의 말씀을 들어보니
1,2년전만해도 expo는 네이티브 기능에 제약사항이 있어서 eject 하는 경우가 많았지만
최근에는 많이 개선되어서 expo를 사용하는 것을 더 추천하시더라구요
그래서 저도 expo로 갈아타보았읍니다.
초기 세팅이 조금 혼란해서 좀 헤맸지만 헤맨김에 정리를 좀 해볼게요
내용은 위 expo 문서에서 참고하였습니다.
시간이 지남에 따라 아래 포스트는 outdated 될 확률이 있으니 웬만하면 공식문서를 추천드립니다.
npx create-expo-app -t
프론트 개발자라면 익숙할 명령어인데 create 뒤가 expo로 바뀔 뿐입니다.
옵션을 통해 탬플릿을 설정해줍니다.
만약 탬플릿을 설정해주지 않으면 쌩 js로 깔리기때문에 ts가 필요한 입장에선 곤란해요
탬플릿에서 navigation을 선택하는 경우 라우터까지 모두 설정된 상태로 되기때문에
학습하는 입장에서는 blank로 설치하는 것이 좋습니다.
아래 내용은 blank로 설치했다는 가정하에 설명합니다.
npx expo install expo-router react-native-safe-area-context react-native-screens expo-linking expo-constants expo-status-bar
다음과 같이 필요한 종속성들을 설치해줍니다.
종속성 설치를 마쳤다면 필요한 세팅을 수행해주겠습니다.
package.json
{
"main": "expo-router/entry"
}
package.json의 main을 다음과 같이 수정하여 진입점을 엑스포라우터로 바꿔주겠습니다.
app.json
{
"scheme": "your-app-scheme"
}
app.json에 다음과같이 스키마를 추가해줍니다 내용은 마음대로 적어주셔도 좋습니다.
자신의 앱 이름을 넣어주시면 좋아요
babel.config.js
module.exports = function (api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
plugins: ['expo-router/babel'],
};
};
babel에서 plugin을 추가해줍니다. 다른부분은 이미 설정되어있을거에요
여기까지 수행하고 나셨다면 라우팅기능을 사용할 모든 준비는 끝났습니다.
expo router는 next.js가 채택한바와 비슷하게 파일 기반 라우팅 시스템을 제공합니다.
pages router의 파일기반 라우팅 시스템과 유사한데요
예컨대 앱라우터에서는 page.tsx 로 작성된 파일만 라우트로 인정되는데에 비해
page router에서는 그냥 그 파일의 이름을 따라가게 되곤하죠
엑스포 라우터에서도 마찬가지입니다.
라우팅 시작하기
app이라는 약속된 이름의 폴더내부에서 라우팅이 이루어지게 됩니다.
폴더명은 app 이고.. 라우팅 규칙은 pages인.. 혼종같은 느낌이 있긴 한데 뭐 따라야겠죠?
app/_layout.tsx
import { Stack } from 'expo-router';
const RootLayout = () => {
return (
<Stack>
<Stack.Screen
name="(tabs)"
options={{
//header 표시 안하기
headerShown: false,
}}
/>
</Stack>
);
};
export default RootLayout;
options의 headerShown은 위에 생성되는 헤더를 보이게할지 말지에 대한 옵션입니다.
기본값은 true인데 뭐.. 없는게 더 깔끔하니까 false로 많이 쓰는 것 같습니다.
layout 파일은 꼭 필요한 것은 아니지만 있으면 좋습니다.
layout 이 존재하면 위와 같이 헤더가 생기게됩니다.
기분이 좋죠 그러니 생성해줍니다.
layout의 tabs.screen 부분을 보면 name에 내용을 넣어주는걸 볼수있는데요
이 name 같은 경우에는 실제 파일명과 경로를 넣어주면 되겠ㅅ브니다.
아까 앞서 설명한바와 같이 page router의 규칙을 유사하게 따르기 때문에
/ 루트에 라우트를 설정해주고 싶으면 app/index.tsx를 만들어주어야하기 때문에
name ="index"인 탭이 곧 루트입니다.
import { Link, router } from 'expo-router';
import React from 'react';
import { Pressable, Text, View } from 'react-native';
interface indexProps {}
const index = ({}: indexProps) => {
return (
<View>
<Text>dsagsdi</Text>
<Link href={'/users/1'}>이동하기</Link>
<Pressable onPress={() => router.push('/users/2')}>
<Text>Go to user2</Text>
</Pressable>
</View>
);
};
export default index;
라우트 이동 역시 next.js와 많이 유사한 형태를 띄는데요
Link 컴포넌트를 사용하거나 router.push를 이용하여 라우트 이동을 구현할 수 있습니다.
https://docs.expo.dev/router/layouts/
레이아웃은 위 문서를 읽어보면 유용한데
이름에서도 예상할 수 있고 next.js에서도 널리 쓰이는 개념이다보니 익숙합니다.
공통 ui를 만들어줄때 유용하게 사용할 수 있고
next.js approuter에서처럼 중첩 레이아웃을 구성하는 것도 가능합니다.
import { Slot } from 'expo-router';
export default function HomeLayout() {
return (
<>
<Header />
<Slot />
<Footer />
</>
);
}
탭 만들기
일반적으로 모바일 애플리케이션은 다양한 화면전환을 위한 "탭" UI가 사용자의 손에 쉽게 닿는
아래쪽에 몰려있는 것을 확인할 수 있습니다.
expo router는 이러한 탭 UI의 구성역시 쉽게 제공해주는데요
app/(tabs)폴더를 만들어서 수정해보겠습니다.
app/(tabs)/users/[slug].tsx
import { Link, useLocalSearchParams } from 'expo-router';
import React from 'react';
import { Text, View } from 'react-native';
interface indexProps {}
const index = ({}: indexProps) => {
const { slug } = useLocalSearchParams<{ slug: string }>();
return (
<View>
<Text>{slug} 슬러그는 이렇습니다.</Text>
<Link href={'/'}>홈으로돌아가기</Link>
</View>
);
};
export default index;
app/(tabs)/index.tsx
import { Link, router } from 'expo-router';
import React from 'react';
import { Pressable, Text, View } from 'react-native';
interface indexProps {}
const index = ({}: indexProps) => {
return (
<View>
<Text>dsagsdi</Text>
<Link href={'/users/1'}>이동하기</Link>
<Pressable onPress={() => router.push('/users/2')}>
<Text>Go to user2</Text>
</Pressable>
</View>
);
};
export default index;
app/(tabs)/_layout.tsx
import { Tabs } from 'expo-router';
const TabsLayout = () => {
return (
<Tabs>
<Tabs.Screen
name="index"
options={{
headerTitle: 'home page',
}}
/>
<Tabs.Screen
name="users/[slug]"
options={{
headerTitle: 'user page',
}}
/>
</Tabs>
);
};
export default TabsLayout;
app/_layout.tsx
import { Stack } from 'expo-router';
const RootLayout = () => {
return (
<Stack>
<Stack.Screen
name="(tabs)"
options={{
//header 표시 안하기
headerShown: false,
}}
/>
</Stack>
);
};
export default RootLayout;
다음과 같이 구성해줍니다. 이렇게 Stack.Screen에 폴더명만 넣어준 경우
expo router는 해당 폴더의 _layout.tsx를 탐색하게됩니다.
우리는 _layout.tsx에 Tabs를 작성해두었으니 이제 저 tab이 나오게되는것이지요
options의 header title을 수정해주게되면 헤더부분의 내용이 url 대신
헤더타이틀 안의 내용으로 바뀌게 됩니다.
원래는 index라고 표시되어야할 헤더 타이틀이 home page로 드러나는 것을 확인할 수 있습니다.
또한 아래쪽에 탭 UI가 생긴것을 확인할 수 있네요
그런데 아래쪽 탭 부분은 여전히 파일명을 나타내고있는게 마음에 들지 않습니다.
이런 경우 option을 통해 해결해줄 수 있는데요
import { Tabs } from 'expo-router';
const TabsLayout = () => {
return (
<Tabs>
<Tabs.Screen
name="index"
options={{
headerTitle: 'home page',
title: 'Home',
}}
/>
<Tabs.Screen
name="users/[slug]"
options={{
headerTitle: 'user page',
title: 'user',
}}
/>
</Tabs>
);
};
export default TabsLayout;
이렇게 title 을 바꿔주면 되겠습니다.
아이콘을 바꾸고싶은 경우에는 title 접두사를 잘 살펴보면 아이콘과 관련된 부분도 있으니 참고하세요
마치며
익숙한 개념도 있으면서 생소한 동작도 있어서 꽤 혼란스러운 것 같습니다.
읽어주셔서 감사하고 좋은 하루 되세용
'frontend' 카테고리의 다른 글
늦은 밤에 도메인 죽은 썰 푼다 (1) | 2024.01.19 |
---|---|
짧은 zed editor 사용후기 (2) | 2024.01.15 |
프론트엔드 클린아키텍처 (2) | 2024.01.05 |
라이브러리 퍼블리시 시 원본 코드도 첨부해야할까? (1) | 2023.12.15 |
npm 라이브러리를 만들고 publish 하기 (1) | 2023.11.28 |