1. 앱을 고려하기
웹 앱과 모바일 앱
- 웹앱: 모바일 화면’도’ 구성한 웹
- HTML, CSS, JS로 개발
- 모바일 기기의 웹 브라우저로 앱처럼 사용
- 다양한 모바일 플랫폼의 지원이 가능
- 유지보수가 쉽고 스스로 업데이트 할 수 있음
- 네이티브 앱보다 생산 비용이 저렴
- 모바일 앱: 모바일 화면’만’ 구성한 앱
- SDK 개발이 필요
- 모바일 기기에 앱을 다운해 사용
- 다양한 모바일 기기의 기능과 호환됨
- 스토어의 승인을 통해 안전성을 보장
- 인터넷 연결 없이 동작
웹 뷰
앱이 웹 컨텐츠를 표시하는 데 사용할 수 있는 내장형 브라우저
- 웹 뷰 내에서 실행되는 자바스크립트는 기본 시스템 API를 호출할 수 있습니다.
- 웹뷰는 js를 통해 네이티브 기능과 통합할 수 있다.
이러한 통신방식을 브릿지라고 함.
브릿지 Bridge
- 네이티브와 웹뷰의 통신을 위해 제공되는 자바스크립트 인터페이스
- 웹뷰가 직접 네이티브 API를 호출할 수 없으므로 반드시 브릿지를 통해 호출
- 즉, 브릿지는 웹뷰 인터페이스의 구현체
대표적인 웹뷰의 통신 객체
- Window 오브젝트 사이에서 안전하게 Cross-Origin 통신이 가능
- 대중적으로 페이지와 팝업, 페이지 내부의 페이지
iframe 간의 통신에 사용 (예: 유튜브)
Window.postMessage를 통해 전달되는 인자는 이벤트 객체를 통해서만 사용 가능
- Window.addEventListener("message", callback)으로 핸들링 가능
웹뷰가 좋은 이유
- 웹과 앱을 한번에 개발 가능
- 앱을 배포하지 않아도 웹뷰를 수정하면 반영 가능 => 한번 심사를 받으면 그 이후 앱스토어 심사 불필요
기술적으로 좋은 이유
- 런타임 시 발생하는 웹 코드 격리 ⏩ 개발자가 로드되는 컨텐츠를 추가적으로 제어 가능
- 웹에 종속적이나 앱에 종속적이지 않음 ⏩ 웹뷰의 보안/부수적인 기능에 대해 재정의 가능
- 웹과 앱의 통신 방법을 다양하게 적용 가능 ⏩ 특정 플랫폼에 종속 되지 않고 통신이 가능
생기는 선택지
- 센서(GPS, 자이로..), 알림, 카메라 등 사용 가능
- 모바일 저장소 사용 가능
- 일정, 연락처 접근 가능
- 앱 대 앱 공유 가능
- 그 외 여러 네이티브 시스템과 깊이 통합 가능
2. 앱을 준비하기
React Native vs Flutter
RN
- 아직까지도 메이저 버전이 릴리즈 되지 않음
- 메타가 사실상 포기
Flutter
- 구글에서 관리하고 꾸준히 업데이트를 통해 발전하는 중
정리
- 웹 없이 앱을 시작하되, 네이티브 개발 리소스가 없다면 => 플러터
- 리액트를 사용하여 웹서비스를 개발 중이라면 => 리액트 네이티브
리액트 네이티브 웹뷰가 제공하는 브릿지 웨이
리액트 네이티브 -> 웹
injectedJavaScript 프로퍼티
injectJavaScript 메서드
웹 -> 리엑트 네이티브
onMessage 프로퍼티
postMessage 메서드
3. 앱을 설정하기
리액트가 네이티브 앱으로 통합되는 과정

- 결국 리액트 네이티브에서 자바스크립트로 한번은 컴파일 되어야 함.
React Native CLI (직접 요리)
- 리액트 네이티브 팀과 커뮤니티 가 제공한 툴
- 기초적인 개발 설정을 제공하지만 추가 구성 및 설정 필요
- 자바스크립트 코드와 네이티브 기기 소스 코드를 합쳐야 한다면 React Native CLI가 좋음
Expo CLI (간편 밀키트)
- 정리된 앱 개발 워크플로우로서 프로젝트 생성 및 코드 작성과 네이티브 기능 통합이 쉬움
- React Native CLI를 사용하는 것보다 훨씬 쉽고 간단해 언제는 React Native CLI로 전환 가능
- EAS: Expo 관리 장치에서 앱을 빌드하고 앱 스토어에 제출하는 프리미엄 서비스
- React Native를 처음 시작하거나, 빠르고 쉽게 앱을 만들어보고 싶을 때 사용. (하지만 기능 확장이 제한될 수 있음)
간단한 CLI 설정
sudo npm install -g expo-cli
cd {원하는 프로젝트 경로}
npx create-expo-app --template {Example}
npm create expo-app
yarn add react-native-webview
4. 앱을 개발하기
필수적으로 알아야 하는 개념
앱에서는 브라우저가 아니기 때문에 라우팅이 없다! 대신 네비게이션이 있다.
- 네비게이션: 화면 중첩과 보호
- 네이티브 기기와 통신: 권한 획득
네비게이션이란?
네비게이션을 구성하는 방법
스택
- 새 화면이 스택 위에 배치
- 화면 간 앱이 전환하는 방법 제공
- iOS, Android 기본 애니메이션이 적용되나 커스텀 가능
import { createNativeStackNavigator } from '@react-navigation/native-stack';
const Stack= createNativeStackNavigator();
const StackNavigator = ()=>(
<Stack.Navigator>
<Stack.screen name="Home" component={HomeScreen} />
</Stack.Navigator>
);
드로어
- 이것 또한 네비게이션
- 제스처를 통해 열고 닫을 수 있는 화면을 렌더링
바텀 탭
- 다른 영역을 전환할 수 있는 화면 하단의 탭 모음
- 영역은 천천히 초기화 되고, 처음 열리기 전까지 마운트 되지 않음
네비게이션들은 전부 스크린에 컴포넌트 props로 navigation, route를 주입함. 이를 이용해 웹뷰에서 넘어오는 코드를 효율적으로 핸들링 할 수 있다.
스크린 컴포넌트
풀스크린 웹뷰가 아니라면..?
- 훅으로 제공하고 있다 !
- useNavigation(), useRoute()
앱을 개발해보기: Hello, Real World!
앱 구현과 기본적인 설계는 어떻게?
- 모바일 웹과 앱에서의 컴포넌트를 어떻게 구분해 제어할까?
- 앱(웹뷰)인지 여부를 판단해서 조건문으로 컴포넌트를 렌더링하자!
- 페이지 라우팅은 어떻게 제어할까?
- router 이벤트를 발생시키지 않고
postMessage로 웹뷰에 보내자!
- 로그인 여부에 따라 다른 화면을 보여줄 수 있을까?
- 쿠키, 로컬 스토리지에 저장된 유저 정보를 전송하고 네비게이션을 충첩해보자
- 유저 정보를 어떻게 저장해둘까?
- 리액트 네이티브 저장소 라이브러리를 적용해보자!
앱, 웹뷰, 모바일 웹 어떻게 판단하죠?
- 윈도우 객체 정보로 판단하기:
window navigator 객체의 userAgent & window.ReactNativeWebView
- 스크린 넓이로 판단하기
- 반응형인데 웹뷰인지 체크해야할 경우 윈도우 객체 정보와 결합해 판단
라우트 이벤트 제공?
-
웹뷰에게 메시지를 전달하기 위한 함수
: 윈도우 객체가 가지고 있는 브릿지 이용. 윈도우 postMessage를 이용해 웹뷰에 전달하면 웹뷰가 핸들링해서 제어.
-
라우팅 발생 시 웹뷰일 때 sendMessage, 웹뷰가 아닐 때 router.push
로그인 유저를 어떻게 구분?
두 가지 케이스: 중첩 네비게이션,
- 다른 네비게이션에 중첩 렌더링
- 상위 네비게이터에서 하위 네비게이터로 디스패치 가능
-
정보 저장 - 로컬스토리지
- `@react-native-async-storage/async-storage` : 리액트 네이티브 커뮤니티에서 개선과 유지보수를 담당하는 라이브러리
- 리액트 네이티브를 위한 암호화되지 않은 키-값 저장소로 비동기 동작
- 다중 플랫폼 지원
- 직렬화를 통한 string 데이터 저장, localStorage와 같은 방법
푸시알림
알림의 종류
- 로컬 알림: 앱이 설치된 기기에서 설치된 앱이 트리거하는 알림 (리마인더, 알람 시계, 할일 앱 등
- 푸시 알림: 내 기기에 설치된 앱에서 트리거된 알림을 다른 기기에 설치된 앱으로 전송
로컬알림
-
expo-notifications 설치
-
코드: https://github.com/pagers-org/webview-app/blob/local-notification/App.js
리액트 네이티브의 코어 컴포넌트
-
HTML이 아니기 때문에 div, h2 태그 등 HTML요소 사용 불가
-
컴파일된 네이티브 코드가 자바스크립트에 의해 번들링 됨

존재하지 않는 CSS
- 브라우저가 아니기 때문에 제어 및 사용 불가
- DOM 구조가 아니므로 스타일 상속이 존재하지 않음
- 프로퍼티를 이용한 인라인 스타일과 StyleSheet객체로 작성 가능
웹과 다른 이벤트
- Click 이벤트 대신
pressable 컴포넌트로 감싸서 이벤트 핸들링
- DOM 이벤트 객체가 없으므로
event.nativeEvent 객체를 활용한 핸들링
- DOM의 스크롤이 없으므로
ScrollView 컴포넌트로 스크롤을 핸들링
앱의 빌드는 EAS의 도움을 받는다
정리
목표는 최소한의 개발, 최대한 빠른 릴리즈
- 화면에 대한 설계: 각 화면의 연결을 어떻게 관리할 것인지 네비게이션 고려
- 웹, 모바일웹, 앱을 구분하는 함수를 만들고 웹과 앱이 통신하는 브릿지 작성
- 유저의 사용성을 개선하기 위한 저장소 추가
- 앱이 배포되기 위한 필요 최저한의 네이티브 개발
- 푸시알림
개발 완료된 웹과 앱

앱 출시는?
계정 준비
- 구글 개발자 계정, 애플 개발자 계정을 각각 등록
에셋 준비

웹뷰만 사용한 앱출시?
-
앱 심사 거절 내용 중 일부
귀하의 앱이 제공하는 경험은 기본 ios기능을 통합해 제공하는 웹 브라우징 경험과 충분히 다르지 않습니다. 특정 사용자 또는 틈새 사용자 그룹을 위해 웹 속성에 대한 편리한 액세스를 제공하고 푸시 알림과 같은 기능으로 해당 경험을 향상시킬 수 있습니다. 그러나 이러한 앱에는 앱 스토어에 적합할 만큼 충분한 기본 ios 기능이 포함되어있지 않습니다.
-
웹과 똑같은데 꼭 앱이어야할 이유가 있는가?
앱을 확장하기
- 스플래시 이미지, 앱 아이콘을 쉽게 등록할 수 있는 app.json
- 상태 표시줄 디자인을 도와주는 statusBar 컴포넌트
- 기기의 모서리, 상단 노치 등의 간격을 조절해주는 SafeAreaView 컴포넌트
- 앱의 테마를 설정할 수 있는 여러 수단: app.json, useTheme, StyleSheet
- 유저 인터랙션 UI에 대한 핸들링
- 리액트 네이티브에서 제공하는 컴포넌트만으로는 더 예뻐질 수 없는 우리의 서비스
나머지 고려사항
-
브릿지 인터페이스의 확장
-
스토어에 배포하기 전 앱의 안정성 관리
- 릴리즈 버저닝, 테스트 및 사용자 앱 버전 관리
-
화면 보호하기
- 웹뷰 URL 노출 숨기기
- 네비게이션 중첩을 활용해 어떻게 사용성을 증가시킬지
-
이벤트 수집: 앰플리튜드, GA, 파이어베이스
-
서비스 로그 수집: 앱, 서버, 인프라 모니터링 수단 강구
-
네트워크 상태가 불안정해도 흔들리지 않는 사용자 경험 제공
- 캐싱 적용
- 웹뷰와 네이티브 컴포넌트의 종속성을 분리해 구성