참고:
1. https://reactnavigation.org/docs/5.x/deep-linking
2. https://reactnavigation.org/docs/5.x/navigation-container
우선 DeepLink
는 기본적으로 2개의 시나리오를 가지고 있습니다.
1. 앱이 열리지 않은 상태인 경우, 링크 기반으로 초기상태 설정하기
2. 앱이 이미 열린 상태인 경우, 수신된 링크를 기반으로 상태를 업데이트
Expo Project에서는 app.json
에 아래와 같이 scheme
을 작성하여 url
을 만들 수 있습니다.
{
"expo": {
"scheme": "mychat"
}
}
단 모든경우에 적용되는 것은 아니며
mychat://
형태로 작동가능하고exp://ip:19000
형태로 지원됩니다.이제 아래 코드를 그대로 넣어봅시다.
import * as Linking from 'expo-linking';
const prefix = Linking.createURL('/');
function App() {
const linking = {
prefixes: [prefix],
};
return (
<NavigationContainer linking={linking} fallback={<Text>Loading...</Text>}>
{/* content */}
</NavigationContainer>
);
}
이 때 Linking.createURL('/');
를 하는 이유는 모드에 따라 url
이 다르기 때문입니다.
mychat://~~~
형태로 저장되며exp://ip:19000/~~~
형태로 저장됩니다.이제 어떤 path
가 호출될 때, 어떤 Component
로 연결할지 맵핑하는 정보를 만듭니다.
맵핑정보는 NavigationContainer
가 가지게 됩니다.
참고:
1. https://reactnavigation.org/docs/5.x/configuring-links/
NavigationContainer
의 linking
프로퍼티는 아래 2개 항목을 반드시 포함해야 합니다.
Linking.createURL("/")
로 만들어진 값을 그대로 이용합니다.https
도메인을 배열에 추가하면 됩니다.path
와 component
를 맵핑합니다. 라우팅 설정이라고도 합니다.component
만 설정할 수 있습니다.아래 예시에서는 <Stack.Navigator>
를 return하는 HomeStack
내에, <Stack.Screen>
인 ChatRoom
으로 path를 설정할때의 config
의 형태를 보여줍니다.
App.tsx
const prefix = Linking.createURL("/");
...
return (
...
<NavigationContainer
linking={{
prefixes: [prefix],
config: {
screens: {
// HomeStack 내에 포함된 components 중 path를 부여하고 싶은 것만 작성합니다.
// :roomId 에 들어가는 값은 navigation의 params로 전달됩니다.
ChatRoom: "room/:roomId",
},
},
// ...
}}}
>
<HomeStack />
</NavigationContainer>
...
)
위에서 설정한 :roomId
는 route
내 params
객체를 통해 전달받을 수 있습니다.
ChatRoom.tsx
const ChatRoom = ({ navigation, route }) => {
console.log(route.params);
//출력 결과
Object {
"roomId": "123",
}
여기까지 오면 화면전환에 필요한 설정은 모두 끝났습니다.
이제 화면전환을 호출하면 설정에 따라 화면이 전환되게 됩니다.
<Link>
로 URL Path 사용하기<Link>
태그를 이용하면 위에서 설정한 path를 앱 내에서 호출할 수 있습니다.
어떻게 보면 navigation.navigate()
함수를 쓰는것보다 이쪽이 더 간단한 것 같네요.
import { Link } from "@react-navigation/native";
...
<Link to="/room/123">
<Label>Go to Jane's profile</Label>
</Link>
push 알림을 받은 사용자가 알림을 선택하면, 해당 컨텐츠가 바로 앱에서 열려야겠죠.
그 부분을 구현해봅시다. 여기서는 push알림에 url이 이미 탑재되어있다고 가정합니다.
deep link url이 포함된 푸시알림을 발생시키는 방법은 다음 링크를 참고해주세요.
https://velog.io/@hamster/Expo-Notification-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-Local
기본 개념은 아래와 같습니다.
1. 화면 이동에 React Navigation
의 DeepLink
는 위에서 설정한 방법 외에도 서드파티 모듈을 통합하여 DeepLink
를 지원할 수 있습니다.
별거 아니고 아래 두 함수를 구현하면 됩니다.
getInitialURL
subscribe
expo-notifications
이 여기서 서드파티 부분에 들어갑니다.
import React from 'react';
import { Linking } from 'react-native';
import * as Notifications from 'expo-notifications';
import { NavigationContainer } from '@react-navigation/native';
const prefix = Linking.createURL("/");
export default function App() {
return (
...
<NavigationContainer
linking={{
prefixes: [prefix],
config: {
// 여기서 url path와 screen을 맵핑합니다.
// 원하는 screen만 맵핑하면 됩니다.
// initialRouteName 에는 앱의 첫 화면 screen 이름을 적어주세요. 최초 화면을 설정하지 않으면, deep link로 들어간 화면이 첫 화면이 되어버려, 앱을 종료할 때까지 home으로 갈 수 없게됩니다.
initialRouteName: "HomeTab",
screens: {
HomeTab: "room",
ChatRoom: "room/:roomId",
},
},
async getInitialURL() {
let url = await Linking.getInitialURL();
if (url != null) {
return url;
}
const response = await Notifications.getLastNotificationResponseAsync();
url = response?.notification.request.content.data.url;
return url;
}
subscribe(listener) {
const onReceiveURL = ({ url }: { url: string }) => listener(url);
// Listen to incoming links from deep linking
Linking.addEventListener('url', onReceiveURL);
// Listen to expo push notifications
const subscription = Notifications.addNotificationResponseReceivedListener(response => {
const url = response.notification.request.content.data.url;
listener(prefix + "room"); // 우선 최초화면으로 먼저 이동합니다. 이렇게 하지 않으면, 변수만 다른(:roomId) 동일한 화면이(ChatRoom) 이미 열려있던 경우, deep link로 인한 화면이동이 발생하지 않습니다.
listener(url); // 원하는 화면으로 이동합니다.
});
return () => {
// Clean up the event listeners
Linking.removeEventListener('url', onReceiveURL);
subscription.remove();
};
},
}}>
{/* Your app content */}
</NavigationContainer>
);
}
정말 감사합니다!