2/2
회원가입 페이지에 사용할 이런 일러스트를 구하려면 unsplash 사용하면 된다
canva에도 있고 ai로 생성해서 써도 됨
pinterest나 dribble같은데서 레퍼런스 찾아도 되고
canva ai나 uizard galileo ai같은거 사용해서 생성해도 되고
생성한것도 레퍼런스 정도 수준이고 결국 내 수정이 필요해서..
flex: 1
flex: 1, the flex prop will define how your items are going to "fill" over the available space along your main axis. Since we only have one container, it will take all the available space of the parent component. In this case, it is the only component, so it will take all the available screen space.
View
Views and mobile development
In Android and iOS development, a view is the basic building block of UI: a small rectangular element on the screen which can be used to display text, images, or respond to user input. Even the smallest visual elements of an app, like a line of text or a button, are kinds of views. Some kinds of views can contain other views. It’s views all the way down!
Native Components
In Android development, you write views in Kotlin or Java; in iOS development, you use Swift or Objective-C. With React Native, you can invoke these views with JavaScript using React components. At runtime, React Native creates the corresponding Android and iOS views for those components. Because React Native components are backed by the same views as Android and iOS, React Native apps look, feel, and perform like any other apps. We call these platform-backed components Native Components.
React Native comes with a set of essential, ready-to-use Native Components you can use to start building your app today. These are React Native's Core Components.
React Native UI Component | Android View | iOS View | Web Analog | Description |
<View> | <ViewGroup> | <UIView> | A non-scrolling <div> | A container that supports layout with flexbox, style, some touch handling, and accessibility controls |
<Text> | <TextView> | <UITextView> | <p> | Displays, styles, and nests strings of text and even handles touch events |
<Image> | <ImageView> | <UIImageView> | <img> | Displays different types of images |
<ScrollView> | <ScrollView> | <UIScrollView> | <div> | A generic scrolling container that can contain multiple components and views |
<TextInput> | <EditText> | <UITextField> | <input type="text"> | Allows the user to enter text |
2/3
brew install tree
맥에서 현재 디렉토리 아래 폴더들 보고싶을때
tree -L 1
기본으로 생성되는 앱 구조가 왜이렇게 많이 변했지??
1.
expo-router라는 파일 기반 라우팅을 도입함 ⇒ app디렉토리, _layout.tsx를 사용하면서 nextjs형태랑 비슷해짐.
2.
cli사용하면 src폴더 사용하면서 react형태와 유사하게 사용할 수 있지만 expo가 주류가 되어서 expo의 기능과 eas의 build기능 등을 적극 활용하는게 더 유리함
3.
typescript가 기본으로 적용됨
4.
react native 0.76 = 새로운 아키텍쳐 ⇒ react 18의 기능들을 사용할 수 있게 되었고 turboModules, fabric렌더러를 통해 (JSI, C++ 코드 직접 호출) → 성능 향상. 네이티브와 비슷한 성능
https://reactnative.dev/blog/2024/10/23/the-new-architecture-is-here
5.
현재 sdk 52고 2년전에 48이었음
expo router가 react navigation을 포함하므로 별도로 install할 필요없음
그리고 자동으로 safe-area-context를 포함하므로 추가로 다운받을 필요 없음
2/4
Expo Router(Next.js 스타일 파일 라우팅)에서 사용하는 특수 파일/폴더 네이밍 컨벤션에 대해 설명드리겠습니다. 이 규칙들은 라우팅 동작을 제어하는 핵심 요소입니다.
폴더 & 파일 네이밍 규칙
패턴 | 의미 | 예시 |
(폴더) | 그룹 라우트 (URL에 노출되지 않음) | (auth)/login.tsx → /login |
+파일 | 예약된 특수 파일 | +not-found.tsx |
_파일 | 내부 전용 파일 (URL 생성 안 됨) | _layout.tsx |
[폴더] | 동적 세그먼트 | [id]/index.tsx → /123 |
...폴더 | 캐치-올 세그먼트 | [...slug]/index.tsx → /a/b/c |
parallax scrolling
요소 간의 스크롤링 속도를 다르게 해서 입체감을 줄 수 있음
react native firebase
npx expo install @react-native-firebase/app
npx expo install @react-native-firebase/auth @react-native-firebase/crashlytics
C++
복사
supabase
npx expo install @supabase/supabase-js @react-native-async-storage/async-storage @rneui/themed react-native-url-polyfill
C++
복사
인증은 최상위에서 구현해야함
app/
├── _layout.tsx (인증 상태 확인 및 라우팅)
├── (auth)/
│ ├── _layout.tsx
│ ├── sign-in.tsx
│ └── sign-up.tsx
└── (tabs)/
├── _layout.tsx (기존 탭 레이아웃)
├── index.tsx
├── quiz.tsx
└── profile.tsx
•
인증되지 않은 사용자는 (auth) 그룹으로 이동
•
인증된 사용자는 (tabs) 그룹으로 이동
•
각 그룹 내에서 독립적인 네비게이션 구조 유지
RootLayout (Stack)
├── (auth) 그룹 (Stack)
│ ├── sign-in
│ └── sign-up
└── (tabs) 그룹 (Tabs)
├── index
├── quiz
└── profile
•
Root Stack: 전체 앱의 최상위 네비게이션 (인증/비인증 상태 분기)
•
Auth Stack: 로그인, 회원가입 등 인증 관련 화면들의 네비게이션
•
Tabs: 인증된 사용자를 위한 메인 탭 네비게이션
figma 빨간선
alt누르고 서로 다른 요소들 클릭하면 거리 나옴
insets
const insets = useSafeAreaInsets();
<View style={{ flex: 1, paddingTop: insets.top }}>
<Text style={{ fontSize: 28 }}>Content is in safe area.</Text>
</View>
JavaScript
복사
creatie
figma에서 inspect가 이제 유료라서 creatie로 넘어감
figjam은 계속 쓸수 있을듯
Pressable
onClick이 view에 없고 Pressable 컴포넌트로 감싸서 onPress를 사용해야함
touchableOpacity도 있는데 pressable을 더 많이 사용함
눌렸을때 pressed를 style의 파라미터로 전달하기 때문에 눌리면 ui바뀌도록 할 수 있다.
bottom sheet
아래에서 올라오는 화면
component
스크롤 가능한 컴포넌트들
ScrollView
FlatList: 레이지 렌더링으로 화면에 보이는 항목만 렌더링해서 성능 최적화함
ListView ⇒ deprecated
•
성능 최적화: FlatList의 keyExtractor를 항상 지정해 주세요.
•
인피니티 스크롤: FlatList의 onEndReached로 구현 가능.
•
커스텀 스크롤바: ScrollView의 showsVerticalScrollIndicator로 제어.
Touchables
TouchableOpacity: 터치시 투명효과 TouchableHighlight: 터치시 배경색 강조
Pressable: 최신 api터치 컴포넌트
Gorhom bottomsheet
snapPoints
Points for the bottom sheet to snap to, points should be sorted from bottom to top. It accepts array of number, string or mix.
const index = () => {
const bottomSheetRef = useRef<BottomSheet>(null)
const onSignUp = () => {
bottomSheetRef.current?.snapToIndex(0)
}
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<SafeAreaView style={styles.container}>
<View style={styles.banner}>
<Text style={styles.bannerText}>Let's get Started!</Text>
</View>
<Image
source={require('../../assets/images/get-started.png')}
style={styles.image}
/>
<AuthButton text='회원 가입하기' onPress={onSignUp}/>
<Guidance guide="이미 계정이 있으신가요?" link="로그인" />
</SafeAreaView>
<BottomSheet
ref={bottomSheetRef}
snapPoints={['70%']}
index={-1} // Start closed
enablePanDownToClose={true}
enableDynamicSizing={false}
>
<BottomSheetView style={styles.contentContainer}>
<Text style={styles.sheetTitle}>Sign Up Form</Text>
{/* Add your sign-up form components here */}
</BottomSheetView>
</BottomSheet>
</GestureHandlerRootView>
)
}
JavaScript
복사
GestureHandlerRootView는 화면 최상단에 넣어야함
SafeAreaView위에 있어야 안 잘린다
그리고 이유모를 에러가 일어났던 부분!!
content size만큼 공간에서 자꾸 snap이 발생하고 snapToIndex도 1로 해야 동작했는데
enableDynamicSizing이 default로 true로 되어있어서 그랬던것.. 이럼 snapPoint가 자동으로 하나 추가되기 때문에 원하지 않았던 형태로 동작함.
2/6
Unistyle
Why should you use Unistyles?
•
Guarantees no re-renders across the entire app (no hooks, no context—just pure JSI bindings)
•
Doesn’t pollute your native view hierarchy (Unistyles has no component wrappers)
•
Includes a cross-platform parser written in C++, ensuring consistent output across all platforms
•
•
Transforms your StyleSheets into enhanced StyleSheets with superpowers
that can access themes, platform-specific values, and more!
Unistyles includes custom native code, which means it does not support Expo Go.
2/8
supabase하니까 좋은점은 prebuild할필요가 없음
supabase연결은 됐고.. 회원가입하고, 이메일 주소 맞는지 validation, 비밀번호 최소 6자리 validation
이름도 이미 존재하는지 validation해야함
로그인 해서 auth받는것도 설치하고 라우팅 따로 되도록 하고
2/12
로컬에서 copilot, 이미지 생성 돌리기
Vocasimple
AI사용해서 만든 UI 수정
SafeAreaView padding적용 안됨
SafeAreaView는 inset에 따라서 padding을 자동으로 조정하므로 안먹는다
해결방법은 그냥 안에 View로 감싸서 쓰기
SafeAreaView에는 flex:1 만 주면 됨
expo go 에서 bottomsheet 애니메이션 없는 문제
reduced motion setting이 적용되어서 expo go에서는 적용이 안된다고 한다. babel.config.js를 설정하면 될 수도 있다고 해서
이 문서를 참고해서 사용자 정의 babel파일 생성
npx expo customize로 생성
module.exports = function (api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
};
};
JavaScript
복사
npx expo start —clear
애니메이션 적용이 안됨.
reanminated문서를 찾아보니
import { ReducedMotionConfig, ReduceMotion } from 'react-native-reanimated';
function App() {
return (
// ...
<ReducedMotionConfig mode={ReduceMotion.Never} />
// ...
);
}
JavaScript
복사
이렇게 컴포넌트 추가하면 세팅 변경할 수 있을 거 같지만 다시 지우기 귀찮아서 넘어감..
경고문구라도 제거해보려고 했는데
import { LogBox } from "react-native";
LogBox.ignoreLogs(["[Reanimated] Reduced motion setting is enabled on this device."])
JavaScript
복사
이걸 루트에 적용하라고 되어있음.
앱의 _layout.tsx에 적용해 보았지만 없어지지 않아서
package.json에서 지정된 entry point인
"main": "expo-router/entry" 에 접근해서 적용해 봤지만 안 없어져서.. 그냥 두기로 했다.
어차피 개발모드에서만 보이는 경고이고
나중에 expo go 대신 expo-dev-client 사용해서 빌드해서 실행하면 reduced animation도 적용되지 않을것이다!
2/13
단어 생성시 supabase storage에 저장
react native picker를 사용해봤는데 괜찮아보임
expo router
const router = useRouter()
router.back()
router.push('/(tabs)')
JavaScript
복사
onPress이벤트 범위를 버튼만으로 제한하기
toastify-react-native 사용해서 스크린을 떠나지 않고 성공, 실패 toast
toast props주는게 헷갈려서 헤맸는데.. <Toast />컴포넌트를 하나 만들고 그걸 돌려서 쓰는거였다..
ScrollView
style적용하려면 contentContainerStyle써야함
showsVerticalScrollIndicator={false}
2/15
단어를 1초이상 꾹 누르면 overlay가 적용되도록 함
Pressable의 onLongPress사용
2/16
tab style 수정하기
home 탭 포커스 시에 데이터 refetch
단어 생성이후에 자동으로 추가 안되니까.. tanstack query쓰기?
갑자기 auto Import왜 안되는거?? suggestion도 안쓰고
settings.json계속 파보고 있는데.. 알수없는 구성이라고 나옴
vscode 버전문제인지.. extension문제인지.. 해결이안되네
home tab에 들어올때마다 refresh하는것도 괜찮음 = useFocusEffect
어차피 단어 생성하고 스크린을 이동해야되니까 스크린 focus맞춰지면 다시 단어들을 가져오는걸로 해도 되고
퀴즈 페이지 UI구현
2/17
퀴즈 페이지
2/18,19
require에는 정적 문자열만 들어갈 수 있다.
그러니까 만약 여러개에 적용해야 한다면
const badges = [
{ title: "Sage", level: 3, image: require("@/assets/images/sage.png") },
{ title: "Knight", level: 2, image: require("@/assets/images/knight.png") },
{ title: "Apprentice", level: 1, image: require("@/assets/images/apprentice.png") },
];
TypeScript
복사
이런식으로 미리 require하기
extension
auto rename tag
docker
es7 react snippet
eslint
github copilot
live server
rainbow csv
prettier
react native tools
tailwindcss intellisense
vscode재설치
지우고 다시 다운받으니까 잘된다!! extension끼리 충돌해서 그런거같은데 앞으로도 안되면 지우고 다시 해보기
2/20
탭바만큼의 하단 패딩이 존재해야 scrollview의 아랫부분을 가리지 않음
contentContainerStyle을 적용해야한다
Expo를 사용하여 Android App Bundle (AAB)을 생성하는 방법은 EAS Build를 활용하는 것이 권장되며, 다음과 같은 단계로 진행할 수 있습니다.
1. EAS CLI 설치 및 로그인
•
EAS CLI를 전역 설치합니다.
npm install -g eas-cli
Shell
복사
•
Expo 계정으로 로그인합니다.
eas login
Shell
복사
2. 프로젝트 설정 (eas.json 구성)
•
프로젝트 디렉터리에서 EAS Build 설정을 초기화합니다.
이 명령어는 eas.json 파일을 생성하며, AAB 생성을 위해 다음과 같이 설정합니다:
eas build:configure
Shell
복사
{
"build": {
"production": {
"android": {
"buildType": "app-bundle"
}
}
}
}
JSON
복사
3. 서명 키(Keystore) 설정
•
Google Play에 배포하려면 서명 키가 필요합니다.
◦
자동 생성: EAS CLI가 빌드 시 자동으로 키를 생성하도록 할 수 있습니다.
◦
기존 키 사용: 기존 키가 있다면 eas credentials 명령어로 관리합니다.
eas credentials
Shell
복사
4. AAB 빌드 실행
•
다음 명령어로 AAB 빌드를 시작합니다.
eas build --platform android --profile production
Shell
복사
◦
빌드 진행 상태는 터미널 또는 Expo 웹 대시보드에서 확인 가능합니다.
◦
완료 후 다운로드 링크가 제공되며, Google Play Console에 직접 업로드할 수 있습니다.
5. app.json 설정 확인
•
app.json 파일에서 Android 관련 설정(패키지명, 버전 코드 등)이 정확한지 확인합니다.
{
"expo": {
"android": {
"package": "com.yourcompany.appname",
"versionCode": 1
}
}
}
JSON
복사
6. 빌드 다운로드 및 테스트
•
빌드 완료 후 제공된 링크에서 AAB 파일을 다운로드합니다.
•
테스트를 위해 Android 에뮬레이터에 설치하려면 다음 명령어를 사용합니다:
eas build:run -p android --latest
Shell
복사
참고 사항
1.
클래식 빌드 (Deprecated):
expo build:android 명령어로도 AAB을 생성할 수 있으나, Expo는 EAS Build를 권장합니다.
2.
로컬 빌드:
Gradle을 직접 사용하려면 npx expo prebuild로 네이티브 코드를 생성한 후 다음 명령어를 실행합니다:
cd android && ./gradlew app:bundleRelease
Shell
복사
3.
배포 전 검증:
AAB 파일은 Google Play 외에도 adb install로 실물 기기에 설치하여 테스트할 수 있습니다.
adb install path/to/app-release.aab
Shell
복사
키가 없으면 앱 업데이트를 수행할 수 없음!
1. Expo SDK 버전 확인
•
현재 프로젝트의 Expo SDK 버전을 확인합니다.app.json 또는 app.config.js 파일에서 sdkVersion 필드를 확인하세요.
{
"expo": {
"sdkVersion": "XX.X.X"
}
}
JSON
복사
2. Expo CLI 업데이트
•
Expo CLI를 최신 버전으로 업데이트합니다.
npm install -g expo-cli
Shell
복사
3. Expo SDK 버전 업데이트
•
프로젝트 디렉터리에서 다음 명령어를 실행하여 Expo SDK를 업데이트합니다.
expo upgrade
Shell
복사
◦
이 명령어는 프로젝트의 package.json 파일을 분석하고, 최신 Expo SDK 버전과 호환되는 패키지 버전을 자동으로 업데이트합니다.
◦
업데이트 후 app.json 또는 app.config.js 파일의 sdkVersion 필드가 최신 버전으로 변경됩니다.
4. 네이티브 코드 재생성 (필요한 경우)
•
Expo SDK 업데이트로 인해 네이티브 코드가 변경될 수 있습니다. 다음 명령어로 네이티브 코드를 재생성합니다.
npx expo prebuild
Shell
복사
◦
이 명령어는 android 및 ios 디렉터리를 업데이트합니다.
◦
기존에 커스텀 네이티브 코드가 있다면 충돌이 발생할 수 있으니 주의하세요.
5. 빌드 및 테스트
•
업데이트된 SDK로 앱을 빌드하고 테스트합니다.
◦
EAS Build 사용 시:
eas build --platform android
eas build --platform ios
Shell
복사
◦
로컬 빌드 사용 시:
expo build:android
expo build:ios
Shell
복사
2/23
1. 네이티브 빌드가 필요한 이유
•
React Native의 아키텍처:
React Native는 JavaScript 코어와 네이티브 모듈(Java/Kotlin, Objective-C/Swift)로 구성됩니다.
Google Sign-In과 같은 기능은 플랫폼별 네이티브 SDK를 필수로 사용해야 합니다.
(예: Android의 GoogleSignInClient, iOS의 GIDSignIn)
•
Expo의 제약 사항:
순수 Expo 프로젝트(Managed Workflow)에서는 android/, ios/ 디렉토리가 숨겨져 있어,
네이티브 코드 수정이 불가능합니다.
→ 커스텀 네이티브 모듈 통합을 위해 네이티브 빌드 환경이 필요합니다.
expo-dev-client vs prebuild
(1) expo-dev-client
•
목적: 개발 단계에서 Expo의 장점을 유지하면서 네이티브 코드를 테스트하기 위해 사용합니다.
•
특징:
◦
기존 Expo Go 앱 대신 커스텀 개발용 앱을 빌드합니다.
◦
expo run:android 또는 expo run:ios로 실시간 리로드가 가능합니다.
◦
네이티브 코드 수정 후 빠른 반영이 필요한 경우 유용합니다.
◦
eas build --profile development로 생성 가능합니다.
(2) prebuild
•
목적: Expo 프로젝트에서 android/, ios/ 디렉토리를 생성하여 네이티브 코드를 직접 제어합니다.
•
특징:
◦
expo prebuild 명령어 실행 시 생성됩니다.
◦
네이티브 코드를 수정한 후 재생성 시 충돌이 발생할 수 있으니 주의가 필요합니다.
◦
일회성 생성이 아니라 지속적인 관리가 필요할 때 사용합니다.
Expo Application Services(EAS)는 클라우드 기반 빌드 시스템으로, 각 프로파일은 목적에 맞는 빌드 설정을 제공합니다.
(1) development
•
용도: 개발 중 실시간 테스트용
•
특징:
◦
디버그 모드 활성화, 로깅 강화.
◦
expo-dev-client가 포함된 빌드.
◦
빠른 빌드 시간 (최적화 비활성화).
(2) production
•
용도: 스토어 배포용 최종 빌드
•
특징:
◦
코드 최적화, 미니피케이션 적용.
◦
프로덕션 환경 변수 사용 (예: Google OAuth 클라이언트 ID).
(3) preview
•
용도: QA 또는 스테이징 환경 테스트
•
특징:
◦
프로덕션과 유사한 설정 but 디버그 기능 일부 유지.
◦
별도 환경 변수로 스테이징 서버 연결 가능.
프로파일 설정 예시 (eas.json)
{
"build": {
"development": {
"distribution": "internal",
"android": { "gradleCommand": ":app:assembleDebug" },
"ios": { "buildConfiguration": "Debug" }
},
"production": { ... }
}
}
Plain Text
복사
4. 구글 로그인 구현 절차
1.
expo-dev-client 설치
npx expo install expo-dev-client
Plain Text
복사
2.
네이티브 프로젝트 생성
npx expo prebuild
Plain Text
복사
3.
Google Sign-In 라이브러리 추가
npx expo install @react-native-google-signin/google-signin
Plain Text
복사
4.
Android/iOS 설정
•
android/app/build.gradle에 Google 서비스 추가.
•
iOS Podfile에 Firebase 종속성 추가.
5.
EAS로 개발 빌드 생성
eas build --profile development --platform android
Plain Text
복사
6.
환경별 설정 분리
•
app.config.js에서 프로파일별 환경 변수 관리:
export default ({ config }) => ({
...config,
extra: {
googleClientId: process.env.GOOGLE_CLIENT_ID,
env: process.env.APP_ENV,
},
});
Plain Text
복사
5. FAQ: 왜 Expo Go로는 안 되나요?
•
Expo Go는 공용 앱으로, 커스텀 네이티브 코드를 포함할 수 없습니다.
•
expo-dev-client는 사용자 전용 개발 앱을 생성하여 이 문제를 해결합니다.
expo run
**expo run:ios**를 사용하여 로컬에서 iOS 시뮬레이터나 디바이스에서 개발을 하려면, 먼저 **eas build --platform ios --profile development**로 개발용 빌드를 생성해야 합니다. 이 과정이 필요한 이유와 단계를 자세히 설명드리겠습니다.
왜 eas build를 먼저 해야 하나요?
1.
Expo Go의 한계:
•
Expo Go는 공용 앱으로, 커스텀 네이티브 코드를 포함할 수 없습니다.
•
Google 로그인과 같은 네이티브 기능을 사용하려면 사용자 전용 개발 앱이 필요합니다.
2.
expo-dev-client의 역할:
•
expo-dev-client는 커스텀 개발용 앱을 생성하여, 네이티브 코드를 포함한 개발이 가능하도록 합니다.
•
이 앱은 eas build를 통해 클라우드에서 빌드됩니다.
3.
expo run:ios의 동작 방식:
•
expo run:ios는 로컬에서 iOS 프로젝트를 빌드하고 실행하는 명령어입니다.
•
하지만 이 명령어를 사용하려면 기본적인 네이티브 프로젝트 구조가 필요합니다.
•
eas build로 개발용 빌드를 생성하면, 이 구조가 준비됩니다.
필요한 단계
1.
expo-dev-client 설치:
expo install expo-dev-client
Plain Text
복사
2.
EAS Build를 위한 설정:
•
eas.json 파일에 개발용 프로파일을 추가합니다:
{
"build": {
"development": {
"distribution": "internal",
"ios": {
"simulator": true
}
}
}
}
Plain Text
복사
3.
개발용 빌드 생성:
eas build는 eas의 서버에서 빌드파일 만들고 로컬로 다운받는거다!
eas build --platform ios --profile development
Plain Text
복사
•
이 명령어는 클라우드에서 개발용 iOS 빌드를 생성합니다.
•
빌드가 완료되면 .ipa 파일이 생성되고, Expo CLI가 이를 로컬에 다운로드합니다.
1.
로컬에서 실행:
•
빌드가 완료되면, 다음 명령어로 시뮬레이터나 디바이스에서 실행합니다:
expo run:ios
Plain Text
복사
•
이 명령어는 로컬에서 Xcode 프로젝트를 빌드하고 실행합니다.
eas build 없이 expo run:ios만 사용할 수 있나요?
•
네, 가능하지만 제약이 있습니다:
◦
expo prebuild로 네이티브 프로젝트를 생성한 경우, expo run:ios를 바로 사용할 수 있습니다.
◦
하지만 이 방식은 로컬에서 네이티브 빌드 환경이 완전히 설정되어 있어야 합니다 (예: Xcode, CocoaPods 등).
◦
또한, expo-dev-client를 사용하려면 여전히 eas build로 개발용 빌드를 생성하는 것이 더 간편합니다.
요약
•
eas build --platform ios --profile development:
개발용 iOS 빌드를 생성합니다. 이 빌드는 expo-dev-client가 포함된 커스텀 개발 앱입니다.
•
expo run:ios:
로컬에서 iOS 시뮬레이터나 디바이스에 앱을 실행합니다.
이 명령어를 사용하려면 먼저 eas build로 개발용 빌드를 생성해야 합니다.
•
expo‑dev‑client는 기본 Expo Go 앱의 한계를 극복하기 위한 “커스텀 개발 클라이언트”입니다. Expo Go는 Expo SDK에서 기본으로 제공하는 모듈만 지원하지만, 프로젝트에 커스텀 네이티브 모듈이나 추가 네이티브 기능이 필요할 경우 Expo Go로는 실행할 수 없습니다. 이때 expo‑dev‑client를 사용하면 필요한 네이티브 기능을 포함한 클라이언트를 직접 빌드하여 개발 중에 사용할 수 있습니다.
•
eas build와의 관계:
EAS Build는 클라우드에서 실제 앱 바이너리(예, IPA, APK)를 빌드하는 서비스입니다. EAS Build를 사용하기 위해 expo‑dev‑client를 반드시 설치해야 하는 것은 아닙니다.
◦
만약 기본 Expo Go가 지원하는 기능만 사용한다면 expo‑dev‑client 없이도 진행할 수 있습니다.
◦
하지만, 커스텀 네이티브 모듈이나 Expo Go에서 지원하지 않는 기능을 사용한다면, 개발 및 디버깅을 위해 expo‑dev‑client로 커스텀 개발 클라이언트를 빌드하는 것이 일반적입니다.
•
expo run:ios의 역할:
이 명령어는 로컬 환경에서 iOS 앱을 “빌드”하고 실행하는 역할을 합니다. 내부적으로 Xcode를 사용해 네이티브 바이너리를 생성하며, 개발 서버(예: Metro Bundler)와 연결되어 자바스크립트 코드 변경 시 fast refresh 또는 hot reload 기능을 통해 변경사항이 빠르게 반영됩니다.
•
expo prebuild와의 차이:
◦
expo prebuild:Expo 설정을 바탕으로 ios 및 android 네이티브 프로젝트 폴더를 생성하는 명령어입니다. 단순히 네이티브 코드의 “스캐폴딩(골격)”을 만들어 주는 역할을 하므로, 이 단계만으로는 앱 실행이나 JS 변경사항의 즉시 반영이 이루어지지 않습니다.
◦
즉시 변경사항 적용:expo run:ios는 빌드와 실행을 함께 처리하고, 개발 서버를 통해 JS 변경사항은 즉각 반영되지만, prebuild는 실행 단계가 아니기 때문에 저장 후에도 바로 반영되지 않습니다.
그러니까 expo-dev-client는 expo go의 대체제이다
정리
npx expo start = expo 개발서버(metro bundler)를 시작함. expo go를 사용할때 쓴다
expo run:ios 네이티브 프로젝트 빌드하고 시뮬레이터에서 실행함. bare workflow일때
expo run:ios —device 실제 기기에서 실행함
expo prebuild
ios, android 네이티브 폴더를 생성하면서 bare workflow로 전환함.
네이티브 모듈을 추가해야하는 경우, prebuild해서 네이티브 파일 만들고, 네이티브 모듈 다운로드 한 다음 혹은 설정을 변경한 다음 혹은 네이티브 코드를 직접 수정한 다음 eas build로 앱을 빌드하는것
expo build로 로컬에서 빌드하는것도 가능함. 하지만 eas build를 권장함.
eas build
클라우드에서 앱을 빌드해주고 기본적으로 expo prebuild는 자동으로 실행함.
eas build를 개발중에 반드시 할 필요는 없고 expo run:ios로 빌드해도 핫 리로딩 등의 기능이 동작한다.
하지만 빌드를 할때 환경 일관성을 유지하고, 다른 os에서도 빌드할수 있고 공유 및 테스트하기 편해서 그렇다
eas build와 expo run:ios로 빌드된 앱은 별도이며 expo run으로 빌드한건 빠른 테스트용이고 eas build는 실제 앱 바이너리를 얻기 위해서 하는것이다!
그러니까 eas build는 출시이전에 개발버전 최종으로 만들었을때 앱 바이너리를 공유하고 하기 위해서 빌드하는것이지 변경사항 확인을 위해서 매번 빌드할 필요는 없음
expo run으로도 앱 바이너리를 얻을수는 있음 디버깅용으로 만들어지지만.
eas build —profile development일때도 expo-dev-client를 포함하지만 production일때는 포함하지 않음
Flow
managed workflow로 작업하다가 네이티브 모듈을 추가해야하는 경우이면, expo prebuild로 ios, andriod 네이티브 코드를 생성하고, 네이티브 설정 혹은 모듈을 수정한 다음 eas build --platform ios를 수행하면 생성되어있는 기존의 코드를 통해서 eas 클라우드에서 빌드를 통해 앱을 생성한다. (만약 생성되어있지 않으면 내 루트폴더에 자동으로 prebuild해 준다. 하지만 네이티브 코드를 추가하거나 설정을 바꾸려면 미리 prebuild해서 적용해놔야한다) 그리고 그걸 내 시뮬레이터에 다운받아준다.
npx expo run:ios를 수행하면 metro 개발서버를 시작시키고 prebuild된 코드를 기반으로 빌드한다(eas build 앱 바이너리를 사용하지 않고 겹치지 않음 그냥 통째로 로컬에서 빌드) 그럼 내 시뮬레이터는 expo-dev-client를 기반으로 expo go처럼 동작하며 js변경사항에 대해서는 핫 리로딩 기능을 제공한다. 하지만 네이티브 변경사항이 있으면 prebuild를 다시 하고 expo run:ios를 해야한다.
expo run:ios는 내부적으로 xcode를 사용해서 빌드를 수행함. 빌드 수행후에 metro 개발서버를 켜주고 그래서 js변경사항이 생기면 실시간으로 적용해서 보여주는것. expo run:ios자체는 그냥 디버깅용 빌드명령일 뿐임
expo prebuild로 먼저 최신 네이티브 코드를 보장하고 expo run:ios해줘야함!!
expo-dev-client는 앱 바이너리에 포함되어서 핫리로딩 등의 기능을 해준다
npx expo start
npx expo start는 꼭 expo go에서만 사용할수있는게 아니다. expo-dev-client에서도 사용가능.
그냥 metro개발서버를 실행시켜주는것
그러니까 빌드 이후에 js변경사항만 있는 경우 맨날 prebuild하고 expo run하지말고 expo start그대로 하면 된다. expo run:ios를 수행하면 네이티브 앱에 expo-dev-client가 포함된다.
최적의 개발 흐름은 네이티브 변경으로 인해서 expo prebuild로 bare workflow → expo run:ios로 빌드하고 expo start 해서 js변경사항 핫 리로딩
npx expo start하면 자동으로 development build로 expo-dev-client로 메트로 서버 실행됨
expo install
네이티브 모듈 다운로드할때 사용함. ios/podfile을 변경해서 종속성 관리해줌.
변경된 podfile적용되려면 cd ios && pod install수행해야 cocoapod(npm같은 패키지 매니저)가 다운로드해줌.
네이티브 모듈을 다운로드하고 버전을 맞추는 역할은 expo install이 하고, 그 변경 사항이 iOS 프로젝트에 적용되도록 하는 건 pod install의 역할입니다. 당신이 이해한 내용은 기본적으로 맞습니다.
pod install
네이티브 모듈 추가한다음 바로 pod install수행해주는게 좋음. expo prebuild하기전에 수행하기!
네이티브 모듈을 제거했을때는
rm -rf Pods Podfile.lock
pod install --clean-install
JavaScript
복사
pod install이 필요한 이유는?
iOS 프로젝트에서 네이티브 종속성(Dependencies)이 변경되었을 때, CocoaPods을 통해 필요한 네이티브 패키지를 설치하고 정리하는 과정이 필요하기 때문이야.
이 작업을 안 하면 빌드할 때 "Could not find module", "Library not found" 같은 에러가 발생할 수 있음.
Error
Warning: Error: [@RNC/AsyncStorage]: NativeModule: AsyncStorage is null.
이 에러가 발생하는 이유?
expo install @react-native-async-storage/async-storage expo-dev-client
expo-dev-client가 다운로드되어있어야하고(이건 네이티브 모듈로 들어가는거임)
expo instsall은 expo와 호환된느 버전인지 자동으로 검사해서 버전 충돌 방지해줌
그니까 npm말고 expo install하기
pod install 해보고, expo run ios해보고 안되길래 앱 지우고 다시 해봤더니 성공함
gradle
./gradlew는 gradle wrapper를 실행시키는것 ⇒ 빌드&테스트 수행
gradle은 빌드 자동화 및 의존성 관리함. cocoapod은 ios에서 의존성 관리
ios는 xcode에서 자동으로 빌드 자동화 해줌
빌드 자동화 = 컴파일, 테스트, 패키징, 배포 등을 자동으로 수행해줌
./gradlew로 빌드하는것과 npx expo run:android의 차이는 gradle은 android프로젝트 파일만 빌드하고 expo run은 js파일도 포함해서 빌드한다.
pod install하는것처럼 의존성 관리하라고 ./gradlew수행하라는거같긴함
ios에서는 xcodebuild명령어를 사용함 마찬가지로 빌드 테스트 ipa파일생성함
2/24
Task :app:mergeDebugResources FAILED
Task :app:mergeDebugResources FAILED
ERROR: [mipmap-mdpi-v4/ic_launcher_foreground] /Users/hank/Desktop/vocasimple/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png [mipmap-mdpi-v4/ic_launcher_foreground] /Users/hank/Desktop/vocasimple/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp: Resource and asset merger: Duplicate resources
ERROR: [mipmap-mdpi-v4/ic_launcher] /Users/hank/Desktop/vocasimple/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp [mipmap-mdpi-v4/ic_launcher] /Users/hank/Desktop/vocasimple/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: Resource and asset merger: Duplicate resources
아이콘 설정이 잘못됐는지 중복으로 생성됐길래 git으로 지워줌.
Task :expo-modules-core:compileDebugKotlin FAILED
Task :expo-modules-core:compileDebugKotlin FAILED
e: This version (1.5.14) of the Compose Compiler requires Kotlin version 1.9.24 but you appear to be using Kotlin version 1.9.25 which is not known to be compatible. Please consult the Compose-Kotlin compatibility map located at https://developer.android.com/jetpack/androidx/releases/compose-kotlin to choose a compatible version pair (or suppressKotlinVersionCompatibilityCheck but don't say I didn't warn you!).
주어진 링크따라서 android/app/build.gradle에서 수정하니까 동작
android {
buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.5.15"
}
kotlinOptions {
jvmTarget = "19"
}
}
// 캐시 삭제
cd android
./gradlew --stop
./gradlew clean
rm -rf ~/.gradle/caches
rm -rf ~/.gradle/wrapper
cd ..
expo run:android
//android/gradle.properties
kotlin.version=1.9.24
//android/build.gradle
dependencies {
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.24")
}
ext {
kotlinVersion = '1.9.24'
}
JavaScript
복사
android emulator
안드로이드 에뮬레이터를 실행하기 위해 jdk 경로를 환경변수로 설정해야함
환경변수 설정한다는 것은 shell이 프로그램을 찾아가는 경로를 지정한다는것
환경변수 $HOME은 안만들어도 자동으로 존재함!!
export JAVA_HOME=/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home
source ./zshrc //터미널에 적용
echo $JAVA_HOME //결과 확인
JavaScript
복사
.zshrc, .bash_profile은 쉘의 설정파일이므로 nano 등으로 열기
export ANDROID_HOME=$HOME/Library/Android/sdk
export PATH=$PATH:$ANDROID_HOME/emulator
export PATH=$PATH:$ANDROID_HOME/platform-tools
JavaScript
복사
android sdk위치 확인하고 path붙여넣기 보통은 /Library/Android/sdk
shell, terminal
warp, terminal 등은 터미널이고 bash, zsh은 터미널에서 명령을 해석하고 실행하는 프로그램이다. warp같은 터미널을 써도 내부적으로 bash나 zsh 중 하나를 쓰고 있을것
터미널별로 다른 shell이 적용되고있는 경우도 있음
나는 zsh쓰고 있었다!
echo $SHELL // 어떤 쉘 쓰는지 확인
nano ~/.zshrc
JavaScript
복사
단어 없을때 에러뜨고 아무것도 없으니 어색함. 에러핸들링하고 백그라운드에 뭐 보여주기!!
계정을 생성했습니다. 이메일 인증 후 로그인해주세요!
보여준 다음 초기화하고 로그인으로 전환
이미 사용중인 이메일입니다 보여주기
존재하지 않거나 인증되지 않은 계정입니다.


