Published on

πŸš… 2023λ…„ 9μ›” 회고

Authors
  • avatar
    Name
    μ΅œμ˜μ€€ (Youngjun Choi)
    Twitter

9μ›”λ™μ•ˆ ν–ˆλ˜ 업무와 ν•™μŠ΅ν•œ λ‚΄μš©λ“€μ„ λŒμ•„λ³΄λ©΄ μŠ€μΏΌλ“œ μ—…λ¬΄λ‘œλŠ” μ‚¬λ‚΄μ˜ μƒˆλ²½μ κ²€μž‘μ—…μ„ μ°Έμ—¬ν–ˆκ³ , 우리 μ œν’ˆμ˜ μ€‘μš”ν•œ 도메인쀑 ν•˜λ‚˜μΈ λ°”λ‘œκ²¬μ μ— λŒ€ν•œ κ°œμ„  μž‘μ—…μ„ ν–ˆλ‹€. κ°œμΈμ μœΌλ‘œλŠ” 맀일 μ‚¬μš©ν•˜μ§€λ§Œ 뢀쑱함을 느꼈던 뢀뢄듀을 κ³΅λΆ€ν–ˆλ‹€.

πŸ˜… μ²˜μŒν•΄λ³Έ μƒˆλ²½ 점검 μž‘μ—…

κ²¬μ λ°œμ†‘μ— κ΄€ν•œ μ±…μž„μ΄ 우리 μŠ€μΏΌλ“œλ‘œ λͺ¨λ‘ λ„˜μ–΄μ˜€λ©΄μ„œ 좔석과 μ—°νœ΄λ₯Ό μ•žλ‘κ³  ν•„μš”ν–ˆλ˜ 9μ›” μƒˆλ²½μ κ²€ μž‘μ—…μ„ μ§„ν–‰ν•˜κ²Œ λ˜μ—ˆλ‹€. 점검을 μœ„ν•΄μ„œ POλΆ„κ³Ό λ°±μ—”λ“œκ°œλ°œμž 뢄듀에 λΉ„ν•΄ μƒλŒ€μ μœΌλ‘œ 적은 μž‘μ—…μ„ ν–ˆμ§€λ§Œ, 점검을 ν™•μΈν•˜κΈ° μœ„ν•΄ 점검 μš°νšŒκ°€ κ°€λŠ₯ν•œ λ²„μ „μ˜ 앱을 λΉŒλ“œν•΄ κ³΅μœ λ“œλ¦¬λŠ” 역할을 λ§‘μ•˜λ‹€.

일을 ν•˜λ©΄μ„œ μ „ μž‘μ—…μžλΆ„λ“€κ³Ό 많이 μ΄μ•ΌκΈ°ν•˜κ³ , μŠ€μΏΌλ“œ λ‚΄λΆ€ 점검 ν…ŒμŠ€νŠΈλ„ μ§„ν–‰ν•˜λ©° μ‹€μ„œλ²„μ—μ„œ 점검을별닀λ₯Έ μΆ”κ°€ μž‘μ—…μ΄ 없어도 될 것이라 μ˜ˆμƒν–ˆλ‹€. ν•˜μ§€λ§Œ μ „λ‹¬λ“œλ¦° λΉŒλ“œλ²„μ „μ΄ PROD μ„œλ²„μ˜ 점검을 μš°νšŒν•˜μ§€ λͺ»ν•˜λŠ” 상황이 λ²Œμ–΄μ‘Œλ‹€. 많이 λ‹Ήν™©μŠ€λŸ¬μ› μ§€λ§Œ μ΅œλŒ€ν•œ 빨리 μ „λ‹¬λ“œλ €μ•Όν•  것 κ°™μ•„ 원인을 μ°Ύμ•„λ³΄μ•˜κ³ , 원인은 μ κ²€μš°νšŒλ₯Ό μœ„ν•œ ν‚€κ°’ μ„€μ • λ•Œλ¬Έμ΄μ—ˆλ‹€.

우리 μ•±μ˜ ν™˜κ²½λ³€μˆ˜λ₯Ό μ„€μ •ν•  λ•Œ configλ₯Ό μ΄μš©ν•΄ μ„œλ“œνŒŒν‹° λΌμ΄λΈŒλŸ¬λ¦¬λ“€μ— ν•„μš”ν•œ ν‚€κ°’ 등을 μ„€μ •ν•˜κ³  μžˆλŠ”λ° Dev/Prod에 따라 μ„œλ²„μ κ²€ 우회 킀값이 λ‹€λ₯΄κ²Œ μ„€μ •λ˜μ–΄ μžˆλ‹€. λ‚΄κ°€ μ „λ‹¬λ“œλ¦° ν…ŒμŠ€νŠΈμš© λΉŒλ“œ 버전은 dev λ²„μ „μ˜ 킀값이기 λ•Œλ¬Έμ— μŠ€μΏΌλ“œ λ‚΄λΆ€ 점검 ν…ŒμŠ€νŠΈλŠ” μš°νšŒν•  수 μžˆμ—ˆμ§€λ§Œ, Prod μ„œλ²„μ— μ ‘κ·Όν•  λ•ŒλŠ” Prod둜 μ„€μ •λ˜μ–΄μžˆλŠ” μ„œλ²„μ κ²€ 우회 킀값이 ν•„μš”ν•΄ λ°œμƒν•œ μƒν™©μ΄μ—ˆλ‹€.

Prod ν‚€ κ°’μœΌλ‘œ μž„μ˜λ‘œ μˆ˜μ •ν•œ 버전을 λ‹€μ‹œ λΉŒλ“œν•΄ μ „λ‹¬λ“œλ¦¬λ©΄μ„œ ν•΄κ²°ν•  수 μžˆμ—ˆμ§€λ§Œ, μ„œλΉ„μŠ€μ— 영ν–₯을 μ£Όμ§€μ•ŠκΈ° μœ„ν•΄ μ΅œλŒ€ν•œ λΉ λ₯΄κ²Œ μž‘μ—…μ„ μ§„ν–‰ν•΄μ•Όν•˜κ³  사전에 μ„Έμ›Œλ‘” ν”„λ‘œμ„ΈμŠ€μ—μ„œ PO, QA뢄듀이 μ§„ν–‰ν•΄μ•Όν•  μž‘μ—…μ΄ λŠ¦μΆ°μ§€λŠ” 것 κ°™μ•„ 많이 λ‹Ήν™©μŠ€λŸ¬μš΄ μˆœκ°„μ΄μ—ˆλ‹€ πŸ˜‚

사전에 PROD μ„œλ²„ 점검을 μœ„ν•΄μ„œλŠ” λ‚΄λΆ€ν…ŒμŠ€ν„° λ˜λŠ” testflight 앱을 λ‹€μš΄λ°›μ•„μ„œ QA ν•˜μ‹€ 수 있게 μ•ˆλ‚΄ν–ˆμ–΄μ•Όν–ˆλŠ”λ° 사전 쀀비와 우리 μ•±μ˜ λ™μž‘μ΄ μ–΄λ–»κ²Œ λ˜λŠ”μ§€μ— λŒ€ν•΄ 이해가 λΆ€μ‘±ν•΄ 생긴 μ΄μŠˆμ˜€λ‹€... ν•˜μ§€λ§Œ κ°œμΈμ μœΌλ‘œλŠ” λͺ¨λ°”일 ν™˜κ²½μ— λŒ€ν•΄ 더 많이 배울 수 있고 이해도λ₯Ό 높일 수 μžˆλŠ” 쒋은 κΈ°νšŒκ°€ λ˜μ—ˆκ³ , 이후 μ κ²€μ‹œ 더 νŽΈν•˜κ²Œ μ§„ν–‰ν•  수 있게 μ„ΈνŒ…μ„ μˆ˜μ •ν•˜λŠ” μž‘μ—…λ„ μΆ”κ°€μ μœΌλ‘œ μ§„ν–‰ν–ˆλ‹€.

image-20231003201510681

😎React-native-reanimated 써보기

μŠ€μΏΌλ“œ μž‘μ—…μœΌλ‘œ λ°”λ‘œκ²¬μ  μ§€μ—­μ„€μ • κ°œμ„  일감을 μ§„ν–‰ν•˜λ©΄μ„œ react-native-reanimated 라이브러리λ₯Ό μ΄μš©ν–ˆλ‹€. 라이브러리λ₯Ό μ΄μš©ν•˜λ©΄μ„œ κ³΅λΆ€ν–ˆλ˜ λ‚΄μš©μ„ 정리해보렀 ν•œλ‹€.

React-native-reanimatedλŠ” react-native ν™˜κ²½μ—μ„œ μ• λ‹ˆλ©”μ΄μ…˜μ„ 60FPS에 맞게 κ΅¬ν˜„ν•  수 있게 λ„μ™€μ£ΌλŠ” λΌμ΄λΈŒλŸ¬λ¦¬λ‹€. μ €λ²ˆλ‹¬μ˜ sticky 헀더 μ• λ‹ˆλ©”μ΄μ…˜μ„ κ΅¬ν˜„ν•˜λ©΄μ„œλ„ μ‚¬μš©ν•˜λ € ν–ˆμ§€λ§Œ, λ‹Ήμ‹œ v1으둜 μ„€μΉ˜λ˜μ–΄μžˆμ—ˆκΈ° λ•Œλ¬Έμ— react native 버전을 0.71둜 μ˜¬λ¦¬λŠ” μž‘μ—…κ³Ό 병λͺ©μ΄ μžˆμ–΄ react-native 자체 animated apiλ₯Ό μ΄μš©ν–ˆλ‹€. 결ꡭ은 μ•ˆλ“œλ‘œμ΄λ“œμ—μ„œ... μ’Œμ ˆν•˜κ²Œ λ˜μ—ˆμ§€λ§Œ...πŸ₯²

그러면 μ™œ reanimatedλŠ” 자체 React-native의 Animated보닀 μ„±λŠ₯을 잘 보μž₯ν•  수 μžˆμ„κΉŒ?

μ§€λ§‰ν•œ React-native-reanimated의 원리

react-native-reanimatedλ₯Ό μ΄ν•΄ν•˜κΈ° μœ„ν•΄μ„œλŠ” λ¨Όμ € RN이 λ‘κ°œμ˜ μŠ€λ ˆλ“œλ‘œ μ΄λ£¨μ–΄μ Έμžˆλ‹€λŠ” 점을 μ•Œμ•„μ•Όν•œλ‹€.

RN의 두가지 μŠ€λ ˆλ“œλŠ” JS μŠ€λ ˆλ“œμ™€ UIμŠ€λ ˆλ“œλ‘œ κ΅¬μ„±λ˜μ–΄μžˆλŠ”λ° 두가지 μŠ€λ ˆλ“œκ°€ ν•˜λŠ” 역할이 λ‹€λ₯΄λ‹€.

  • JS μŠ€λ ˆλ“œ: λ‚΄κ°€ μž‘μ„±ν•˜λŠ” JS μ½”λ“œ(react)κ°€ λ™μž‘ν•˜λŠ” κ³³
  • UI μŠ€λ ˆλ“œ: native(IOS/AOS) μ½”λ“œκ°€ λ™μž‘ν•˜λŠ” κ³³

두가지 λ‹€λ₯Έ μŠ€λ ˆλ“œλŠ” Bridgeλ₯Ό ν†΅ν•΄μ„œ JSON ν˜•μ‹μœΌλ‘œ μ†Œν†΅ν•΄ λ‚΄κ°€ μ›ν•˜λŠ” UIλ₯Ό λ§Œλ“€κ²Œ λœλ‹€. μ΄λŸ¬ν•œ μ†Œν†΅κ³Όμ •μ—μ„œ JS μŠ€λ ˆλ“œμ—μ„œ μ‹œκ°„μ΄ 많이 μ†Œμš”λ˜λŠ” μž‘μ—…μ΄ 진행쀑이라면 UI μŠ€λ ˆλ“œμ— 반영이 λŠ¦μ–΄μ Έ ν”„λ ˆμž„ λ“œλžμ΄ λ°œμƒν•˜κ²Œ λ˜λ©΄μ„œ μš°λ¦¬κ°€ μ›ν•˜λŠ” μžμ—°μŠ€λŸ¬μš΄ μ• λ‹ˆλ©”μ΄μ…˜ κ΅¬ν˜„μ— 어렀움이 μƒκΈ°κ²Œ λœλ‹€.


μ €λ²ˆλ‹¬μ— μ• λ‹ˆλ©”μ΄μ…˜μ˜ 어렀움을 κ²ͺμ—ˆλ˜ 이유λ₯Ό λΆ„μ„ν–ˆλ˜ 것 처럼 layout을 μ΄λ™μ‹œν‚€λŠ” 것은 RN의 Animated APIλ₯Ό μ΄μš©ν•  λ•Œ useNativeDriverλ₯Ό μ‚¬μš©ν•  수 μ—†κΈ° λ•Œλ¬Έμ—, JS μŠ€λ ˆλ“œμ—μ„œ λ™μž‘ν•˜κΈ° λ•Œλ¬Έμ— λ²„λ²…μž„μ΄ λ°œμƒν•œ κ²ƒμœΌλ‘œ 이해할 수 μžˆμ—ˆλ‹€.

그러면 reanimatedλŠ” μ΄λŸ¬ν•œ 문제λ₯Ό μ–΄λ–»κ²Œ ν•΄κ²°ν•˜λŠ” 걸까?


reanimatedλŠ” μžμ—°μŠ€λŸ¬μš΄ μ• λ‹ˆλ©”μ΄μ…˜μ„ μœ„ν•΄ 두가지λ₯Ό μ΄μš©ν•˜λŠ”λ° λ°”λ‘œ Shared value와 worklet ν•¨μˆ˜μ΄λ‹€.

sharedValueλŠ” JSμŠ€λ ˆλ“œμ™€ UIμŠ€λ ˆλ“œ λͺ¨λ‘μ—μ„œ 읽을 수 μžˆλŠ” 값이고 workletν•¨μˆ˜λŠ” UI μŠ€λ ˆλ“œμ—μ„œ μž‘λ™ν•˜λŠ” μžλ°”μŠ€ν¬λ¦½νŠΈ ν•¨μˆ˜λ₯Ό μ˜λ―Έν•˜λŠ”λ°, μ• λ‹ˆλ©”μ΄μ…˜μ„ λΉ„λ™κΈ°μ μœΌλ‘œ μ „λ‹¬ν•˜λŠ” 것이 μ•„λ‹ˆλΌ UI μŠ€λ ˆλ“œμ—μ„œ λ°”λ‘œ λ™μž‘ν•  수 μžˆκ²Œν•¨μœΌλ‘œμ¨ μ„±λŠ₯을 보μž₯ν•œλ‹€.

function App() {
  // shared value
  const sv = useSharedValue(0)

  const handlePress = () => {
    sv.value += 10
  }

  // worklet function
  const style = useAnimatedStyle(() => {
    console.log("Running on the UI thread")
    return { opacity: 0.5 }
  })
}

JS μ½”λ“œλ₯Ό λ°”λ‘œ UI μŠ€λ ˆλ“œλ‘œ λ™μž‘ν•˜κ²Œ μœ„ν•΄μ„œλŠ” Reanimated의 자체 babel plugin을 톡해 workletν•¨μˆ˜λ₯Ό νŒŒμ•…ν•¨μœΌλ‘œμ¨ λ™μž‘ν•  수 μžˆλ‹€. μ™œ reanimated μ„€μΉ˜μ‹œ babel.config.js에 ν”ŒλŸ¬κ·ΈμΈμ„ μΆ”κ°€ν•˜κ²Œ ν•˜λŠ”μ§€ 이해할 수 μžˆμ—ˆλ‹€.

[Reanimated μ„€μΉ˜μ‹œ ν•„μš”ν•œ ν”ŒλŸ¬κ·ΈμΈ]

module.exports = {
  presets: [
    // ... // don't add it here :)
  ],
  plugins: [..."react-native-reanimated/plugin"],
}

μ’€ 더 κΉŠμ€ λ‚΄μš©μ€ Reanimated ν”ŒλŸ¬κ·ΈμΈ READMEλ₯Ό 톡해 이해할 수 μžˆλ‹€.


[Reanimatedλ₯Ό μ΄μš©ν•΄ UI μŠ€λ ˆλ“œμ—μ„œ λ™μž‘ν•˜λŠ” μ• λ‹ˆλ©”μ΄μ…˜ μ½”λ“œ]

Reaniamtedλ₯Ό μ΄μš©ν•΄ λ‚΄κ°€ λ§Œλ“€μ—ˆλ˜ μ• λ‹ˆλ©”μ΄μ…˜

κ°„λ‹¨ν•˜κ²Œ reanimatedλ₯Ό 톡해 κ΅¬ν˜„ν–ˆλ˜ μ• λ‹ˆλ©”μ΄μ…˜ μ½”λ“œλ₯Ό 정리해보렀 ν•œλ‹€. λ‚΄κ°€ κ΅¬ν˜„ν•΄μ•Όν•˜λŠ” μš”κ΅¬μ‚¬ν•­μ€ 쑰건에 따라 둀링이 λ˜λŠ” μ„Ήμ…˜μœΌλ‘œ 쑰건에 따라 λ‹€μŒμœΌλ‘œ λ„˜μ–΄κ°€λ“―μ΄ λ‚˜νƒ€λ‚˜κ²Œ λ˜λŠ” μ• λ‹ˆλ©”μ΄μ…˜μ΄μ—ˆλ‹€.

이λ₯Ό μœ„ν•œ μ½”λ“œ μ˜ˆμ‹œλŠ” κ°„λ‹¨νžˆ λ‹€μŒκ³Ό κ°™λ‹€.

export default function App() {
  const animatedOpacity = useSharedValue(1)
  const animatedTranslateY = useSharedValue(0)
  const animatedStyle = useAnimatedStyle(() => {
    return {
      opacity: animatedOpacity.value,
      transform: [{ translateY: animatedTranslateY.value }],
    }
  })

  const handlePressSteady = () => {
    animatedTranslateY.value = withTiming(0, { duration: DURATION })
    animatedOpacity.value = withTiming(1, { duration: DURATION })
  }

  const handlePressUp = () => {
    animatedTranslateY.value = withTiming(-DISTANCE, { duration: DURATION })
    animatedOpacity.value = withTiming(0, { duration: DURATION })
  }

  const handlePressDown = () => {
    animatedTranslateY.value = withTiming(DISTANCE, { duration: DURATION })
    animatedOpacity.value = withTiming(0, { duration: DURATION })
  }

  return (
    <View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
      <Animated.View style={animatedStyle}>
        <View
          style={{
            width: 100,
            height: 100,
            backgroundColor: "teal",
            justifyContent: "center",
            alignItems: "center",
          }}
        >
          <Text style={{ color: "white", fontSize: 30 }}>λŒκ±°μ•Ό</Text>
        </View>
      </Animated.View>
      <View style={{ flexDirection: "row", marginTop: 100 }}>
        <Button onPress={handlePressUp} title="μ˜¬λΌκ°€μœ " />
        <Button onPress={handlePressSteady} title="λ³΄μ—¬μœ " />
        <Button onPress={handlePressDown} title="λ‚΄λ €κ°€μœ " />
      </View>
    </View>
  )
}

μœ„ μ½”λ“œλ‘œ κ΅¬ν˜„ν•œ μ• λ‹ˆλ©”μ΄μ…˜μ€ λ‹€μŒκ³Ό κ°™λ‹€.

이제 ν•˜λ‚˜μΌλ•Œκ°€ μ•„λ‹ˆλΌ μ—¬λŸ¬κ°œ μΌλ•Œμ˜ μ• λ‹ˆλ©”μ΄μ…˜μ„ λ§Œλ“€μ–΄ 보자.

const RollingView: React.FC<{ text: string; show: boolean }> = ({
  text,
  show,
}) => {
  const animatedOpacity = useSharedValue(1)
  const animatedTranslateY = useSharedValue(0)
  const animatedStyle = useAnimatedStyle(() => {
    return {
      opacity: animatedOpacity.value,
      transform: [{ translateY: animatedTranslateY.value }],
    }
  })

  const startAnimation = useCallback(() => {
    if (show) {
      animatedTranslateY.value = withTiming(0, { duration: DURATION })
      animatedOpacity.value = withTiming(1, { duration: DURATION })
    } else {
      animatedTranslateY.value = withSequence(
        withTiming(-DISTANCE, { duration: DURATION }),
        withTiming(DISTANCE, { duration: 0 })
      )
      animatedOpacity.value = withTiming(0, { duration: DURATION / 2 })
    }
  }, [animatedOpacity, animatedTranslateY, show])

  useEffect(() => {
    startAnimation()
  }, [startAnimation])

  return (
    <Animated.View
      style={[
        {
          backgroundColor: "teal",
          position: "absolute",
          justifyContent: "center",
          alignItems: "center",
        },
        animatedStyle,
      ]}
    >
      <Text style={{ color: "white", fontSize: 30 }}>{text}</Text>
    </Animated.View>
  )
}

export default function App() {
  const [showingNumber, setShowingNumber] = useState(1)

  const handlePressOne = () => {
    setShowingNumber(1)
  }

  const handlePressTwo = () => {
    setShowingNumber(2)
  }

  return (
    <View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
      <View
        style={{
          position: "relative",
          justifyContent: "center",
          overflow: "hidden",
          width: 100,
          height: 100,
        }}
      >
        <RollingView text={"1번"} show={showingNumber === 1} />
        <RollingView text={"2번"} show={showingNumber === 2} />
      </View>
      <View style={{ flexDirection: "row", marginTop: 100 }}>
        <Button onPress={handlePressOne} title="1번 λ³΄μ—¬μ€˜" />
        <Button onPress={handlePressTwo} title="2번 λ³΄μ—¬μ€˜" />
      </View>
    </View>
  )
}

μœ„ μ½”λ“œλ₯Ό λ™μž‘μ‹œν‚€λ©΄ λ‹€μŒκ³Ό 같은 μ• λ‹ˆλ©”μ΄μ…˜μ΄ λ§Œλ“€μ–΄μ§„λ‹€.

λ‚΄κ°€ ν•œ 방법이 μ΅œμ„ μ€ 아닐 μˆ˜λ„ μžˆμ§€λ§Œ reanimatedλ₯Ό μ΄μš©ν•΄μ„œ μ• λ‹ˆλ©”μ΄μ…˜ μš”κ΅¬μ‚¬ν•­μ„ AOS/IOS λͺ¨λ‘μ—μ„œ μ μ ˆν•˜κ²Œ κ΅¬ν˜„ν•  수 μžˆμ–΄μ„œ λΏŒλ“―ν–ˆλ˜ μΌκ°μ΄μ—ˆλ‹€.

πŸ˜Šν•˜λ£¨ν•˜λ£¨ λ‚΄κ°€ κ³΅λΆ€ν•΄μ˜¨ 것듀

개발자둜 8κ°œμ›”μ΄λž€ μ‹œκ°„μ΄ μŒ“μ΄λ©΄μ„œ λ‚΄κ°€ μš°μ„ μ‹œν•΄μ„œ 곡뢀해야할 것이 λ¬΄μ—‡μΌκΉŒ κ³ λ―Όν–ˆλ‹€. 9월은 λΈ”λ‘œκ·Έμ— κΈ°λ‘ν•˜μ§€λŠ” μ•Šμ•˜μ§€λ§Œ 3μ›”λΆ€ν„° ν΄λ¦°μ½”λ“œ, 클린 μ•„ν‚€ν…μ²˜, ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°, λ¦¬νŒ©ν„°λ§ 4ꢌ의 책을 μ½μ—ˆκ³  λ‹€μŒμ€ μ–΄λ–€κ±Έ κ³΅λΆ€ν•΄λ³ΌκΉŒ 고민이 λ˜λŠ” μ‹œμ μ΄μ—ˆλ‹€. μ•„μΉ¨ 저녁 μΆœν‡΄κ·Ό μ‹œκ°„μ— μ„ λ°° κ°œλ°œμžλΆ„λ“€μ˜ 유튜브 μ˜μƒλ“€μ„ 많이 μ°Ύμ•„λ³΄λŠ”λ°, κ·Έλ•Œ λ“œλ¦Όμ½”λ”©μ˜ 개발 곡뢀 μ œλŒ€λ‘œ ν•˜λŠ” 법 πŸ€“ (μ •μ²΄κΈ°μ—μ„œ μ„±μž₯기둜 κ°€λ³΄μž, 함 ν•΄λ³΄μž!) 의 일정관리 뢀뢄에 λŒ€ν•΄ λ“€μœΌλ©΄μ„œ λ‚΄κ°€ μš°μ„ ν•΄μ„œ ν•™μŠ΅ν•΄μ•Όν•  λ‚΄μš©μ€ μ–΄λ–€ 것인지 μ •ν•΄λ³΄κ²Œ λ˜μ—ˆλ‹€.

νƒ€μž…μŠ€ν¬λ¦½νŠΈλ₯Ό μ•„μ„Έμš”? 🧐

λ‚˜λŠ” react-nativeλ₯Ό μ΄μš©ν•΄ λͺ¨λ°”일 μ—”μ§€λ‹ˆμ–΄λ‘œ μΌν•˜κ³  있고 개발 μ–Έμ–΄λŠ” Typescript둜 κ°œλ°œν•˜κ³  μžˆλ‹€. κ·Έλ ‡λ‹€λ©΄ λ‚΄κ°€ 더 많이 νšŒμ‚¬μ— κΈ°μ—¬ν•˜κ³  μ„±μž₯ν•˜κΈ° μœ„ν•΄μ„œ μš°μ„ μ‹œ ν•΄μ„œ μž˜ν•΄μ•Όν•  뢀뢄이 μ–΄λ–€ 것인지에 λŒ€ν•΄ μƒκ°ν•΄λ³΄μ•˜μ„ λ•Œ, κ°€μž₯ λ¨Όμ € λ– μ˜¬λžλ˜ 뢀뢄이 Typescript μ˜€λ‹€.

"λ‚˜λŠ” νƒ€μž…μŠ€ν¬λ¦½νŠΈλ₯Ό μž˜μ•Œκ³  μžˆλ‚˜?"λΌλŠ” μ§ˆλ¬Έμ„ ν–ˆμ„ λ•Œ κ·Έλ ‡μ§€ μ•Šλ‹€λŠ” 생각이 λ“€μ—ˆλ‹€. λ‹¨μˆœνžˆ λ‚΄κ°€ type alias와 interfaceλ₯Ό μ •μ˜ν•˜κ³  μ‚¬μš©ν•˜λŠ” 것에 그치고 μžˆμ—ˆλ‹€. "그러고 λ³΄λ‹ˆ λ‚˜λŠ” ν•œλ²ˆλ„ νƒ€μž…μŠ€ν¬λ¦½νŠΈ κ³΅μ‹λ¬Έμ„œλ₯Ό 보지 μ•Šμ•˜κ΅¬λ‚˜... "λΌλŠ” 생각에 ν•˜λ£¨μ— ν•œνŽ˜μ΄μ§€μ”© νƒ€μž…μŠ€ν¬λ¦½νŠΈ κ³΅μ‹λ¬Έμ„œ ν•Έλ“œλΆμ„ μ •λ¦¬ν•΄λ³΄μžλŠ” λͺ©ν‘œκ°€ 생겼닀.

λ‚˜λ¦„ 맀일 ν•œ 챕터씩 μ •λ¦¬ν•΄μ„œ ν˜„μž¬ 거의 λŒ€λΆ€λΆ„μ˜ ν•Έλ“œλΆ λ‚΄μš©μ„ ν•œλ²ˆμ”© λ‹€μ½μ–΄λ³΄μ•˜λ‹€. μ½μœΌλ©΄μ„œ μ™œ μ½”λ“œλ¦¬λ·°λ•Œ switch문의 default문을 μž‘μ„±ν•  λ•Œ never νƒ€μž…μœΌλ‘œ λ³€μˆ˜λ₯Ό λ§Œλ“€μ–΄μ„œ μ μš©ν•˜λŠ” 게 μ’‹κ² λ‹€κ³  λ§μ”€ν•΄μ£Όμ…¨λŠ”μ§€, enumκ³Ό objectλŠ” μ–΄λ–»κ²Œ λ‹€λ₯Έμ§€ 등등을 μ•Œ 수 μžˆμ—ˆλ‹€.

λ‚΄λ§˜λŒ€λ‘œ μ •λ¦¬ν•œ Typescript Handbook λ‚΄μš©μ€ 쑰금 더 λ‹€λ“¬μ–΄μ„œ typescript μ„Ήμ…˜μ— 정리해보렀 ν•œλ‹€.

[λ‚΄λ§˜λŒ€λ‘œ μ •λ¦¬ν•œ Typescript HandBook λ‚΄μš©]

Native도 κ³΅λΆ€ν•΄λ³΄μž 🫑

챕터내 μ—…λ¬΄λ‘œ μ—λŸ¬/μ˜ˆμ™Έμ²˜λ¦¬ 고도화 업무λ₯Ό λ§‘μ•„μ„œ μ§„ν–‰ν•˜λ©΄μ„œ λ„€μ΄ν‹°λΈŒ μ—λŸ¬λ“€μ„ 보면 잘 이해가 μ•ˆλ˜κ³  ν•΄κ²°ν•˜μ§€ λͺ»ν•΄μ„œ λ‹΅λ‹΅ν•˜κ²Œ λŠκ»΄μ‘Œλ‹€. 우리 ν”„λ‘œμ νŠΈ λ‚΄μ˜ μ½”λ“œκ°€ μ•„λ‹ˆλΌ λΌμ΄λΈŒλŸ¬λ¦¬λ“€μ΄λ‚˜ react-nativeκ°€ κ°€μ§€κ³  μžˆλŠ” 문제둜 인해 λ°œμƒν•˜λŠ” κ²½μš°κ°€ λ§Žμ•˜κΈ° λ•Œλ¬Έμ— java라고 μ ν˜€μžˆκΈ°λ§Œ ν•˜λ©΄ 괜히 λ¬΄μ„œμš΄ λŠλ‚Œμ΄ λ“€κ³ , ν•΄κ²°ν•˜κΈ° μ–΄λ ΅κ² λ‹€λŠ” 생각에 ν›„μˆœμœ„λ‘œ λ―Έλ€˜λ‹€.

ν•˜μ§€λ§Œ Firebase의 Crashanalytics에 μ œλ³΄λ˜κΈ°λ„ ν•˜κ³  μ—λŸ¬λ‘œκ·Έμ— κ°‘μžκΈ° μ£½λŠ” λ‘œκ·Έλ“€μ„ λ³΄λ©΄μ„œ λ‚΄κ°€ 더 κ³΅λΆ€ν•œλ‹€λ©΄ 더 λ§Žμ€ 것을 우리 챕터에 κΈ°μ—¬ν•  수 μžˆκ² λ‹€λŠ” 생각이 λ“€μ–΄ Native에 λŒ€ν•œ 이해도λ₯Ό ν•΄κ²°ν•˜κ³ μž μ•ˆλ“œλ‘œμ΄λ“œλ₯Ό κ³΅λΆ€ν•˜κΈ° μ‹œμž‘ν–ˆλ‹€.

λ‚΄κ°€ 처음 μžλ°”μŠ€ν¬λ¦½νŠΈλ₯Ό 배울 λ•Œ 처럼 μš°μ„ μ€ μ½”ν‹€λ¦° 문법, μ½”λ”©ν…ŒμŠ€νŠΈ λ¬Έμ œλ“€μ„ ν’€κ³ , 클둠 μ½”λ”© κ°•μ˜λ“€μ„ λ³΄λ©΄μ„œ μ–΄λ–»κ²Œ 앱을 λ§Œλ“€μ–΄κ°€λŠ”μ§€λ₯Ό 보고 λ”°λΌν•˜λ©° ν•™μŠ΅ν•˜κ³  μžˆλ‹€. ν•™μŠ΅ν•  수둝 기쑴에 μ‚¬μš©ν•˜λ˜ μžλ°”μŠ€ν¬λ¦½νŠΈ, 파이썬과 λΉ„κ΅ν•˜λ©΄μ„œ 동적 νƒ€μž… 언어와 μ •μ νƒ€μž… μ–Έμ–΄μ˜ 차이점듀을 많이 λŠλ‚„ 수 μžˆμ—ˆκ³ , μžλ°”μŠ€ν¬λ¦½νŠΈμ™€ 코틀린이 μ–΄λ–€ 점이 λ‹€λ₯Έμ§€ μ–΄λ–€ 점은 λΉ„μŠ·ν•œμ§€ 느끼며 ν•΄λ‹Ή 뢀뢄도 정리해가고 μžˆλ‹€. 이뢀뢄도 λΈ”λ‘œκ·Έμ— μΆ”κ°€μ μœΌλ‘œ κΈ°λ‘ν•΄λ‚˜κ°ˆ μ˜ˆμ •μ΄λ‹€.

마치며

멀리 λ©‹μžˆμ–΄λ³΄μ΄λŠ” 것듀이 λ‚˜μ˜¬ λ•Œλ§ˆλ‹€ 저것을 λ°°μš°μ§€ μ•ŠμœΌλ©΄ 뒀쳐지지 μ•Šμ„κΉŒ 걱정도 λ˜μ§€λ§Œ, μ§€κΈˆ λ‚΄κ°€ μžˆλŠ” μžλ¦¬μ—μ„œ ν•„μš”ν•œ 뢀뢄듀을 μ±„μ›Œλ‚˜κ°€λŠ” 것을 λ¨Όμ €ν•΄μ•Όκ² λ‹€κ³  λ‹€μ‹œ ν•œλ²ˆ μƒκ°ν•œ ν•œλ‹¬μ΄μ—ˆλ‹€. 맀일 μ‚¬μš©ν•˜λŠ” νƒ€μž…μŠ€ν¬λ¦½νŠΈμ™€ Git, λ¦¬μ•‘νŠΈμ™€ λ„€μ΄ν‹°λΈŒ μ½”λ“œλ“€, μΆ©λΆ„νžˆ 잘 μ΄ν•΄ν•˜κ³  μžˆλŠ”μ§€ μ κ²€ν•΄λ³΄λ©΄μ„œ μš°μ„ μˆœμœ„λ₯Ό μ„ΈμšΈ 수 μžˆμ—ˆλ‹€. 더 많이 λ‚˜λˆ„κ³  더 많이 κΈ°μ—¬ν•˜κΈ° μœ„ν•΄μ„œλŠ” λ‚΄κ°€ λ¨Όμ € μ±„μ›Œμ Έμ•Όν•¨μ„ 많이 λŠλ‚€λ‹€. 아직 8κ°œμ›” μ°¨ 응애(?)κ³  맀일맀일 μƒˆλ‘­κ²Œ 배울게 λ„˜μ³λ‚˜μ§€λ§Œ μ—¬κΈ°μ„œ μ£Όμ–΄μ§€λŠ” ν‚€μ›Œλ“œλ“€μ„ λ†“μΉ˜μ§€ μ•Šκ³  λ‚΄κ²ƒμœΌλ‘œ λ§Œλ“€λ‹€λ³΄λ©΄ λ‚΄κ°€ 보고 λ°°μ›Œμ•Όκ² λ‹€κ³  λŠλΌλŠ” λ™λ£Œλ“€μ˜ λͺ¨μŠ΅μ„ λ‚˜λ„ κ°€μ§€κ²Œ λ˜μ–΄κ°€μ§€ μ•Šμ„κΉŒ μƒκ°ν•œλ‹€. κ·Έλƒ₯ κΎΈμ€€νžˆ ν•˜λŠ” 것, λ‚΄κ°€ 제일 μž˜ν•˜λŠ” κΎΈμ€€νžˆλ₯Ό 맀일 ν•΄λ³΄μž.

[μ°Έκ³ ν•œ 자료]