HATEOAS를 알아보다 알게 된 것들… (REST API, Charset, Link)
[소소한 개발 일지] React Native 프로젝트에 루트 디렉토리 외부의 파일 임포트하기
2020-12-07
Explanation
오늘은 지난 주말에 저의 반나절의 시간을 빼앗아간 문제에 대해 적어 보려 합니다.
사실 리액트 네이티브를 제대로 사용해 본 적이 없어서, 사실 엄청 간단한 건데 저만 고생한 걸 굳이 글로 쓰고 있는 건 아닌지 조금 걱정이 되긴 하지만… 빼앗긴 시간이 너무 아까운 나머지 보상 심리로..
짧게 적어보려 합니다.
반나절을 빼앗겼다고 적었지만 사실.. 해결은 아래 링크의 글을 통해 한방에 해결하였답니다.
링크. https://medium.com/@dushyant_db/how-to-import-files-from-outside-of-root-directory-with-react-native-metro-bundler-18207a348427
그리고 제가 작성한 예시는 그냥 ‘npx react-native init projectName’ 하면 생성되는 파일 그대로입니다.
그래도 혹시 전체 코드를 확인이 필요하시다면 아래의 깃허브 리포지토리에서 확인하실 수 있습니다.
링크. https://github.com/falsy/blog-post-example/tree/master/react-native-import
저는 리액트 네이티브 프로젝트 디렉토리 밖의 js 파일을 임포트 해야 하는 일이 있었는데, 리액트 네이티브 프로젝트 디렉토리에서 상대 경로로 루트 디렉토리 밖의 파일을 임포트하면 아래와 같이 모듈을 찾지 못하는 문제가 생긴답니다.
저는 외부에 external 이라는 폴더를 만들고 그 안에 test.js 파일을 만들고 그 안에 내용은 아래와 같습니다.
1 2 |
// ../external/test.js export default { test: 'test' }; |
그리고 리액트 네이티브의 시작인 index.js 파일에 아래와 같이 코드를 추가하였습니다.
1 2 3 4 5 6 7 8 |
// index.js import {AppRegistry} from 'react-native'; import App from './App'; import {name as appName} from './app.json'; import test from '../external/test'; console.log(test); AppRegistry.registerComponent(appName, () => App); |
문제의 화면은 아래와 같습니다.
react-native init을 하면 metro.config.js 파일이 있는데요. 바로 요놈을 아래와 같이 수정하면 된답니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// metro.config.js const path = require('path'); const watchFolders = [ path.resolve(__dirname + '/../external'), ]; module.exports = { transformer: { getTransformOptions: async () => ({ transform: { experimentalImportSupport: false, inlineRequires: false, }, }), }, watchFolders, }; |
보통 이런 내용 다음에는 metro가 무엇인지 설명해야 하지만, 그것은 이 글의 논지가 아니므로!
간단하게 리액트 네이티브에서 사용하는 자바스크립트 번들러랍니다.
사실, metro는 지하철 말고는 잘 모릅니다.
대충 속성명으로 딱 추측이 가능하듯, 왓치할 폴더를 추가해주면 아래와 같이 문제가 해결된답니다.
그런데 만약에 저 외부의 파일에서 내부의 모듈을 사용하려고 하면 또 아래와 같은 문제가 생긴답니다.
예를 들어 test.js 파일에 React를 임포트 하면,
1 2 3 4 |
// ../external/test.js import React from 'react'; export default { test: 'test' }; |
아래와 같은 오류가 출력된답니다.
다시 metro.config.js 파일을 아래와 같이 수정합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
// metro.config.js const path = require('path'); const extraNodeModules = { 'external': path.resolve(__dirname + '/../external'), }; const watchFolders = [ path.resolve(__dirname + '/../external'), ]; module.exports = { transformer: { getTransformOptions: async () => ({ transform: { experimentalImportSupport: false, inlineRequires: false, }, }), }, resolver: { extraNodeModules: new Proxy(extraNodeModules, { get: (target, name) => name in target ? target[name] : path.join(process.cwd(), `node_modules/${name}`), }), }, watchFolders, }; |
와우, 잘 모르는데 설명하는 글을 적으려니 이런 곤욕이 없군요…
역시 잘 모르지만 속성명으로 추측하면, metro는 자바스크립트의 번들러고 resolver 속성은 번들러가 번들을 진행될 때 참조가 되는 속성일 거에요. 그리고 extraNodeModules속성은 이름 그대로 노드 모듈을 추가 해주는 역할을 하겠네요.
그전에 extraNodeModules 라는, 이후에 Proxy 객체의 타겟으로 사용될 대상을 지정해주었어요.
Proxy 객체는 ES6에 추가된 객체인데요. Proxy 객체를 설명하는 건 너무 어려운 일이니까.
우리의 MDN 형, 누나가 알려줄 거에요.
링크. https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Proxy
그러면 우리가 지정한 타겟(../external)에게 ‘process.cwd()’ 절대 경로에 있는 node_modules디렉토리에서 모듈을 찾아서 연결해주나봐요.
말도 안 되는 설명글이었지만…
위와 같이 설정을 해주면 아래와 같이 React를 임포트에도 오류가 출력되지 않는답니다.