hoon's bLog

Javascript 자바스크립트 코딩의 기술 10장 컴포넌트 아키텍처를 이용해 관련 파일을 모아라 본문

IT/Javascript

Javascript 자바스크립트 코딩의 기술 10장 컴포넌트 아키텍처를 이용해 관련 파일을 모아라

개발한기발자 2024. 3. 12. 11:42
반응형


10장 컴포넌트 아키텍처를 이용해 관련 파일을 모아라

tip47. 가져오기와 내보내기로 기능을 분리하라

  • 프로젝트를 개발하다보면 html, css, javascript 등 파일을 여러개로 분리해서 작업을 해야한다.
  • 이때 분리된 파일 각각을 모듈(module)이라고 하는데, 모듈은 클래스 하나 또는 특정 목적을 가진 복수의 함수로 구성된 라이브러리 하나로 구성된다.
  • 이 때 모듈에 export와 import 키워드를 사용하면, 다른 모듈을 내보내고, 불러들이는 일종의 기능 공유가 가능하다.
// address.js
import { capitalize } from '../single/util';

export function parseRegion(address) {
  const region = address.state || address.providence || '';
  return region.toUpperCase();
}

export function parseStreet({ street }) {
  return street.split(' ')
    .map(part => capitalize(part))
    .join(' ');
}

export default function normalize(address) {
  const street = parseStreet(address);
  const city = address.city;
  const region = parseRegion(address);
  return `${street} ${city}, ${region}`;
}
  • line 02 : 다른 모듈인 ../single/util 경로로부터 capitalize 함수를 가져옴
  • line 04, 09 : 해당 모듈에서 parseRegion과 parseStreet 함수를 내보냄
  • line 15 : export default로 모듈 당 단 한개의 default export가 있어야 한다. 보통 메인급이라 할 수 있는 변수, 함수, 클래스를 설정하는 것이 좋다.
  • address.js 코드를 아래 list.js에서와 같이 import해서 사용할 수 있다.
// list.js
import normalize, { parseRegion } from './address';

function getAddress(user) {
  return normalize(user.address);
}

export function getAddressByRegion(users) {
  return users.reduce((regions, user) => {
    const { address } = user;
    const region = parseRegion(address);
    const addresses = regions[region] || [];
    regions[region] = [...addresses, normalize(address)];
    return regions;
  }, {});
}

const bars = [
  {
    name: 'Saint Vitus',
    address: {
      street: '1120 manhattan ave',
      city: 'Brooklyn',
      state: 'NY',
    },
  },
];
getAddressByRegion(bars);
// {
//    NY: ["1120 Manhattan Ave Brooklyn, NY"]
// }
  • line 02 : 다른 모듈인 ./address 경로로부터 normalize와 parseRegion 함수를 가져와서 사용하고 있다.
    여기서 normalize는 default export로 바로 가져 올 수 있고, parseRegion은 named export로 명시적으로 가져와야 한다.
    또한 아까 address.js 파일에서 export했던 parseStreet는 export했음에도 안가져와도 상관 없다.
  • 이번엔 클래스를 정의하며 내보내고 있다.
import { capitalize } from '../single/util';

export default class Address {
  constructor(address) {
    this.address = address;
  }

  normalize() {
    const street = this.parseStreet(this.address);
    const city = this.address.city;
    const region = this.parseRegion(this.address);
    return `${street} ${city}, ${region}`;
  }

  parseStreet({ street }) {
    return street.split(' ')
      .map(part => capitalize(part))
      .join(' ');
  }

  parseRegion(address) {
    const region = address.state || address.providence || '';
    return region.toUpperCase();
  }
}
  • normalize, parseStreet, parseRegion 함수들은 해당 모듈 클래스 내부에 정의된 함수들로 function 키워드는 물론, 클래스를 export하고 있기 때문에 각각에 함수 앞에 export할 필요없다.
  • parseStreet의 매개변수인 { street }는 구조 분해 할당 문법으로, street 속성을 가진 객체를 받아들여 해당 속성을 추출하여 사용하겠다는 뜻이다. { street }는 address 객체에서 street 속성을 추출하여 변수 street에 할당하는 것을 의미하고 있다.
  • 이렇게 클래스를 export하면 각각의 변수나, 함수에 대해 일일이 export할 필요 없다.

tip48. npm으로 커뮤니티 코드를 끌어와라

npm(node package manager, 자바스크립트 패키지 매니저)

  • 라이브러리 코드를 프로젝트에 직접 내려받고, 버전을 관리하고, 익숙한 규칙에 따라 개별 파일에서 코드를 가져와 사용할 수 있다.
  • 프로젝트의 메타데이터와 구성 정보를 설정하고, 명령줄 스크립트를 실행하고, 다른 사람들이 쓸 수 있도록 프로젝트를 게시할 수도 있다.
  • node.js를 설치하면 npm도 자동으로 설치되는데, 설치 과정은 필자의 포스팅을 확인하기 바란다.
  • lodash를 프로젝트에 사용해보자
    • Lodash란 일반적인 유틸 함수들을 모아서 제공해주는 라이브러리로, 자바스크립트 용 유틸리티 라이브러리로 가장 많이 쓰이고 최신의 기능을 제공하는 라이브러리이다.
  • 설치 순서
    • npm install --save lodash(--save 플래그를 반드시 써야하는 것은 아니지만 습관이 되면 좋다)
    • node_modules 디렉터리에 패키지를 내려받음
    • 설치하는 패키지의 버전 번호로 package.json 파일을 갱신
    • 설치하는 코드의 버전에 대한 세부 정보를 담은 package-lock.json 파일을 생성
    • 하나의 패키지를 설치할 때 실제로는 여러 개의 패키지를 설치하는 경우, 함께 설치되는 패키지는 package-lock.json 파일이나 node_modules 디렉터리에서 확인할 수 있다.
    • package.json 파일에는 원래 설치했던 lodash만 표시된다.

tip49. 컴포넌트 아키텍처를 이용해 애플리케이션을 만들어라

  • 컴포넌트 아키텍처의 장점 : 관련 있는 모든 코드를 조합해 하나의 디렉터리에 담기 때문에 조각을 하나씩 추가하는 방법으로 웹 페이지나 애플리케이션을 만들 수 있다.
  • 컴포넌트 아키텍처의 단점 : 가장 큰 문제는 빌드 도구와 프레임워크에 의존한다
  • 조금 더 알아보기
    • 나뉜 CSS 파일이 하나의 파일로 결합되어 별도의 css 디렉터리로 옮겨진다. 이미지도 마찬가지이다.
    • 컴포넌트 아키텍처의 유일한 어려움은 모든 것을 연결하기가 쉽지 않다는 점이다.
    • 코드를 영리하게 결합하는 훌륭한 도구가 존재한다.

tip50. 빌드 도구를 이용해 컴포넌트를 결합하라

브라우저에서 코드 실행되게 만들기

  • babel 설치
    • babel: ES6 이후 문법으로 작성한 자바스크립트를 변환할 수 있을 뿐만 아니라, 아직 논의 단계에 있는 문법도 사용할 수 있도록 구성할 수 있다.
  • npm install --save-dev @babel/cli @babel/preset-env @babel/preset-react
    @babel/preset-env : ES6 이후 문법을 변환
    @babel/preset-react : 리액트 코드를 변환
  • .babelrc 파일 설정 : 이 파일은 바벨이 다룰 코드의 종류와 변환 방법을 지정하기 위해 사용한다.
  • package.json 파일에 스크립트 추가
    "build": "babel src/index.js -o build/bundle.js"
    컴파일한 결과는 파일 하나로 출력되어 build 디렉터리에 bundle.js로 저장.
  • 컴파일된 코드를 사용하기 위해 index.html 파일을 수정
...
<script src="./build/bundle.js"></script>
...
  • 이제 브라우저에서 컴파일된 bundle.js를 실행하려고 하면 문제가 발생한다.
  • 바벨은 코드를 변환하지만 가져오기와 내보내기를 처리하는 module loader는 내장되어 있지 않다.
  • module loader : 가져오기와 내보내기를 처리
    예) webpack, rollup.js
  • webpack : 자바스크립트 병합뿐만 아니라 CSS와 Sass 처리, 이미지 변환도 해결
    loader라고 부르는 방법을 이용해 파일 확장자에 따라 필요한 다른 동작을 선언할 수 있다.
    loader는 다른 빌드 도구의 '작업(task)'이라고 생각할 수 있다.
  • webpack 실행
    • 먼저 설치를 해야 하는데 webpack을 위한 babel loader도 설치해야 한다.
    • 바벨로 코드를 컴파일하기 위해서는 babel-loader가 필요하다.
    • npm install --save-dev babel-loader webpack-cli
  • webpack.config.js 파일 생성 : 이 파일에는 원본 코드의 진입점과 컴파일이 완료된 파일이 출력될 경로를 선언한다.
  • webpack이 코드를 어떻게 처리할지 설정(loader 사용)
    • webpack은 정규 표현식을 사용해 loader마다 처리해야 할 파일을 정한다.
    • 예를 들어 .js인 파일만 처리하려고 할 때, webpack이. js인 파일을 발견했을 때 어떤 로더가 이것을 처리할지 설정해줘야 한다.
    • 여기서는. js 파일에 babel-loader를 실행해야 한다.
const path = require('path');

module.exports = {
  entry: './src/index.js',
  module: {
    loaders: [
      {
        test: /\.js?/,
        use: 'babel-loader',
      },
    ],
  },
  output: {
    filename: 'build/bundle.js',
    path: path.resolve(__dirname),
  },
};
  • webpack을 실행하기 위해 package.json 스크립트를 수정
    • webpack은 우리가 설정한 webpack.config.js 파일을 확인하기 때문에 별도의 플래그나 인수가 필요하지 않다.
    • 다음과 같이 스크립트에서 바벨을 실행하던 부분을 수정해 webpack을 사용하도록 하는 것이 전부이다.
// 수정 전
"scripts": {
    "build": "babel src/index.js -o build/bundle.js"
}

// 수정 후
"scripts": {
    "build": "webpack"
}
  • 수정된 스크립트를 실행하면 브라우저에서 코드가 실행될 것이다.
  • 우리의 목표는 모든 의존성을 처리하는 컴포넌트를 만드는 것이다.
  • webpack으로는 자바스크립트를 컴파일할 수 있을 뿐만 아니라, CSS를 컴파일하고 이미지를 불러올 수도 있다.

CSS 컴파일

  • CSS를 다룰 수 있는 도구는 많이 있지만 여기서는 간단하게 알아보자.
  • 두 가지 loader를 설치한다.
    css-loader : CSS 파일을 해석
    style-loader : 스타일을 페이지의 요소에 주입
    npm install --save-dev css-loader style-loader
  • loader 추가 : webpack 설정에서 확장자가 css로 끝나는 파일을 위한 loader를 추가한다.
...
{
    test: /\.css$/,
    use: [
        'style-loader',
        'css-loader',
    ],
},
...
  • 이제 빌드 스크립트를 실행하고 나서 index.html을 열면, 컴포넌트에 올바른 스타일이 적용된 것을 확인할 수 있다.

이미지 처리

  • 이미지는 컴파일하지 않는다. 대신 webpack으로 파일을 옮기고 고유한 이름으로 파일명을 바꾼다.
  • webpack은 마크업에 있는 경로를 파일이 옮겨진 경로로 자동으로 바꿔준다.
  • 이미지에 특별한 조작을 하지 않으므로 file-loader를 사용해서 파일을 옮기고 경로를 갱신하자.
  • webpack 설정에 svg 파일을 위한 조건을 추가한다.
  • 옵션도 전달해야하므로 객체를 담은 배열을 전달한다.
    이미지를 옮길 디렉터리 옵션만 추가해 보자.
    이 디렉터리는 브라우저에서 이미지를 찾는 경로이므로 build 디렉터리를 재사용하는 것이 가장 좋다.
...
{
    test: /\.svg?/,
    use: [
        {
        loader: 'file-loader',
        options: {
            outputPath: 'build/',
        },
        },
    ],
},
...

설정을 마친 뒤 build 스크립트를 실행하고, index.html을 열어보면 컴포넌트를 확인할 수 있다.
빌드 도구를 다룰 때 가장 중요한 것은 천천히 한 번에 하나씩 추가하는 것이다.
큰 프로젝트에 설정을 추가하는 것은 한 번에 하나씩 추가하는 것보다 훨씬 어렵다.
webpackrollup은 복잡한 프로젝트가 될 수 있다.

tip51. CSS 애니메이션을 활용하라

읽기 쉬운 코드를 작성하는 비법은 문제 해결에 가장 적합한 도구를 사용하는 것이다.
간단한 애니메이션은 자바스크립트 대신 CSS로 대체할 수 있다고 한다...는게 왜 팁인지...ㅎㅎ

 

이리하여 장장 51개의 자바스크립트 코딩 시 팁을 알아봤다.

나름 도움 되는 부분도 있었고, 몰랐던 부분도 알아가며 공부도 했지만,

흠... 글쎄 잘 모르겠다.

추후 자세한 책 리뷰를 통해 알아보겠고,

책 한 권을 너무 길게 포스팅하기도 해서,

나 자신에게 조금 반성하는 시간이 되기도 했다.

 

이번 마지막 자바스크립트 코딩의 기술 포스팅을 통해,

더욱 책과 공식문서를 들여다보도록 노력해야겠다.

 

끝.

Reference

자바스크립트 코딩의 기술 요약 / 정리

728x90
반응형