Skip to main content

Command Palette

Search for a command to run...

JavaScript 서브 라이브러리

Updated
5 min readView as Markdown
K

프론트엔드 개발자 김가영입니다. 개발과 일에 대한 생각을 주로 씁니다. https://velog.io/@kykim_dev/posts (2023 이전 블로깅)

JS 기반 프로젝트 진행시 JS 기반 프로젝트 진행시 주요 라이브러리(JS, CSS 라이브러리) 외 개발에 필요한 추가 라이브러리를 통해 작업 생산성, 효율성을 높일 수 있다. 사내에서 프로젝트 세팅시 협업과 효율성을 위해 설치했던 도구들을 소개한다.

Craco

  • Create-React-App Configuration Override의 약어로, CRA에 config 설정을 덮어쓰기 위한 패키지

  • Webpack의 번거로운 설정을 줄이기 위해 다양한 오버라이딩 패키지들이 등장했으며, 대표적으로 Craco, react-app-rewired 등이 있다.

/cf/ CRA Webpack 설정

  • CRA는 기본적으로 프로젝트 디렉토리를 간결하게 유지하기 위해 웹팩 설정이나 script 폴더들을 숨겨놓는다. 하지만, 이를 커스텀해야 할 경우 eject 명령어를 통해 이를 추출할 수 있다.

  • 이렇게 추출된 폴더 및 파일들은 이제 디렉토리 상에 노출되며, 단 eject를 한 번 하면 이전 상태로 돌아갈 수 없다는 단점이 있다.

  • eject를 하게 되면 설정에 관련된 config, scripts 폴더 및 package.json의 dependency, babel 및 jest 설정코드가 드러난다. 또한, 한 번 eject를 하면 React APP의 버전업에 대한 구성요소 업그레이드를 할 수 없다는 단점도 존재한다.

설치 및 세팅

  1. Craco 최신 버전 설치
npm i -D @craco/craco
npm i -D @craco/types *타입스크립트 사용시
  1. 프로젝트 루트 디렉토리에 craco.config.js 파일 생성, 덮어쓸 설정(alias, less loader 등) 추가
// craco.config.js
module.exports = {
  plugins: [
    {
      plugin: CracoAlias,
      options: {
        source: "tsconfig",
        baseUrl: "./src",
        tsConfigPath: "tsconfig.paths",
      },
    },
  ],
};
  1. package.json command 수정
// package.json

"scripts": {
    "start": "craco start",
    "build": "craco build",
    "test": "craco test",
    "eject": "craco eject"
}

Husky

  • git-hook에 따라 원하는 동작을 하게 도와주는 패키지로, git add, commit, push가 시행되기 전이나 후에 원하는 스크립트를 실행시켜준다.

설치 및 세팅

  1. 자동 설치
npx husky-init && npm install
  1. package.json 스크립트 추가
// package.json
{
  "scripts": {
    "prepare": "husky install"
  }
}

hook 생성

  • hook을 실행하거나 새로운 것을 추가 할 때, husky install 을 먼저 실행하고, husky add <File> [cmd]를 쓴다.
npx husky add .husky/pre-commit "npm test"
git add .husky/pre-commit
  • commit 하기
git commit -m "Keep calm and commit"

Lodash(_)

  • array, collection, date 등 데이터의 구조를 간편하게 함수형으로 다룰 수 있다.

  • 특히, JS의 배열 안의 객체들의 값을 핸들링 할때 (배열, 객체 및 문자열 반복 / 복합적인 함수 생성) 코드 몇 줄만으로 유기적으로 다룰수가 있어서 매우 유용하다.

  • 특히 Frontend 환경에서 서버(DB)에서 받은 데이터를 정렬하고 가공할때 많이 쓰인다.

  • Lodash는 밑줄 _ 기호를 처음에 선언하여 사용된다. _.(변수) 로 작성할 경우 lodash wrapper로 변수를 감싸게 되면서 해당 변수에 대한 chaining을 시작한다.

설치 및 사용

npm 설치

$ npm i -g npm
$ npm i --save lodash

l사용 방법

// ES6
import _ from "lodash";

// commonJs
var _ = require("lodash");

var myFriend = [
  { name: "kys", job: "developer", age: 27 },
  { name: "cys", job: "webtoons man", age: 27 },
  { name: "yhs", job: "florist", age: 26 },
  { name: "chj", job: "nonghyup man", age: 27 },
  { name: "ghh", job: "coffee man", age: 27 },
  { name: "ldh", job: "kangaroo", age: 27 },
];

// 콜백함수가 처음으로 참이되는 객체를 반환
_.find(myFriend, function (friend) {
  return friend.age < 28;
}); // → { name: 'kys',job:'developer' ,'age': 27}
  • JS ES6 문법에 비해 실행 속도는 느린 편이나, 함수 확장성이 크다.
var myFriend = [
  { name: "kys", job: "developer", age: 27 },
  { name: "cys", job: "webtoons man", age: 27 },
  { name: "yhs", job: "florist", age: 26 },
  { name: "chj", job: "nonghyup man", age: 27 },
];

myFriend.findIndex(function (friend) {
  return friend.age === 26; // 2
});

_.findIndex(myFriend, function (friend) {
  return friend.age === 26; // 2
});
  • ES6의 findIndex()는 파라미터로 콜백함수만을 반환하지만, lodash의 findIndex()는 객체값 또한 줄 수 있다.
// 처음 일치하는 object의 index 값을 반환
_.findIndex(myFriend, { name: "cys", job: "webtoons man", age: 27 });
// -> 1

// 나이가 26인 객체가 처음으로 나오는 index 반환
_.findIndex(myFriend, { age: 26 });
// → 2

Yup + react-hook-form

  • Yup은 폼 형식의 데이터에 대한 유효성 검사 및 그 상황에 맞는 에러 메시지를 효율적으로 관리할 수 있는 라이브러리다. 유효성 검사 항목이 많아지는 경우 코드가 길어지고 불필요한 렌더링이 일어나는데, 코드를 줄이고 유지보수 측면에서 효율적이다.

  • react-hook-form 은 기존 React의을 통해 입력값을 처리하는 과정에서 생겨나는 비효율적인 과정을 줄여주는 비제어 컴포넌트 방식으로 더 효율적인 input값을 관리할 수 있다.

설치 및 사용

npm i yup
npm install react-hook-form

yup 스키마 작성

import * as yup from "yup";

export const crewRequiredValidation = yup.object({
  // 사번
  crewId: yup
    .string()
    .required("사번을 입력해주세요.")
    .max(10, "사번은 10자리 이하여야 합니다."),
  // 한글 이름
  crewName: yup
    .string()
    .required("이름을 입력해주세요.")
    .max(15, "이름은 15자리 이하여야 합니다."),
  // 영문 이름
  crewNameEn: yup
    .string()
    .required("영문 이름을 입력해주세요.")
    .max(30, "영문 이름은 30자리 이하여야 합니다."),
  //코코네 아이디
  coconeId: yup
    .string()
    .matches(/^[A-Za-z_]+$/, "영어와 특수문자만 입력 가능합니다.")
    .required("코코네 아이디를 입력해주세요.")
    .max(30, "코코네 아이디는 영문 30자리 이하여야 합니다."),
  // 조직원 상태
  activeStatus: yup.string().required("조직원 상태를 선택해 주세요."),
  // 근무형태
  workType: yup.string().required("근무형태를 선택해 주세요."),
  // 브랜치
  branchId: yup.string().required("Branch를 선택해 주세요."),
  // 부서
  deptId: yup.string().required("부서를 선택해 주세요."),
  //직책
  dutyId: yup.string().required("직책을 선택해 주세요."),
  // 직군
  jobKind: yup.string().required("직군을 선택해 주세요."),
  // 세부 직군
  jobPart: yup.string().required("세부직군을 선택해 주세요."),
  // 생년월일
  birthday: yup
    .date()
    .typeError("생년월일을 입력해 주세요.")
    .required("생년월일을 입력해 주세요."),
  // 입사일
  hireDate: yup
    .date()
    .typeError("입사일을 입력해 주세요.")
    .required("입사일을 입력해 주세요."),
  email: yup
    .string()
    .email("이메일 형식에 맞춰 작성해 주세요.")
    .required("이메일을 입력해 주세요."),
});

export const crewOptionalValidation = yup.object({
  // 핸드폰 번호
  phoneNo: yup
    .string()
    .nullable()
    .matches(
      /^01([0|1|6|7|8|9]?)-?([0-9]{3,4})-?([0-9]{4})$/,
      "형식에 맞춰 입력해 주세요.",
    ),
  // 비상 연락처
  emergencyCall: yup
    .string()
    .nullable()
    .matches(
      /(^01([0|1|6|7|8|9]?)-?([0-9]{3,4})-?([0-9]{4})$)|(^$)/,
      // /^01([0|1|6|7|8|9]?)-?([0-9]{3,4})-?([0-9]{4})$/,
      "형식에 맞춰 입력해 주세요.",
    ),
  // 겸직
  deptCrewList: yup.array().of(
    yup.object().shape({
      deptId: yup.string().required("부서를 선택해 주세요."),
      dutyId: yup.string().required("직책을 선택해 주세요."),
    }),
  ),
  // 개인 이메일
  privateEmail: yup
    .string()
    .nullable()
    .email("이메일 형식에 맞춰 작성해 주세요."),
});
  • Yup에 다양한 내장 함수를 사용해 스키마를 작성할 수 있다. 문자열인지 검사해 주는 string(), email인지 혹은 정규식으로 커스텀된 규칙을 사용하는 email()과 matches() 그리고 필수로 들어가야하는 required() 등이 있다.

  • 함수 argument로 문자열을 넣으면, 해당 조건에 부합하지 못할 경우 문자열을 에러메시지로 반환시킬 수 있다. matches()는 정규식을 삽입하고, 두번째 argument로 입력한다.

reac-hook-form의 useForm 호출

import { yupResolver } from '@hookform/resolvers/yup';

export default function RequiredForm() {
    const methods = useForm({
        resolver: yupResolver(crewRequiredValidation),
        mode: 'onBlur',
        defaultValues: formData,
    });

    const { handleSubmit, watch, resetField } = methods;

    const onSubmit = (data: Crew) => {
        setFormData({ ...formData, ...data });
        onClickNextStep();
    };

    return (
        <FormProvider {...methods}>
            <ContentWrapper>
                <Row gutter={[24, 10]}>
                    <Col span={12}>
                        <FormInputRadio
                            name="isActive"
                            label="사원 ON/OFF"
                            options={isActiveOptions}
                        />
                    </Col>
                    <Col span={12}>
                        <FormInputText label="이름" name="crewName" />
                    </Col>
                    <Col span={12}>
                        <FormInputText label="사번" name="crewId" />
                    </Col>
                    <Col span={12}>
                        <FormInputText label="cocone ID" name="coconeId" />
                    </Col>
                    <Col span={12}>
                        <FormInputSelect
                            name="workType"
                            label="고용형태"
                            options={workTypeOptions}
                        />
                    </Col>
                    ....
                </Row>
            </ContentWrapper>
            <ButtonWrapper>
                <Button type="primary" onClick={handleSubmit(onSubmit)}>
                    다음
                </Button>
            </ButtonWrapper>
        </FormProvider>
    );
}
  • react-hook-form의 useForm에서, yupResolver 로 스키마를 호출하면 form의 input 값의 검증은 Yup에서 값은 useForm에서 관리하게 된다.

More from this blog

React 렌더링 최적화

React 렌더링이란? 리액트에서 렌더링이란, 컴포넌트가 현재 props와 state의 상태에 기초하여 UI를 어떻게 구성할지 컴포넌트에게 요청하는 작업을 의미한다. 즉 사용자 화면에 View(내용)를 보여 주는 것. 초기 렌더링 렌더링을 담당하는 render 함수는 컴포넌트의 정보를 이용해 화면을 구성(렌더링)한다. 컴포넌트 내부에는 또 다른 컴포넌트들이 들어갈 수 있어, render 함수가 실행되면 그 내부에 있는 컴포넌트들도 재귀적으로 렌...

May 21, 20243 min read

로컬에서 Aws Ec2 인스턴스에 배포하기

EC2 (컴퓨팅) Elastic Compute Cloud(EC2)로 클라우드 컴퓨팅 서비스 클라우드를 통해 서버, 스토리지, 데이터베이스 등의 컴퓨팅 서비스를 제공하는 것으로 AWS에서 원격으로 제어할 수 있는 가상의 컴퓨터 한 대를 임대하는 것과 같다. 제공되는 가상 이미지를 ‘인스턴스(Instance)’라고 하며, 필요에 따라 사양(CPU 코어 수, 메모리 용량, 스토리지)을 변경할 수 있다. 서버에 Build 가져오기 1. 로컬에...

Apr 10, 20242 min read

DevNotes by kykim

23 posts