본문 바로가기
Front-End

[React Native Web] 앱과 웹을 한번에 개발하기 - 1

by kimik 2021. 2. 7.

 

React를 처음 학습하면서 Parcel이란 번들러를 사용하여 React Todolist를 개발한 적이 있습니다. 벌써 거의 2년이 되어가네요.

 

이제 실무에서도 React를 1년넘게 사용하면서, 앱에도 욕심이 나서 React Native를 학습해보았는데 웹은 따로 개발해야하는게

 

굉장히 부담(이라쓰고 귀찮)되더라구요. React Native나 React나 FaceBook에서 개발했으니 충분히 같이

 

개발할 수 있지않을까.. 하던차에 React native Web이라는 것이 등장했고, Strapi로 api개발에 대해서 한번 글을 썼으니

 

이것을 주제로 프론트단을 구성해보면어떨까 하여 글을 써보겠습니다.

 

node 버전은 10이상을 권장하며 필자는 14버전을 사용하였습니다. (node 버전 변경이 쉬운 nvm추천)

npm은 7.5.1 yarn을 사용해도 무방합니다.

1. React Naitve 설치

React Native는 앱 어플리케이션 개발을 위해 ios와 android에 관한 파일도 설정되어야하기 때문에 React native에서 

 

제공하는 CLI를 활용합시다. 

npm install -g react-native-cli

를 설치하여 cli를 설치하신 후 프로젝트 폴더를 아래와 같은 커맨드로 설정해줍시다.

npx react-native init rnwClient

설치는 꽤 시간이 걸리고 끝나고 나면 해당 폴더로 이동합니다.

 

기존에 Web만을 위한 React 세팅과는 달리 ios와 android를 포함하고있기 때문에 Web까지 전부 설정하고 실행했을때

 

문제가 생기면 문제점을 찾기가 힘듭니다. 그렇기 때문에 스텝하나를 밟을때마다 실행이 잘되는지를 확인해주도록 합니다. 

2. IOS 및 Android 확인

(윈도우의 경우에는 IOS를 확인하려면 애플개발자계정 및 ios기기가 혹은 Expo를 사용해야합니다.)

 - ios를 에뮬레이터로 확인

 

ios를 확인하려면 기본적으로 맥북이나 아이맥에 Xcode가 설치되어있어야합니다. (Xcode는 앱스토어가 아닌 애플 개발자 사이트에서 받으세요!)

npm run ios

위의 코드를 실행해주면 

위와 같은 화면이 뜨면 정상적으로 설치된것입니다.

 

 - andorid 확인

reactnative.dev/docs/environment-setup

 

Setting up the development environment · React Native

This page will help you install and build your first React Native app.

reactnative.dev

react native공식홈에서 가이드한 대로 homebrew, watchman, JDK, Android Studio를 설치 후에 

npm run android

를 실행해줍니다. 

 

위와같이 실행된다면 OK!

 

3. React native web 세팅

이제 Web환경을 위한 npm 패키지들을 설치해보도록 하겠습니다. React native에서 React는 설치되어있으므로, 

npm install --save react-dom
npm install --save-dev @babel/core babel-loader @babel/preset-react
npm install --save-dev webpack webpack-cli webpack-dev-server html-webpack-plugin

설치가 완료되면 package.json의 script부분을 아래와 같이 수정해줍니다.

"scripts": {
    "android": "react-native run-android",
    "ios": "react-native run-ios",
    "start": "react-native start",
    "build-react": "webpack --mode production",
    "start-react": "webpack serve --config ./webpack.config.js --mode development",
    "test": "jest",
    "lint": "eslint ."
  },

(* webpack버전이 변경될때 dev-server의 실행명령이 자주 변경되니 참고바랍니다.)

 

프로젝트의 루트에 webpack.config.js를 만들고 아래와 내용을 복사 붙여넣기 합니다.

const path = require('path')
const HTMLWebpackPlugin = require('html-webpack-plugin')

const HTMLWebpackPluginConfig = new HTMLWebpackPlugin({
  template: path.resolve(__dirname, './public/index.html'),
  filename: 'index.html',
  inject: 'body',
})

module.exports = {
  entry: path.join(__dirname, 'index.web.js'),
  output: {
    filename: 'bundle.js',
    path: path.join(__dirname, '/build'),
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules\/(?!()\/).*/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-react'],
          },
        },
      },
    ],
  },
  plugins: [HTMLWebpackPluginConfig],
  devServer: {
  	open: true,
    historyApiFallback: true,
    contentBase: './',
    hot: true,
  },
}

이 포스트는 React native web이 주 내용이므로 위에 관해서는 webpack5 버전에 대한 문서를 참고바랍니다.

 

webpack에 대한 설정이 완료되었으니 뼈대가 될 html을 만들어줍니다. webpack에서 설정한 경로대로 

 

루트에 public폴더를 만들고 index.html을 만든 후에 아래내용을 붙여 넣습니다.

<!DOCTYPE html>
<html>
  <head>
    <title>React Native Web</title>
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>

저 app이라는 div에 react로 작성된 코드가 들어가게됩니다.

 

그뒤에 index.web.js라는 파일을 루트에서 생성하고 아래의 내용을 붙여 넣습니다.

import React from 'react'
import ReactDOM from 'react-dom'

import App from './App.web'

ReactDOM.render(<App />, document.getElementById('app'))

불러올 App.web.js도 루트에 생성해줍니다.

import React from 'react'

function App() {
  return (
    <>
      <h1>Hello world from react</h1>
    </>
  )
}

export default App

이 **.web.js들은 앱용 네이티브파일과 웹용 네이티브 파일을 분리하기위한 확장자로 이해하시면됩니다.

 

일반 네이티브와 웹을 같이 쓰는경우에는 **.js,

웹에서만 사용하려면 **.web.js,

네이티브에서만 사용하려면 **.native.js. 

ios에서만 사용하려면 **.ios.js

android에서만 사용하려면 **.android.js로 파일을 생성해서 사용하면됩니다.

이에 대해서는 나중에 플랫폼 분기를 칠때 더 설명드리겠습니다.

파일구조는 이렇게되어있습니다. 

 

그럼 web버전이 잘 실행되는지 체크해보도록 하겠습니다.

npm run start-react

위와같이 뜨면 성공! 인데..

 

사실 아직 React Naitve의 코드를 변환해서 띄운게 아닙니다 ㅎㅎ..

npm install react-native-web

위와같이 실행했을때 혹시 종속성 문제(react, react-dom과의 버전문제)가 발생한다면

npm install --legacy-peer-deps react-native-web

으로 설치하시길 바랍니다. 그리고 webpack에 설정에 

resolve: {
  alias: {
    'react-native$': 'react-native-web',
  },
},

위의 구문을 추가하여 아래와 같이 완성해줍니다.

const path = require('path')
const HTMLWebpackPlugin = require('html-webpack-plugin')

const HTMLWebpackPluginConfig = new HTMLWebpackPlugin({
  template: path.resolve(__dirname, './public/index.html'),
  filename: 'index.html',
  inject: 'body',
})

module.exports = {
  entry: path.join(__dirname, 'index.web.js'),
  output: {
    filename: 'bundle.js',
    path: path.join(__dirname, '/build'),
  },
  resolve: {
    alias: {
      'react-native$': 'react-native-web',
    },
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules\/(?!()\/).*/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-react'],
          },
        },
      },
    ],
  },
  plugins: [HTMLWebpackPluginConfig],
  devServer: {
    open: true,
    historyApiFallback: true,
    contentBase: './',
    hot: true,
  },
}

그리고 App.web.js 파일을 열어

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

function App() {
  return (
    <View>
      <Text>Hello world from react</Text>
    </View>
  )
}

export default App

위와같이 태그를 React native 코드로 변환하고 

npm run start-react

를 실행해봅시다.

 

위와같이 뜬다면 React native Web패키지는 정상동작하는 걸 확인했네요. 

 

다음글에서는 React native로 작성한 코드가 ios android web 모든 플랫폼에서 동일하게 나오도록 설정하고

 

React native의 컴포넌트 들에 대해 조금 더 알아보도록 하겠습니다 

 

번외 - React Native를 사용하여 굳이 Web까지 하는이유!!

 * 단점

 - 기존에 익혔던 HTML태그를 사용할 수 없으므로 러닝커브 발생

 - 어느 한 플랫폼에서 버그 발생시 해당 플랫폼을 수정하면 다른 플랫폼에서 버그가 발생할 가능성이 농후

 

 * 장점

 - 하나의 코드로 모든 플랫폼을 개발할 수 있으며, 위에 살짝 언급한대로 파일 분리로 플랫폼 분리도 용이함

 - React Native의 Switch, Modal 등 손수 개발하기 약간 귀찮은 컴포넌트들을 웹에서도 쉽게 사용가능

 - 전체적인 코드 구성은 React와 다르지않아 컴포넌트를 제외한 러닝커브가 적음

 - Native-Base, React-native-Element 등 UI 라이브러리에서도 Web을 제공하여 모든 플랫폼에 UI를 쉽게 개발가능

 

단점보다는 장점이 명확히 더 좋으므로 이렇게 글을 쓰게되었습니다. 이 개발 환경을 바탕으로

 

Typescript와 Strapi(백엔드서버)와 연동하여 개발하는 과정을 시리즈로 작성해볼예정입니다. 

 

감사합니다. 

댓글