스토어 배포 없이 React Native 앱 변경하기 - 2편

Park June Chul·2021년 3월 10일
0

ReactNative

목록 보기
2/2
post-thumbnail

이 구현은 간단한 아이디어에서 시작합니다.

Javascript에는 eval이라는 함수가 있습니다. 주어진 string의 코드를 실행하고 결과값을 리턴하는 함수인데, 모두들 이 함수를 무조건적으로 싫어합니다.

저는 eval을 쓰지 말라고 하는 대부분의 이유에 반박을 할 수 있지만, 그렇게 되면 이 글은 엄청나게 논점에서 벗어나게 됩니다. 중요한 것은 우리는 https 를 통해서 안전하게 다운받은 소스코드만 실행시킬것입니다. (물론 https또한 로컬 디바이스의 바이러스나 MITM등으로 조작될 수 있지만, 이 시점에서 이미 eval의 위험성은 아예 문제가 되지 않겠지요.)

만약 우리가 eval을 쓰는것에 대해 개의치 않고, 다음으로 넘어갈 준비가 되었다면, 아마 이러한 코드를 작성해볼 수 있을 것입니다.

const getScore = (user) => {
  return eval(fetch('https://mycode.com/getScore'), { user });
};

유저의 스코어를 계산하는 가상의 함수인데, 스코어 계산식이 바뀌어도 언제든지 앱이 최신 공식으로 작동하도록 할 수 있겠지요.

이러한 부분은 당연히 RPC 혹은 REST로 처리해야 합니다. 하지만 우리가 최종적으로 하고자 하는 UI 렌더링은 이 방법으로는 불가능하지요.

이제 UI를 eval을 통해서 구현하는 방법을 알아보겠습니다.

아주 당연한 이야기지만, React Component의 소스코드도 eval에 넣을 수 있습니다.

const Boo = eval(`
const Boo = () => {
  return /*#__PURE__*/React.createElement(Text, null, "boo");
};
Boo; // 이 줄을 작성해야 eval이 Boo를 리턴합니다.
`);

eval은 JS 실행기이고, jsx는 JS의 영역이 아니기 때문에 transpile된 최종 결과물을 넣어야 합니다.
Babel REPL
에서 jsx코드를 순수 js 코드로 변환시킬 수 있습니다.

console.log(Boo) 를 이용해서 리턴값을 찍어보면 실제로 함수가 반환되는것을 알 수 있습니다.

이 아이디어를 이용한 전체 코드(아래) 는 신기할정도로 잘 동작합니다.

import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
import Constants from 'expo-constants';

export default function App() {
  this.React = React;
  this.Text = Text;
  const Component = eval(`
const Boo = () => {
  return /*#__PURE__*/React.createElement(Text, null, "boo");
};
Boo;
  `);

  return (
    <View>
      <Component />
    </View>
  );
};

https://snack.expo.io/@pjc/rebellious-pretzels

이제 우리는 동적 코드 스트링으로부터 React 컴포넌트를 얻어서 렌더링할 수 있습니다.

물론 이 아이디어가 무조건적으로 맘에 들지 않는 분들이 많을 것으로 예상합니다. 하지만 여기서 하고자 하는 것은 기존 틀에서 벗어난것이고, Retrofit, 심지어는 JSX같은 불가능을 가능으로 바꾸어놓는 구현체들은 보이지 않는 곳에서 보기에 불편해보이는 코드를 작성하는 경우는 많습니다.


다음 글은 마지막입니다. 이 글에서는 string을 ReactComponent로 변환하는 아주 간단한 방법에 대해 설명했지만, 이걸로 실제 UI를 구성하기에는 많이 부족합니다. 다음 글에서는 아래의 문제를 해결하는 방법에 대해 다룹니다.
  • 컴포넌트는 Image를 포함할 수 있어야 합니다.
    컴포넌트에서 사용(require)하는 리소스는 디자인을 업데이트하면서 변경될 수 있습니다. 컴포넌트에서 사용하는 모든 리소스 리스트 목록을 작성하고 이를 번들링 하는 간단한 스크립트를 만듭니다.
  • eval 내부의 코드가 import 혹은 require에 대응해야 합니다.
  • 단순 렌더링이 아닌 상태 관리, 혹은 상위 컴포넌트와 통신이 가능해야 합니다.

참고

profile
다른 곳에서 볼 수 없는 이상한 주제를 다룹니다. https://pjc0247.github.io/new-home

0개의 댓글