본문 바로가기

React

이슈 6 단 한 줄! index.js로 내 코드 깔끔하게 import하기

반응형

수정 사항

이 코드는 export default class에 대해 작동하지만, export { foo, bar }와 같은 형식에선 작동하지 않습니다.
이에 대한 수정 사항이은 아래 게시글에서 확인하실 수 있습니다.

 

이슈 11 React.createElement: type is invalid

단 한 줄! index.js로 내 코드 깔끔하게 import하기 수정 전 코드: import React, { Component } from 'react'; import { Col, Row, Form, FormGroup, Input } from 'reactstrap'; import SearchID from '../compo..

roomedia.tistory.com

수정 전 코드:

import React, { Component } from 'react';
import { Col, Row, Form, FormGroup, Input } from 'reactstrap';
import SearchID from '../components/search_id';
import Info from '../components/info';
import CancelOkBtn from '../components/cancel_ok_btn';
import ReserveTable from '../components/reserve_table';
import Feedback from '../components/feedback';

개발을 하다보니, 컴포넌트가 점점 많아지면서 import를 몇 줄씩 쓰다보니 이상함이 느껴졌습니다. react는 되는데 나는 왜...? 한 눈에 비교되는 모습.. 그래서 오늘은 내가 짠 코드를 react처럼 import 하는 법을 알아보도록 하겠습니다.

결과물:

import React, { Component } from 'react';
import { Col, Row, Form, FormGroup, Input } from 'reactstrap';
import { SearchID, Info, CancelOkBtn, ReserveTable, Feedback } from '../components';

먼저 저의 프로젝트 디렉토리 구조입니다. UI를 하나의 단위 별로 나누어 components 폴더에 넣었습니다. 이를 조합하여 하나의 기능을 수행하는 containers가 있고, 컨테이너가 조합되어 renderer 폴더 안에 있는 App.js가 있습니다.

 

componentscontainers의 내용이 점점 늘어나기 때문에, 이 두 폴더를 모듈화 해보도록 하겠습니다. 제일 먼저 할 일은 각 폴더 아래에 index.js 파일을 만들어주는 것입니다. 예시를 위해 components 아래에 만들어보았습니다.

언뜻 보기에도 더러워보이는 디렉토리...

 

index.js에 다음 코드를 붙여넣으면 됩니다. 다음 코드에서 select 부분은 패턴으로, 패턴은 glob documentation을 참고하여 넣었습니다.

const glob = require('glob');
const path = require('path');

const folder = "./src/components/";
const select = "!(index)"; // 이 파일 제외
const format = ".js";
const local = folder + select + format;

module.exports = {};
glob.sync(local).forEach(file => {
  const name = path.basename(file, format);
  const m = require('./' + name).default;
  module.exports[m.name] = m;
});

귀엽다

주의할 점

export default class *;

위와 같은 방식을 사용할 경우, 기존 코드에서 default로 설정한 부분만 export 되고, 마찬가지로 default로 설정한 부분만 import 할 수 있습니다. 저는 평소에 아래와 같이 작성하다보니 수정할 일이 없었습니다만, 혹시 모르니!!

export default class ReserveTable extends Component {
  render() {
    return (
      <Table striped>
        <thead>
          <tr>
            <th>#</th>
            <th>학번</th>
            <th>시간</th>
          </tr>
        </thead>
        <tbody>
        </tbody>
      </Table>
    );
  }
}

Uncaught TypeError: Cannot assign to read only property 'exports' of object '#'

const glob = require('glob'); 대신 import glob from 'glob';를 사용하면 이 에러가 발생합니다.

Uncaught TypeError: Cannot assign to read only property 'exports' of object '#<Object>'
    at Module.eval (index.js?2af9:10)
    at eval (index.js:21)
    at Module../src/components/index.js (renderer.js:1610)
    at __webpack_require__ (renderer.js:728)
    at fn (renderer.js:102)
    at eval (reserve_seat.js:7)
    at Module../src/containers/reserve_seat.js (renderer.js:1646)
    at __webpack_require__ (renderer.js:728)
    at fn (renderer.js:102)
    at eval (App.js?bd96:1)

간단히 말하자면, importmodule.exports는 같이 사용할 수 없습니다. export { m.name } from file; 과 같은 문구는 top level이 아닌 곳에서 사용할 수 없고요. 더 자세한 내용은 다음 글을 참고해주시기 바랍니다!!

require와 import, module.exports와 export는 뭐가 다를까?

Uncaught Error: Cannot find module './*'

    at webpackEmptyContext

경로와 패턴, 파일 포맷을 변수화 하였지만, const m = require('./' + name).default;에서 './'를 변수로 빼면 아래와 같은 오류가 납니다.

Uncaught Error: Cannot find module './cancel_ok_btn'
    at webpackEmptyContext (eval at ./src/components sync recursive (renderer.js:1587), <anonymous>:2:10)
    at eval (index.js?2af9:13)
    at Array.forEach (<anonymous>)
    at eval (index.js?2af9:11)
    at Object../src/components/index.js (renderer.js:1598)
    at __webpack_require__ (renderer.js:728)
    at fn (renderer.js:102)
    at eval (reserve_seat.js:7)
    at Module../src/containers/reserve_seat.js (renderer.js:1634)
    at __webpack_require__ (renderer.js:728)

분명 변수 처리하지 않은 string과 동일한 값이지만, webpack을 거치는 과정에서 에러가 나는 걸로 보입니다. 아래 내용에 대한 해결 방법은 알아내는대로~ 글로 작성하도록 하겠습니다~!!

반응형