[RN] 리액트네이티브 커스텀폰트 적용하기 (파이널)

tech·2023년 1월 25일
0

0. intro

1년 반 전에 쓴 글들을 보니, 읽으신 많은 분들께 죄송한 마음이 들어 오늘 최종판을 작성하고자 합니다(ㅎㅎㅎ).


이하 음슴체 또는 평어 양해 부탁드립니다.


우선, 커스텀 폰트 적용하는 것에는 여러가지 방법이 있겠지만 나는 아래의 방법으로 최종 적용하여 우리 팀에서는 상용 서비스에 배포를 하였다.

간혹 development 상태에서 공유된 정보는 production 상태에서 먹통이 되기도 하여, 애를 많이 먹었던 것 같다.

다행히 본 정보는 production 상태에서도 무리 없이 사용 가능하다는 점은 참고해주기 바란다.



스펙 공유)

우리 프로젝트의 프론트엔드는 bareworkflow react-native 이지만,
expo 제공 라이브러리를 여러가지 사용하였는데 그 중 expo-font는 커스텀폰트 적용시 매우 유용한 툴이라고 생각한다.
또한 아이콘 적용 시에도 expo/vector-icons 를 사용하였다.
폰트 및 아이콘 적용시 ios 설정에 유의하도록 하자.

커스텀폰트로는 프리텐다드를 사용하였다.

1. 폴더에 폰트 저장하기.

폴더 세팅은 각자 다 다르겠지만, 우리는 다음과 같이 저장해두었다.
otf 나 ttf 중 하나만 저장해도 무방하다.


📦 프로젝트
 ┣ 📜android
 ┣ 📜ios
 ┣ 📜assets
 | ┣ 📜fonts
 | | ┣ 📜Pretendard-Black.otf
 | | ┣ 📜Pretendard-Black.ttf
 | | ┣ 📜Pretendard-Bold.otf
 | | ┣ 📜Pretendard-Bold.ttf
 | | ┣ 📜Pretendard-ExtraBold.otf
 | | ┣ 📜Pretendard-ExtraBold.ttf
 | | ┣ 📜Pretendard-ExtraLight.otf
 | | ┣ 📜Pretendard-ExtraLight.ttf
 | | ┣ 📜Pretendard-Light.otf
 | | ┣ 📜Pretendard-Light.ttf
 | | ┣ 📜Pretendard-Medium.otf
 | | ┣ 📜Pretendard-Medium.ttf
 | | ┣ 📜Pretendard-Regular.otf
 | | ┣ 📜Pretendard-Regular.ttf
 | | ┣ 📜Pretendard-SemiBold.otf
 | | ┣ 📜Pretendard-SemiBold.ttf
 | | ┣ 📜Pretendard-Thin.otf
 | | ┣ 📜Pretendard-Thin.ttf
 | | ┗ 📜PretendardVariable.ttf
 ┣ 📜src
 |┗ 📜app.tsx
 ...
 ┣ 📜app.json
 ┣ 📜index.js
 ┣ 📜package.json
 ┗ 📜tsconfig.json

2. app.tsx에서 설정.



코드는 아래와 같다.

App.tsx)

import React, {useState, useEffect} from "react" ;
import * as Font from "expo-font";
import { Ionicons } from "@expo/vector-icons";
import { Asset } from "expo-asset";
import SplashScreen from 'react-native-splash-screen'


const App = () => {
  
  ... (중략)
  
 const preloadAssets = () => {
    const fontToLoad = [Ionicons.font];
    const fontPromises = fontToLoad.map((font: any) => Font.loadAsync(font)); 
      const imagesToLoad = [
      require("./assets/icons/icon_home_inactive.png"),
      require("./assets/icons/icon_home_active.png"),
      require("./assets/icons/icon_home_active_dark.png"),
      require("./assets/icons/icon_search_inactive.png"),
      require("./assets/icons/icon_search_active.png"),
      require("./assets/icons/icon_community_active.png"),
      require("./assets/icons/icon_community_inactive.png"),
      require("./assets/icons/icon_community_active_dark.png"),
      require("./assets/icons/icon_rewards_active_dark.png"),
      require("./assets/icons/icon_rewards_inactive.png"),
      require("./assets/icons/icon_rewards_active.png"),
      require("./assets/icons/icon_my_active_dark.png"),
      require("./assets/icons/icon_my_inactive.png"),
      require("./assets/icons/icon_my_active.png"),
    ];
    const imagePromises = imagesToLoad.map((image) => Asset.loadAsync(image));
    return Promise.all<void | Asset[]>([...fontPromises, ...imagePromises]);
 }
  // preloadAssets 은 앱 실행 로딩 중 신속하게 불러와야 하는 에셋을 정의합니다.
 
 	  const fetchFonts = () => {
    return Font.loadAsync({
      Pretendard: require("./assets/fonts/PretendardVariable.ttf"),
      "Pretendard-Light": require("./assets/fonts/Pretendard-Light.otf"),
      "Pretendard-Black": require("./assets/fonts/Pretendard-Black.otf"),
      "Pretendard-Bold": require("./assets/fonts/Pretendard-Bold.otf"),
      "Pretendard-ExtraBold": require("./assets/fonts/Pretendard-ExtraBold.otf"),
      "Pretendard-Thin": require("./assets/fonts/Pretendard-Thin.otf"),
      "Pretendard-ExtraLight": require("./assets/fonts/Pretendard-ExtraLight.otf"),
      "Pretendard-SemiBold": require("./assets/fonts/Pretendard-SemiBold.otf"),
      "Pretendard-Regular": require("./assets/fonts/Pretendard-Regular.otf"),
      "Pretendard-Medium": require("./assets/fonts/Pretendard-Medium.otf"),
    });
  };
  	
  
   const preload = async () => {
     	//AsyncStorage에서 꺼내와야 하는 아이템 출력. (생략)
    	return await preloadAssets() && fetchFonts(); 
   }
  
   // 앱 실행시 한 번 만 불러옵니다.
   // preload 가 완료되면 스플래시 화면이 꺼지도록 설정
   useEffect(()=> {
     preload().then((context)=> {
       SplashScreen.hide();
     });
   }, []); 
  
  
  
   return (
     .... 
   	<NavigationContainer ref={navigationRef} linking={linking}>
        <RootNav />
    </NavigationContainer>
   .... 
   );
  
}

export default App;

이렇게 코드를 짜면,
앱을 켰을때 스플래시 스크린이 먼저 띄워질 것이고, 그동안 preload 함수가 실행되어 폰트 및 이미지들이 신속하게 로딩될 것이다.
완료 후, 스플래시 화면이 꺼지고 미리 설계한 화면이 나타난다면
app.tsx(app.js)설정은 잘 된 것이다.

도움이 되면 좋겠다.

끝 !

profile
in Hinter

1개의 댓글

comment-user-thumbnail
2023년 7월 19일

안녕하세요, RN for web(expo managed) 환경에서도 같은방법으로 커스텀폰트를 가져올수있나요? 제가 알기론 rn for web 환경에는 splash없는걸로 알고있는데, splash 없어도 커스텀 폰트 불러올수있을지 궁금합니당!

답글 달기