Published on

๐Ÿฅ 2024๋…„ 1์›”ํšŒ๊ณ 

Authors
  • avatar
    Name
    ์ตœ์˜์ค€ (Youngjun Choi)
    Twitter

1์›”์—๋Š” ์Šค์ฟผ๋“œ์—์„œ ์ฑ•ํ„ฐ๋กœ ์†Œ์†์ด ๋ฐ”๋€Œ๋ฉด์„œ ์—…๋ฌด๊ฐ€ ๊ธฐ๋Šฅ๊ฐœ๋ฐœ์—์„œ, ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”ํ•˜๊ณ  ์•ˆ์ •์„ฑ์„ ๋†’์ด๊ธฐ ์œ„ํ•œ ์—…๋ฌด๋“ค์ด ์ฃผ๋ฅผ ์ด๋ฃจ๊ฒŒ ๋˜์—ˆ๋‹ค. ํฌ๊ฒŒ ์ง‘์ค‘ํ•ด์„œ ์ง„ํ–‰ํ–ˆ๋˜ ์—…๋ฌด๋Š” App Start์‹œ๊ฐ„์„ ์ตœ์ ํ™”์™€ ์—๋Ÿฌ๋ฐ”์šด๋”๋ฆฌ ์ ์šฉ์ด์—ˆ๋‹ค. ๋‘ ๊ฐ€์ง€ ์ฑ•ํ„ฐ ์—…๋ฌด์™€ ํ•จ๊ป˜ ๋ถˆํ•„์š”ํ•œ API ํ˜ธ์ถœ์„ ๊ฐ์ง€ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๊ณ ๋ฏผํ•˜๊ณ  ํ•ด๊ฒฐ๋ฐฉ๋ฒ•์„ ์ฐพ์•„ ์ ์šฉํ•ด๋ณด์•˜๋‹ค.

1์›” ์—…๋ฌด๋ฅผ ์ƒˆ๋กญ๊ฒŒ ๋ฐฐ์šฐ๊ฒŒ ๋œ ์ ๊ณผ ๋А๊ผˆ๋˜ ์ ๋“ค์„ ๊ฐ„๋‹จํžˆ ์ •๋ฆฌํ•ด๋ณด๋ ค ํ•œ๋‹ค.

โš ๏ธ ๋ถˆํ•„์š”ํ•œ API ํ˜ธ์ถœ์„ ๊ฐ์ง€ํ•ด๋ณด์ž

๋ถˆํ•„์š”ํ•œ API๋ฅผ ์ค„์ด๋Š” ๊ฒƒ์€ ์„œ๋น„์Šค๋ฅผ ์ด์šฉํ•˜๋Š” ๊ณ ๊ฐ์˜ ์‚ฌ์šฉ์„ฑ์„ ๋†’์ด๊ณ , ์„œ๋ฒ„์˜ ๋ถ€ํ•˜๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ๋Š” ๋‘ ๊ฐ€์ง€ ์žฅ์ ์ด ์žˆ๋‹ค. ๊ทธ ์ค‘์š”์„ฑ์„ ์ €๋ฒˆ ๊ฒฌ์  ๋ฐœ์†ก ์‹œ๊ฐ„์„ ์ค„์ด๋ฉด์„œ ๋А๋ผ๊ณ  ๊ฐœ๋ฐœ๋‹จ๊ณ„์—์„œ ์•„๋Š” ๋ฐฉ๋ฒ•์ด ์—†์„์ง€ ๊ณ ๋ฏผํ–ˆ๊ณ , ์ด๊ฒƒ์„ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ axios interceptor๋ฅผ ์ด์šฉํ•ด๋ณด๊ธฐ๋กœ ํ–ˆ๋‹ค.

axios interceptor

axios interceptor๋Š” axios์˜ ์š”์ฒญ๊ณผ ์‘๋‹ต์„ ๊ฐ€๋กœ์ฑ„๋Š” ๊ธฐ๋Šฅ์ด๋‹ค. ์ด๋ฅผ ์ด์šฉํ•ด ์š”์ฒญ๊ณผ ์‘๋‹ต์— ๋Œ€ํ•œ ๋กœ์ง์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์–ด ๊ณตํ†ต์ ์ธ ์š”์ฒญ๊ณผ ์‘๋‹ต์— ๋Œ€ํ•ด ์ฒ˜๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ๋‹ค.

[axios interceptor ๊ณต์‹๋ฌธ์„œ ์˜ˆ์‹œ ์ฝ”๋“œ]

// Add a request interceptor
axios.interceptors.request.use(
  function (config) {
    // Do something before request is sent
    return config
  },
  function (error) {
    // Do something with request error
    return Promise.reject(error)
  }
)

// Add a response interceptor
axios.interceptors.response.use(
  function (response) {
    // Any status code that lie within the range of 2xx cause this function to trigger
    // Do something with response data
    return response
  },
  function (error) {
    // Any status codes that falls outside the range of 2xx cause this function to trigger
    // Do something with response error
    return Promise.reject(error)
  }
)

์ด๋Ÿฌํ•œ ๊ธฐ๋Šฅ์„ ์ด์šฉํ•ด ๊ตฌํ˜„ํ•œ ์ค‘๋ณต API๋ฅผ ์ฒดํฌํ•˜๊ธฐ ์œ„ํ•œ ์ฝ”๋“œ๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

[axios interceptor๋ฅผ ์ด์šฉํ•œ ์ค‘๋ณต API ์ฒดํฌ interceptor]

const requestMap = new Map<string, { lastTime: number; count: number }>()

const ์ค‘๋ณต์ฒดํฌ_request_interceptor = async (
  config: InternalAxiosRequestConfig
) => {
  const { method, url, params, data } = config
  const requestKey = `${method?.toUpperCase()} ${url} ${JSON.stringify(
    params
  )} ${JSON.stringify(data)}`

  const request = requestMap.get(requestKey) ?? { lastTime: 0, count: 0 }
  const now = Date.now()
  if (request.lastTime === 0 || now - request.lastTime > 1000) {
    requestMap.set(requestKey, { lastTime: now, count: 1 })
  } else {
    requestMap.set(requestKey, { lastTime: now, count: request.count + 1 })
    console.warn(
      `${method?.toUpperCase()} ${url} ๋ฐ˜๋ณต ์š”์ฒญ ${request.count + 1} times`
    )
  }
  return config
}

์œ„์™€ ๊ฐ™์ด interceptor๋ฅผ ํ†ตํ•ด ๋“ค์–ด์˜จ ์š”์ฒญ ์ •๋ณด๋ฅผ key๋กœ ํ•œ Map์— ๊ธฐ๋กํ•˜๊ณ  ์ค‘๋ณต API๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์˜ ๊ธฐ์ค€์€ ์šฐ์„  1์ดˆ ์ •๋„๋กœ ์ •ํ•ด๋ณด๊ธฐ๋กœ ํ–ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ๊ตฌํ˜„ํ•˜๊ณ  ๋‚˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด warning์ด ์ฐํžˆ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

[warning์œผ๋กœ ์ฐํžŒ ์ค‘๋ณตํ˜ธ์ถœ ๋กœ๊ทธ]

์ค‘๋ณตํ˜ธ์ถœ๋กœ๊ทธ

๊ตฌํ˜„ํ•˜๊ณ  ๋‚˜๋‹ˆ, ์‹ค์ œ๋กœ ๋ฐœ์ƒํ•˜๊ณ  ์žˆ๋Š” API๋“ค์„ ์ฐพ์„ ์ˆ˜ ์žˆ์—ˆ๋Š”๋ฐ, ์ค‘๋ณต API๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ๋งˆ๋‹ค ์ฐํžˆ๋‹ค ๋ณด๋‹ˆ ๋กœ๊ทธ๊ฐ€ ๋„ˆ๋ฌด ๋งŽ์ด ์ฐํžˆ๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๋‹ค. ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ ๊ฐ„๋‹จํ•˜๊ฒŒ debounce๋ฅผ ์ด์šฉํ•ด logging ์ฝ”๋“œ๋ฅผ ๊ฐ์‹ธ์ฃผ์—ˆ๋‹ค.

[debounce๋ฅผ ์ ์šฉํ•œ ์ค‘๋ณต API ์ฒดํฌ interceptor]

const notify = debounce(({ method, url, count }) => {
  console.warn(`${method?.toUpperCase()} ${url} ๋ฐ˜๋ณต ์š”์ฒญ ${count + 1} times`)
}, 1000)

const requestMap = new Map<string, { lastTime: number; count: number }>()

const ์ค‘๋ณต์ฒดํฌ_request_interceptor = async (
  config: InternalAxiosRequestConfig
) => {
  const { method, url, params, data } = config
  const requestKey = `${method?.toUpperCase()} ${url} ${JSON.stringify(
    params
  )} ${JSON.stringify(data)}`

  const request = requestMap.get(requestKey) ?? { lastTime: 0, count: 0 }
  const now = Date.now()
  if (request.lastTime === 0 || now - request.lastTime > 1000) {
    requestMap.set(requestKey, { lastTime: now, count: 1 })
  } else {
    requestMap.set(requestKey, { lastTime: now, count: request.count + 1 })
    notify({ method, url, count: request.count })
  }
  return config
}

[ํ•˜๋‚˜๋งŒ ์ฐํžˆ๋Š” ๋กœ๊ทธ]

์ค‘๋ณตํ˜ธ์ถœ๋กœ๊ทธ

๊ตฌํ˜„ ํ›„, ๊ฐœ๋ฐœ๊ณผ์ •์—์„œ ์ค‘๋ณต ํ˜ธ์ถœ๋˜๋Š” API๋“ค์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๊ณ , ์ด๋ฅผ ํ†ตํ•ด ์‹ค์ œ๋กœ ์–ด๋–ค ํ™”๋ฉด์—์„œ ๋ฐœ์ƒํ•˜๊ณ  ์žˆ๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ์—ˆ๋‹ค. ์กฐ๊ธˆ ์•„์‰ฌ์šด ์ ์€ ๊ฐœ๋ฐœํ™˜๊ฒฝ์—์„œ ์ธ์ง€ํ•˜๊ณ  ์‹ถ์–ด์„œ ์ถ”๊ฐ€ํ•œ ์ฝ”๋“œ์ด์ง€๋งŒ ์šฐ๋ฆฌ ํ”„๋กœ์ ํŠธ ์ฝ”๋“œ์— ์ถ”๊ฐ€๋˜๊ธฐ๋ณด๋‹ค debugger์— ํ‘œ๊ธฐ๋˜๋Š” ๊ฒŒ ๋” ์ข‹์•„ ๋ณด์˜€๋‹ค.

์ดํ›„์— RN ๋””๋ฒ„๊ฑฐ๋ฅผ ๋ถ„์„ํ•ด๋ณด๋ฉด์„œ ํ•ด๋‹น ๊ธฐ๋Šฅ์„ ๋งŒ๋“ค์–ด๋ณด๋Š” ๊ฒƒ๋„ ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.

๐Ÿ›ซApp Start ์‹œ๊ฐ„ ์ค„์ด๊ธฐ

์ฑ•ํ„ฐ๋กœ ์†Œ์†์ด ๋ณ€๊ฒฝ๋˜๊ณ  24๋…„ 1๋ถ„๊ธฐ ๋ชจ๋ฐ”์ผ ์ฑ•ํ„ฐ ๋ชฉํ‘œ๋กœ App Start ์‹œ๊ฐ„ ๋‹จ์ถ• ์ผ๊ฐ์„ ๋‹ด๋‹นํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค. ๊ธฐ์กด์— ์ธก์ •ํ•˜๊ณ  ์žˆ๋˜ ๊ธฐ์ค€์€ ์ตœ์ƒ์œ„ ํŒŒ์ผ์ธ App.tsx๊ฐ€ ๋ Œ๋”๋ง ๋œ ์ดํ›„ ๋ถ€ํ„ฐ Splash์„ ๊ฑฐ์ณ ํ™ˆํ™”๋ฉด์— ์ง„์ž…ํ•˜๊ธฐ๊นŒ์ง€์˜€๋‹ค.

์ธก์ • ๊ธฐ์ค€ ์žก๊ธฐ

๊ฐ€์žฅ ๋จผ์ € ์‹œ๋„ํ•œ ๋ฐฉ๋ฒ•์€ ๋„คํŠธ์›Œํฌ ์  ๋ณ‘๋ชฉ์ด ์žˆ๋Š”์ง€ ์ฒดํฌํ•จ์œผ๋กœ์จ ๋ถˆํ•„์š”ํ•œ API๋“ค์€ ์ œ๊ฑฐํ•˜๊ณ  ์ฐจ๋ก€๋กœ ์ง„ํ–‰๋˜๊ณ  ์žˆ๋Š” ๋ณ‘๋ชฉ์ง€์ ๋“ค์„ ๋ณ‘๋ ฌํ™”ํ•จ์œผ๋กœ์จ ์‹œ๊ฐ„์„ ๋‹จ์ถ•ํ•˜๋ ค ํ–ˆ๋‹ค.

ํ™ˆํ™”๋ฉด์— ๋“ค์–ด๊ฐ€๊ธฐ ์ „์— ์ฃผ์š”ํ•˜๊ฒŒ ์ง„ํ–‰ํ•ด์•ผ ํ•  ํ”„๋กœ์„ธ์Šค๋Š” ์„ธ ๊ฐ€์ง€๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ์•ฑ ๋ฒ„์ „ ์ฒดํฌ ๋ฐ ์—…๋ฐ์ดํŠธ
  • ์ธ์ฆํ† ํฐ์„ ์ด์šฉํ•œ ๋กœ๊ทธ์ธ
  • ๋กœ๊ทธ์ธ ํ›„ ์ดˆ๊ธฐํ™” ์ž‘์—…

์œ„ ์„ธ ๊ฐ€์ง€๊ฐ€ ๋ชจ๋‘ ์™„๋ฃŒ๋˜๊ณ  ๋‚˜์„œ ํ™ˆ ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด ์„ธ ๊ฐ€์ง€ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋ชจ๋‘ ์™„๋ฃŒ๋˜๋Š” ๋ฐ๊นŒ์ง€ ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ฐ ์Šคํ…์˜ ์™„๋ฃŒ์ง€์ ์— checkpoint๋ฅผ ์ฃผ์–ด ์–ผ๋งˆ์˜ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฌ๋Š”์ง€ ์ •๋ณด๋ฅผ ์ถ”๊ฐ€ํ–ˆ๋‹ค.

[์ค‘์š” ์ง€์ ์— ์ฒดํฌํฌ์ธํŠธ๋ฅผ ๋ฐ˜์˜๋œ Splash ํ™”๋ฉด ์ฝ”๋“œ]

const ์ดˆ๊ธฐํ™”_์‹คํ–‰ = async () => {
  try {
    await ํ† ํฐ๊ฐ€์ ธ์˜ค๊ธฐ()
    performanceTracker.addCheckPoint("์ธ์ฆํ† ํฐ ๊ฐ€์ ธ์˜ค๊ธฐ")

    await ์—…๋ฐ์ดํŠธ๋ฒ„์ „์ฒดํฌ()

    const deepLink = await ๋”ฅ๋งํฌ_์ •๋ณด๊ฐ€์ ธ์˜ค๊ธฐ()
    performanceTracker.addCheckPoint("๋”ฅ๋งํฌ ์ •๋ณด ๊ฐ€์ ธ์˜ค๊ธฐ")

    await ๋กœ๊ทธ์ธ()
    performanceTracker.addCheckPoint("ํ† ํฐ ๊ธฐ๋ฐ˜ ๋กœ๊ทธ์ธ")

    await tracker.stopTrace("๊ธฐ์กด_trace_์ธก์ •_์™„๋ฃŒ")
    await ํ™ˆ_ํ™”๋ฉด์œผ๋กœ_์ด๋™(deepLink)
    performanceTracker.addCheckPoint("ํ™ˆ ํ™”๋ฉด ์ด๋™")

    await ์ดˆ๊ธฐํ™”์ž‘์—…1()
    // ...
    await ์ดˆ๊ธฐํ™”์ž‘์—…N()
    await tracker.stopTrace("์ƒˆ๋กœ์šด trece_์ธก์ •_์™„๋ฃŒ")
  } catch (error) {
    ์—๋Ÿฌํ•ธ๋“ค๋ง_๋ฐ_๋กœ๊น…()
  }
}

์œ„ ์ฝ”๋“œ์—์„œ ์ƒˆ๋กœ์šด trace๋ฅผ ์ถ”๊ฐ€ํ•œ ์ด์œ ๋Š” ์ดˆ๊ธฐํ™”๊ฐ€ ๋ชจ๋‘ ์™„๋ฃŒ๋˜๋Š” ๋ฐ๊นŒ์ง€ ์‹œ๊ฐ„์„ ์•Œ๊ณ  ์‹ถ์—ˆ๋‹ค. ํ™ˆ ํ™”๋ฉด์œผ๋กœ ์ด๋™์‹œํ‚ค๊ณ , ์ดํ›„์— ์ผ๋ถ€ ์ดˆ๊ธฐํ™” ์ž‘์—…์ด ์ง„ํ–‰๋˜๊ณ  ์žˆ์–ด, ํ™”๋ฉด์ „ํ™˜์ด ์‘๋‹ต์†๋„๋ณด๋‹ค ๋น ๋ฅธ ๊ฒฝ์šฐ๋Š” ๊นœ๋นก์ด๊ฑฐ๋‚˜ layout shift๊ฐ€ ๋ฐœ์ƒํ•˜๊ณ  ์žˆ๋‹ค๋Š” ์ ์„ ๋ฐœ๊ฒฌํ•˜๊ฒŒ ๋˜์–ด ๋ชจ๋‘ ์™„๋ฃŒํ•˜๋Š” ๊ฒŒ ์œ ์ € ๊ฒฝํ—˜์— ๋” ์ข‹์„ ๊ฒƒ ๊ฐ™์•˜๋‹ค. ๊ทธ๋ž˜์„œ ์šฐ์„  ์ „์ฒด ์ดˆ๊ธฐํ™”๋ฅผ ์™„๋ฃŒํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ์‹œ๊ฐ„์„ ํ•จ๊ป˜ ๋ณด๊ณ ์ž ํ–ˆ๋‹ค.

ํ˜„์žฌ ์ถ”๊ฐ€ํ•œ ์ค‘๊ฐ„์ง€์ ๋“ค์˜ ๋ฐ์ดํ„ฐ๋ฅผ IOS 90% ์œ ์ € ๊ธฐ์ค€์œผ๋กœ, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ฐ์ดํ„ฐ๋ฅผ ์Œ“์•„๋ณผ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

  • ์ธ์ฆํ† ํฐ ๊ฐ€์ ธ์˜ค๊ธฐ: 1.6์ดˆ (์ตœ์ƒ์œ„ App.tsx๋ฅผ ๋ Œ๋”๋งํ•œ ํ›„๋ถ€ํ„ฐ Splash ํ™”๋ฉด์— ์ง„์ž…ํ•œ ํ›„์— ์ธ์ฆํ† ํฐ์„ ๊ฐ€์ ธ์˜ค๊ธฐ๊นŒ์ง€)
  • ๋”ฅ๋งํฌ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ: 3์ดˆ (๋ฒ„์ „ ์ฒดํฌ, ๋”ฅ๋งํฌ ์ •๋ณด ๋ถˆ๋Ÿฌ์˜ค๊ธฐ๊นŒ์ง€)
  • ํ† ํฐ ๊ธฐ๋ฐ˜ ๋กœ๊ทธ์ธ: 5.8์ดˆ (๋กœ๊ทธ์ธ+ ์ผ๋ถ€ ๋กœ๊ทธ์ธ ํ›„ ์ž‘์—…๊นŒ์ง€)
  • ํ™ˆ ํ™”๋ฉด ์ด๋™: 6.3์ดˆ (๋กœ๊ทธ์ธ ํ›„ ํ™ˆ ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•˜๊ธฐ๊นŒ์ง€)

์œ„ ์ธก์ •๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ณ  ๋จผ์ € ๋”ฅ๋งํฌ ์ •๋ณด๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ณ  ๋‚˜์„œ ํ™”๋ฉด ์ด๋™๊นŒ์ง€์˜ ์‹œ๊ฐ„์„ ๋‹จ์ถ•ํ•ด ๋ณด๋ ค ํ–ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด์„œ ์œ ์ € ํƒ€์ž…์„ ๊ธฐ์ค€์œผ๋กœ ์ดˆ๊ธฐํ™” ์ž‘์—…์„ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฆฌํŒฉํ† ๋งํ–ˆ๋‹ค.

์œ ์ €ํƒ€์ž…์„ ์ค‘์ ์œผ๋กœ ์ƒ๊ฐํ–ˆ๋˜ ์ด์œ ๋Š” ๋‘ ๊ฐ€์ง€๋กœ, ๋จผ์ € ์œ ์ €ํƒ€์ž…๋ณ„๋กœ ์ดˆ๊ธฐํ™” ์ž‘์—…์„ ์œ„ํ•œ API ํ˜ธ์ถœ ํšŸ์ˆ˜๊ฐ€ ๋‹ฌ๋ž๋‹ค. ๋น„ํšŒ์›/๊ณ ๊ฐ/๊ณ ์ˆ˜ ๋ชจ๋‘๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ๊ณตํ†ต ์ดˆ๊ธฐํ™” ๋กœ์ง, ๊ณ ๊ฐ๊ณผ ๊ณ ์ˆ˜๋งŒ์„ ์œ„ํ•œ ์ดˆ๊ธฐํ™” ๋กœ์ง, ๊ณ ์ˆ˜๋งŒ์„ ์œ„ํ•œ ์ดˆ๊ธฐํ™” ๋กœ์ง ์ด ์„ธ ๊ฐ€์ง€๋กœ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ์—ˆ๊ณ , ์œ ์ €๊ฐ€ ๊ณ ์ˆ˜๋ผ๋ฉด ์„ธ ๊ฐ€์ง€ ๋ชจ๋‘๋ฅผ ์ง„ํ–‰ํ•ด์•ผ ํ•ด์„œ ๊ฐ€์žฅ ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ์œ ์ € ํƒ€์ž…์œผ๋กœ ์˜ˆ์ƒ๋˜์—ˆ๋‹ค.

๋‘๋ฒˆ์งธ๋กœ๋Š” ๊ธฐ์กด์—๋Š” ๋กœ๊ทธ์ธ ํ•จ์ˆ˜ ๋‚ด๋ถ€์— ์ผ๋ถ€ ์ดˆ๊ธฐํ™” ์ž‘์—…์ด ํฌํ•จ๋˜์–ด์žˆ๊ฑฐ๋‚˜ ์ดˆ๊ธฐํ™” ์ž‘์—… ๊ฐ๊ฐ ๋‚ด๋ถ€์—์„œ ๋กœ๊ทธ์ธ ์—ฌ๋ถ€ ๋˜๋Š” ์œ ์ € ํƒ€์ž…์„ ์ฒดํฌํ•ด ์‹คํ–‰ํ•˜๊ฒŒ ๋˜์–ด ์žˆ์—ˆ๋˜ ๊ฒƒ์„ ํƒ€์ž…๋ณ„๋กœ ๋ฌถ์–ด ๋ณ‘๋ ฌ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด๋ณด์˜€๋‹ค.

์œ ์ €ํƒ€์ž…๋ณ„ ์ดˆ๊ธฐํ™” ๋ฆฌํŒฉํ† ๋ง

์„ค๊ณ„๋ฅผ ๋งˆ์น˜๊ณ  ๋‚˜์„œ๋Š” ํ•„์š”ํ•˜์ง€ ์•Š์€ API๋ฅผ ์ฐพ๋Š” ๊ฒƒ๊ณผ ํ•„์š”ํ•œ API๋“ค์˜ ์ˆœ์„œ ์ •ํ•˜๊ธฐ๋Š” ๊ฐœ๋ณ„ API๋ฅผ ๋ถ„๋ฅ˜ํ•˜๋Š” ์ž‘์—…์„ ์ง„ํ–‰ํ–ˆ๋‹ค. ํ•„์š”ํ•˜์ง€ ์•Š์€ API๋ฅผ ์ฐพ๋Š” ์ž‘์—…์— ์•ž์„œ ๊ตฌํ˜„ํ•œ ์ค‘๋ณต API ์ฒดํฌ ์œ ํ‹ธ ๋•๋ถ„์— ์–ด๋–ค API๊ฐ€ ์ค‘๋ณต๋˜๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ์—ˆ๊ณ , ์ด๋ฅผ ํ†ตํ•ด ํ•„์š”ํ•˜์ง€ ์•Š์€ API๋ฅผ ์ฐพ์•„ ์ œ๊ฑฐํ•˜๋Š” ์ž‘์—…์„ ์ง„ํ–‰ํ–ˆ๋‹ค.

์ด์–ด์„œ ๋‚จ์€ ํ•„์š”ํ•œ API๋“ค์€ ์„œ๋กœ์˜ ๋…ผ๋ฆฌ์  ์ „ํ›„ ๊ด€๊ณ„๋ฅผ ์ •๋ฆฌํ•ด ํ† ํฐ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ - ๋กœ๊ทธ์ธ -์œ ์ €ํƒ€์ž…๋ณ„ ์ดˆ๊ธฐํ™” ์ˆœ์œผ๋กœ ํ๋ฆ„์ด ์ง„ํ–‰๋  ์ˆ˜ ์žˆ๊ฒŒ ํ–ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ์„ธ ๊ฐ€์ง€๋กœ ๋ถ„๋ฅ˜๋œ ํ๋ฆ„ ์†์—์„œ ์œ ์ € ํƒ€์ž…๋ณ„ ์ดˆ๊ธฐํ™” ์ž‘์—…๋“ค์„ ๋ณ‘๋ ฌ๋กœ ์ฒ˜๋ฆฌํ•ด ์‹œ๊ฐ„์„ ๋‹จ์ถ•ํ•˜๋ ค ํ–ˆ๋‹ค.

[์œ ์ €ํƒ€์ž…์„ ๋“ค์–ด๋‚ผ ์ˆ˜ ์žˆ๊ฒŒ ๋ฆฌํŒฉํ† ๋งํ•œ ์ดˆ๊ธฐํ™” ์ฝ”๋“œ]

// ์œ ์ €ํƒ€์ž…๋ณ„ ์ดˆ๊ธฐํ™”
const ์œ ์ €ํƒ€์ž…๋ณ„_์ดˆ๊ธฐํ™” = async (userType: UserType) => {
  await Promise.all([
    ๊ณตํ†ต_์ดˆ๊ธฐํ™”(),
    ์œ ์ €_์ดˆ๊ธฐํ™”(userType),
    ๊ณ ์ˆ˜_์ดˆ๊ธฐํ™”(userType),
  ])
}

const ์ดˆ๊ธฐํ™”_์‹คํ–‰ = async () => {
  try {
    await ํ† ํฐ๊ฐ€์ ธ์˜ค๊ธฐ()

    await ์—…๋ฐ์ดํŠธ๋ฒ„์ „์ฒดํฌ()

    const deepLink = await ๋”ฅ๋งํฌ_์ •๋ณด๊ฐ€์ ธ์˜ค๊ธฐ()
    performanceTracker.addCheckPoint("๋”ฅ๋งํฌ ์ •๋ณด ๊ฐ€์ ธ์˜ค๊ธฐ")

    const userType = await ๋กœ๊ทธ์ธ()
    performanceTracker.addCheckPoint("ํ† ํฐ ๊ธฐ๋ฐ˜ ๋กœ๊ทธ์ธ")

    await ์œ ์ €ํƒ€์ž…๋ณ„_์ดˆ๊ธฐํ™”(userType)

    await ํ™ˆ_ํ™”๋ฉด์œผ๋กœ_์ด๋™(deepLink)
    performanceTracker.addCheckPoint("ํ™ˆ ํ™”๋ฉด ์ด๋™")

    await ๋กœ๊น…()
    await tracker.stopTrace("์ƒˆ๋กœ์šด_์ธก์ •_์™„๋ฃŒ")
  } catch (error) {
    ์—๋Ÿฌํ•ธ๋“ค๋ง_๋ฐ_๋กœ๊น…()
  }
}

์ž‘์—…์„ ์™„๋ฃŒํ•˜๊ณ  ๊ฐœ๋ฐœํ™˜๊ฒฝ๊ณผ Prodํ™˜๊ฒฝ์ด ๋‹ค๋ฅด๋‹ค ๋ณด๋‹ˆ ์–ผ๋งˆ๋‚˜ ์ค„์–ด๋“ค ์ˆ˜ ์žˆ์„์ง€, ์˜ˆ์ƒ์ด ๋˜์ง€ ์•Š์ง€๋งŒ ์•ž์„œ ์ดˆ๊ธฐํ™” ์ž‘์—…์ด ํ™”๋ฉด์ด๋™๋ณด๋‹ค ๋Šฆ์–ด์ ธ์„œ layout shift๊ฐ€ ์ผ์–ด๋‚˜๋Š” ๋ฌธ์ œ๋Š” ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์—ˆ๊ณ , ์˜ˆ์™ธ์ฒ˜๋ฆฌ๋„ ์ ์šฉํ•จ์œผ๋กœ์„œ ๋ณด๋‹ค ์•ˆ์ •์ ์œผ๋กœ ํ™ˆํ™”๋ฉด์œผ๋กœ ์ง„์ž…ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค. ํ˜„์žฌ ๋ฐฐํฌ๋˜์ง€ ์•Š์€ ์ƒํ™ฉ์ด๋ผ ๊ฒฐ๊ณผ๊ฐ€ ์–ด๋–ป๊ฒŒ ๋ ์ง€ ๊ฑฑ์ • ๋ฐ˜, ๊ธฐ๋Œ€๋ฐ˜์œผ๋กœ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ๋‹ค.

๊ทธ์™ธ ์‹œ๊ฐ„์„ ์ค„์ด๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•๋“ค

์•ž์„œ ๋‚˜๋ˆ ๋‘์—ˆ๋˜ ์„ธ๊ฐ€์ง€ ์ธก์ •์ง€์ ์— ๋”ฐ๋ผ ๋‹ค์Œ ๋ฐฉ๋ฒ•๋“ค์— ๋Œ€ํ•ด ๊ณ ๋ฏผํ•˜๊ณ  ์ฑ•ํ„ฐ๋‚ด์—์„œ ๋…ผ์˜๋ฅผ ์ง„ํ–‰ํ–ˆ๋‹ค. ๋จผ์ € ์—…๋ฐ์ดํŠธ ๋ฒ„์ „์ฒดํฌ์™€ ๋”ฅ๋งํฌ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์ง€์ ์„ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์–ด ๋ณด์˜€๋‹ค. ์—ฌ๊ธฐ์„œ ๊ฐ€์žฅ ํ•ต์‹ฌ์ด ๋˜์—ˆ๋˜ ๋ถ€๋ถ„์€ ์•ฑ๋ฒ„์ „ ์—…๋ฐ์ดํŠธ ์ฒดํฌ๋กœ ์ฝ”๋“œํ‘ธ์‹œ์˜ ์ž์ฒด ๋ฉ”์†Œ๋“œ๋ฅผ ์ด์šฉํ•ด์„œ App center์˜ ์˜ฌ๋ผ์™€์žˆ๋Š” ๋ฒ„์ „๊ณผ ํ˜„์žฌ ์•ฑ์˜ ๋ฒ„์ „์„ ์ฒดํฌํ•˜๊ณ  ์žˆ๊ณ , ์ฒดํฌํ•˜๋Š”๋ฐ 90ํ”„๋กœ ์œ ์ € ๊ธฐ์ค€์œผ๋กœ 1.6์ดˆ๊ฐ€ ์†Œ์š”๋˜๊ณ  ์žˆ์—ˆ๋‹ค.

๋‹จ์ถ•ํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ๋ฐฐํฌ๊ณผ์ •์—์„œ ํ•ด๋‹น ๋ฒ„์ „๊ณผ ํ•„์ˆ˜ ์—…๋ฐ์ดํŠธ ํ•„์š” ์—ฌ๋ถ€๋“ฑ์„ ๊ธฐ๋กํ•˜๋Š” ์ž์ฒด ํ”Œ๋ž˜๊ทธ๋ฅผ ๋งŒ๋“ ๋‹ค๋ฉด codepush ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•ด๋ณด์˜€๋‹ค. ํ•˜์ง€๋งŒ ์ง„์‹ค์˜ ์›์ฒœ์ด๋ผ ํ•  ์ˆ˜ ์žˆ๋Š” App Center์˜ ๋ฒ„์ „์„ ์ฒดํฌํ•˜์ง€ ์•Š๊ณ  ์ž์ฒด์ ์œผ๋กœ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์€ ์•ˆ์ •์„ฑ์— ๋Œ€ํ•œ ์šฐ๋ ค๊ฐ€ ์žˆ๊ณ , ๋น„์šฉ์ด ํฐ ์ž‘์—…์ด ๋  ๊ฒƒ ๊ฐ™์•„ ์•ž์„  ๊ฐœ์„ ์ž‘์—…์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ณ  ์ž‘์—…ํ•ด๋ณด๊ธฐ๋กœ ํ–ˆ๋‹ค.

๋งˆ์ง€๋ง‰ ๋‚จ์€ ๋ฐฉ๋ฒ•์œผ๋กœ๋Š” ์ธ์ฆ ์ดˆ๊ธฐํ™” ์ „๊นŒ์ง€์˜ ๋‹จ๊ณ„, ์•ฑ ๋ฒˆ๋“ค์„ ๋ถˆ๋Ÿฌ์˜ค๊ณ  ์‹คํ–‰ํ•  ๋•Œ ๋ณ‘๋ชฉ์ง€์ ์„ ์ฐพ๋Š” ๊ฒƒ์ด์—ˆ๋‹ค. ์ด๋ถ€๋ถ„์€ ์•„์ง ์ •ํ™•ํ•œ ์ง€์ ์„ ์ฐพ์ง€๋ชปํ•ด ๋„คํŠธ์›Œํฌ์ ์ธ ์ ‘๊ทผ์™ธ์—๋„ ์—ฌ๋Ÿฌ React native ์ตœ์ ํ™”์™€ ๊ด€๋ จ๋œ ๊ธ€๊ณผ ๋…ผ์˜๋ฅผ ๋ณด๋ฉด์„œ ๋ฐฉ๋ฒ•์„ ์ฐพ๊ณ ์žˆ๋‹ค.

Bundle Splitting, Hermes, JSI๋“ฑ์— ๋Œ€ํ•ด ๊ฒ€ํ† ํ•ด ๋ณด์•˜์ง€๋งŒ, ์ด๋ฏธ ์šฐ๋ฆฌ ์•ฑ์—์„œ๋Š” Hermes์—”์ง„์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ณ , ํ˜„์žฌ ์šฐ๋ฆฌ๊ฐ€ ์ธก์ •๊ธฐ์ค€์— ๋งž์ถ˜ ์ตœ์ ํ™”๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— JS ์Šค๋ ˆ๋“œ ์ž์ฒด์˜ ๋ถ€๋‹ด์„ ์ค„์ผ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๊ณ ๋ฏผ์ด ํ•„์š”ํ•ด ๋ณด์˜€๋‹ค.

๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ๋ถˆํ•„์š”ํ•œ ๋ฆฌ๋ Œ๋”๋ง์„ ์ค„์ด๋Š” ์ž‘์—…์„ ๋จผ์ € ์ง„ํ–‰ํ•˜๊ณ , ์ดํ›„์— ๋ฒˆ๋“ค์˜ ํฌ๊ธฐ๋ฅผ ์ค„์ด๋Š” ๋“ฑ์˜ ์ž‘์—…์„ ์ง„ํ–‰ํ•  ์˜ˆ์ •์ด๋‹ค.

๐Ÿšฅ ์—๋Ÿฌ๋ฐ”์šด๋”๋ฆฌ ์ ์šฉ

๋“œ๋””์–ด ์—๋Ÿฌ ๋ฐ”์šด๋”๋ฆฌ๋ฅผ ์ ์šฉ ์ž‘์—…์„ ์‹œ์ž‘ํ–ˆ๋‹ค. ๋‚ด๊ฐ€ ๊ณ„ํšํ•œ ์ ์šฉ๋ฐฉ๋ฒ•์€ ๊ฐ€์žฅ ๋ฐ”๊นฅ์ชฝ๋ถ€ํ„ฐ ์•ˆ์ชฝ์œผ๋กœ ์—๋Ÿฌ๋ฐ”์šด๋”๋ฆฌ๋ฅผ ์ ์šฉํ•˜๋Š” ๊ฒƒ์œผ๋กœ, ์ตœ์ƒ์œ„ ์—๋Ÿฌ๋ฐ”์šด๋”๋ฆฌ๋ฅผ ์‹œ์ž‘์œผ๋กœ ์Šคํฌ๋ฆฐ๋‹จ์œ„๋กœ ์ ์šฉํ•ด ๋‚˜๊ฐˆ ์˜ˆ์ •์ด์—ˆ๋‹ค.

ํ•„์š”ํ•œ ์—๋Ÿฌ๋ฐ”์šด๋”๋ฆฌ๋ฅผ ์ตœ์ƒ์œ„์— ์ ์šฉํ•˜๊ธฐ ์œ„ํ•ด App.tsx๋ฅผ ์ˆ˜์ •ํ–ˆ๊ณ , error๋ฅผ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ๊ฒŒ ์ ์šฉํ–ˆ๋‹ค.

class App extends Component<{}, State> {
    state: State = {
        hasError: false,
    };

    constructor(props: Record<string, never>) {
        super(props);
    }

    componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
       ์—๋Ÿฌ๋กœ๊น…()
    }

    static getDerivedStateFromError() {
        return { hasError: true };
    }

    handleRestartApp = () => {
        CodePush.restartApp();
    };

    render(): ReactElement {
        const { hasError } = this.state;

        if (hasError) {
            return (
                <FallabckComponent retry={handleRestartApp} />
            );
        }
        return (
            //...
        );
    }
}

export default App;

์ตœ์ƒ์œ„ ์—๋Ÿฌ๋ฐ”์šด๋”๋ฆฌ์— ์—๋Ÿฌ๊ฐ€ ๋„๋‹ฌํ–ˆ์„ ๋•Œ์— ์•ฑ์„ ์žฌ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ฃผ๋Š” ๊ฒŒ ์ข‹์„ ๊ฒƒ ๊ฐ™์•„, Codepush๋ฅผ ์ด์šฉํ•œ restart ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ–ˆ๋‹ค.

๊ตฌํ˜„์ž์ฒด๋Š” ์–ด๋ ต์ง€ ์•Š์•˜์ง€๋งŒ, ์กฐ๊ธˆ ๋” ๊ณ ๋ฏผ์ด ๋˜์—ˆ๋˜ ๊ฒƒ์€ ์–ด๋–ป๊ฒŒ ์•ˆ๋‚ดํ•ด์ฃผ๋Š” ๊ฒŒ ์œ ์ €์ž…์žฅ์—์„œ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ์„๊นŒ์˜€๋‹ค. ํ˜ผ์ž ๊ณ ๋ฏผํ•˜๋‹ค๊ฐ€ ์ฑ•ํ„ฐ์›๋ถ„๋“ค์˜ ๋„์›€์„ ๋ฐ›์•„ ๋‹ค์–‘ํ•œ ์‹œ์•ˆ์„ ๋งŒ๋“  ํ›„์—, UX writer ๋ถ„๊ณผ ํ”Œ๋žซํผ ๋””์ž์ด๋„ˆ๋ถ„๋“ค์˜ ๋„์›€์„ ๋ฐ›์•„ ์™„์„ฑํ–ˆ๋‹ค.

์ฑ•ํ„ฐ๋‚ด์˜ ์—…๋ฌด์ธ๋ฐ ๋‹ค๋ฅธ ์ฑ•ํ„ฐ๋ถ„๋“ค๊ป˜ ์ผ์„ ๋งŒ๋“ค์–ด ๋“œ๋ฆฌ๋Š” ๊ฑด ์•„๋‹๊นŒ๋ผ๋Š” ๊ณ ๋ฏผ์ด ๋˜์—ˆ์ง€๋งŒ ์‹ค์ œ๋กœ ์š”์ฒญ๋“œ๋ ธ์„ ๋•Œ ๋„ˆ๋ฌด ํ”์พŒํžˆ ๋„์›€์„ ์ฃผ์…จ๊ณ , ์˜คํžˆ๋ ค ํ˜„์žฌ ์ด๋ฒˆ๋…„๋„ ๋ถ„๊ธฐ OKR๊ณผ ์—ฐ๊ด€๋œ ์ž‘์—…์ด๋ผ ๊ฐœ๋ฐœ์ž๋ถ„๋“ค๊ป˜ ์—๋Ÿฌ ๋ฐœ์ƒ์‹œ ํ™”๋ฉด๋“ค์— ๋Œ€ํ•œ ์กฐ์‚ฌ๋ฅผ ๋ถ€ํƒ๋“œ๋ฆฌ๋ ค ํ–ˆ๋‹ค๋Š” ์ด์•ผ๊ธฐ๋ฅผ ๋“ค์–ด ํ•จ๊ป˜ ํ˜‘์—…ํ•˜๋Š” ์ข‹์€ ๊ณ„๊ธฐ๊ฐ€ ๋˜์—ˆ๋‹ค.

๋‚˜๋ณด๋‹ค ๋” ์ž˜ ์•„์‹œ๊ณ , ์ž˜ ํ•˜์‹œ๋Š” ๋ถ„๊ป˜ ์ ์ ˆํ•œ ๋„์›€์„ ๋ฐ›๋Š”๊ฒŒ ์ค‘์š”ํ•จ์„ ๋˜ ๋‹ค์‹œ ๋А๋‚„ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

๐Ÿ“š๊ทธ์™ธ์— ๋ฐฐ์šด์ 

App Start๊ฐœ์„  ์ž‘์—…๋“ค์„ ์ง„ํ–‰ํ•˜๋ฉด์„œ ํ˜„์žฌ React Native ์•„ํ‚คํ…์ณ ์ž์ฒด์— ๋Œ€ํ•œ ๊ณต๋ถ€๊ฐ€ ํ•„์š”ํ–ˆ๋‹ค. ํ•ด๋‹น ๋‚ด์šฉ๋“ค์„ ๋”ฐ๋กœ ์ •๋ฆฌํ•˜๋ฉด์„œ ๋ธ”๋กœ๊ทธ์— ์˜ฌ๋ ค๋ณด๊ณ  new Architecture, JSI๋“ฑ RNํŒ€์—์„œ ๋งŽ์€ ๋…ธ๋ ฅ์„ ๊ธฐ์šธ์ด๊ณ  ์žˆ๋‹ค๋Š” ์ ๋„ ์•Œ ์ˆ˜ ์žˆ์—ˆ๋‹ค. ๋˜ํ•œ ์—๋Ÿฌ๋ฐ”์šด๋”๋ฆฌ๋ฅผ ์ ์šฉํ•˜๋ฉด์„œ ์‹ค์ œ์ ์œผ๋กœ ์ œ์•ˆํ•˜๊ณ  ์ ์šฉํ•˜๋ฉด์„œ ์•ฑ์˜ ์•ˆ์ •์„ฑ์—๋„ ๊ธฐ์—ฌํ•  ์ˆ˜ ์žˆ์–ด ์ข‹์•˜๋˜ ํ•œ๋‹ฌ์ด์—ˆ๋‹ค.

๊ฐœ์ธ์ ์œผ๋กœ ๊ณ„์†ํ•ด์„œ ์ž๋™ํ™”๋‚˜ ์กฐ๊ธˆ ๋” ์ผ์„ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•๋“ค๋„ ๊ณ ๋ฏผํ•˜๊ฒŒ ๋˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค. ์ค‘๋ณต APIํ˜ธ์ถœ ๊ฐ์ง€ ์œ ํ‹ธ์„ ๋งŒ๋“ค๊ธฐ๋„ ํ•˜๊ณ , App Start ์‹œ๊ฐ„์„ ์ค„์ด๋Š” ์ž‘์—…์„ ํ•˜๋ฉด์„œ JS Bundle ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด Lodash ํŒจํ‚ค์ง€ ์ „์ฒด๋ฅผ ์ง์ ‘ importํ•˜์ง€ ์•Š๊ฒŒ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ๋„ ํ–ˆ๋‹ค. ์œ ์˜๋ฏธํ•œ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜ํƒ€๋‚˜๊ฒŒ ๋˜๋ฉด ๋ธ”๋กœ๊ทธ์— ๊ธ€๋„ ์ž‘์„ฑํ•ด๋ณผ ์˜ˆ์ •์ด๋‹ค.

์•„์ง ๋„ˆ๋ฌด๋„ˆ๋ฌด ๋ฐฐ์šธ๊ฒŒ ๋งŽ๋‹ค๊ณ  ๋А๊ปด ๋ฒ„๊ฒ๊ฒŒ ๋А๊ปด์ง€๊ธฐ๋„ ํ•˜์ง€๋งŒ, ๋” ์ข‹์€ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์น˜์—ดํ•˜๊ฒŒ ๊ณ ๋ฏผํ–ˆ๋˜ ํ•œ๋‹ฌ์ด์—ˆ๋‹ค. ํฐ ๊ฐœ์„ ์ด ๋˜์ง€ ์•Š๋”๋ผ๋„, ์น˜์—ดํ•˜๊ฒŒ ๊ณ ๋ฏผํ•˜๋Š” ๊ฒƒ ์ž์ฒด๊ฐ€ ๋‚ด๊ฐ€ ์„ฑ์žฅํ•ด๊ฐ€๋Š” ๊ณผ์ •์ด๊ธธ ๋ฐ”๋ผ๋ฉด์„œ ๋งˆ์ณ๋ณธ๋‹ค.