Develop

[React Expo] 시작해보기

De_Santa 2026. 6. 21. 00:39

 

현재 다니고 있는 회사에서 갑작스럽게 안드로이드 기반 OS에서 실행되는 서비스를 개발해야할 것 같다는 이야기를 들어

순수  Native 앱이 아닌 그나마 빠르게 개발할 수 있는 React Native로 개발해보는 것으로 방향을 잡았습니다

 

리액트 네이티브와 Expo 차이는 뭘까?

비교항목 리액트 네이티브 Expo
개념 React 프레임워크(엔진자체) 리액트 네이티브 기반으로 만든 툴킷
네이티브 폴더 ios/android 폴더 노출되어 직접관리 ios/android 폴더를 숨겨두고 Expo가 알아서 관리
초기 세팅 Xcode, Android Studio, 환경변수 설정 필수 (매우 복잡) Node.js와 스마트폰만 있으면 5분 만에 끝Expo Go 어플을 설치해야함!
네이티브 코드수정 Java, Swift, Objective-C 코드를 직접 수정 가능 기본적으로 불가능했으나, 최근 버전에서는 커스텀 가능
빌드/배포 내 컴퓨터 자원을 써서 직접 빌드 Expo의 클라우드 서버(EAS)를 통해 윈도우에서도 빌드 가능

 

네이티브 폴더

네이티브 폴더를 직접관리하는 것 과 자동으로 관리한다는 말은 각 os에 구동을 하기 위해 관련된 설정 파일(네이티브)들과 연관된 기능을 개발하거나 수정한다 했을때 각 os의 기능을 맡는 Swift , Kotlin 등의 파일을 직접 수정해야하지만 Expo의 미리 개발된 기능들(푸쉬알림 등)에 대해서 수정을 할 경우 따로 네이티브 파일을 수정할 필요없이 루트에 있는 app.json 설정 파일에 필요한 옵션을 적어두거나 Expo가 미리 만들어 둔 자바스크립트 API를 호출하기만 하면 각 os에 맞는 네이티브 코드가 자동으로 생성되며 반영됩니다

 

초기세팅

과거 유니티엔진으로 개발을 해보면서 알게된 사실이었지만 안드로이드배포를 위해 초기개발환경 셋팅이 굉장히 까다로운 부분이 많았습니다 안드로이드 스튜디오설치 및 테스트할 스마트폰의 버전과 맞는 SDK 설치하고 환경변수 셋팅까지 이 중에서 하나라도 박자가 안맞으면 뿜어대는 오류들 상당히 골치아팠는데 Expo를 사용하면 이 문제가 해결됩니다 이러니 안쓰고 버틸수 없죠 

 

단점은 없을까?

물론 완벽하지 않습니다 Expo는 카메라, GPS, 푸시알림과 같은 주요 네이티브 기능을 Expo에서 미리 API로 개발을 해뒀기 때문에 끌어다 사용하면 되는데 특수한 경우(금융 앱 보안모듈, 결제 SDK) 등 C계열 또는 네이티브 코드로 작성된 라이브러리들을 연결하여 사용하기가 상당히 까다로운 부분이 있다고합니다 그리고 순수 리액트 네이티브로 빌드된 앱보다 당연히 용량 면에서 좀 더 무거운 점도 있습니다.

 

과거에는 Expo로 개발하다가 기능 제약의 한계로 인해 리액트 네이티브로 다시 개발하는 경우가 있었는데 최근 Expo에서 필요하면 언제든지 네이티브 코드를 생성하고 커스텀할 수 있도록 expo prebuild 기능을 지원해서 이 문제도 해결됐다고 합니다.

 

 

Expo 시작해보기 - 프로젝트 생성

npx create-expo-app@latest my-first-app --template blank-typescript

node 개발을 많이 해보신 분이라면 쉽게 이해할 수 있는 패키지 설치 명령어입니다 "my-first-app"가 프로젝트명입니다.

 

프로젝트 실행하기

npm run start

 

실행이 정상적으로 됐다면 위와 같이 QR코드와 url 이 나타나는데 플레이 스토어에서 Expo Go 어플을 설치한 뒤 QR을 스캔하면 실시간으로 변경내용을 모바일에서 확인할 수 있습니다

 

만약 위와같이 문제가 발생한다면 

npx expo start --tunnel

위 명령어로 실행한뒤 다시 QR을 찍으면 정상적으로 연결이 됩니다 예상으로 네트워크환경 문제로인해 연결이 안되는 상황이 있을 수 있어 Tunnel 모드로 실행하면 방화벽을 무시하고 연결이됩니다.

 

화면 수정해보기

import React, { useState } from 'react';
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';

export default function App() {
  const [count, setCount] = useState(0);

  return (
    <View style={styles.container}>
      <Text style={styles.title}>안녕하세요, 시니어 멘토님!</Text>
      <Text style={styles.counterText}>현재 카운트: {count}</Text>
      
      {/* 웹의 <button> 대신 클릭(터치) 가능한 TouchableOpacity 사용 */}
      <TouchableOpacity 
        style={styles.button} 
        onPress={() => setCount(count + 1)}
      >
        <Text style={styles.buttonText}>클릭해서 숫자 올리기</Text>
      </TouchableOpacity>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1, // 화면 전체를 다 차지하겠다는 뜻
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center', // 세로 방향 기준으로 가운데 정렬
  },
  title: {
    fontSize: 22,
    fontWeight: 'bold',
    marginBottom: 20,
  },
  counterText: {
    fontSize: 18,
    marginBottom: 20,
    color: '#333',
  },
  button: {
    backgroundColor: '#007AFF',
    paddingVertical: 12,
    paddingHorizontal: 24,
    borderRadius: 8,
  },
  buttonText: {
    color: '#fff',
    fontSize: 16,
    fontWeight: '600',
  },
});

스마트폰 화면에 버튼이 정상적으로 보이고 클릭 시 카운트가 된다면 정상적으로 개발환경이 셋팅되었습니다.