React Native Expo 프로젝트 초기 설정

2_현주·2026년 2월 25일
post-thumbnail

지난 글에서 디자인까지 마쳤으니, 이번엔 본격적으로 개발 환경을 세팅하고 프로젝트 구조를 잡는 과정을 담아보려 한다.


프로젝트 생성

RN에 Expo를 함께 사용할거라 이 명령어로 프로젝트를 만들었다.

npx create-expo-app@latest

그리고 테일윈드가 너무 좋아서 바~~~로 테일윈드까지 설치 해버렸습니다.

npm install nativewind tailwindcss

React Native에서 스타일을 적용하는 방법은 크게 두 가지인데, 기본적으로 제공하는 StyleSheet를 사용하거나 NativeWind처럼 테일윈드 기반 라이브러리를 사용하는 방법이 있다.

StyleSheet는 애니메이션처럼 동적으로 스타일 값이 바뀌는 경우에 더 유리하지만, 스타일을 확인하려면 정의해둔 곳을 찾아 계속 왔다갔다 해야 한다는 단점이 있다.

반면 테일윈드는 태그 바로 옆에 클래스명으로 스타일이 다 보이니까 훨씬 직관적이었다. 그래서 복잡한 애니메이션에는 StyleSheet를 쓰고 기본적인 UI 스타일 작업에는 테일윈드를 쓰기로 정했다.


NativeWind 초기 설정

이후에는 NativeWind 사용을 위해 초기 파일을 설정해주었다.
이 블로그를 참고해서 현재 프로젝트에서 숨김 처리 되어있는 babel.config.js + metro.config.js 이 파일을 꺼내야 한다.

tailwind.config.js

module.exports = {
  content: [
    './app/**/*.{js,jsx,ts,tsx}',
    './components/**/*.{js,jsx,ts,tsx}',
  ],
  presets: [require('nativewind/preset')],
  theme: {
    extend: {
      colors: {
        primary: '#5B0E14',
        secondary: '#F1E194',
        ivory: '#F9F5EB',
        'primary-light': '#8B3A3A',
        'primary-dark': '#4A1515',
        white: '#F5F5F5',
        black: '#333333'
      },
    },
  },
  plugins: [],
};

색상은 지난 글에서 Stitch로 잡아둔 디자인 시스템을 그대로 가져왔다.

global.css

@tailwind base;
@tailwind components;
@tailwind utilities;

babel.config.js

module.exports = function(api) {
  api.cache(true);
  return {
    presets: [
      ['babel-preset-expo', { jsxImportSource: 'nativewind' }],
      'nativewind/babel',
    ],
  };
};

metro.config.js

const { getDefaultConfig } = require('expo/metro-config');
const { withNativeWind } = require('nativewind/metro');

const config = getDefaultConfig(__dirname);

module.exports = withNativeWind(config, { input: './global.css' });

nativewind-env.d

/// <reference types="nativewind/types" />

tsconfig.json

{
  "extends": "expo/tsconfig.base",
  "compilerOptions": {
    "strict": true,
    "paths": {
      "@/*": ["./*"]
    }
  },
  "include": [
    "**/*.ts",
    "**/*.tsx",
    ".expo/types/**/*.ts",
    "expo-env.d.ts",
    
    // 추가한 두 줄
    "**/*.css",
    "nativewind-env.d.ts"
  ]
}

휴,,, 일단 라이브러리를 위한 초기 설정을 다 해주었다.


일단 코드부터 짜봤다

구조를 먼저 잡아야지... 하면서도 디자인이 머릿속에 생생할 때 바로 화면을 만들어보고 싶어서 냅다 기본 구조에 코드 먼저 작성해봤다.ㅋㅋㅋㅋㅋ

그러다 모달 부분에서 조금 막혔었는데 이 블로그의 글을 보고 참고해 아주 부드러운 모달을 완성할 수 있었다.

모달 완성


디렉토리 구조 잡기

파일이 더 많아지기 전에 구조를 잡아야 할 것 같아서 여기저기 서치해서 구조를 정했다.

구조를 짜면서 헷갈렸던 부분이 두 가지 있었다.

1. screens/ 폴더가 필요할까?

여러 RN 프로젝트 구조를 보면 screens/ 폴더가 있는 경우가 많아서 나도 넣어야 하나 싶었는데, 알고 보니 React Navigation을 직접 쓸 때 필요한 폴더였다. Expo Router는 app/ 폴더 자체가 라우팅이랑 스크린 역할을 동시에 하기 때문에 따로 만들 필요가 없었다.

2. app/src/를 분리해야 할까?

Expo Router를 쓰면 app/ 폴더가 라우팅 역할을 고정으로 담당하기 때문에, 여기에 비즈니스 로직까지 섞이면 나중에 관리가 힘들어질 것 같았다. 그래서 라우팅은 app/에, 나머지 로직은 전부 src/ 안에 넣는 구조로 분리하기로 했다.

그렇게 해서 최종적으로 정한 구조가 이거다!

my-app/
├── app/                        # Expo Router 라우팅
│   ├── (tabs)/                 # 탭 네비게이션
│   ├── (modals)/               # 모달 그룹
│   ├── products/               # 완성품 관련 라우트
│   ├── materials/              # 재료 관련 라우트
│   └── _layout.tsx             # 루트 레이아웃
│
├── src/                        # 비즈니스 로직
│   ├── components/             # 컴포넌트
│   ├── hooks/                  # 커스텀 훅
│   ├── services/               # API 통신
│   ├── store/                  # Zustand store
│   ├── types/                  # 타입 정의
│   ├── utils/                  # 유틸 함수
│   └── constants/              # 상수 (색상, 설정 등)
│
├── assets/                     # 정적 파일
│
├── app.json
├── tailwind.config.js
└── package.json

마치며

이제 이 구조대로 본격적으로 개발을 시작해보려 한다! 다음 글에서는 실제 화면 구현 과정을 담아볼 예정이다.

profile
프론드엔드 개발자 이현주 입니다.

0개의 댓글