/dramatic-note

๐ŸŽฌ Ready, Set, Action ... and Dispatcher, Store and View

Primary LanguageJavaScript

Dramatic Note

๋“œ๋ผ๋งˆ์•ค์ปดํผ๋‹ˆ ์›น ๊ฐœ๋ฐœ ๊ทธ๋ฃน ๋ฉด์ ‘ ๊ณผ์ œ๋กœ ์ œ์ž‘ํ•œ single page application ์ž…๋‹ˆ๋‹ค.

์‚ฌ์šฉ ๋ฒ„์ „

  • Python 3.5.1
  • Node 6.0.0

์‹คํ–‰ ์Šคํฌ๋ฆฝํŠธ

pip install -r requirements.txt
npm install

npm run build
npm run start

npm run test # for test

๊ธฐ์ˆ  ์Šคํƒ

Server-side

Client-side

  • ๋ทฐ ๋ ˆ์ด์–ด : React
  • ๋ผ์šฐํŒ… : React-router
  • ์ƒํƒœ(๋ฐ์ดํ„ฐ) ๊ด€๋ฆฌ : Redux
  • ๋ฆฌ์•กํŠธ์™€ ๋ฆฌ๋•ํŠธ ๋ฐ”์ธ๋”ฉ : React-redux
  • ํ”„๋ก ํŠธ์—”๋“œ ํ”„๋ ˆ์ž„์›Œํฌ : Bootstrap

Tools

  • ๋ชจ๋“ˆ ๋ฒˆ๋“ค๋ง : Webpack
  • ํŠธ๋žœ์ŠคํŒŒ์ผ๋Ÿฌ : Babel
  • ์„œ๋ฒ„์‚ฌ์ด๋“œ ์˜์กด์„ฑ ๊ด€๋ฆฌ : pip
  • ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ์˜์กด์„ฑ ๊ด€๋ฆฌ ๋ฐ ์Šคํฌ๋ฆฝํŒ… : npm
  • ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํ…Œ์ŠคํŒ… : tape

์•ฑ ๊ตฌ์กฐ

๊ธฐ๋ณธ์ ์œผ๋กœ ๋ฆฌ๋•์Šค์˜ ์„ธ ๊ฐ€์ง€ ์›์น™์„ ๋”ฐ๋ฅด๊ฒŒ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

  1. Single source of truth : ์ด ์›์น™์— ๋”ฐ๋ฅด๋ฉด ์•ฑ ๋‚ด์˜ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋Š” ํ•˜๋‚˜์˜ store tree ๋‚ด์— ์ €์žฅ๋˜์–ด์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ œ๊ฐ€ ๋งŒ๋“  ์•ฑ์—์„œ๋Š” react-router๊ฐ€ ๊ด€๋ฆฌํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ๋ผ์šฐํŒ… ๊ด€๋ จ ์ •๋ณด๋ฅผ ์ œ์™ธํ•œ ๋ชจ๋“  ์ •๋ณด๊ฐ€ redux store์— ์ €์žฅ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฆฌ์•กํŠธ๋Š” redux store ๋‚ด์˜ ๋ฐ์ดํ„ฐ๋ฅผ props๋กœ ๋ฐ›์•„์„œ ๋ Œ๋”๋ง ํ•˜๋Š” ์—ญํ• ๋งŒ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค.

  2. State is read-only : ์‚ฌ์šฉ์ž ์•ก์…˜์œผ๋กœ ์ธํ•ด UI ์ƒ์˜ ๋ณ€ํ™”๊ฐ€ ์ผ์–ด๋‚˜๊ณ , redux store ์— ์ €์žฅ๋˜์–ด ์žˆ๋Š” ์•ฑ ๋‚ด ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•  ํ•„์š”๊ฐ€ ์ƒ๊ฒผ์„ ๋•Œ, UI๋‹จ์—์„œ ์ง์ ‘ store๋ฅผ ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋Œ€์‹  ํ•ด๋‹นํ•˜๋Š” ์•ก์…˜์„ react-redux๋ฅผ ํ†ตํ•ด dispatch ํ•˜๊ณ , ์ด dispatch ๋œ ์•ก์…˜์„ ๋ฆฌ๋“€์„œ์—์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ์‹์œผ๋กœ store์— ๋ฐ˜์˜ํ•ฉ๋‹ˆ๋‹ค.

  3. Changes are made with pure functions : ๋ฆฌ๋“€์„œ๋Š” ๊ธฐ์กด์˜ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ , ๊ธฐ์กด์˜ ์ƒํƒœ์™€ ์•ก์…˜์„ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›์•„ ์ƒˆ๋กœ์šด ์ƒํƒœ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ˆœํ•จ์ˆ˜(pure function)์œผ๋กœ ์ž‘์„ฑ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

Flux structure

Flux ์•„ํ‚คํ…์ณ์™€ ๊ฐ™์€ ๊ตฌ์กฐ๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ๊ณ , ๊ฐ๊ฐ ์•„๋ž˜์™€ ๊ฐ™์€ ๋ถ€๋ถ„์„ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค.

  • Store : Redux(์ €์žฅ์†Œ)
  • Dispatcher : React-redux
  • View : React

๋ฐ์ดํ„ฐ ํ๋ฆ„์„ ๊ธฐ์ค€์œผ๋กœ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  1. ๋งจ ์ฒ˜์Œ React๊ฐ€ ์„œ๋ฒ„์—์„œ ๋ฐ›์•„์˜จ ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ทฐ ๋ Œ๋”๋ง
  2. ๋ทฐ์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ํ–‰๋™(e.g. ๋ฉ”๋ชจ ์ƒ์„ฑ)์„ ํ•  ์‹œ ์•ก์…˜ ์ƒ์„ฑ
  3. React-redux๋ฅผ ํ†ตํ•ด ์ƒ์„ฑ๋œ ์•ก์…˜์„ ์Šคํ† ์–ด๋กœ dispatch
  4. ๋ฆฌ๋“€์„œ์—์„œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ฒ˜๋ฆฌํ•˜๊ณ  ์Šคํ† ์–ด์— ์ƒˆ๋กœ์šด ์ƒํƒœ ํ• ๋‹น
  5. ์ƒˆ๋กœ์šด ์ƒํƒœ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ทฐ ์žฌ ๋ Œ๋”๋ง
  6. 2๋กœ ๊ฐ€์„œ ๋ฐ˜๋ณต

babel(ํŠธ๋žœ์ŠคํŒŒ์ผ)๊ณผ webpack(๋ชจ๋“ˆ ๋ฒˆ๋“ค๋ง)์„ ์ด์šฉํ•ด ์ตœ์ข…์ ์œผ๋กœ ์„œ๋น„์Šค ์„œ๋ฒ„๋Š” _bundle.js ํ•œ ํŒŒ์ผ๋งŒ ์„œ๋น™ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ฝ”๋“œ์—์„œ ์‚ฌ์šฉํ•œ ES6 ํ”ผ์ณ๋“ค์ด IE์—์„œ๋„ ์ •์ƒ์ ์œผ๋กœ ์ž‘๋™ํ•˜๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด babel-polyfill์„ CDN์—์„œ๋ถ€ํ„ฐ ๋ฐ›์•„์˜ต๋‹ˆ๋‹ค.

ํด๋” ๊ตฌ์กฐ

โ”œโ”€โ”€ README.md                 - ๋ฆฌ๋“œ๋ฏธ ํŒŒ์ผ
โ”‚
โ”œโ”€โ”€ app/                      - ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ํด๋”
โ”‚   โ”œโ”€โ”€ __init__.py           - ์„œ๋ฒ„ ํŒŒ์ด์ฌ ๋ชจ๋“ˆ ์ดˆ๊ธฐํ™”
โ”‚   โ”œโ”€โ”€ models.py             - ์„œ๋ฒ„ ๋ชจ๋ธ ์ •์˜
โ”‚   โ”‚โ”€โ”€ views.py              - ์„œ๋ฒ„ ๋ทฐ ํ•จ์ˆ˜(API ์—”๋“œํฌ์ธํŠธ) ์ •์˜
โ”‚   โ”‚ 
โ”‚   โ”œโ”€โ”€ src/                  - ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ํด๋”
โ”‚   โ”‚   โ”œโ”€โ”€ actions.js        - ์•ก์…˜ ์ •์˜
โ”‚   โ”‚   โ”œโ”€โ”€ components/       - ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ
โ”‚   โ”‚   โ”œโ”€โ”€ containers/       - ๋ฆฌ์•กํŠธ ์ปจํ…Œ์ด๋„ˆ
โ”‚   โ”‚   โ”œโ”€โ”€ main.js           - ๋ฉ”์ธ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ (webpack ์—”ํŠธ๋ฆฌ ํฌ์ธํŠธ)
โ”‚   โ”‚   โ”œโ”€โ”€ main.scss         - ๋ฉ”์ธ ์Šคํƒ€์ผ์‹œํŠธ
โ”‚   โ”‚   โ””โ”€โ”€ reducers.js       - ๋ฆฌ๋“€์„œ ์ •์˜
โ”‚   โ”‚   โ””โ”€โ”€ test/             - ํด๋ผ์ด์–ธํŠธ ํ…Œ์ŠคํŠธ ํŒŒ์ผ ํด๋”
โ”‚   โ”‚ 
โ”‚   โ”œโ”€โ”€ static/               - ์Šคํƒœํ‹ฑ ํด๋” (๋นŒ๋“œ ๊ฒฐ๊ณผ๋ฌผ)
โ”‚   โ”‚   โ”œโ”€โ”€ _bundle.js        - webpack์„ ํ†ตํ•ด ๋นŒ๋“œ๋œ ์„œ๋น™์šฉ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ
โ”‚   โ”‚   โ””โ”€โ”€ fonts/            - ๋ถ€ํŠธ์ŠคํŠธ๋žฉ์ด ์‚ฌ์šฉํ•˜๋Š” ํฐํŠธ๋“ค
โ”‚   โ”‚ 
โ”‚   โ””โ”€โ”€ templates/            - ํ…œํ”Œ๋ฆฟ ํด๋”
โ”‚       โ””โ”€โ”€ main.html         - React container๋ฅผ ํฌํ•จํ•˜๋Š” ๋ฉ”์ธ ํ…œํ”Œ๋ฆฟ
โ”‚ 
โ”œโ”€โ”€ config.py                 - flask ์•ฑ ์„ค์ • ํŒŒ์ผ
โ”œโ”€โ”€ dramatic.db               - SQLite3 ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค
โ”œโ”€โ”€ package.json              - npm ์„ค์ •
โ”œโ”€โ”€ requirements.txt          - pip ๋””ํŽœ๋˜์‹œ ๋ฆฌ์ŠคํŠธ
โ”œโ”€โ”€ run.py                    - ์„œ๋ฒ„ ์‹œ์ž‘ ์Šคํฌ๋ฆฝํŠธ
โ”œโ”€โ”€ run_with_dummy.py         - ๋”๋ฏธ ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋Š” ์„œ๋ฒ„ ์‹œ์ž‘ ์Šคํฌ๋ฆฝํŠธ
โ”œโ”€โ”€ storeSpec.js              - store ์ŠคํŽ™ ์ •์˜ (์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ํŒŒ์ผ)
โ””โ”€โ”€ webpack.config.js         - webpack ์„ค์ •

๊ฐœ์„  ์‚ฌํ•ญ

reducers.js ํŒŒ์ผ ๋ฆฌํŒฉํ† ๋ง

๋ฆฌ๋“€์„œ๋Š” ์ƒํƒœ์™€ ์•ก์…˜์„ ๋ฐ›์•„ ์ƒˆ๋กœ์šด ์ƒํƒœ๋ฅผ ๋ฆฌํ„ดํ•˜๋Š” ์ˆœํ•จ์ˆ˜๋กœ ์งœ์—ฌ์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๋„ค์ดํ‹ฐ๋ธŒ Object API์—๋Š” ํŒŒ์ด์ฌ์˜ dictionary comprehension ๊ฐ™์€, ๊ธฐ์กด์˜ ๊ฐ์ฒด์— ์–ด๋–ค ๋ณ€๊ฒฝ์„ ๊ฐ€ํ•œ ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด ๋ฆฌํ„ดํ•˜๋Š” ๊ฐ„ํŽธํ•œ ๋ฐฉ๋ฒ•์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ES6์—์„œ ์ถ”๊ฐ€๋œ Object.assign ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ๋ชฉ์ ์€ ๋‹ฌ์„ฑํ–ˆ์ง€๋งŒ, ๊ฒฐ๊ณผ์ ์œผ๋กœ ์ฝ”๋“œ๊ฐ€ ๋งค์šฐ verbose ํ•ด์กŒ๊ณ , ๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์ง€๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ด ์ƒํ™ฉ์„ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ•ด๊ฒฐ์ฑ…์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ผ๋‹จ ๋‹ค๋ฅธ ์ž๋ฃŒ๊ตฌ์กฐ, ๊ตฌ์ฒด์ ์œผ๋กœ๋Š” ImmutableJS์˜ Map ์ž๋ฃŒ๊ตฌ์กฐ๋กœ ํ˜„์žฌ ์Šคํ† ์–ด์—์„œ ์‚ฌ์šฉ์ค‘์ธ ๋„ค์ดํ‹ฐ๋ธŒ Object๋ฅผ ์™„๋ฒฝํ•˜๊ฒŒ ๋Œ€์ฒดํ•˜๋ฉด์„œ ํ›จ์”ฌ ๋ช…๋ฃŒํ•œ ์ฝ”๋“œ๋ฅผ ์งค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ:

labels: Object.assign({}, ...Object.keys(state.labels)
  .filter(id => id != action.id)
  .map(id => ({ [id]: state.labels[id]}))
  )

๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋Œ€์ฒดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

labels: state.labels.filter((key, value) => key != action.id)

๊ทธ๋ฆฌ๊ณ , redux์˜ combineReducers๋ฅผ ์ด์šฉํ•ด state์˜ ์„ธ ํ•„๋“œ(memos, labels, checkedMemoIds)๋ฅผ ๋‹ด๋‹นํ•˜๋Š” ๋ฆฌ๋“€์„œ๋ฅผ ์ชผ๊ฐฌ์œผ๋กœ์„œ ํ›จ์”ฌ ๊ฐ€๋…์„ฑ์ด ์ข‹์€ ์ฝ”๋“œ๋ฅผ ์งค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ ๋กœ์ง์ƒ์œผ๋กœ๋Š” memos์™€ labels๋ฅผ ๋™์‹œ์— ์กฐ์ž‘ํ•˜๋Š” ์•ก์…˜(๋ฉ”๋ชจ์— ๋ผ๋ฒจ์„ ๋ถ™์ด๊ฑฐ๋‚˜ ๋–ผ๋Š” ์•ก์…˜)์ด ์กด์žฌํ•ด์„œ memos์™€ labels์˜ ๋ฆฌ๋“€์„œ๋ฅผ ๋–ผ์–ด๋†“์ง€ ๋ชปํ–ˆ๋Š”๋ฐ, ํ•ด๋‹น ์ž‘์—…์„ ๋‘ ๊ฐœ์˜ ์•ก์…˜์œผ๋กœ ๋‚˜๋ˆˆ ๋’ค์— ๊ทธ ๋‘˜์„ ํ•˜๋‚˜์˜ ํŠธ๋žœ์žญ์…˜์œผ๋กœ ๋ฌถ์„ ์ˆ˜ ์žˆ๋‹ค๋ฉด ๋ถ„๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๊ณ  ์ฝ”๋“œ๊ฐ€ ํ›จ์‹  ๊น”๋”ํ•ด ์งˆ ๊ฒƒ์ด๋ผ ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์„œ๋ฒ„-ํด๋ผ์ด์–ธํŠธ ์‹ฑํฌ ๋ฌธ์ œ

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

์ด ๋•Œ ํ˜„์žฌ๋Š” ๋ณด์ˆ˜์ ์ธ ์ ‘๊ทผ์œผ๋กœ ์ผ๋‹จ ํด๋ผ์ด์–ธํŠธ ๋‹จ์—์„œ API ์ฝœ์ด ๋‚ ์•„๊ฐ„ ๋’ค ์„œ๋ฒ„ ์ธก์—์„œ ์‘๋‹ต์ด ๋“ค์–ด์™”์„ ์‹œ์—๋งŒ ์•Œ๋งž๊ฒŒ ํด๋ผ์ด์–ธํŠธ ๋‹จ ์Šคํ† ์–ด๋ฅผ ๋ณ€๊ฒฝํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฐฉ์‹์œผ๋กœ๋Š” ๋กœ์ง์ด ๊ฐ„๋‹จํ•˜๊ณ  ์„œ๋ฒ„์— ๋ฐ˜์˜๋œ ๋ฐ์ดํ„ฐ๋งŒ ํด๋ผ์ด์–ธํŠธ์—์„œ ๋ณด์—ฌ์ค€๋‹ค๋Š” ์žฅ์ ์ด ์žˆ์ง€๋งŒ, ๋„คํŠธ์›Œํฌ ํ™˜๊ฒฝ์ด ์ข‹์ง€ ์•Š์„ ์‹œ ํด๋ผ์ด์–ธํŠธ์˜ ์•ก์…˜์ด ์ผ์–ด๋‚œ ํ›„ ์‹ค์ œ๋กœ ์•ฑ์— ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ์ด ๋ฐ˜์˜๋˜๊ธฐ๊นŒ์ง€์˜ ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆฐ๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๋‹จ์ ์„ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•ด ๋‚™๊ด€์ ์œผ๋กœ ์ผ๋‹จ ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ์˜ ์ƒํƒœ๋ฅผ ๋จผ์ € ๋ณ€๊ฒฝํ•œ ๋’ค API ์ฝœ์„ ๋‚ ๋ฆฌ๊ณ  ๋งŒ์•ฝ ์‘๋‹ต์„ ๋ฐ›์€ ํ›„ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์‹œ ์ „์ฒด ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค์‹œ ๋ฐ›์•„์™€ ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ฒ„์™€ ์‹ฑํฌ ์‹œํ‚ค๋Š” ๋“ฑ์˜ ์ ‘๊ทผ์„ ์ทจํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•์„ ์ฑ„ํƒํ•  ์‹œ ์˜ˆ๋ฅผ ๋“ค์–ด ํด๋ผ์ด์–ธํŠธ๋‹จ์—์„œ ์ƒˆ๋กœ ์ƒ์„ฑ๋œ ๋ฉ”๋ชจ์˜ id๋ฅผ ๊ฒฐ์ •ํ•ด์ค˜์•ผ ํ•˜๋Š” ๋“ฑ ๊ท€์ฐฎ์•„์ง€๋Š” ๋ถ€๋ถ„์ด ์กฐ๊ธˆ ์ƒ๊ธฐ๋Š”๋ฐ, Google Keep ๊ฐ™์€ ํ”„๋กœ๊ทธ๋žจ์„ ๋ณด๋ฉด ํž˜๋“ค์–ด๋„ ๋งŒ๋“ค ์ˆ˜๋Š” ์žˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

React component / container ๋ถ„๋ฆฌ

React์—์„œ๋Š” props๋ฅผ ๋ฐ›์•„ ๋ Œ๋”๋ง๋งŒ ํ•˜๋Š”, ๋ทฐ๋ฅผ ๋‹ด๋‹นํ•˜๋Š” component์™€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ฐ์ดํ„ฐ(state)์— ๋Œ€ํ•ด ์•Œ๊ณ  ์žˆ๊ณ  ๋ณ€๊ฒฝ์„ ์œ„ํ•œ ์•ก์…˜์„ ์ทจํ•  ์ˆ˜ ์žˆ๋Š” container๋ฅผ ๋ถ„๋ฆฌํ•˜๋„๋ก ๊ถŒ์žฅํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฒˆ ๊ณผ์ œ์—์„œ๋Š” ๋น ๋ฅด๊ฒŒ ๊ฐœ๋ฐœํ•˜๋ ค๋‹ค๋ณด๋‹ˆ ๋Œ€๋ถ€๋ถ„์˜ ์ปดํฌ๋„ŒํŠธ๊ฐ€ container๋กœ ๋ถ„๋ฅ˜๋˜๊ฒŒ ๋˜์—ˆ์ง€๋งŒ, ๋งŒ์•ฝ ์ข€ ๋” ์‹œ๊ฐ„์„ ๊ฐ–๊ณ  ์ฝ”๋“œ๋ฅผ ๋ฆฌํŒฉํ† ๋งํ•ด representation ์„ ๋‹ด๋‹นํ•˜๋Š” ๋ถ€๋ถ„์€ component๋กœ ๋นผ์ฃผ๊ณ  container์—๋Š” ๋ฐ์ดํ„ฐ๋งŒ ๋‹ด๋„๋ก ๊ด€์‹ฌ์‚ฌ์˜ ๋ถ„๋ฆฌ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค๋ฉด ์žฅ๊ธฐ์ ์œผ๋กœ ์œ ์ง€๋ณด์ˆ˜์„ฑ์ด ๋” ์ข‹์•„์งˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

UX๋ฅผ ์œ„ํ•œ ์Šคํƒ€์ผ์‹œํŠธ ๊ฐœ์„ 

ํ˜„์žฌ ์Šคํƒ€์ผ์‹œํŠธ ์ƒ์—์„œ๋Š” ์ƒˆ๋กœ์šด ๊ธ€ ์ž‘์„ฑ, ๋˜๋Š” ๊ธ€ ์ˆ˜์ •์„ ์œ„ํ•œ ํŒ๋„ฌ์ด ํ•œ ๋ˆˆ์— ์‚ฌ์šฉ์ž์—๊ฒŒ ๋“ค์–ด์˜ค์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํŠน์ • ๋ฉ”๋ชจ๋ฅผ ์„ ํƒํ•œ ์ƒํ™ฉ์—์„œ ๋‹ค์‹œ ๋ฉ”๋ชจ ์ž‘์„ฑ์œผ๋กœ ๋Œ์•„๊ฐ€๊ธฐ ์œ„ํ•œ (๋ชจ๋“  ๋ผ๋ฒจ LabelItem์— ์žˆ๋Š”) ์ƒˆ ๋ฉ”๋ชจ ์ž‘์„ฑ ๋ฒ„ํŠผ๋„ ์ƒ๋Œ€์ ์œผ๋กœ ๋ˆˆ์— ๋„์ง€ ์•Š๋Š” ํŽธ์ธ๋ฐ, ์นผ๋ผ๋ง๋งŒ ์ž˜ ํ•ด์ค˜๋„ ์‚ฌ์ดํŠธ์˜ ํ†ต์ผ์„ฑ์„ ํ•ด์น˜์ง€ ์•Š์œผ๋ฉด์„œ ์ด๋Ÿฌํ•œ ์„ ํƒ์ง€๋“ค์„ ์ข€ ๋” ๋ˆˆ์— ๋„๊ฒŒ ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŒ…

์‹œ๊ฐ„ ๊ด€๊ณ„์ƒ redux synchronous action creator ์™€ reducer ์— ๊ด€ํ•œ ํ…Œ์ŠคํŠธ๋งŒ์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์„œ๋ฒ„์ธก ์—”๋“œํฌ์ธํŠธ, ๋น„๋™๊ธฐ API ์ฝœ, ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ ๋“ฑ์— ๋Œ€ํ•ด ์ปค๋ฒ„ํ•˜๋Š” ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ํ˜„์žฌ ์ปค๋ฒ„ํ•˜๋Š” ๋ถ€๋ถ„๋“ค์— ๋Œ€ํ•ด์„œ๋„ ์ข€ ๋” ๋‹ค์–‘ํ•˜๊ณ  ๋งŽ์€ ์ผ€์ด์Šค๋ฅผ ์ปค๋ฒ„ํ•˜๋„๋ก ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค๋ฅผ ๋ณด๊ฐ•ํ•˜๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์„œ๋ฒ„์ธก ํ…Œ์ŠคํŠธ๋Š” Flask-Testing ํ™•์žฅ์„ ์‚ฌ์šฉํ•˜๋ฉด ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๊ณ , ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ ํ…Œ์ŠคํŠธ๋Š” Redux ๊ณต์‹ ๋‹คํ๋ฉ˜ํ…Œ์ด์…˜์—์„œ ์ถ”์ฒœํ•˜๋Š” Enzyme์„ ์“ฐ๋ฉด ๋  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๊ธฐํƒ€

  • ESLint ๋ฅผ ํ†ตํ•œ ์Šคํƒ€์ผ ๋ฆฐํŒ…
  • ๋ช…๋ช…๋ฒ• ๋œ verbose ํ•˜๊ฒŒ ๋ณ€๊ฒฝ
  • (์‹ค์ œ ์„œ๋น„์Šค๋กœ ๋งŒ๋“ค์‹œ) ์œ ์ € ๋ฐ ์„ธ์…˜ ๊ด€๋ จ ๊ธฐ๋Šฅ ๊ตฌํ˜„
  • (์‹ค์ œ ์„œ๋น„์Šค๋กœ ๋งŒ๋“ค์‹œ) ์Šคํƒ€์ผ์‹œํŠธ ๋ชจ๋“ˆํ™”