초기 설정

박정빈·2024년 10월 29일

Expo 시작

dir 생성

mkdir ./[폴더이름]
cd ./[폴더이름]

Expo 프로젝트 초기화

npx create-expo-app@latest --template expo-template-blank-typescript .

의존성 설치

npm 으로 시작이 되었다면,
node_module package-lock.json 을 삭제하고 다음을 실행한다.

yarn install

Tailwind CSS

nativewind
이 링크는 nativewind 깃허브 read.me 에서 소개한 nativewind 홈페이지 인데..
공식을 따라하다가 안되어서 구글링해서 방법을 찾았다.

nativewind 설치

yarn add nativewind@2.0.11 react-native-reanimated@3.10.1 tailwindcss@3.3.2

nativewind 는 2.0.11 버전,
react-native-reanimated 는 3.10.1 버전,
tailwindcss 는 3.3.2 버전으로 받아야한다.
그 이상의 버전을 사용하면 에러가 난다.

tailwind.config.js 생성

npx tailwindcss init

파일 수정

//tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ["./App.{js,jsx,ts,tsx}", "./src/**/*.{js,jsx,ts,tsx}"],
  theme: {
    extend: {},
  },
  plugins: [],
};
//babel.config.js
module.exports = function(api) {
  api.cache(true);
  return {
    presets: ['babel-preset-expo'],
    plugins: ["nativewind/babel"],
  };
};

nativewind-env.d.ts

nativewind-env.d.ts 파일을 생성해서 다음과 같이 써주면 해결된다.

//nativewind-env.d.ts
/// <reference types="nativewind/types" />

스토리북

참고

스토리북 생성

npx storybook@latest init

metro 설정

//metro.config.js
const path = require('path');
const { getDefaultConfig } = require('expo/metro-config');
const withStorybook = require('@storybook/react-native/metro/withStorybook');

const config = getDefaultConfig(__dirname);

module.exports = withStorybook(config, {
enabled: true,
configPath: path.resolve(__dirname, './.storybook'),
});

app.json 편집

app.jsonapp.config.js로 바꾼뒤 다음과 같이 작성한다.
app.config.js를 사용하면, js를 사용해서 동적으로 설정을 해줄 수 있다.

//app.config.js
export default ({ config }) => ({
    ...config,
    name: "등대",
    slug: "lighthouse",
    version: "1.0.0",
    orientation: "portrait",
    icon: "./assets/icon.png",
    extra: {
      storybookEnabled: process.env.STORYBOOK_ENABLED,
    },
    splash: {
      image: "./assets/splash.png",
      resizeMode: "contain",
      backgroundColor: "#ffffff",
    },
    updates: {
      fallbackToCacheTimeout: 0,
    },
    assetBundlePatterns: ["**/*"],
    ios: {
      supportsTablet: true,
    },
    android: {
      adaptiveIcon: {
        foregroundImage: "./assets/adaptive-icon.png",
        backgroundColor: "#FFFFFF",
      },
    },
    web: {
      favicon: "./assets/favicon.png",
    },
  });

extra 설정을 통해서 expo 상수를 사용하여 앱에서 storybookEnabled 변수에 액세스할 수 있게 했다.

extra: {
    storybookEnabled: process.env.STORYBOOK_ENABLED,
  },

이런 식으로 사용한다는 말이다.

import Constants from 'expo-constants';
const apiUrl = Constants.expoConfig.extra.storybookEnabled;

App.tsx 수정

이제 storybookEnabled 변수가 true 이면 스토리북이 실행되고, false 이면 앱이 실행되도록 바꾸자

...
import Constants from "expo-constants";

function App() {  return ...  }

let AppEntryPoint = App;
                
if (Constants.expoConfig?.extra?.storybookEnabled === "true") {
  AppEntryPoint = require("./.storybook").default;
}

export default AppEntryPoint;

package.json 수정

   yarn add cross-env

STORYBOOK_ENABLED 플래그를 true로 설정하여 앱을 실행하는 새로운 명령을 추가,

yarn start를 실행하면 앱 코드가 표시되고,
yarn storybook를 실행하면 스토리북이 표시됩니다.

"scripts": {
    "storybook": "cross-env STORYBOOK_ENABLED='true' expo start",
}

main.ts 수정

stories 폴더를 src밑에서 관리하기 위해 경로를 수정한다.

.storybook/main.ts
...
  stories: ['../src/stories/**/*.stories.?(ts|tsx|js|jsx)'],
...

폰트 설정

preview.tsx 파일을 수정해주어 스토리북에서도 폰트가 적용되게 한다.

//.storybook/preview.tsx
import { loadAsync } from 'expo-font';

const loadFonts = async () => {
  await loadAsync({
    "MusticaPro-SemiBold": require("../assets/fonts/MusticaPro-SemiBold.otf"),
    "Pretendard-Bold": require("../assets/fonts/Pretendard-Bold.otf"),
    "Pretendard-Regular": require("../assets/fonts/Pretendard-Regular.otf"),
  });
};

(async () => {
  await loadFonts();
  // 폰트가 로드될 때까지 기다려~
})();

const preview = {
  parameters: {
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/,
      },
    },
  },
};

export default preview;

네비게이션

설치

yarn add @react-navigation/native @react-navigation/native-stack
npx expo install react-native-screens react-native-safe-area-context

App.tsx 수정

import {NavigationContainer} from '@react-navigation/native';
import {createNativeStackNavigator} from '@react-navigation/native-stack';
import HomeScreen from "./src/screens/HomeScreen";
...
const Stack = createNativeStackNavigator();
...
function App() {
  ...
 return (
    <NavigationContainer>
    <Stack.Navigator>
      <Stack.Screen
        name="Home"
        component={HomeScreen}
        options={{title: 'Welcome'}}
      />
    </Stack.Navigator>
  </NavigationContainer>
  );
}

SVG

설치

yarn add --dev react-native-svg-transformer

metro.config.js 설정

스토리북 설정 위에 추가 작성 한다.

const { getDefaultConfig } = require("@expo/metro-config");
const withStorybook = require('@storybook/react-native/metro/withStorybook');
const path = require('path');

module.exports = ( () => {
  const config = getDefaultConfig(__dirname);
  const { transformer, resolver } = config;

  config.transformer = {
    ...transformer,
    babelTransformerPath: require.resolve("react-native-svg-transformer/expo")
  };
  config.resolver = {
    ...resolver,
    assetExts: resolver.assetExts.filter((ext) => ext !== "svg"),
    sourceExts: [...resolver.sourceExts, "svg"]
  };
  config.resolver.assetExts.push("otf"); // 'otf' 확장자 추가

  return withStorybook(config, { // 두 개의 module.exports를 합침
    enabled: true,
    configPath: path.resolve(__dirname, './.storybook'),
  });
})();

declaration.d.ts 추가

declare module '*.svg' {
  const content: any;
  export default content;
}

폰트

expo-font 설치

yarn add expo-font

폰트 설치

/assets/fonts/ 에 원하는 폰트파일 .otf 를 옮긴다.

App.tsx 수정

import * as Font from "expo-font";
...다른 코드 모두 생략
const fetchFonts = () => {
  return Font.loadAsync({
    "Pretendard-Medium": require("./assets/fonts/Pretendard-Medium.otf"),
  });
};
...
export default function App() {
  const [fontsLoaded, setFontsLoaded] = useState(false);

  useEffect(() => {
    const loadFonts = async () => {
      await fetchFonts();
      setFontsLoaded(true);
    };
    loadFonts();
  }, []);

  if (!fontsLoaded) {
    // 폰트가 로드되기 전에는 아무것도 렌더링하지 않음
    return null;
  }

  return (...

사용

사용하고자 하는 파일에서 다음과 같은 형식으로 사용가능

<Text style={{fontFamily: "Pretendard-Medium"}}>text</Text>

0개의 댓글