timelinejs

2019-01-10

TimeLineJS라이브러리를 사용하여 차트 컴포넌트를 만들게 되었다.
https://timeline.knightlab.com/ 참고

외부 라이브러리를 커스텀하면서 가장 힘들었던 점은 컴포넌트화 작업을 하는 부분이었다.
나만 쓰는게 아니라 다른 개발자들이 사용할 수 있게 표준화된 컴포넌트를 만드는 일은 참 힘들었다.
아래는 개발하면서 힘들었던 점들에 대해 짚어볼 것이다.

  1. 해당 라이브러리는 javascript파일로 되었있지만 모든 기능들을 한 파일에 다 모아놓았다.
    일일히 다 수정하기에는 너무 일이 커질 거 같아서 필요한 속성들만 받을 수 있게 수정해놓았다.
    그런데 문제는 babel7.x.x 버전은 ES5 변환 불가능한 것들은 그냥 그대로 읽는거 같다. 하지만 우리 회사 전체 프로젝트는
    babel 6.x.x 버전은 모든 파일을 ES5로 변환하는 것 같다.
    (babel: browser가 인식할 수 있는 ES5 문법으로 변환시켜주는 transpiler이다.)
    해결책으로는 jsx파일로 만들었다. 왜냐하면 공통으로 webpack-dev-server.config.js 파일에 js파일만 babel로 컴파일하기로
    되어있기 때문이다.

    그러나 큰 문제가 또 발생했다. 개발된 프로젝트를 build돌리면 jsx파일도 컴파일을 시키는 것이다.
    일일히 수동으로 빌드 돌릴 때마다 jsx파일을 바꿔치기 할 수 도 없다.
    해결책으로는 package.json에 빌드명령에 npm run build:babel && npm run build:copy-files 이렇게 되어 있다.
    src하위 폴더를 다 빌드시키고 copy-files라는 파일에 있는 것들도 함께 빌드를 시키라는 명령어이다.
    그래서 copy-files.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
    /* eslint-disable no-console */
    const files = [
    'README.md',
    'CHANGELOG.md',
    'LICENSE',
    './src/ARITimeLine/ARITimeLineLib.jsx' // 이 부분!!!
    ];

    Promise.all(
    files.map((file) => copyFile(file))
    )
    .then(() => createPackageFile());

    function copyFile(file) {
    const buildPath = resolveBuildPath(file);
    return new Promise((resolve) => {
    fse.copy(
    file,
    buildPath,
    (err) => {
    if (err) throw err;
    resolve();
    }
    );
    })
    .then(() => console.log(`Copied ${file} to ${buildPath}`));
    }

이 방법이 맞나 싶기는 한데 timelinejs라이브러리를 일일히 다 커스텀하기에는 아무래도 일 이 커질 것 같다.

  1. 컴포넌트화 시키고 다른 프로젝트에서 import해서 쓰는데 문제가 발생했다.
    Minified React error 에러였다. 찾아보니 react 에서 와이어를 통해 보내는 바이트 수를 줄이기 위해 전체 에러를 보내는 것을
    피한다고 한다. 결국 타임라인을 개발한 프로젝트로 가서 오류를 보니 render에서 return할 때 timeline라이브러리를 리턴하는데
    이게 object 형태로 되어 있어 발생한 에러였다. 항상 return할때는 배열이나 Fragments를 사용하여 자식목록을 그룹화한다.
    내가 사용한 방법은 react-addons-create-fragment를 사용했는데 더이상 안쓰인다. react 16버전부터는 Fragment를 지원한다.
    그러나 우리회사는 react 15버전이므로 사용했다.
    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
    import createFragment from 'react-addons-create-fragment';

    export function createChildFragment(fragments) {
    const newFragments = {};
    let validChildrenCount = 0;
    let firstKey;

    // Only create non-empty key fragments
    for (const key in fragments) { //object의 key값만을 뽑아서 반복문 돌릴 때는 'for in'사용
    let currentChild = fragments[key];
    if (typeof currentChild === 'object') {
    createChildFragment(currentChild)
    }
    if (typeof currentChild === 'object') return;

    if (currentChild) {
    if (validChildrenCount === 0) firstKey = key;
    newFragments[key] = currentChild;
    validChildrenCount++;
    }
    }
    if (validChildrenCount === 0) return undefined;
    if (validChildrenCount === 1) return newFragments[firstKey];
    return createFragment(newFragments);
    }

이렇게 해결을 하였다!!!

사실 내가 한 방법이 맞는지 모르겠지만 잘 돌아가니 우선 덮어두기로…