react-table-mapping νŒ¨ν‚€μ§€λ₯Ό μ†Œκ°œν•©λ‹ˆλ‹€!

μ–΄μ©Œλ‹€ 직접 λ§Œλ“€μ—ˆλ‚˜

μ˜¬ν•΄ 5μ›” λΆ€ν„°, νŒ€ λ‚΄λΆ€μ—μ„œ μ°¨μ„ΈλŒ€ UI 개편 ν”„λ‘œμ νŠΈ Version 2 λ₯Ό μ§„ν–‰ν•˜λ©°, λͺ‡ 개의 λΌμ΄λΈŒλŸ¬λ¦¬κ°€ React 19 λ²„μ „μœΌλ‘œ 올라였며, 버전 ν˜Έν™˜ 문제둜 λ™μΌν•œ 라이브러리λ₯Ό μ“°λŠ”λ°μ— μ œμ•½μ‚¬ν•­μ΄ μžˆμ—ˆμŠ΅λ‹ˆλ‹€.

λ‚˜: νŒ€μž₯λ‹˜, 저희 κΈ°μ‘΄ 라이브러리 λͺ‡ κ°œκ°€ React 19 λ²„μ „μœΌλ‘œ μ˜¬λΌμ˜€λ©΄μ„œ, 버전 ν˜Έν™˜
문제둜 λ™μΌν•œ 라이브러리λ₯Ό μ“°λŠ”λ°μ— μ œμ•½μ‚¬ν•­μ΄ μžˆλŠ”λ° μ–΄λ–»κ²Œ ν•˜λ©΄ μ’‹μ„κΉŒμš”?

νŒ€μž₯λ‹˜: 직접 λ§Œλ“€μ–΄λ΄.

λ‚˜: λ„€.

λ‚˜: (λ„€?)

λ‹Ήν™©μŠ€λŸ¬μ› μ§€λ§Œ, μ˜€ν”ˆμ†ŒμŠ€ νŒ¨ν‚€μ§€λ₯Ό 직접 λ§Œλ“€μ–΄λ³΄λŠ” 것 λ˜ν•œ μž¬λ°Œμ„ 것 κ°™μ•„, 직접 λ§Œλ“€μ–΄λ³΄κΈ°λ‘œ ν•˜μ˜€μŠ΅λ‹ˆλ‹€. κ·Έλ ‡κ²Œ μ™„μ„±λœ μ €μ˜ 첫번째 μ˜€ν”ˆμ†ŒμŠ€ νŒ¨ν‚€μ§€λŠ” λ°”λ‘œ !!

react-table-mapping μ΄λΌλŠ” νŒ¨ν‚€μ§€ μž…λ‹ˆλ‹€.

DEMO

κ°„λ‹¨ν•˜κ²Œ μ‹œμž‘ μ§€μ μ˜ ν…Œμ΄λΈ”μ˜ 각 λ‘œμš°μ™€, 끝 μ§€μ μ˜ ν…Œμ΄λΈ”μ˜ 각 둜우λ₯Ό λ“œλž˜κ·Έ μ•€ λ“œλ‘­μœΌλ‘œ λ§€ν•‘ν•  수 μžˆλŠ” GUI μ»΄ν¬λ„ŒνŠΈμž…λ‹ˆλ‹€. λ§Žμ€ μˆ˜μ •κ³Ό μ‹œν–‰μ°©μ˜€κ°€ μžˆμ–΄ 무수히 λ§Žμ€ 베타버전이 μ‘΄μž¬ν•˜μ§€λ§Œ.. ν˜„μž¬λŠ” ν•΄λ‹Ή 라이브러리λ₯Ό νŒ€ λ‚΄λΆ€μ—μ„œ 적용 μ™„λ£Œν•œ μƒνƒœλ©°, κ³§ 버전 1.0.0 으둜 배포할 μ˜ˆμ •μž…λ‹ˆλ‹€ πŸ˜€


λ™μž‘ 방식

μ–΄λ–€ λ°©μ‹μœΌλ‘œ λ™μž‘μ„ ν•΄μ•Όν• κΉŒ?

첫번째둜 κ΅¬ν˜„ν•œ 방식 - μ˜μ‘΄μ„± λ°°μ—΄μ˜ 문제 πŸ”₯

μ²˜μŒμ—λŠ” λ‹¨μˆœνžˆΒ μ‚¬μš©μž 관점이 μ•„λ‹Œ, 라이브러리λ₯Ό λ§Œλ“œλŠ” μž…μž₯μ—μ„œλ§Œ μƒκ°ν–ˆμŠ΅λ‹ˆλ‹€. ν”„λ‘œμ νŠΈ 초기 λ‹Ήμ‹œ 기간이 촉박해 빨리 λ§Œλ“€μ–΄μ•Όκ² λ‹€λŠ” μƒκ°λ§ŒΒ κ°•ν–ˆλ˜ 것 κ°™μŠ΅λ‹ˆλ‹€.

맡핑에 ν•„μš”ν•œΒ μƒνƒœλ₯Ό ν•œΒ κ³³μ—μ„œ κ΄€λ¦¬ν•˜κΈ°Β μœ„ν•΄Β Providerλ₯ΌΒ λ§Œλ“€μ–΄ μƒνƒœλ₯Ό κ΄€λ¦¬ν–ˆμŠ΅λ‹ˆλ‹€.

그리고 같은 라인 λ§΅ν•‘ν•˜κΈ°, λ™μΌν•œ 이름 λ§΅ν•‘ν•˜κΈ°, 라인 λ‹€μ‹œ 그리기 λ“± λͺ¨λ“  κΈ°λŠ₯을 μ»€μŠ€ν…€ ν›…μœΌλ‘œ λ§Œλ“€μ–΄ μ‚¬μš©μžλ“€μ΄ μ“Έ 수 있게 ν•˜μžλŠ” μ·¨μ§€λ‘œ μ§„ν–‰ν–ˆμŠ΅λ‹ˆλ‹€.

μ„Έ 달간 μ—΄μ‹¬νžˆ κ°œλ°œν•˜κ³ Β Providerλ₯Ό ν¬ν•¨ν•œ λΌμ΄λΈŒλŸ¬λ¦¬κ°€ μ™„μ„±λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

이λ₯Ό μ μš©ν•˜κΈ° μœ„ν•΄ μΆœκ·Όν•΄μ„œΒ npm registry에 배포된 νŒ¨ν‚€μ§€λ₯Ό μ„€μΉ˜ν•˜κ³  μ μš©ν•˜λ˜Β μ€‘,Β Maximum rerender...Β λ°”λ‘œ λ¬΄ν•œ λ£¨ν”„μ—Β λΉ μ Έλ²„λ ΈμŠ΅λ‹ˆλ‹€.

원인은 μ˜μ‘΄μ„± λ°°μ—΄ λ¬Έμ œμ˜€μŠ΅λ‹ˆλ‹€.

useEffect(() => {
  updateSourceFields(sourceFieldsFromProps)
}, [sourceFieldsFromProps]) // μ‚¬μš©ν•˜λŠ” μͺ½μ˜ μƒνƒœκ°€ 계속 λ°”λ€ŒκΈ° λ•Œλ¬Έμ— λ¬΄ν•œλ£¨ν”„

λ‘λ²ˆμ§Έλ‘œ κ΅¬ν˜„ν•œ 방식 - 섀계 μ‹€νŒ¨λ‘œ μΈν•œ μƒνƒœ 동기화 문제 πŸ”₯

κ·Έλ ‡κ²Œ λ„λ‹¬ν•œ 두 번째 κ²°κ³ΌλŠ”..

useEffect 훅을 μ‚¬μš©ν•˜λ˜, μ˜μ‘΄μ„± 배열을 빈 λ°°μ—΄λ‘œ μž‘μ„±ν•˜μ—¬, 초기 μƒνƒœ (sources, targets, initialMappings) 만 μ£Όμž…ν•˜κ³ , 라이브러리 λ‚΄λΆ€μ—μ„œ μƒνƒœλ₯Ό λͺ¨λ‘ κ΄€λ¦¬ν•˜μ—¬, onMappingChange λΌλŠ” props둜 λ³€κ²½λœ μƒνƒœλ₯Ό μ•Œ 수 있게 ν•˜μž!

μ˜€μŠ΅λ‹ˆλ‹€.

<TableMappingProvider>
  <TableMapping
    lineType="bezier"
    sourceColumns={sourceColumns}
    targetColumns={targetColumns}
    sources={sourceFields}
    targets={targetFields}
    initialMappings={initialMappings}
    onMappingChange={(mappings) => {
      console.info("mappings", mappings)
    }}
  />
</TableMappingProvider>

예λ₯Ό λ“€μ–΄ μœ„μ™€ 같이 μ‚¬μš©ν•˜λ©΄, 라이브러리 λ‚΄λΆ€μ—μ„œ μƒνƒœλ₯Ό λͺ¨λ‘ κ΄€λ¦¬ν•˜κ³ , onMappingChange λΌλŠ” props둜 λ³€κ²½λœ μƒνƒœλ₯Ό μ•Œ 수 있게 ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

μ΄λ ‡κ²Œ κ°œμ„ ν•˜λ‹ˆ, 초기 ν˜ΈμΆœμ—λŠ” λ¬΄ν•œ 루프에 λΉ μ§€μ§€ μ•Šκ³  잘 λ™μž‘ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

κ·ΈλŸ¬λ‚˜..

onMappingChange={(mapping) =>
  setSomethingState((prev) => ({ ...prev, mapping }))
}

μœ„μ™€Β κ°™μ΄ μ‚¬μš©ν•˜λ©° μ‚¬μš©ν•˜λŠ”Β μͺ½κ³Ό 라이브러리 λ‚΄λΆ€ μƒνƒœμ˜Β μ‹±ν¬λ₯Ό λ§žμΆ”λ©° κ°œλ°œν•˜λ˜ 쀑,Β λΌμ΄λΈŒλŸ¬λ¦¬μ—μ„œ μ œκ³΅ν•˜λŠ” hook으둜 라이브러리 λ‚΄λΆ€Β μƒνƒœμ™€ μ‚¬μš©ν•˜λŠ”Β μͺ½ μƒνƒœλ₯Ό λ™μ‹œμ— λ°”κΎΈκ²Œ λ˜λ‹ˆ,

또 λ‹€μ‹œ μ°Ύμ•„μ˜¨Β  Maximum rerender...Β λ°”λ‘œ λ¬΄ν•œ 루프 πŸ˜‡

두 번째 이슈λ₯Ό κ²ͺκ³  λ‚˜λ‹ˆ, 처음으둜 λŒμ•„κ°€ 초기 섀계뢀터 λ‹€μ‹œ μƒκ°ν•΄λ³΄κ²Œ λ˜μ—ˆμŠ΅λ‹ˆλ‹€.


원인 뢄석

κ°œλ°œν•˜κΈ° μ „, μžμ‹ μ—κ²Œ 던쑌던 μš”κ΅¬μ‚¬ν•­μ€ λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

  1. μ‚¬μš©μžκ°€ 라이브러리 hook을 μ‚¬μš©ν•˜μ—¬ μƒνƒœ λ³€κ²½ 및 Mapping UI λ³€κ²½ ν–‰μœ„λ₯Ό ν•  수 μžˆμ—ˆμœΌλ©΄ μ’‹κ² λ‹€.
  2. 라이브러리 λ‚΄λΆ€ mapping μƒνƒœκ°€ 변경될 λ•Œ λ§ˆλ‹€ μ‚¬μš©μžκ°€ μ•Œ 수 μžˆμ—ˆμœΌλ©΄ μ’‹κ² λ‹€.
  3. λŒ€ν‘œμ μΈ μ•‘μ…˜ (mapping, update, remove) μ‹œμ—, μ „μ²˜λ¦¬, ν›„μ²˜λ¦¬ κΈ°λŠ₯이 μžˆμ—ˆμœΌλ©΄ μ’‹κ² λ‹€.

그리고 κ΅¬μƒν–ˆλ˜ ν”„λ‘œμ„ΈμŠ€λŠ” μ•„λž˜μ™€ κ°™μŠ΅λ‹ˆλ‹€.


κ΅¬μƒν–ˆλ˜ ν”„λ‘œμ„ΈμŠ€ πŸ˜€
  1. μ‚¬μš©μž 이벀트 (λ“œλž˜κ·Έ&λ“œλ‘­, onChange λ“±)

    ↓

  2. 라이브러리 λ‚΄λΆ€ μƒνƒœ λ³€κ²½

    ↓

  3. props둜 전달 받은 onMappingChange 콜백 호좜

    ↓

  4. λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈμ˜ μƒνƒœ μ—…λ°μ΄νŠΈ (setSomethingState)

    ↓

  5. UI λ³€κ²½

λ¬Έμ œκ°€ 됐던 ν”„λ‘œμ„ΈμŠ€ πŸ˜‡
  1. μ‚¬μš©μž 이벀트 λ°œμƒ

    ↓

  2. λΌμ΄λΈŒλŸ¬λ¦¬μ—μ„œ μ œκ³΅ν•˜λŠ” hook 호좜 (ex: onBeforeMappingChange)

    ↓

  3. hookμ—μ„œ 라이브러리 λ‚΄λΆ€ μƒνƒœ λ³€κ²½ + λΆ€λͺ¨ μƒνƒœ λ³€κ²½ λ™μ‹œ λ°œμƒ

    ↓

  4. onMappingChange 콜백 호좜

    ↓

  5. λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈ μƒνƒœ μ—…λ°μ΄νŠΈ (setSomethingState)

    ↓

  6. λΆ€λͺ¨ λ¦¬λ Œλ”λ§μœΌλ‘œ μƒˆλ‘œμš΄ props 전달

    ↓

  7. 라이브러리 λ‚΄λΆ€μ—μ„œ props λ³€κ²½ 감지

    ↓

  8. λ‹€μ‹œ μƒνƒœ 동기화 μ‹œλ„

    ↓

  9. 7 ~ 8번 ν”„λ‘œμ„ΈμŠ€ λ¬΄ν•œ 반볡

    ↓

  10. Maximum rerender…

문제점 뢄석

원인을 λΆ„μ„ν•˜κ³  λ‚˜μ„œ, λ‹€λ₯Έ 라이브러리의 μƒνƒœλŠ” μ–΄λ–»κ²Œ κ΄€λ¦¬λ˜κ³  μžˆμ„κΉŒβ€¦ μƒκ°ν•˜κ²Œ λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

그리고 자주 μ‚¬μš©ν•˜λŠ” 라이브러리인 react-hook-form μ΄λΌλŠ” νŒ¨ν‚€μ§€κ°€ λ– μ˜¬λžκ³ , μ œμ–΄ μ»΄ν¬λ„ŒνŠΈμ™€ λΉ„μ œμ–΄ μ»΄ν¬λ„ŒνŠΈ κ΄€μ μ—μ„œ μƒκ°ν•΄λ³΄κ²Œ λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

핡심 λ¬Έμ œμ λ“€
  1. μƒνƒœ μ†Œμœ κΆŒμ˜ λͺ¨ν˜Έν•¨μ΄ μ‘΄μž¬ν–ˆμŠ΅λ‹ˆλ‹€.
// 라이브러리 λ‚΄λΆ€ μƒνƒœ
const [internalMappings, setInternalMappings] = useState(initialMappings)
 
// μ‚¬μš©μž μΈ‘ μƒνƒœ
const [userMappings, setUserMappings] = useState(initialMappings)
 
// 문제: μƒνƒœ 동기화가 νž˜λ“€κ³ , λ¬΄ν•œλ Œλ”μ˜ μ£Όμš”μ›μΈμ΄ λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

μ–΄λ–€ μƒνƒœκ°€ μ‹€μ œ 데이터인지 λͺ…ν™•ν•˜μ§€ μ•Šμ•˜κΈ°μ—, 두 μƒνƒœ κ°„ 동기화 κ³Όμ •μ—μ„œ λ§Žμ€ 좩돌이 λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€.


  1. λ‚˜λ„ λͺ¨λ₯΄κ²Œ React μ—μ„œ μ–‘λ°©ν–₯ 데이터 바인딩을 μ‹œλ„ν•΄λ²„λ¦° μΌ€μ΄μŠ€

1번의 λ¬Έμ œμ μ„ νŒŒμ•…ν•˜κ³  λ‚˜λ‹ˆ, 단방ν–₯ 데이터 흐름을 μ§€ν–₯ν•˜λŠ” Reactμ—μ„œ μžμ‹ λ„ λͺ¨λ₯΄κ²Œ μ–‘λ°©ν–₯ 데이터 바인딩을 좔ꡬ해버렸닀고 생각도 λ“€μ—ˆμŠ΅λ‹ˆλ‹€.

//library hooks
const { updateSourceFields } = useTableMapping()
 
//local state
const [newSourceFields, setNewSourceFields] = useState<SourceFields>({
  //..
})
 
const handleSomeAction = (sourceFields: SourceFields) => {
  updateSourceFields(sourceFields) // 1. 라이브러리 λ‚΄λΆ€ μƒνƒœ λ³€κ²½
  setNewSourceFields(sourceFields) // 2. μ‚¬μš©μž μΈ‘ μ§€μ—­ μƒνƒœ λ³€κ²½
}

μœ„μ˜ μ½”λ“œμ™€ 같이 μž‘μ„±ν•˜κ³  μžˆμ—ˆλŠ”λ°, μ–‘λ°©ν–₯으둜 μƒνƒœλ₯Ό λ™κΈ°ν™”ν•˜λ €λ‹€ λ³΄λ‹ˆ, μƒνƒœ 변경이 μ—°μ‡„μ μœΌλ‘œ λ°œμƒν•˜μ—¬ λ¬΄ν•œ λ£¨ν”„μ˜ 주된 원인이 λ˜μ—ˆλ˜ 것 κ°™μ•˜μŠ΅λ‹ˆλ‹€.

λ‚΄λ¦° κ²°λ‘ 

μ·¨μ—… μ€€λΉ„ μ‹œμ ˆ μ‚¬μš©ν•΄λ΄€λ˜ μƒνƒœ 관리 라이브러리인 Redux λΌλŠ” νŒ¨ν‚€μ§€λ₯Ό μƒκ°ν•΄λ³΄κ²Œ λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

ReduxλŠ” View μ»΄ν¬λ„ŒνŠΈμ—μ„œ μ „μ—­ μƒνƒœλ₯Ό κ΅¬λ…ν•˜κ³ , Dispatch ν•¨μˆ˜λ₯Ό 톡해 νŠΉμ • Action typeκ³Ό λ³€κ²½ν•  μƒνƒœ, 즉 payloadλ₯Ό 보내어 데이터λ₯Ό μ—…λ°μ΄νŠΈ ν•˜λŠ” Flux μ•„ν‚€ν…μ²˜λ₯Ό μ§€ν–₯ν•©λ‹ˆλ‹€.

Action β†’ Dispatcher β†’ Store β†’ View
  ↑                           ↓
  └─────── User Interaction β”€β”€β”˜

Flux μ•„ν‚€ν…μ²˜ 의 핡심은 단방ν–₯ 데이터 흐름 이기에, λΌμ΄λΈŒλŸ¬λ¦¬μ— λΉ„μŠ·ν•œ ν˜•μ‹μœΌλ‘œ μ μš©ν•΄λ³΄κΈ°λ‘œ ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

μ μš©ν•΄λ³΄κΈ°

Hook 제곡 방식 λ³€κ²½

κΈ°μ‘΄ useTableMapping을 ν˜ΈμΆœν•˜μ—¬ hook을 μ‚¬μš©ν•˜λ˜ λ°©μ‹μ—μ„œ, refλ₯Ό λ°›μ•„ μ‚¬μš©ν•˜λŠ” λ°©μ‹μœΌλ‘œ κ°œμ„ ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

μ΄μœ λŠ” μ•„λž˜μ™€ κ°™μ•˜μŠ΅λ‹ˆλ‹€.

  1. Provider 제거둜 μΈν•œ useTableMapping을 μ‚¬μš©ν•˜κ³  μžˆλŠ” μ»΄ν¬λ„ŒνŠΈμ˜ λΆˆν•„μš”ν•œ λ Œλ”λ§ 방지될 것이닀..
  2. 보일러 ν”Œλ ˆμ΄νŠΈ μ½”λ“œκ°€ κ°μ†Œν•  것이닀.
  3. λΆ€λͺ¨ μ»΄ν¬λ„ŒνŠΈμ—μ„œ μ§μ ‘μ μœΌλ‘œ 라이브러리λ₯Ό μ œμ–΄ν•˜λ©°, ν˜ΈμΆœν•΄λ„ onMappingChange둜 λ³€κ²½λœ μƒνƒœλ§Œ μ „λ‹¬λ˜κΈ° λ•Œλ¬Έμ—, λ¬΄ν•œλ Œλ”λ§μ„ λ°©μ§€ν•  수 μžˆμ„ 것이닀
<AddButton
  variant="outline"
  onClick={() => {
	if (tableMappingRef.current) {
	  tableMappingRef.current.appendSource(generateSourceDefaultValue());
	}
  }}
>

μ‹€μ œλ‘œ μœ„μ™€ 같이 μ‚¬μš©ν•  수 있게 λ˜μ—ˆμŠ΅λ‹ˆλ‹€ πŸ˜€

μƒνƒœ κ΄€λ¦¬μ˜ κ°œμ„ 

데이터가 단방ν–₯으둜 흐λ₯Ό 수 있게 κ°œμ„ ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

라이브러리 λ‚΄λΆ€μ—μ„œλŠ” μƒνƒœλ₯Ό κ΄€λ¦¬ν•˜μ§€ μ•ŠμœΌλ©°, νŠΉμ • Action이 일어났을 μ‹œ, Action typeκ³Ό λ³€κ²½λœ μƒνƒœλ₯Ό λ‹΄κ³  μžˆλŠ” Payloadλ₯Ό μ‚¬μš©ν•˜λŠ” 츑으둜 μ „λ‹¬ν•©λ‹ˆλ‹€.

const useTableMapping = ({
  sources: sourcesFromProps,
  targets: targetsFromProps,
  mappings: mappingsFromProps,
  onStateChange,
}: UseTableMappingProps) => {
  const sourceFields = sourcesFromProps as FieldItem[]
  const targetFields = targetsFromProps as FieldItem[]
  const mappings = mappingsFromProps
 
  const notifyChange = (
    newSources: FieldItem[],
    newTargets: FieldItem[],
    newMappings: Mapping[],
    action: NotifyAction,
  ) => {
    onStateChange({
      sources: newSources,
      targets: newTargets,
      mappings: newMappings,
      action,
    })
  }
 
  //...
}

μœ„μ™€ 같이, λΌμ΄λΈŒλŸ¬λ¦¬μ—μ„œ μ œκ³΅ν•˜λŠ” apiλ₯Ό ν˜ΈμΆœν•˜κ±°λ‚˜, 라이브러리 λ‚΄λΆ€μ—μ„œ μƒνƒœ λ³€ν™”κ°€ 일어났을 μ‹œ, λ‚΄λΆ€μ μœΌλ‘œ notifyChangeλΌλŠ” ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜κ³ , μ΅œμ’…μ μœΌλ‘œ onMappingChange 둜만 λ³€κ²½λœ μƒνƒœκ°€ μ „λ‹¬λ©λ‹ˆλ‹€

예λ₯Ό λ“€μ–΄, λͺ¨λ“  맡핑을 μ œκ±°ν•˜κΈ° μœ„ν•΄ λ‹€μŒκ³Ό 같이 ν˜ΈμΆœν•˜κ²Œ λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

<TrashButton
  variant="outline"
  className="border-[var(--color-border-default)]"
  onClick={() => {
	if (tableMappingRef.current) {
	  tableMappingRef.current.clearMappings();
	}
  }}
>

그러면 onMappingChange둜 μ•„λž˜μ™€ 같은 μƒνƒœκ°€ μ „λ‹¬λ˜κ²Œ λ©λ‹ˆλ‹€ πŸ˜€

<TableMapping
  //..
  onMappingChange={(stateWithAction) => {
    const { sources, targets, mappings, action } = stateWithAction;
 
Β  Β  console.log(stateWithAction);
 
	// sources: λ³€κ²½λœ sources
	// targets: λ³€κ²½λœ targets
	// mappings: λ³€κ²½λœ mappings
	// action: {
	//   type: 'REMOVE_MAPPING',
	//   paload: {
	//      mappingId: string;
Β  Β  //Β  Β    removedMapping: Mapping | undefined;
	//   }
    // }
Β }
/>

κ·Έλ ‡κ²Œ μ™„μ„±λœ κ²°κ³Όλ¬Ό .. πŸ“š


ν™œμ„±ν™” μƒνƒœ
λΉ„ν™œμ„±ν™” μƒνƒœ

λŠλ‚€ 점 🀡

μ΄λ²ˆΒ λΌμ΄λΈŒλŸ¬λ¦¬Β κ°œλ°œμ„Β ν†΅ν•΄Β Reactμ˜Β μƒνƒœΒ κ΄€λ¦¬μ— λŒ€ν•΄ 더 깊게 μƒκ°ν•΄λ³΄κ²Œ 된 계기가 λ˜μ—ˆμŠ΅λ‹ˆλ‹€.Β μ²˜μŒμ—λŠ”Β λ‹¨μˆœνžˆΒ "λΉ¨λ¦¬Β λ§Œλ“€μ–΄μ•ΌΒ ν•œλ‹€" λŠ” μƒκ°μœΌλ‘œ μ ‘κ·Όν–ˆμ§€λ§Œ, λ¬΄ν•œΒ λ Œλ”λ§μ΄λΌλŠ”Β μ΄μŠˆμ—Β λΆ€λ”ͺνžˆλ©΄μ„œ κ·Όλ³Έμ μΈΒ μ„€κ³„μ˜Β μ€‘μš”μ„±μ„Β κΉ¨λ‹¬μ•˜μŠ΅λ‹ˆλ‹€.

특히 단방ν–₯ 데이터 νλ¦„μ—μ„œμ˜Β μƒνƒœλ₯Ό λˆ„κ°€ κ΄€λ¦¬ν•˜λŠ”κ°€ λΌλŠ” κ°œλ…μ΄Β μ–Όλ§ˆλ‚˜Β μ€‘μš”ν•œμ§€Β μ•Œκ²ŒΒ λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

μ΄ˆκΈ°μ— μ„€κ³„ν–ˆλ˜ κ΅¬μ‘°λŠ”, κ°œμ„  ν›„ μƒκ°ν•΄λ³΄λ‹ˆ μ‚¬λžŒ 두 λͺ…이, μžλ™μ°¨ 핸듀을 μ₯κ³  μ„œλ‘œ 쒌우둜 λŒλ¦¬λŠ” λŠλ‚Œμ΄μ˜€λ˜ 것 κ°™μŠ΅λ‹ˆλ‹€.

이번 react-table-mapping νŒ¨ν‚€μ§€ κ°œμ„  이후, λ‹€λ₯Έ νŒ¨ν‚€μ§€λ₯Ό λ§Œλ“€κ²Œ λ˜λŠ” 날이 였면, μ²˜μŒλΆ€ν„°Β λͺ…ν™•ν•œ μƒνƒœ κ΄€λ¦¬Β μ „λž΅μ„ μˆ˜λ¦½ν•˜κ³ , μ‚¬μš©μž κ΄€μ μ—μ„œμ˜Β κ°œλ°œμž κ²½ν—˜μ„Β μš°μ„ μ μœΌλ‘œ κ³ λ €ν•΄μ•Όκ² λ‹€λŠ”Β λ‹€μ§μ„ ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

μ΄μƒμœΌλ‘œ 였늘 ν¬μŠ€νŒ…μ„ λ§ˆμΉ˜κ² μŠ΅λ‹ˆλ‹€ !