Giter VIP home page Giter VIP logo

took's Introduction

๐Ÿ‘ฃ 2023

  • 2023.09 9oormthon 7th ๐Ÿ’ป repo
  • 2023.08.20 Junction Asia 2023 Track 2nd winner ๐Ÿ’ป repo
  • 2023.06.23 Next.js Docs Translation
  • 2023.07.22~ DEPROMMEET 13th ๋Œ€์ƒ / Na Lab FE ๐ŸŒ nalab web ๐Ÿ’ป repo
  • 2023.05.06 Chakra UI Ark Docs Bug Fix
  • 2023.05.15 React Docs Translation
  • 2023.04.26 2023 ๋•์„ฑ 5K(OK)! Plus O2O ์ฐฝ์—…๊ฒฝ์ง„๋Œ€ํšŒ ๋Œ€์ƒ
  • 2023.01.29 SPARCS 2023 StartUp Hackathon ์šฐ์ˆ˜์ƒ
  • 2023.02 ํ…Œ์˜ค์˜ ์Šคํ”„๋ฆฐํŠธ 14๊ธฐ ๐Ÿ’ป repo

๐Ÿ‘ฃ 2024

took's People

Contributors

baesi avatar dependabot[bot] avatar jeonbyeongmin avatar sumi-0011 avatar

Stargazers

 avatar

Forkers

jeonbyeongmin

took's Issues

๋กœ๊ทธ์ธ ์ดํ›„ ํšŒ์›๊ฐ€์ž…์„ ๋‹ค์‹œ ํ•˜๊ณ  ์‹ถ์„ ๋•Œ

// /src/common/HOC/AuthHoc.tsx

import React, {ComponentType} from 'react';
import {isLoggedIn} from '@common/api/fireAuth';

export default function <P extends object>(Component: ComponentType<P>) {
  function AuthenticationCheck({...props}) {
    // if (isLoggedIn() === false) {
    //   props.navigation.replace('Auth');
    // }

    props.navigation.replace('Auth');

    return <Component {...(props as P)} />;
  }
  return AuthenticationCheck;
}

์œ„์™€ ๊ฐ™์ด ์ˆ˜์ •ํ•˜๊ณ  ์žฌ๋กœ๊ทธ์ธ, ํšŒ์›๊ฐ€์ž… ์ง„ํ–‰ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. git ์— ์ปค๋ฐ‹ํ• ๋•Œ๋Š” ๋‹น์—ฐํžˆ ์›๋ž˜๋Œ€๋กœ ์ˆ˜์ •ํ•ด์ฃผ์‹œ๋ฉด ๋˜๊ฒ ์Šต๋‹ˆ๋‹ค.

Feat: ๋งˆ์ดํŽ˜์ด์ง€ ์ œ์ž‘

  • ์œ ์ € ์ •๋ณด
  • ์‚ฌ์šฉ์ž ํ™œ๋™ ์‹œ๊ฐํ™”
  • ๋“ฑ๋ก๋œ ์“ฐ๋ ˆ๊ธฐํ†ต ํ™•์ธ
  • ๋“ฑ๋ก๋œ ์“ฐ๋ ˆ๊ธฐํ†ต ์‚ญ์ œ
  • ์ฆ๊ฒจ์ฐพ๊ธฐ ์“ฐ๋ ˆ๊ธฐํ†ต ํ™•์ธ
  • ์ฆ๊ฒจ์ฐพ๊ธฐ ์“ฐ๋ ˆ๊ธฐํ†ต ์‚ญ์ œ

React(-Native) ํ…Œ์ŠคํŠธ์— ๊ด€ํ•˜์—ฌ..


ํ…Œ์ŠคํŠธ ๊ณต๋ถ€๋Š” ์ž˜๋ผ๊ฐ€์‹œ๋‚˜์š”. ํ•™๊ต์—์„œ ์‹œํ‚จ๋‹ค๋Š” ์ด์œ  ๋•Œ๋ฌธ์— ๋งน๋ชฉ์ ์œผ๋กœ ํ•˜์ง€๋ง๊ณ  ์šฐ๋ฆฌ๊ฐ€ ์ง€๊ธˆ ํ•˜๊ณ  ์žˆ๋Š”๊ฒŒ ๋Œ€์ฒด ๋ฌด์—‡์ธ์ง€ ์ƒ๊ฐํ•ด๋ณด์ž๊ตฌ์š”.


ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋Š” ์ด์œ  ๐Ÿค”

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

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

๊ฒฐ๊ตญ ํ…Œ์ŠคํŠธ๋Š” ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ์œ„ํ•œ ๊ฒƒ์ด๊ธฐ๋„ ํ•˜์ง€๋งŒ ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ ๊ฒƒ์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. Lint, Typescript ๋ฅผ ์“ฐ๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ๋งฅ๋ฝ์ด์ง€์š”.


React(-Native) ์—์„œ ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๊ธฐ ์ „์—..

์•ฑ์˜ ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅ์„ฑ์„ ์˜ฌ๋ฆฌ๋ ค๋ฉด UI๋Š” UI ๋Œ€๋กœ, ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์€ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๋Œ€๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์ปดํฌ๋„ŒํŠธ์—์„œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด๋‚˜ ๋กœ์ง๋“ค์„ ๋ถ„๋ฆฌํ•˜๋ผ๋Š” ์˜๋ฏธ๊ฒ ์ง€์š”!!

๋˜ ํ…Œ์ŠคํŠธ ๋ฐฉ๋ฒ•๋ก  ์ค‘์—๋Š” ๋งŽ์€ ๊ฒƒ๋“ค์ด ์žˆ๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ํ”ํžˆ ์•Œ๊ณ  ์žˆ๋Š” TDD(ํ…Œ์ŠคํŠธ ์ฃผ๋„ ๊ฐœ๋ฐœ๋กœ, ์‹ค์ œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์ „์— ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ๋จผ์ € ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•๋ก )๋„ ์ด๋“ค ์ค‘ ํ•˜๋‚˜์ผ ๋ฟ์ž…๋‹ˆ๋‹ค. ๋‹จ์ง€ ์š”์ฆ˜ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๊ณ  ์„ฑ๋Šฅ์ด ํ™•์‹คํ•˜๋‹ˆ๊นŒ ๋งŽ์€ ๊ธฐ์—…๋“ค์—์„œ TDD๋ฅผ ์ถ”๊ตฌํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹๊นŒ ์‹ถ์Šต๋‹ˆ๋‹ค.

ํ•˜๊ณ  ์‹ถ์€ ๋ง์€ ์šฐ๋ฆฌ๊ฐ€ ๊ผญ ํ…Œ์ŠคํŠธ ์ฃผ๋„ ๊ฐœ๋ฐœ์„ ํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค๋Š” ๊ฒƒ์ด๋ž๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ํ…Œ์ŠคํŠธ๊ฐ€ ๊ฐ€๋Šฅํ•œ ์ฝ”๋“œ๋ฅผ ๋จผ์ € ์ž‘์„ฑํ•˜๊ณ  ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ด ํ‹€๋ฆฐ ๋ฐฉ๋ฒ•์ด ์•„๋‹™๋‹ˆ๋‹ค! ํ…Œ์ŠคํŠธ๋ฅผ ๋Œ€์ฒด ์™œ ํ•˜๋Š”์ง€ ๋ชธ์†Œ ๊นจ๋‹ซ๊ณ  ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ด ์ต์ˆ™ํ•ด์งˆ ๋•Œ TDD ๊ฐ™์€ ๋ฐฉ๋ฒ•์„ ๊ณ ๋ คํ•˜๋Š” ๊ฒƒ์ด ์–ด๋–จ๊นŒ์š”? ์šฐ๋ฆฐ ์•„์ง ํ…Œ์ŠคํŠธ ์ดˆ๋ณด์ž–์•„์š”~


@testing-library/react-native, Jest ๋กœ ํ…Œ์ŠคํŠธํ•˜๊ธฐ

ํ…Œ์ŠคํŠธ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์งง๊ณ  ํ•œ๊ฐ€์ง€๋งŒ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ฒƒ์ด ์ด์ƒ์ ์ž…๋‹ˆ๋‹ค. it ํ•จ์ˆ˜๋Š” ํ…Œ์ŠคํŠธ ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€ ๋ณผ๊นŒ์š”.

it('given a date in the past, colorForDueDate() returns red', () => {
  expect(colorForDueDate('2000-10-20').toBe('red'));
}

it given a date in the past, colorForDueDate() returns red ๊ฐ€ ํ•˜๋‚˜์˜ ๋ฌธ์žฅ์œผ๋กœ ์™„๋ฒฝํ•œ ๊ฒƒ์„ ๋ˆˆ์น˜์ฑ„์…จ๋‚˜์š”. ์•„๋ž˜์™€ ๊ฐ™์€ ํ‚ค์›Œ๋“œ๋กœ ์–ด๋–ค ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š”์ง€ ๋ถ„๋ช…ํ•˜๊ฒŒ ํ•ฉ์‹œ๋‹ค.

  1. given : ์‚ฌ์ „ ์กฐ๊ฑด
  2. when : ํ…Œ์ŠคํŠธ ์ค‘์ธ ํ•จ์ˆ˜์— ์˜ํ•ด ์‹คํ–‰๋˜๋Š” ํŠน์ • ์•ก์…˜
  3. then : ์˜ˆ์ƒ๋˜๋Š” ๊ฒฐ๊ณผ

jest ์—์„œ it ๊ณผ test ํ•จ์ˆ˜๋Š” ์ด๋ฆ„๋นผ๊ณ  ๋‹ค ๋˜‘๊ฐ™์•„์š”. ๋‹จ์ง€ ์ฒซ๋ฒˆ์งธ ์ธ์ž์— ํ•œ๊ธ€์„ ์‚ฌ์šฉํ•  ๋•Œ์—๋Š” it ๋ณด๋‹ค๋Š” test ๊ฐ€ ๋” ์ž˜ ์™€๋‹ฟ๋Š” ๊ฒƒ ๊ฐ™์•„์š”.

๋‹จ์œ„ ํ…Œ์ŠคํŠธ?

๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋Š” ๊ฐœ๋ณ„ ํ•จ์ˆ˜๊ฐ™์€ ์ฝ”๋“œ์˜ ๊ฐ€์žฅ ์ž‘์€ ๋ถ€๋ถ„์„ ํ…Œ์ŠคํŠธ ํ•ฉ๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ ์ค‘์ธ ๊ฐ์ฒด์— dependency ๊ฐ€ ์žˆ๋‹ค๋ฉด, mock ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•  ์ˆ˜๋„ ์žˆ์–ด์š”. mock ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋Š” ์„ธ ๊ฐ€์ง€๋กœ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ์–ด์š”.

  1. ํ…Œ์ŠคํŠธ๊ฐ€ ๋Š๋ฆฌ๊ณ  ๋ถˆ์•ˆ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
  2. ํ•ด๋‹น dependency๊ฐ€ ํ•ญ์ƒ ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค๊ณ  ๋ณด์žฅํ•  ์ˆ˜ ์—†๋‹ค.
  3. ์„œ๋“œํŒŒํ‹ฐ ์„œ๋น„์Šค๋ฅผ ํ˜„์žฌ ์‚ฌ์šฉํ•˜์ง€ ๋ชปํ•˜๋Š” ์ƒํ™ฉ์ผ ์ˆ˜ ์žˆ๋‹ค.

ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ?

ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ์—์„œ๋Š” ๊ฐ ๋‹จ์œ„๋“ค์ด ์ƒํ˜ธ ์ž‘์šฉํ•˜๋Š” ๊ฒƒ์„ ํ…Œ์ŠคํŠธํ•ด์š”. ์ฆ‰, ๊ฐ ๊ฐœ๋ฐœ ๋‹จ์œ„๋“ค์ด ๊ฒฐํ•ฉ๋˜๊ณ  ํ•จ๊ป˜ ํ…Œ์ŠคํŠธ๋˜์–ด ์˜ˆ์ƒ๋Œ€๋กœ ์ž‘๋™ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ด์ง€์š”.

์ปดํฌ๋„ŒํŠธ ํ…Œ์ŠคํŠธ?

๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์˜ ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€๊ฐ€ ๋†’๊ณ  ์ •ํ™•ํ•˜๋”๋ผ๋„, ์ปดํฌ๋„ŒํŠธ ํ…Œ์ŠคํŠธ๊ฐ€ ์—†๋‹ค๋ฉด ์‚ฌ์šฉ์ž์—๊ฒŒ ์˜๋„์™€ ๋‹ค๋ฅธ UI๋ฅผ ์ œ๊ณตํ•  ์ˆ˜๋„ ์žˆ์–ด์š”. ์ปดํฌ๋„ŒํŠธ ํ…Œ์ŠคํŠธ๋Š” ๋‹จ์œ„ ํ…Œ์ŠคํŠธ์™€ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ์—์„œ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์–ด์š”. ์šฐ๋ฆฌ๋Š” ์ปดํฌ๋„ŒํŠธ์˜ ์–ด๋–ค ๊ฒƒ์„ ํ…Œ์ŠคํŠธํ•ด์•ผ ํ• ๊นŒ์š”?

  1. ์ƒํ˜ธ์ž‘์šฉ : ์‚ฌ์šฉ์ž์™€ ์ƒํ˜ธ ์ž‘์šฉํ•  ๋•Œ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด (์˜ˆ๋ฅผ ๋“ค๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ!)
  2. ๋ Œ๋”๋ง : ๋ฆฌ์•กํŠธ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ ๋ Œ๋”๋ง์ด ์˜ฌ๋ฐ”๋ฅธ์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด (์˜ˆ๋ฅผ ๋“ค๋ฉด UI์—์„œ ๋ฒ„ํŠผ์˜ ๋ชจ์–‘ ๋ฐ ๋ฐฐ์น˜๊ฐ™์€ ๊ฒƒ!)

์˜ˆ๋ฅผ ๋“ค๋ฉด onPress ๋ฆฌ์Šค๋„ˆ๊ฐ€ ์žˆ๋Š” ๋ฒ„ํŠผ์ด ์žˆ์„ ๋•Œ, ๋ฒ„ํŠผ์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํ‘œ์‹œ๋˜๊ณ  ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋Š” ๊ฒƒ์ด ์ปดํฌ๋„ŒํŠธ์—์„œ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ฒ˜๋ฆฌ๋˜๋Š”์ง€ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ฒƒ์ด์ง€์š”. ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ํ™•์ธํ•ด๋ณผ๊นŒ์š”.

function GroceryShoppingList() {
  const [groceryItem, setGroceryItem] = useState('');
  const [items, setItems] = useState([]);

  const addNewItemToShoppingList = useCallback(() => {
    setItems([groceryItem, ...items]);
    setGroceryItem('');
  }, [groceryItem, items]);

  return (
    <>
      <TextInput
        value={groceryItem}
        placeholder="Enter grocery item"
        onChangeText={(text) => setGroceryItem(text)}
      />
      <Button
        title="Add the item to list"
        onPress={addNewItemToShoppingList}
      />
      {items.map((item) => (
        <Text key={item}>{item}</Text>
      ))}
    </>
  );
}

์œ„ ์ฝ”๋“œ๋Š” ๊ฝค ์ˆœ์ˆœํ•œ UI ์ปดํฌ๋„ŒํŠธ๋ผ๊ณ  ์ƒ๊ฐํ•ด์š”. ๋ฌผ๋ก  addNewItemToShoppingList ์™€ ๊ฐ™์€ ์ƒํƒœ๊ด€๋ฆฌ๋ฅผ ํ•˜๋Š” ๋กœ์ง์ด View์™€ ํ˜ผ์žฌ๋˜์–ด ์žˆ์ง€๋งŒ ์ด ์ •๋„๋Š” ๋Œ€๋ถ€๋ถ„์˜ ์ƒํ™ฉ์—์„œ ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ˆ˜์ค€์ด๋ผ๊ณ  ์ƒ๊ฐํ•ด์š”.

์ž, ์•„๋ฌดํŠผ ์šฐ๋ฆฌ๋Š” ์œ„ ์ฝ”๋“œ์—์„œ ์–ด๋–ค ๊ฒƒ์„ ํ…Œ์ŠคํŠธํ•ด์•ผ ํ• ๊นŒ์š”? props์— ์–ด๋–ค ๊ฒƒ๋“ค์ด ๋“ค์–ด์˜ค๊ณ , state์˜ ๊ฐ’์ด ๋ฌด์—‡์ธ์ง€ ํ…Œ์ŠคํŠธํ•˜์ง€๋งˆ์„ธ์š”! ์ด๋Š” ๋ฆฌํŒฉํ† ๋ง์œผ๋กœ ์ธํ•ด ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๊ฐ€ ์‰ฝ๊ฒŒ ๊นจ์งˆ ์ˆ˜ ์žˆ๊ณ  ๋‹ค์‹œ ์ž‘์„ฑํ•ด์•ผํ•  ์ˆ˜ ์žˆ์–ด์š”. ๊ฒฐ๋ก ์€ UI๊ฐ€ ์ž˜ ๋‚˜ํƒ€๋‚ฌ๊ณ , ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ ์˜ˆ์ƒ๋˜๋Š” ๋™์ž‘์ด ์ž˜ ๋˜๋Š”์ง€ ํ…Œ์ŠคํŠธํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค!

test('given empty GroceryShoppingList, user can add an item to it', () => {
  const { getByPlaceholder, getByText, getAllByText } = render(
    <GroceryShoppingList />
  );

  fireEvent.changeText(
    getByPlaceholder('Enter grocery item'),
    'banana'
  );
  fireEvent.press(getByText('Add the item to list'));

  const bananaElements = getAllByText('banana');
  expect(bananaElements).toHaveLength(1); // expect 'banana' to be on the list
});

์ด ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋Š” <GroceryShoppingList/> ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ฃผ์–ด์กŒ์„ ๋•Œ ์œ ์ €๊ฐ€ item ์„ list ์— ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์„ ํ…Œ์ŠคํŠธ ํ•ฉ๋‹ˆ๋‹ค. ์ •ํ™•ํ•˜๊ฒŒ ํ•˜๋‚˜์˜ ๊ธฐ๋Šฅ์„ ํ…Œ์ŠคํŠธ ํ•˜๋Š” ๊ฒƒ์ด์ฃ . ์ด ์ผ๋ จ์˜ ๊ณผ์ •์„ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋กœ ์ž‘์„ฑํ•ด๋ด…์‹œ๋‹ค.

๋จผ์ € fireEvent ๋Š” jest์—์„œ ์ œ๊ณตํ•˜๊ณ  changeText() ๋ฅผ ์ด์šฉํ•˜์—ฌ ํ•ด๋‹น ๋ถ€๋ถ„์— Text ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์œ ์ €๊ฐ€ input ์— ๋ฌด์–ธ๊ฐ€ ์ž‘์„ฑํ–ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๋Š” ๊ฒƒ์ด์ฃ . ๊ทธ ๋‹ค์Œ press() ๋ฅผ ์ด์šฉํ•˜์—ฌ Add the item to list ๋ผ๋Š” Text ๋ฅผ ๊ฐ€์ง„ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ๋‹ค์Œ getAllByText('banana') ๋กœ ๋ฐ”๋‚˜๋‚˜๋ผ๋Š” ํ…์ŠคํŠธ๋ฅผ ๊ฐ€์ง„ ๋ชจ๋“  ์—˜๋ ˆ๋ฉ˜์ธ ๋ฅผ ๊ฐ€์ ธ์˜ต์‹œ๋‹ค. ๋งŒ์•ฝ ์ด๊ฒƒ์˜ ๊ธธ์ด๊ฐ€ 1์ด๋ผ๋ฉด list ์— ์ž˜ ์ถ”๊ฐ€ํ–ˆ๋‹ค๊ณ  ์˜ˆ์ƒํ•  ์ˆ˜ ์žˆ์–ด์š”.


๊ฒฐ๋ก 

์ œ ์ƒ๊ฐ์—๋Š” ์–ด๋–ค ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ…Œ์ŠคํŠธํ•˜๋ƒ์— ๋”ฐ๋ผ์„œ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ํ…Œ์ŠคํŠธ๋ฅผ ์ ์šฉํ•  ์ˆ˜ ์žˆ์„ ๊ฑฐ ๊ฐ™์•„์š”.

  1. components : ์ด ๋””๋ ‰ํ† ๋ฆฌ์— ์กด์žฌํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋“ค์€ ๋ชจ๋‘ View๋ฅผ ๋‹ด๋‹นํ•ด์š”. ๋”ฐ๋ผ์„œ ์ด ๋””๋ ‰ํ† ๋ฆฌ๋Š” ์ปดํฌ๋„ŒํŠธ ํ…Œ์ŠคํŠธ, ๋‹จ์œ„ ํ…Œ์ŠคํŠธ, ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๋ฅผ ์ ์šฉํ•ฉ์‹œ๋‹ค.
  2. screens : ์ด ๋””๋ ‰ํ† ๋ฆฌ์— ์กด์žฌํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋“ค์€ ๋งŽ์€ ์ปดํฌ๋„ŒํŠธ๋“ค์ด ์‚ฌ์šฉ๋˜๋Š” ๊ณณ์ด๋‹ˆ, ์ปดํฌ๋„ŒํŠธ ํ…Œ์ŠคํŠธ, ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๋ฅผ ์ ์šฉํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์•„์š”.
  3. ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง : ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๋“ค์€ ์ „๋ถ€ hooks๋กœ ๋นผ์„œ ๋”ฐ๋กœ ๋‹จ์œ„ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ฒŒ ์ข‹์„ ๊ฑฐ ๊ฐ™์•„์š”.

๋˜ Jest ์—์„œ๋Š” ์Šค๋ƒ…์ƒท ํ…Œ์ŠคํŠธ๋ฅผ ์ œ๊ณตํ•ด์š”. ๋ง๊ทธ๋Œ€๋กœ ํ™”๋ฉด์„ ์ฐ์–ด์„œ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ฝ์„ ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š” ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•ด์š”. ๋งŽ์€ ๊ธ€๋“ค์—์„œ ์Šค๋ƒ…์ƒท ํ…Œ์ŠคํŠธ๋ฅผ ๊ถŒ์žฅํ•˜์ง€ ์•Š์•„์š”. ๊ทธ ์ด์œ ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์•„์š”.

  1. View๊ฐ€ ๋ณ€๊ฒฝ๋˜์–ด fail ๋œ ๊ฒƒ์ธ์ง€, ๋ฒ„๊ทธ๋กœ ์ธํ•ด fail ๋œ ๊ฒƒ์ธ์ง€ ์•Œ ์ˆ˜ ์—†๋‹ค.
  2. View๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด jest --update-snapshots ๋กœ ์ƒˆ๋กœ์šด View ์Šค๋ƒ…์ƒท์„ ์—…๋ฐ์ดํŠธ ํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ด๋Š” ์Šค๋ƒ…์ƒท์„ ์—…๋ฐ์ดํŠธํ•˜๋ฉด ์–ธ์ œ๋“ ์ง€ ์Šค๋ƒ…์ƒทํ…Œ์ŠคํŠธ๊ฐ€ ํ†ต๊ณผ๋  ์ˆ˜ ์žˆ์Œ์„ ์˜๋ฏธํ•ด์š”.
  3. ์Šค๋ƒ…์ƒท์€ ์ด๋ฏธ ๋งŒ๋“ค์–ด์ง„ UI ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ฐ๋Š” ๊ฒƒ์ด๋ผ TDD ๊ฐ™์€ ๋ฐฉ๋ฒ•๋ก ์„ ์‚ฌ์šฉํ•  ๋•Œ์— ์Šค๋ƒ…์ƒท ํ…Œ์ŠคํŠธ๋Š” ๋ฌด์กฐ๊ฑด ์‹คํŒจํ•  ์ˆ˜ ๋ฐ–์— ์—†์–ด์š”.
  4. UI๋Š” ์ •์ ์ด์ง€ ์•Š์•„์š”. ์ž์ฃผ ๋ณ€๊ฒฝ๋˜๋Š” UI ๋ฅผ ๋‹ค๋ฃจ๋Š” ์ƒํ™ฉ์—์„œ๋Š” ์Šค๋ƒ…์ƒท ์—…๋ฐ์ดํŠธ๋ฅผ ์ž์ฃผ ํ• ํ…Œ๊ณ  ์ด๋Ÿฐ ๋ฐฉ์‹์˜ ํ…Œ์ŠคํŠธ๋Š” ๋„ˆ๋ฌด ํ—ˆ์ˆ ํ•œ๊ฑฐ์ฃ .

Source

react-native official docs
์Šค๋ƒ…์ƒท ํ…Œ์ŠคํŠธ์˜ ๋‹จ์ 


TEST : ๋งˆ์ดํŽ˜์ด์ง€ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ

  • ์‚ฌ์šฉ์ž ํ™œ๋™ ์‹œ๊ฐํ™” ๋ฐ์ดํ„ฐ๊ฐ€ ์ž˜๋‚˜์˜ค๋Š”์ง€
  • ์ฆ๊ฒจ์ฐพ๊ธฐ ํ•ญ๋ชฉ์ด ์ž˜ ๋‚˜์˜ค๋Š”์ง€
  • ์ฆ๊ฒจ์ฐพ๊ธฐ ํ•ญ๋ชฉ ์‚ญ์ œ๊ฐ€ ์ž˜ ๋˜๋Š”์ง€
  • ๋“ฑ๋กํ•œ ์“ฐ๋ ˆ๊ธฐํ†ต์ด ์ž˜ ๋‚˜์˜ค๋Š”์ง€
  • ๋“ฑ๋กํ•œ ์“ฐ๋ ˆ๊ธฐํ†ต ์‚ญ์ œ๊ฐ€ ์ž˜ ๋˜๋Š”์ง€

Native Base ์•„์ด์ฝ˜

์•„์ด์ฝ˜์„ ์–ด๋””์„œ ์‚ฌ์šฉํ•ด์•ผ ํ• ๊นŒ
native์—์„œ ์ œ๊ณตํ•˜๋Š” ์•„์ด์ฝ˜๋„ ์žˆ๋Š”๋ฐ
์ด๊ฑด ํ•œ๊ณ„๊ฐ€ ์žˆ๊ณ ,... ๋” ์žˆ์„๊ฑฐ๊ฐ™์€๋ฐ ์ฐพ์„์ˆ˜๊ฐ€ ์—†๋‹ค.

NativeBase ์“ด ํ”„๋กœ์ ํŠธ์—์„œ Jest ๋กœ ํ…Œ์ŠคํŠธํ•  ์‹œ์— ๋ฐ˜๋“œ์‹œ ์•„๋ž˜์™€ ๊ฐ™์€ ํ˜•์‹์„ ์ทจํ•  ๊ฒƒ..!

@sumi-0011 @BAESI NativeBase ์“ด ํ”„๋กœ์ ํŠธ์—์„œ Jest ๋กœ ํ…Œ์ŠคํŠธํ•  ์‹œ์— ๋ฐ˜๋“œ์‹œ ์•„๋ž˜์™€ ๊ฐ™์€ ํ˜•์‹์„ ์ทจํ•  ๊ฒƒ..!

import {NativeBaseProvider} from 'native-base';

const inset = {
  frame: {x: 0, y: 0, width: 0, height: 0},
  insets: {top: 0, left: 0, right: 0, bottom: 0},
};

function getComponent(props) {
  return (
    <NativeBaseProvider initialWindowMetrics={inset}>
      <LoginScreen {...props} />
    </NativeBaseProvider>
  );
}

์ด๋ ‡๊ฒŒ ํ•˜์ง€ ์•Š์œผ๋ฉด Jest๊ฐ€ ์ฝ”๋“œ๋ฅผ ์ œ๋Œ€๋กœ ์ฝ์ง€ ์•Š๊ณ  ์Šค๋ƒ…์ƒท์„ ์ฐ์œผ๋ฉด ์•„๋ฌด๊ฒƒ๋„ ์บก์ฒ˜๋˜์–ด ์žˆ์ง€ ์•Š์€ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Œ.

Originally posted by @jeonbyeongmin in #45 (comment)

android camera๋ฅผ ์ด์šฉํ•ด ์‚ฌ์ง„์„ ์ฐ์œผ๋ฉด file์— ์ €์žฅ๋˜๋Š” ๋ฌธ์ œ

"file:///data/user/0/com.took/cache/Camera/4fdacfa2-a7b3-4687-8096-8337d6587547.jpg"

์• ๋ฎฌ๋ ˆ์ดํ„ฐ์•ˆ์˜ url๋กœ ์ €์žฅ์ด ๋˜๊ณ , ์„œ๋ฒ„๋กœ ์ „์†กํ•ด์„œ ๋‹ค๋ฅธ ํฐ์—์„œ ๋ณด๊ฒŒํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ์ง€๋ฅผ ๋ชจ๋ฅด๊ฒ ์–ด์š”..

  • ViewProps Waring <- ์ผ๋‹จ์€ ๋ฌด์‹œ!

์“ฐ๋ ˆ๊ธฐํ†ต ๋“ฑ๋ก ์ง€๋„ ์œ„์น˜ ์ˆ˜์ • ๊ธฐ๋Šฅ

๋“ฑ๋กํ™”๋ฉด ์ง„์ž… ์‹œ ์ฒ˜์Œ์—๋Š” ๊ธฐ๊ธฐ์˜ GPS๋ฅผ ์ด์šฉํ•˜์—ฌ ์ดˆ๊ธฐ ์œ„์น˜๋ฅผ ์„ค์ •ํ•˜๋‚˜ ์‚ฌ์šฉ์ž๊ฐ€ ์ง์ ‘ ์„ธ๋ฐ€ํ•œ ์œ„์น˜ ์กฐ์ •์ด ๊ฐ€๋Šฅํ•˜๋„๋ก ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•ด์•ผํ•จ

์ˆ˜์ •์‚ฌํ•ญ

  • mytook์„ ๋ˆ„๋ฅด๋ฉด ๋ชจ๋‹ฌ์ด ๊บผ์กŒ๋‹ค ๋‹ค์‹œ ์ผœ์ง€๋Š”๋ฐ ์ˆ˜์ •ํ–ˆ์œผ๋ฉด ์ข‹๊ฒ ์–ด์š”.

๋น„๋™๊ธฐํ™” ๋ฌธ์ œ Help

interface CheckTrashVolProps {
    currentTrashCanID: string;
}

function CheckTrashVol({currentTrashCanID}: CheckTrashVolProps) {
    const [answer, setAnswer] = useState<boolean>(false);
    const [userInfo, setUserInfo] = useRecoilState<UserInfoType>(UserState);
    const [isLoading, setIsLoading] = useState<boolean>(false);
    const [isStar, setIsStar] = useState<boolean>(false);
    const [isTook, setIsTook] = useState<boolean>(false);
    const [selectTrashCanInfo, setSelectTrashCanInfo] =
        useState<TrashCanInfoType>();

    const fetchMapModalData = useCallback(
        async (isRefetch: boolean = false) => {
        try {
            !isRefetch && setIsLoading(true);
            const [user, trashCan] = await Promise.all([
            getUser(),
            getTrashCan(currentTrashCanID),
            ]);
            console.log('user, trashCan: ', user, trashCan);
            setUserInfo(user);
            setSelectTrashCanInfo(trashCan);

            const elapsedHour = getElapsedTime(user.lastTookTime);

            elapsedHour >= 3 ? setIsTook(true) : setIsTook(false);

            const target = user.stars.find(star => star === currentTrashCanID);

            if (target) {
            setIsStar(true);
            } else {
            setIsStar(false);
            }
        } catch (error) {
            console.log(error);
        }
        !isRefetch && setIsLoading(false);
        },
        [currentTrashCanID, setUserInfo],
    );

    useEffect(() => {
        console.log(answer);
    },[answer]);

    useEffect(() => {
        fetchMapModalData();
    }, [fetchMapModalData]);

    const handleTookBtnClick = useCallback(async () => {
        /**
         * ์งˆ๋ฌธ์— ๋‹ต์— ๋Œ€ํ•œ ์นด์šดํŒ… ์ถ”๊ฐ€
         */
        console.log('ํ•จ์ˆ˜์‹คํ–‰๋Œ');
        if(answer === true) {
            console.log('์˜ˆ๋ฅผ ํด๋ฆญ');
        } else {
            console.log('์•„๋‹ˆ์˜ค๋ฅผ ํด๋ฆญ');
        }

        if (!isLoggedIn) {
          console.log('๋กœ๊ทธ์ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.');
        } else {
          try {
            await updateLastTookTime(userInfo.tookCnt);
            await fetchMapModalData(true);
          } catch (error) {
            console.warn('updateLastTookTime error: ', error);
          }
        }
      }, [fetchMapModalData, userInfo.tookCnt]);

    return (
      <Box
        borderTopRadius="20"
        p={5}
        w="100%"
        position={'absolute'}
        bottom="0"
        minH="280px"
        bgColor={'#fff'}>
        <Box flex={1} alignSelf="center" paddingY={'10'}>
          <Text fontSize={'lg'} bold>์“ฐ๋ ˆ๊ธฐํ†ต์ด ๊ฐ€๋“ ์ฐผ๋‚˜์š”?</Text>
        </Box>
        <Box padding={'3'}>
          <Btn name="์˜ˆ" onPress={() => 
            {setAnswer(true);
            handleTookBtnClick();}} />
        </Box>
        <Box padding={'3'}>
          <Btn name="์•„๋‹ˆ์˜ค" onPress={() =>
          {setAnswer(false);
          handleTookBtnClick();}}/>
        </Box>
      </Box>
    );
}

์ปดํฌ๋„ŒํŠธ ๋ถ„๋ฆฌ๋ฅผ ์–ด๋Š์ •๋„ ํ• ์ง€

  • ์ปดํฌ๋„ŒํŠธ๋กœ ์—ฌ๋Ÿฌ๊ฐœ ์ชผ๊ฐœ์ง€ ์•Š๊ณ , ํด๋ž˜์Šค์ด๋ฆ„์ด๋‚˜ props๋กœ ์ œ์–ด(๋„ˆ๋ฌด ์„ธ์„ธํ•˜๊ฒŒ ๋‚˜๋ˆ„์ง€ ์•Š๊ณ )
  • ๊ฐ™์€ ์ผ์„ ํ•˜๋Š”๋ฐ ๋‚˜๋ˆ ๋†“์ง€ ๋ง์ž
  • ํ•œ ์ปดํฌ๋„ŒํŠธ ์•ˆ์—๋Š” ํ•˜๋‚˜์˜ ์˜๋ฏธ๋ฅผ, ํ•˜๋‚˜์˜ ์ผ๋งŒ ํ•˜๋„๋ก (๋…๋ฆฝ์ ์ด๊ฒŒ)
  • ์Šคํ† ๋ฆฌ๋ถ์ฒ˜๋Ÿผ

์„ค๊ณ„์— ๋Œ€ํ•œ ๊ณ ๋ฏผ์ด ๋งค์šฐ ๋งŽ์ด ํ•„์š”ํ•˜๋‹ค.
VAC๋กœ ์—ฌ๋Ÿฌ ์ƒํ™ฉ์„ ์กฐ๊ธˆ์€ ํ”ผํ• ์ˆ˜์žˆ๋‹ค.

๋„˜๋‚˜ ์–ด๋ ต๋Œฑ...

Convert coordinate to address on MapScreen

๋“ฑ๋ก ์‹œ ๊ฐ™์€ ์œ„์น˜์— ์“ฐ๋ ˆ๊ธฐํ†ต ๋“ฑ๋ก์„ ๋ง‰๊ธฐ ์œ„ํ•ด ์ฃผ์†Œ์˜ ์ค‘๋ณต์„ ํ™•์ธํ•˜์—ฌ ๋ฐฉ์ง€ ํ•  ๊ณ„ํš ์ด๋ฅผ ์œ„ํ•ด ์ขŒํ‘œ๊ฐ’์„ ์ด์šฉํ•˜์—ฌ ์ฃผ์†Œ๋ฅผ ์•Œ์•„๋‚ด์–ด ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•ด์•ผํ•จ

์‚ฌ์šฉํ•  API

  • Reverse GeoCoding : ์ขŒํ‘œ => ์ฃผ์†Œ
  • GeoCoding : ์ฃผ์†Œ => ์ขŒํ‘œ

์“ฐ๋ ˆ๊ธฐํ†ต ์œ„์น˜ ํƒ์ƒ‰ ๋ชจ๋‹ฌ ๊ธฐ๋Šฅ ๊ตฌํ˜„

  • firestore ๊ธฐ๋Šฅ ์ถ”๊ฐ€
  • ์ฆ๊ฒจ์ฐพ๊ธฐ ๊ธฐ๋Šฅ ๊ตฌํ˜„
  • ๋ฒ„๋ฆฌ๊ธฐ ๊ธฐ๋Šฅ ๊ตฌํ˜„

์ฆ๊ฒจ์ฐพ๊ธฐ ๊ธฐ๋Šฅ

์œ ์ €์˜ ์ •๋ณด์— ํ•ด๋‹น ์“ฐ๋ ˆ๊ธฐํ†ต์˜ id๋ฅผ ์ €์žฅ,
๋งˆ์ดํŽ˜์ด์ง€์—์„œ ์œ ์ €์˜ ์ •๋ณด๋ฅผ ์ฝ์–ด์„œ ์ฆ๊ฒจ์ฐพ๊ธฐํ•œ ์“ฐ๋ ˆ๊ธฐํ†ต์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.

  • ์ฆ๊ฒจ์ฐพ๊ธฐ๋ฅผ ํด๋ฆญํ•˜๋ฉด user์˜ uid๋ฅผ ๊ฐ€์ง€๊ณ  DB์—์„œ user์˜ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.
  • user์˜ ์ฆ๊ฒจ์ฐพ๊ธฐ๋ฆฌ์ŠคํŠธ์—์„œ ํ•ด๋‹น ์“ฐ๋ ˆ๊ธฐํ†ต์˜ id๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
  • id๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ์“ฐ๋ ˆ๊ธฐํ†ต์„ ํด๋ฆญํ•œ ๊ฒฝ์šฐ ์ฆ๊ฒจ์ฐพ๊ธฐ์— ์ถ”๊ฐ€ํ•˜๊ณ  ๋—
  • ์กด์žฌํ•œ๊ฒฝ์šฐ์—๋Š” ์‚ญ์ œํ•˜๊ณ  ๋— (toggle)

๋ฒ„๋ฆฌ๊ธฐ ๊ธฐ๋Šฅ ๊ตฌํ˜„

  • ์“ฐ๋ ˆ๊ธฐํ†ต์„ ํด๋ฆญํ•˜๋ฉด, ์œ ์ €์˜ ์ •๋ณด๋ฅผ ์ฝ์–ด ํ•ด๋‹น ์“ฐ๋ ˆ๊ธฐํ†ต์„ ์–ธ์ œ ๋งˆ์ง€๋ง‰์œผ๋กœ ํด๋ฆญํ–ˆ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
  • ๋งˆ์ง€๋ง‰์œผ๋กœ ํด๋ฆญ ํ•œ ์ง€ ์ผ์ • ์‹œ๊ฐ„์ด ์ง€๋‚˜์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋Š” ๋ฒ„๋ฆฌ๊ธฐ๋ฒ„ํŠผ์„ ๋น„ํ™œ์„ฑํ™” ํ•˜๊ณ 
  • (+ ์ขŒํ‘œ๋ฅผ ๊ณ„์‚ฐํ•˜์—ฌ ์œ ์ €์˜ ์œ„์น˜์™€ ํ•ด๋‹น ์“ฐ๋ ˆ๊ธฐํ†ต์˜ ๊ฑฐ๋ฆฌ๋ฅผ ๊ณ„์‚ฐํ•˜์—ฌ ์ผ์ •๊ฑฐ๋ฆฌ ์ด์ƒ์ด๋ฉด ๋ฒ„ํŠผ์„ ๋น„ํ™œ์„ฑํ™”)
  • ๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋ฉด, ๋ฒ„๋ฆฌ๊ธฐ๋ฒ„ํŠผ์„ ํ™œ์„ฑํ™” ํ•œ๋‹ค.
  • ๋ฒ„๋ฆฌ๊ธฐ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด
  • ์œ ์ €์˜ ์ •๋ณด์— ํ•ด๋‹น ์“ฐ๋ ˆ๊ธฐํ†ต์˜ ์•„์ด๋””์™€, ํ˜„์žฌ ์‹œ๊ฐ„์„ ์ €์žฅํ•˜๊ณ 
  • ์œ ์ €์˜ ํด๋ฆญ ํšŸ์ˆ˜?๋ฅผ ํ•˜๋‚˜ ์ฆ๊ฐ€์‹œํ‚จ๋‹ค.

10/28 TODO

@sumi-0011

  • auth ํ™•์ธํ•˜๊ณ ,
  • ๋กœ๊ทธ์•„์›ƒ ํ–ˆ์„๋–„ ์ •๋ณด๊ฐ€ ๋‚จ์•„์žˆ๋Š” ๋ฌธ์ œ ํ”ฝ์Šค (๋ฆฌ๋กœ๋“œ ํ•˜๋Š” ํ˜•์‹์œผ๋กœ ๋ ๊ฑฐ๊ฐ™์Œ)
  • ๋ชจ๋‹ฌ์ฐฝ ๋ฐ”๊พธ๊ธฐ
  • ๋กœ๊ทธ์ธ ์ฐฝ ํŒจ๋”ฉ

@BAESI

  • ๊ฐ€๋“ ์ฐฌ ์ƒํƒœ ํ”„๋กœ๊ทธ๋ž˜์Šค๋ฐ” ์ž…๋ ฅ์œผ๋กœ ๊ต์ฒด

@jeonbyeongmin

  • ์นด๋ฉ”๋ผ ์‚ฌ์ง„ ๋กœ์ปฌ ์ €์žฅ -> ํŒŒ์ด์–ด๋ฒ ์ด์Šค Storage์— ์ €์žฅ

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.