최근 만들고 있는 대부분의 어드민 툴은 ant design으로 만들고 있다.

얼마전에 3.x 대 버전에서 4.x로 버전업을 했는데, 달라진 부분들이 좀 있어서 마이그레이션 해본 김에 정리를 조금 해본다.

크게 두 개의 컴포넌트에 대격변이 있었다.

Form

form hooks 추가

  • 기존에는 HOC 형태로 form을 만들어서 썼는데, 이게 TypeScript랑 묘하게 궁합이 안 맞아서 골치가 아팠었다. 이것이 useForm이라는 hooks의 등장으로 한결 편해졌다.
  • getFieldDecorator가 없어졌다. rules, initialValue 와 같은 설정은 Form.Item 컴포넌트의 props로 변경 되었다.

코드로 보면 확실히 느껴지는데 이랬던 코드가

// 3.x form
function SimpleForm({ form }) {
  const handleSubmit = () => {
    form.validateFields((err, values) => {
      // form 값은 values에 들어있음
    })
    
  }
  
  return (
    <Form onSubmit={handleSubmit}>
      <Form.Item label="사용자명">
        {form.getFieldDecoretor('username')(<Input />)}        
      </Form.Item>
      <Button htmlType="submit">submit</Button>
    </Form>
  )
}

export default WrappedSimpleForm = Form.create()

이렇게 변했다.

// 4.x form
function SimpleForm() {
  const handleFinish = (values) => {
  }
  const hanleFinishFailed = (errorInfo) => {
  }
  
  return (
    <Form onFinish={handleFinish} onFinishFailed={handleFinishFailed}>
      <Form.Item label="사용자명" name="username">
        {form.getFieldDecoretor('name')(<Input />)}
      </Form.Item>
      <Button htmlType="submit">submit</Button>
    </Form>
  )
}

기본적으로는 form 객체를 통하지 않고도 컨트롤 할 수 있도록 변경한 것으로 보이며, 기존처럼 form 객체를 통해 디테일한 컨트롤이 필요한 경우 useForm hooks를 이용하면 되는 것 같다.

이 경우 useForm으로 만든 form을 Form의 props로 넘겨주면 된다.

function SimpleForm() {
  const [form] = useForm()
  
  useEffect(() => {
    // form을 직접 조작하기
    form.setFieldsValue({
      username: 'roto'
    })
  }, [])
  const handleFinish = (values) => {
  }
  const hanleFinishFailed = (errorInfo) => {
  }
  
  return (
    <Form form={form} onFinish={handleFinish} onFinishFailed={handleFinishFailed}>
      <Form.Item label="사용자명" name="username">
        {form.getFieldDecoretor('name')(<Input />)}
      </Form.Item>
      <Button htmlType="submit">submit</Button>
    </Form>
  )
}

이렇게만 놓고 보면 사용성이나 가독성이 이전에 비해 월등하게 좋아졌다.

onSubmit props가 onFinishonFinishFailed 두 개로 나뉜 것도 눈여겨볼만 하다.

마이그레이션 해야합니다.

  • 물론 이렇게 큰 변화가 있었으므로 기존 3.x 버전대의 form 코드는 그대로 쓸 수 없고, @ant-design/compatible 모듈을 설치해야한다.
  • 기존의 Form 및 관련 모듈들의 import를 @ant-design/compatible/lib/form/Form 여기서 import 해서 쓰면 된다.

campatible form의 class명 변경

  • 기존 폼은 클래스 명이 ant-legacy-form 형태로 바뀌어서, @ant-design/compatible에 있는 css로 로딩해야 정상적으로 렌더링 된다.
  • @import '~@ant-design/compatible/assets/index.css';를 한줄 추가해주자.

Icon

모듈 분리

  • Icon 컴포넌트가 별도의 @ant-design/icon 패키지로 분리되었다. 이제 저 패키지를 설치해서 써야한다.
  • 아이콘만 꾸준히 버전업하기 편하도록 분리한 게 아닐까..? 싶다.

컴포넌트화

  • 기존에는 <Icon type="icon type" />과 같은 식으로 사용 되었었는데, 모든 아이콘이 별도의 컴포넌트화가 되었다.
  • <Icon type="plus" /> 라고 썼던 것을 <PlusOutlined /> 같은 식으로 써야한다.
    • 이건 아이콘 단독으로 쓰이는 것을 포함해서 Button 컴포넌트에 icon props에서도 똑같다.
    • Filled, Tow Tone 두 가지의 스타일을 더 제공하는데 각각 <PlusCircleFilled />, <PlusCircleTwoTone /> 이런 식으로 써야한다.
  • https://ant.design/components/icon/ 요기서 아이콘 검색해서 클릭해서 복사하면 기존처럼 아이콘 type text가 복사되는 게 아닌, 컴포넌트 코드 형태로 복사된다.
    • 요건 왜 이런식으로 변경했는지 잘 모르겠다. css in js를 쓰는 형태로 확장했나?
    • 이렇게 썼을 때 장점은 있을 법한 아이콘은 적당히 입력한 후에 import 대상을 찾아서 쓰면 되니까 위의 url 들어갈 필요가 적어지긴 한다.

그외

마이그레이션을 하면서 그외에 느꼈던 자잘한 변경사항들도 있다.

Row

Row 컴포넌트가 flex 기반이 되었다. 그래서 불필요하게 <Row /> 로만 래핑해둔 친구들은 레이아웃이 깨진다. div로 바꾸던가 빼자.

자세한 변경점은 https://ant.design/docs/react/migration-v4 여기에 잘 정리가 되어있다.

IE는 11만 지원

  • 👍👍👍👍👍

React 16.9 이후만 지원

  • hooks 때문에 그런 듯 하다.

맺으며

한땀한땀 마이그레이션을 마치고 난 후에 https://github.com/ant-design/codemod-v4 이런 도구의 존재를 발견했다.

작업하기 전에 문서를 먼저 꼼꼼히 읽는 습관을 들이도록 하자.....