Asana- ๐Ÿง˜โ€โ™€๏ธ ๋ช…์ƒ ์Œ์•… ์ŠคํŠธ๋ฆฌ๋ฐ ์ €์žฅ์†Œ

bbio3oยท2021๋…„ 1์›” 25์ผ
3

โœจ ํ”„๋กœ์ ํŠธ Projects

๋ชฉ๋ก ๋ณด๊ธฐ
3/4
post-thumbnail

๐Ÿ” Project Overview

Asana๋Š” ๋ช…์ƒ์ด๋‚˜ ์ง‘์ค‘์„ ์œ„ํ•ด ์ž์‹ ์ด ์ฃผ๋กœ ๋“ฃ๋Š” ์Œ์•… ๋งํฌ๋ฅผ ์ €์žฅํ•ด ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ๋ฅผ ๋ณด์—ฌ์ฃผ๊ณ , ํ”Œ๋ ˆ์ด ํ•  ์ˆ˜ ์žˆ๋Š” url ๋งํฌ ์ €์žฅ์†Œ ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค.
์ด๋ฒˆ ํ”„๋กœ์ ํŠธ๋Š” TypeScript์™€ GraphQL, next.js์„ ๊ณต๋ถ€ํ•˜๋ฉด์„œ, ๊ฐ„๋‹จํ•œ ํ”„๋กœ์ ํŠธ๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“ค์–ด ๋ณด์•„์•ผ๊ฒ ๋‹ค ๋‹ค์ง์„ ํ•˜๋ฉฐ ์‹œ์ž‘ํ•˜๊ฒŒ ๋œ ์ž‘์—…์ž…๋‹ˆ๋‹ค.
์„œ๋น„์Šค์˜ ๊ธฐ๋Šฅ์€ ๋‹จ์ˆœํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ํšŒ์›๊ฐ€์ž…์„ํ•˜๊ณ  ๋กœ๊ทธ์ธ์„ ํ•˜๋ฉด youtube๋‚˜ sound cloud ๋“ฑ์—์„œ ๋ช…์ƒ์Œ์•…์ด๋‚˜ ๊ฐœ์ธ์ด ๋งˆ์Œ์—๋“œ๋Š” ์Œ์•… ๋“ฑ์˜ ๋งํฌ๋ฅผ iframe url์„ ์ž…๋ ฅํ•ด ์ƒ์„ฑํ•˜๋ฉด,
streams ํŽ˜์ด์ง€์—์„œ ์ž์‹ ์ด ๋“ฑ๋กํ•œ ์Œ์•…์„ ๊ฐ์ƒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ƒ์„ฑํ•œ ์˜์ƒ๋งํฌ๋Š” ์‚ญ์ œ์™€ ์ˆ˜์ •์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

โœจ ์•„๋ž˜ ๋งํฌ์—์„œ ํ”„๋กœ์ ํŠธ ๋ฐ๋ชจ ํ™•์ธ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
Asana Demo


์‚ฌ์šฉ๊ธฐ์ˆ 

  • HTML5 / CSS3
  • Typescript
  • React
  • GraphQL
  • next.js
  • Apollo
  • Styled-components, material-ui

๊ตฌํ˜„๊ธฐ๋Šฅ์‚ฌํ•ญ

  • ํšŒ์›๊ฐ€์ž…/๋กœ๊ทธ์ธ/๋กœ๊ทธ์•„์›ƒ
  • ์Œ์•… stream CRUD
  • ๋žœ๋”ฉํŽ˜์ด์ง€ scrollDown, scrollUp
  • ๋ฐ˜์‘ํ˜• ์›น


โœจ ์ฒซ ๋žœ๋”ฉํŽ˜์ด์ง€


์ฒซ ํ™”๋ฉด ๋žœ๋”ฉ ํŽ˜์ด์ง€ ์ž…๋‹ˆ๋‹ค.


โœจ ํšŒ์›๊ฐ€์ž… / ๋กœ๊ทธ์ธ / ๋กœ๊ทธ์•„์›ƒ


jwt๋ฅผ ์ด์šฉํ•˜์—ฌ ํ† ํฐ์„ ์ƒ์„ฑํ•ด ์œ ์ €์™€ ํ† ํฐ์„ ํด๋ผ์ด์–ธํŠธ์— ์ „๋‹ฌํ•˜์—ฌ ํ† ํฐ์„ ์ €์žฅํ•ด์ฃผ๊ณ **(ํšŒ์›๊ฐ€์ž…)** , email๋กœ DB์˜ user ์œ ๋ฌด๋ฅผ ํ™•์ธํ•˜๊ณ  ์œ ์ €๊ฐ€ ์žˆ๋‹ค๋ฉด, bcrypt๋ฅผ ์ด์šฉํ•ด ํŒจ์Šค์›Œ๋“œ ๋น„๊ตํ•ฉ๋‹ˆ๋‹ค.(๋กœ๊ทธ์ธ), ํด๋ผ์ด์–ธํŠธ์—์„œ ์ €์žฅ๋œ ํ† ํฐ์„ ๋น„์›Œ์ฃผ๋Š” ๋ฐฉ์‹**(๋กœ๊ทธ์•„์›ƒ)**์„ ํ†ตํ•ด ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค.


โœจ Create ํŽ˜์ด์ง€


๋กœ๊ทธ์ธ ํ›„์— Create ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๋ฉด, Title๊ณผ Description, iframe URL์ž…๋ ฅ์„ ํ†ตํ•ด stream์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ƒ์„ฑ ํ›„์—๋Š” next.js์˜ useRouter๋ฅผ ๊ธฐ๋Šฅ์„ ์ด์šฉํ•ด ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋Š” Streams ํŽ˜์ด์ง€๋กœ ์ด๋™๋˜๋„๋ก ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

โœจ Update, Delete ๊ธฐ๋Šฅ

์ƒ์„ฑํ•œ stream ๋‚ด์šฉ์„ ์ˆ˜์ •ํ•˜๊ณ  ์‚ญ์ œํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

โœจ Streams ํŽ˜์ด์ง€

๋กœ๊ทธ์ธ ํ›„ StreamsํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๋ฉด, ์ƒ์„ฑํ•œ ๋ช…์ƒ์Œ์•… ๋ฆฌ์ŠคํŠธ๊ฐ€ ํ™•์ธ ๊ฐ€๋Šฅํ•˜๋ฉฐ, ํด๋ฆญํ•˜๋ฉด, ์ €์žฅํ•œ ๋…ธ๋ž˜๋ฅผ ์žฌ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


โœจ scrollDown, scrollUp, ๋žœ๋”ฉํŽ˜์ด์ง€ ์„น์…˜์ด๋™ ์Šคํฌ๋กค ๋ฒ„ํŠผ


ํ™”์‚ดํ‘œ ์ด๋ฏธ์ง€ svg์— ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ฃผ์–ด ์‚ฌ์šฉ์ž ๋ˆˆ์— ๋Œ ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„ํ•˜๊ณ , ์œ ์ €๊ฐ€ ์Šคํฌ๋กค์„ ํ•˜๋ฉด window.pageYOffset์„ ์ด์šฉํ•ด ์ตœ์ƒ๋‹จ์œผ๋กœ ์ž๋™ ์Šคํฌ๋กค ์—…์„ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฒ„ํŠผ์„ ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค.


โœจ ํ—ค๋”์ƒ‰ Dynamic ๋ณ€๊ฒฝ


MOMOํ”„๋กœ์ ํŠธ๋ฅผ ํ• ๋•Œ์—๋Š” 'react-router-dom'์—์„œ ์ œ๊ณตํ•˜๋Š” useLocation์„ ํ†ตํ•ด pathname์— ์ ‘๊ทผํ•ด

 <nav className={location.pathname === '/' ? 'nav nav--dark' : 'nav'}>

๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌํ˜„ํ•˜์˜€๋Š”๋ฐ, ์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” nextjs์˜ useRouter๊ธฐ๋Šฅ์„ ํ†ตํ•ด ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

  const navItemsBg = {
    backgroundColor: router.pathname !== '/' ? 'white' : 'transparent',
  };

Next.js useRouter ์•Œ์•„๋ณด๊ธฐ


โœจ ๋ฐ˜์‘ํ˜• ์›น


๋ฐ์Šคํฌํƒ‘, ์•„์ดํŒจ๋“œ, ๋ชจ๋ฐ”์ผ ์ˆœ์œผ๋กœ ๋ฐ˜์‘ํ˜• ์›น์„ ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค.




๐ŸŒฟ ํ›„๊ธฐ

Asana ํ”„๋กœ์ ํŠธ ์—์„œ๋Š” ์ข€ ๋” ๋‹ค์–‘ํ•œ ํ”„๋ ˆ์ž„์›Œํฌ์™€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์ต์ˆ™ํ•ด ์ง€๋ ค GraphQL, Next.js ๋“ฑ์„ ๋„์ž…ํ•˜์˜€์Šต๋‹ˆ๋‹ค.
์ดˆ๊ธฐ ํ™˜๊ฒฝ์„ค์ • ์…‹ํŒ…์˜ ์ง€์˜ฅ..๐Ÿ˜ฑ ๋” ๊ณต๋ถ€ํ•ด์„œ ์ต์ˆ™ํ•ด์ ธ์•ผ ๊ฒ ๋‹ค ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค.
graphql, typescript, next.js ๋“ฑ ์ƒˆ๋กœ์šด ํ”„๋ ˆ์ž„์›Œํฌ, ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์„ ์ ์šฉํ•˜๋ ค๋‹ˆ ํ™˜๊ฒฝ์„ค์ • ํ•˜๋‹ค๊ฐ€ ๋จธ๋ฆฌ๊ฐ€ ํ•‘ํ•‘ ๋Œ์•˜์ง€๋งŒ, ๊ฐ•์˜ ๊ฐ™์€๊ฑฐ ๋ณด๋ฉด์„œ ์—ด์‹ฌํžˆ ๋”ฐ๋ผํ•ด์„œ ๋๊นŒ์ง€ ์˜ฌ ์ˆ˜ ์žˆ๊ธฐ๋Š” ํ–ˆ์—ˆ๋Š”๋ฐ, ์•„์ง ์—ฐ์Šต์ด ๋” ํ•„์š”ํ•œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
Node.js์™€ Javascript, react๋งŒ์œผ๋กœ ์›น์„ ๊ตฌํ˜„ ํ•  ๋•Œ๋Š” ๋‹ค์ด๋‚ด๋ฏนํ•œ ์ž์œ ๋กœ์›€์ด ์žˆ์—ˆ์ง€๋งŒ,

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

Next.js์™€ ํ•จ๊ป˜ ์„œ๋ฒ„์‚ฌ์ด๋“œ ๋ Œ๋”๋ง ์ „์ฒด์ ์ธ ํ๋ฆ„์„ ์ฝ์„ ์ˆ˜ ์žˆ์—ˆ์œผ๋ฉฐ,
์ฝ”๋“œ๋ฅผ ์ฝ๊ธฐ ์‰ฝ๊ฒŒ ๋„์™€์ฃผ๊ณ , ๋ฐ์ดํ„ฐ์— ํƒ€์ž…์„ ๋ช…์‹œํ•ด์ฃผ์–ด ์•ˆ์ •์ ์ธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด ๊ฐ€๋Šฅํ•˜๋„๋ก ํ•˜๋Š” TypeScript๋ฅผ ๋ฐฐ์šธ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. static ์–ธ์–ด์ธ TypeScript๋ฅผ ๋” ๊ณต๋ถ€ํ•˜์—ฌ OOP์— ์ต์ˆ™ํ•ด์ง€๋ คํ•ฉ๋‹ˆ๋‹ค.

๋˜, static ์–ธ์–ด์ธ ํƒ€์ž… ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋” ๊ณต๋ถ€ํ•˜์—ฌ OOP์— ๋Œ€ํ•ด ์ต์ˆ™ํ•ด์ง€๋ คํ•ฉ๋‹ˆ๋‹ค.
Typescript๋Š” runtime์—์„œ ํƒ€์ž…์ด ์ •์˜๋˜๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์™€ ๋‹ฌ๋ฆฌ ํƒ€์ž…์„ ๋”ฐ๋กœ ์ •ํ•ด์ค˜์•ผ ํ•œ๋‹ค๋Š” ์ ์ด ๊ท€์ฐฎ์ง€๋งŒ,
์ด ๊ท€์ฐฎ์Œ์— ์ต์ˆ™ํ•ด์ ธ์„œ ๋‚˜์ค‘์— ํ˜„์—…์—์„œ ๊ทœ๋ชจ์žˆ๊ณ  ์•ˆ์ •์ ์ธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์„œ๋น„์Šค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋„๋ก ๋…ธ๋ ฅํ•ด์•ผ๊ฒ ์Šต๋‹ˆ๋‹ค.

profile
๊ทธ๋ฆผ๋„ ๊ทธ๋ฆฌ๋Š” ๊ฐœ๋ฐœ์ž ๐ŸŽจ๐Ÿ‘ฉโ€๐Ÿ’ป

0๊ฐœ์˜ ๋Œ“๊ธ€