ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [React.js] Components Interact, Import/Export
    Front-End(Web)/React - 프레임워크(React, Next) 2020. 11. 26. 00:28
    반응형

    🤷 Component(컴포넌트)의 상호작용이란?

     

    React App은 수많은 컴포넌트들로 구성되어 있으며, 각각이 담당하는 정보의 display가 있다.

    React가 유행하는 이유는 단순히 UI를 컴포넌트로 구분해서가 아닌, 그들의 상호작용에 기인했음을 알고 시작했다.


    📒 Component Interact

    클래스형 컴포넌트의 render() 함수는 JSX뿐만 아니라, 다른 컴포넌트도 반환할 수 있다.

    class OMG extends React.Component {
      // JSX(<h1>) return
      render() {
        return <h1>Whooaa!</h1>;
      }
    }
     
    class Crazy extends React.Component {
      // Component(OMG) return
      render() {
        return <OMG />;
      }
    }

    이렇듯 컴포넌트는 서로를 입출력할 수 있으며, 성질/용도에 따라 나눠진 모듈(JS파일)들 간 주고받는 동작이 이뤄진다.


    📒 import & export

    React 메소드 사용뿐만 아니라, 모듈간의 컴포넌트를 말 그대로 수입/수출하기 위해 사용되는 구문이다.

     

    * ProfilePage.js (import)

    import React from 'react';
    import ReactDOM from 'react-dom';
    import { NavBar } from './NavBar';			// * import NavBar from NavBar.js
    
    class ProfilePage extends React.Component {
      render() {
        return (
          <div>
            <NavBar />
            <h1>All About Me!</h1>
            <p>I like movies and blah blah blah blah blah</p>
            <img src="https://content.codecademy.com/courses/React/react_photo-monkeyselfie.jpg" />
          </div>
        );
      }
    }
    
    ReactDOM.render(
      <ProfilePage />,
      document.getElementById('app')
    )

     

    * NavBar.js (export)

    import React from 'react';
    
    export class NavBar extends React.Component {			// * export to other JS
      render() {
        const pages = ['home', 'blog', 'pics', 'bio', 'art', 'shop', 'about', 'contact'];
        const navLinks = pages.map(page => {
          return (
            <a href={'/' + page}>
              {page}
            </a>
          )
        });
    
        return <nav>{navLinks}</nav>;
      }
    }

     

    - export 문법

    내보내고자 하는 메소드(변수, 클래스) 등 앞에 붙여도 되고, 메소드를 선언한 뒤 export 처리해도 된다.

    // (1) 메소드 앞에 export 붙이는 경우
      export const MODULES_BECAME_STANDARD_YEAR = 2015;
    
      export class User {
        constructor(name) {
          this.name = name;
        }
      }
     
     
    
    // (2) 메소드 선언 후 export 처리
      function sayHi(user) {
        alert(`Hello, ${user}!`);
      }
    
      function sayBye(user) {
        alert(`Bye, ${user}!`);
      }
    
      export {sayHi, sayBye}; // 두 함수를 내보냄 

     

    - import 문법

    가져오고자 하는 메소드 명을 직접 사용해도 되고, 객체 형태로 가져와서 사용해도 된다.

    // (1) say.js 내 필요한 메소드 명으로 가져옴
    import {sayHi, sayBye} from './say.js';
    
    sayHi('John'); // Hello, John!
    sayBye('John'); // Bye, John!
    
    
    // (2) say.js 자체를 say(객체) 가져와서 사용
    import * as say from './say.js';
    
    say.sayHi('John');
    say.sayBye('John');

    두 번째 방법은 import 코드가 짧아지고 효율적이나, 첫 번째 방법처럼 구체적으로 명시하는걸 권장한다.

    • 웹팩(webpack)과 같은 모던 빌드 툴은 로딩속도를 높이기 위해 모듈들을 모으는 번들링과 최적화를 수행한다. 이러한 '가지치기(tree-shaking)' 과정이 길어질 수가 있음.
    • 실제 코드를 작성하는 부분에선 첫 번째 방법이 간결함. sayHi() > say.sayHi()
    • 어떤 JS파일에서 어느 메소드가 사용되는지 명확하기 때문에 코드구조 파악 및 유지보수에 유리함.

     

    - import & export 심화문법

     

    1) .js 생략

     

    import 시 from 'string' 부분에 '.' 이나 '/' 등이 포함되어 있으면 파일경로로 인식되어 .js를 붙일 필요가 없다.

    import User from './user.js';
    
    // shorter
    import User from './user';

     

    2) as 구문

     

    컴포넌트를 import/export 할 때, 이름을 간결하게 바꾸고자 할 때 사용되는 구문이다.

    // import 'as'
    import {sayHi as hi, sayBye as bye} from './say.js';
    
    hi('John'); // Hello, John!
    bye('John'); // Bye, John!
    
    
    // export 'as'
    
    // 📁 say.js
    export {sayHi as hi, sayBye as bye};
    
    // 📁 main.js
    import * as say from './say.js';
    
    say.hi('John'); // Hello, John!
    say.bye('John'); // Bye, John!

     

    3) export default 구문

     

    모듈은 복수의 메소드를 포함한 모듈 / 한 개의 메소드만 선언된 모듈들 두 가지 경우로 나뉘며 후자를 선호한다.

    파일 개수가 많아지기 때문에, 모듈에서 하나의 메소드를 제공하는 것을 명시하는 export default 구문이 존재한다.

    // 📁 user.js
    export default class User { 	// export 옆에 'default'를 추가
      constructor(name) {
        this.name = name;
      }
    }
    
    // 📁 main.js
    import User from './user.js'; 	// {User}가 아닌 User로 클래스 가져옴
    
    new User('John');

     

    default는 메소드 선언 후 export 시, 아래와 같이 지정할 수 있다.

    function sayHi(user) {
      alert(`Hello, ${user}!`);
    }
    
    // 함수 선언부 앞에 'export default'를 붙여준 것과 동일
    export {sayHi as default};

     

    돌아가서, 처음 코드처럼 default 메소드가 존재하는 경우 import 시 {}를 사용할 필요가 없다.

    named export default export
    export class User {...} export default class User {...}
    import {User} from ... import User from ...

    named와 default 동시에 사용하는 모듈도 문제는 없지만 자주 통용되는 방법은 아니다. (named는 이름 없으면 에러!)

    만약 둘 다 존재하는 모듈이 있다면 아래와 같이 가져올 수 있다.

     

    * export part

    // 📁 user.js
    export default class User {				// default export
      constructor(name) {
        this.name = name;
      }
    }
    
    export function sayHi(user) {				// named export
      alert(`Hello, ${user}!`);
    }

    * import part

    // (1) named 가져올 때 처럼 중괄호({}) 활용
    import {default as User, sayHi} from './user.js';
    
    new User('John');
    
    
    // (2) *로 모듈 내 모든 메소드 가져오기(defalut = User)
    // 📁 main.js
    import * as user from './user.js';
    
    let User = user.default; // default export
    new User('John');

    첫 번째 경우처럼 default는 이름을 지정할 수 있지만, 통상 모듈명(파일명)으로 지정하는 것이 암묵적인 규칙이다.

     

     

    4) 모듈 다시 내보내기 (export {컴포넌트} from '경로')

     

    export - from 문법을 통해, 컴포넌트를 가져옴과 동시에 내보낼 수 있다.

     

    NPM을 통해 외부에 공개할 '패키지(package)'를 만들고 있다고 가정하자. 여기에는 수많은 모듈이 포함되어 있을거고, d일부는 외부에 표현되는 기능, 일부는 이를 도와주는 헬퍼를 담당하고 있다.

    auth/
        index.js
        user.js
        helpers.js
        tests/
            login.js
        providers/
            github.js
            facebook.js
            ...

    이와 같은 패키지라고 하면, 진입점 역할인 index.js를 통해 외부 개발자들은 필요한 컴포넌트를 가져갈 것이다.

    import {login, logout} from 'auth/index.js'

    이 때, 패키지 내부를 외부 개발자가 건드리지 못하도록 필요기능을 index.js에 실어서 바로 내보낼 때 사용된다.

    // 📁 auth/index.js
    export {login, logout} from './helpers.js';
    //import {login, logout} from './helpers.js';
    //export {login, logout};
    
    
    export {default as User} from './user.js';
    //import User from './user.js';
    //export {User};

    아래가 default를 다시 내보낸 경우인데, User 클래스명이 아닌 {default as User} 혹은 {default} 로 내보내야 한다.

    또한, *로 내보낼 경우 named export만 처리되므로, 반드시 아래와 같이 named와 default 각각 내보내야 한다.

    export * from './user.js'; 			// named export를 다시 내보내기
    export {default} from './user.js'; 		// default export를 다시 내보내기

    Codecademy로 튜토리얼 진행하면서, 상호작용 전체(import/export + props, state)를 한번에 적으려했으나 많았다...

    대신 단순하다고 생각한 import/export의 심화적인 알고리즘도 공부하는 좋은 기회였다.

    특히, import 시 중괄호({}) 사용유무의 이유에 대해 정확히 알게 된 좋은 계기였다.

     

    import/export 부분은 아래 사이트를 많이 참고 및 차용하였다.

    ko.javascript.info/import-export (출처: JAVASCRIPT.INFO 전문)
    반응형

    'Front-End(Web) > React - 프레임워크(React, Next)' 카테고리의 다른 글

    [React.js] Lifecycle  (0) 2020.11.27
    [React.js] State  (0) 2020.11.26
    [React.js] Props  (0) 2020.11.26
    [React.js] Component 기본  (0) 2020.11.24
    [React.js] JSX(Syntax extension for JS)  (0) 2020.11.23
Designed by Tistory.