[Portfolio] 🎢 FLOrida music

jinyoung985Β·2022λ…„ 10μ›” 21일
0

Portfolio

λͺ©λ‘ 보기
2/7
post-thumbnail

πŸ“‹ FLOrida

πŸ’‘ νŒ€λͺ… : FLOrida

  • λͺ¨ν‹°λΈŒλ‘œ ν•œ μ‚¬μ΄νŠΈ : https://www.music-flo.com/
  • FE : κΉ€μ§„μ˜ κΉ€μΆ©λ§Œ μž„μ§€μ˜ 졜승철
  • BE : 김ꡐ은 이신희
  • κ°œλ°œκΈ°κ°„ : 9/19(μ›”) ~ 9/30(λͺ©) 14:00 (12일)

μ‚¬μš©ν•œ 기술 μŠ€νƒ
FE : JavaScript React.js styled-component react-h5-audio-player MUI λ“±
BE :JavaScript Node.js MySQL Express.js jwt bcrypt λ“±

JUSTCODE κ³Όμ •μ—μ„œ μ§„ν–‰λœ 2μ°¨ νŒ€ ν”„λ‘œμ νŠΈμž…λ‹ˆλ‹€.

이 ν”„λ‘œμ νŠΈλŠ” νŒ€μž₯은 λ”°λ‘œ μ—†κ³  FE 총 4λͺ…, BE 2λͺ…μœΌλ‘œ 이루어진 νŒ€μœΌλ‘œ μ§„ν–‰ν–ˆμŠ΅λ‹ˆλ‹€.

μ²˜μŒμ— 제 μ·¨λ―Έκ°€ μŒμ•… 감상이라 μŒμ•… ν”Œλ ˆμ΄μ–΄ 및 개인 ν”Œλ ˆμ΄λ¦¬μŠ€νŠΈ 관리 λ“±μ˜ κΈ°λŠ₯을 해보고 싢기도 ν•˜κ³ , 1μ°¨ ν”„λ‘œμ νŠΈλ³΄λ‹€ κΈ°λŠ₯도 λ‹€μ–‘ν–ˆκΈ° λ•Œλ¬Έμ— μ œμ•ˆν–ˆκ³  νŒ€μ›λΆ„λ“€λ„ λͺ¨λ‘ λ™μ˜ν•΄ μ£Όμ…”μ„œ FLO μ‚¬μ΄νŠΈλ₯Ό λͺ¨ν‹°λΈŒλ‘œ μ œμž‘ν•˜κ²Œ λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

μ—¬κΈ°μ„œ λͺ¨ν‹°λΈŒλ‘œ μ œμž‘ν•˜μ˜€λ‹€λŠ” 건, λˆ„κ΅°κ°€μ˜ μ½”λ“œλ₯Ό κ·ΈλŒ€λ‘œ 볡사 λΆ™μ—¬λ„£κΈ° ν•œ 것이 μ•„λ‹Œ νŽ˜μ΄μ§€μ˜ ꡬ쑰λ₯Ό μ°Έκ³ ν•˜μ—¬ 직접 μ½”λ“œλ₯Ό μž‘μ„±ν•œκ²ƒμ„ λœ»ν•©λ‹ˆλ‹€.


πŸ”— 링크

πŸ’» GitHub

πŸ“‹ 회고둝


πŸ”§ λ‚΄κ°€ κ΅¬ν˜„ν•œ κΈ°λŠ₯

πŸŽ₯ λ‚΄κ°€ κ΅¬ν˜„ν•œ κΈ°λŠ₯ μ‹œμ—° μ˜μƒ

μ œκ°€ 맑은 뢀뢄을 μ„œλ²„κ°€ μ—΄λ €μžˆμ„ λ•Œ μ΄¬μ˜ν•˜μ—¬ μœ νŠœλΈŒμ— μ—…λ‘œλ“œν–ˆμŠ΅λ‹ˆλ‹€.

1. μŒμ•… ν”Œλ ˆμ΄μ–΄

μŒμ•… ν”Œλ ˆμ΄μ–΄λŠ” react-h5-audio-player 라이브러리λ₯Ό 톡해 μž‘μ—…ν–ˆμŠ΅λ‹ˆλ‹€.

1-1. ν˜„μž¬ μž¬μƒλͺ©λ‘

ν˜„μž¬ μž¬μƒλͺ©λ‘μ€ state와 μ„Έμ…˜ μŠ€ν† λ¦¬μ§€μ— μ €μž₯ν•˜μ—¬ κ΄€λ¦¬ν–ˆμŠ΅λ‹ˆλ‹€.

μ„Έμ…˜ μŠ€ν† λ¦¬μ§€λ‘œλ„ κ΄€λ¦¬ν•˜μ—¬ 마운트 μ‹œ μ„Έμ…˜ μŠ€ν† λ¦¬μ§€μ—μ„œ ν˜„μž¬ μž¬μƒλͺ©λ‘μ„ κ°€μ Έμ˜€κΈ° λ•Œλ¬Έμ— μƒˆλ‘œκ³ μΉ¨μ„ 해도 ν˜„μž¬ μž¬μƒλͺ©λ‘μ΄ μœ μ§€λ©λ‹ˆλ‹€.

1-2. 곑 μ…”ν”Œ κΈ°λŠ₯

μ…”ν”Œ κΈ°λŠ₯은 λΌμ΄λΈŒλŸ¬λ¦¬μ— μ‘΄μž¬ν•˜μ§€ μ•Šμ•„μ„œ 직접 κ΅¬ν˜„ν–ˆμŠ΅λ‹ˆλ‹€.

  const shuffleMusic = () => {
    if (JSON.parse(sessionStorage.getItem('tracks')).length !== 0) {
      const randomTracks = [...musicTracks].sort(() => Math.random() - 0.5);
      if (randomTracks[0] === musicTracks[0]) {
        let lastIndex = randomTracks.length - 1;
        let randomValue = Math.floor(Math.random() * (lastIndex - 1) + 1);
        const temp = randomTracks[0];
        randomTracks[0] = randomTracks[lastIndex];
        randomTracks[lastIndex] = temp;
      }
      setMusicTracks(randomTracks);
    }
  };

array.sort λ©”μ†Œλ“œλ₯Ό 톡해 λžœλ€ν•˜κ²Œ ν˜„μž¬ μž¬μƒλͺ©λ‘μ„ λ’€μ„žκ³ , 첫 번째 곑이 λ°”λ€Œμ§€ μ•Šμ•˜μ„ 경우 첫 번째 곑을 또 λžœλ€ν•œ μΈλ±μŠ€μ— μœ„μΉ˜ν•˜κ²Œ ν•˜λ„λ‘ λ‘œμ§μ„ κ΅¬ν˜„ν–ˆμŠ΅λ‹ˆλ‹€.

1-3. 곑 닀쀑 선택 κΈ°λŠ₯

곑을 λ‹€μ€‘μœΌλ‘œ 선택해 ν˜„μž¬ μž¬μƒλͺ©λ‘μ—μ„œ μ‚­μ œ 및 ν”Œλ ˆμ΄ λ¦¬μŠ€νŠΈμ— μΆ”κ°€ν•  수 μžˆλ„λ‘ κ΅¬ν˜„ν–ˆμŠ΅λ‹ˆλ‹€.

곑을 μ„ νƒν–ˆμ„ λ•Œ, 배열에 곑의 IDλ₯Ό λ‹΄μ•„ state둜 κ΄€λ¦¬ν•˜μ—¬ μ‚­μ œ 및 λ°±μ—”λ“œλ‘œ 전달(보관함에 μΆ”κ°€) ν•  수 μžˆλŠ” λ‘œμ§μž…λ‹ˆλ‹€.

1-4. 검색 κΈ°λŠ₯

μž¬μƒ 쀑인 곑을 λ°”κΎΈλ €λ©΄ 인덱슀 값을 λ³€κ²½ν•΄μ•Ό ν•©λ‹ˆλ‹€.

그런데 검색을 ν•˜λ©΄ λ°°μ—΄μ˜ 길이가 쀄어듀기 λ•Œλ¬Έμ— 곑을 ν΄λ¦­ν•˜λ©΄ μ›λž˜ μž¬μƒλͺ©λ‘μ˜ μΈλ±μŠ€μ— ν•΄λ‹Ήν•˜λŠ” 곑이 μ‹€ν–‰λ˜μ–΄λ²„λ¦½λ‹ˆλ‹€.

κ·Έλž˜μ„œ μƒκ°ν•œ 것이 검색 κΈ°λŠ₯을 톡해 ν•„ν„°λ§λœ 곑듀은 곑 url을 빈 λ¬Έμžμ—΄λ‘œ 섀정해버렀 빈 λ¬Έμžμ—΄μ„ κ°€μ§„ 곑듀은 좜λ ₯λ˜μ§€ μ•Šκ²Œ λ‘œμ§μ„ κ΅¬ν˜„ν–ˆμŠ΅λ‹ˆλ‹€.

2. 보관함

2-1. 보관함 닀쀑 선택 κΈ°λŠ₯

μœ„μ˜ 곑 선택 둜직과 λ˜‘κ°™μŠ΅λ‹ˆλ‹€. ν”Œλ ˆμ΄λ¦¬μŠ€νŠΈ IDλ₯Ό 배열에 μ €μž₯ν•˜μ—¬ state둜 κ΄€λ¦¬ν•©λ‹ˆλ‹€.

2-2. ν”Œλ ˆμ΄λ¦¬μŠ€νŠΈ μž¬μƒ 둜직

  const playSongs = () => {
    if (playlistSongs[0].songTitle) {
      fetch(`ν”Œλ ˆμ΄λ¦¬μŠ€νŠΈμš”μ²­URL`, {
        headers: {
          Authorization: sessionStorage.getItem('token'),
        },
      })
        .then(res => res.json())
        .then(plData => {
          const musicTracksId = musicTracks.map(el => el.songId);
          const filteredNewTracks = plData.filter(
            (el, i) => musicTracksId.includes(el.songId) === false
          );
          setMusicTracks([...filteredNewTracks, ...musicTracks]);
          setAlertOn('ν˜„μž¬ μž¬μƒλͺ©λ‘μ— μΆ”κ°€λ˜μ—ˆμŠ΅λ‹ˆλ‹€. μ€‘λ³΅λœ 곑은 μ œμ™Έλ©λ‹ˆλ‹€.');
        })
        .catch(err => {
          if (sessionStorage.getItem('token'))
            setAlertOn(
              'μ΄μš©κΆŒμ„ ꡬ맀해야 μŒμ•… μž¬μƒ μ„œλΉ„μŠ€λ₯Ό μ΄μš©ν•˜μ‹€ 수 μžˆμŠ΅λ‹ˆλ‹€.'
            );
        });
    }
  };

전체 μž¬μƒ λ²„νŠΌμ„ λˆ„λ₯΄λ©΄ ν•΄λ‹Ή ν”Œλ ˆμ΄λ¦¬μŠ€νŠΈμ˜ 곑듀을 μš”μ²­ν•©λ‹ˆλ‹€.

그리고 ν”Œλ ˆμ΄λ¦¬μŠ€νŠΈμ˜ λͺ¨λ“  곑듀을 λ°›μ•„ λ‚΄ ν˜„μž¬ ν”Œλ ˆμ΄λ¦¬μŠ€νŠΈμ— μžˆλŠ” 곑듀을 아이디λ₯Ό 톡해 비ꡐ해 μ€‘λ³΅λ˜μ§€ μ•ŠλŠ” κ³‘λ“€λ§Œ μΆ”κ°€ν•˜λ„λ‘ λ‘œμ§μ„ κ΅¬ν˜„ν–ˆμŠ΅λ‹ˆλ‹€.

2-3. κ°œλ³„ 곑 μž¬μƒ 둜직

μž¬μƒ λ²„νŠΌμ„ λˆ„λ₯΄λ©΄ ν˜„μž¬ ν”Œλ ˆμ΄λ¦¬μŠ€νŠΈμ— μ€‘λ³΅λ˜λŠ” 곑이 μžˆλ‹€λ©΄ μΆ”κ°€ν•˜μ§€ μ•Šλ„λ‘ κ΅¬ν˜„ν–ˆμŠ΅λ‹ˆλ‹€.

3. 보관함 μƒμ„ΈνŽ˜μ΄μ§€

3-1. ν”Œλ ˆμ΄λ¦¬μŠ€νŠΈλͺ… μˆ˜μ •

바뀐 ν”Œλ ˆμ΄λ¦¬μŠ€νŠΈμ˜ 값을 백으둜 μ „λ‹¬ν•˜κ³  λ°”λ‘œ λ°˜μ˜ν•©λ‹ˆλ‹€. λ˜ν•œ useRef와 focus λ©”μ†Œλ“œλ₯Ό 톡해 μˆ˜μ • λ²„νŠΌ 클릭 μ‹œ, λ°”λ‘œ 포컀싱 λ˜λ„λ‘ μ„€μ •ν–ˆμŠ΅λ‹ˆλ‹€.

3-2. μŒμ•… ν”Œλ ˆμ΄μ–΄ μœ„ μ•Œλ¦Όμ°½

μ•Œλ¦Ό μ°½ μ»΄ν¬λ„ŒνŠΈλ₯Ό λ§Œλ“€μ–΄ setAlert(”메세지”) λ₯Ό 톡해 μ›ν•˜λŠ” λ©”μ„Έμ§€λ₯Ό 좜λ ₯ν•  수 μžˆλ„λ‘ ν–ˆμŠ΅λ‹ˆλ‹€.

alert μ»΄ν¬λ„ŒνŠΈλŠ” λ‚˜νƒ€λ‚œ λ’€ 3초 후에 μžλ™μœΌλ‘œ μ‚¬λΌμ§‘λ‹ˆλ‹€.

κ·Έ μ™Έ ν˜„μž¬ μž¬μƒλͺ©λ‘ 쀑볡 λ°©μ§€ 및 닀쀑 선택 κΈ°λŠ₯은 λ™μΌν•©λ‹ˆλ‹€.

4. λ‘œλ”© μ»΄ν¬λ„ŒνŠΈ

데이터λ₯Ό 뢈러였기 μ „κΉŒμ§€ λ‘œλ”© μ»΄ν¬λ„ŒνŠΈκ°€ 빈 ν™”λ©΄ λŒ€μ‹  좜λ ₯λ˜λ„λ‘ ν•˜κ³  λ‹€λ₯Έ λͺ¨λ“  νŽ˜μ΄μ§€μ— μ μš©ν–ˆμŠ΅λ‹ˆλ‹€.

λ‚˜μ€‘μ— μ‹œκ°„μ΄ λœλ‹€λ©΄ μŠ€μΌˆλ ˆν†€μœΌλ‘œλ„ κ΅¬ν˜„ν•΄ 보고 μ‹ΆμŠ΅λ‹ˆλ‹€.


🀯 기얡에 λ‚¨λŠ” νŠΈλŸ¬λΈ”

ν”„λ‘œμ νŠΈ μ‹œμž‘ μ „, ν‹°μΌ“ 뢄배에 μ‹€νŒ¨ν•΄ 각쒅 μƒμ„ΈνŽ˜μ΄μ§€, 인기 차트λ₯Ό λ§‘μœΌμ‹  뢄이 티켓을 λ„ˆλ¬΄ 많이 맑게 λ˜μ–΄ 쑰금 더 뢄업을 ν•΄μ„œ 보관함 μƒμ„ΈνŽ˜μ΄μ§€λŠ” μ œκ°€ 맑게 λ˜μ—ˆκ³  인기 μ°¨νŠΈλŠ” λ‹€λ₯Έ ν•œ 뢄이 맑게 λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

보관함 μƒμ„ΈνŽ˜μ΄μ§€λ₯Ό κ΅¬ν˜„ν•˜κ²Œ 될 μ°¨λ‘€κ°€ λ˜μ–΄μ„œ μŒμ•… μ»΄ν¬λ„ŒνŠΈλ₯Ό μž¬ν™œμš©ν•΄μ•Όν•  μ§€, μ•„λ‹ˆλ©΄ μ–΄λ–»κ²Œ ν•΄μ•Ό ν• μ§€ ν† μ˜ν•˜λ‹€κ°€ μ‹œκ°„ 관계상 κ²°κ΅­ 각자 λ§Œλ“€μ–΄λ†“μ€ μŒμ•… μ»΄ν¬λ„ŒνŠΈμ— μ œκ°€ λ§Œλ“  μž¬μƒ 둜직, 닀쀑 선택 둜직, λ‚΄ λ¦¬μŠ€νŠΈμ— μΆ”κ°€, 더 보기 κΈ°λŠ₯ 등을 κ·ΈλŒ€λ‘œ μ μš©ν•˜κΈ°λ‘œ κ²°μ •λμŠ΅λ‹ˆλ‹€.

문제의 μŒμ•… μ»΄ν¬λ„ŒνŠΈ ↓

ν•˜μ§€λ§Œ μ œκ°€ λ§Œλ“  μž¬μƒ 둜직, 닀쀑 선택, λ‚΄ 리슀트 μΆ”κ°€, 더 보기 등을 νŒ€μ›λ“€μ˜ μ»΄ν¬λ„ŒνŠΈμ— μ μš©ν•˜λŠ” κ³Όμ •μ—μ„œ μœ„κΈ°κ°€ λ‹₯μ³μ™”μŠ΅λ‹ˆλ‹€.

제좜 전날이 λ˜μ–΄μ„œμ•Ό λ‹€λ₯Έ λΆ„λ“€μ˜ μ»΄ν¬λ„ŒνŠΈμ— 제 λ‘œμ§μ„ μ μš©ν•˜λ‹€ λ³΄λ‹ˆ μ•„λ¬΄λž˜λ„ μƒμˆ˜ 및 λ³€μˆ˜ λͺ…도 λ‹€λ₯΄κ³  μ»΄ν¬λ„ŒνŠΈ ꡬ쑰 μžμ²΄λ„ 달라 μ μš©ν•˜κΈ°κ°€ 쉽지 μ•Šμ•˜μŠ΅λ‹ˆλ‹€.

κ²°κ΅­ 거의 밀을 μƒˆμ›Œ μ–΄λŠ 정도 끝마치고 λ°œν‘œ 당일 아침에 λ‹€μ‹œ ν•œλ²ˆ μ •λΉ„ν•΄ κ²°κ΅­ μ„±κ³΅μ μœΌλ‘œ μž‘λ™ν•˜κΈ΄ ν–ˆμ§€λ§Œ, ν”„λ‘œμ νŠΈλ₯Ό μ‹œμž‘ν•˜κΈ° μ „ λ‹€ ν•¨κ»˜ μ‚¬μ΄νŠΈ 전체 ꡬ쑰λ₯Ό νŒŒμ•…ν•΄ μž¬ν™œμš©ν•  μ»΄ν¬λ„ŒνŠΈλ‚˜ μ‚¬μ΄νŠΈ ꡬ쑰 등을 μƒκ°ν•˜κ³  μ‹œμž‘ν–ˆλ‹€λ©΄ μ’€ 더 쒋은 κ²°κ³Όκ°€ μžˆμ§€ μ•Šμ•˜μ„κΉŒ μ‹ΆμŠ΅λ‹ˆλ‹€.


πŸ’ͺ λ‚΄κ°€ μ„±μž₯ν•œ λΆ€λΆ„

1. 문제 ν•΄κ²° 및 예방 λŠ₯λ ₯

1μ°¨ ν”„λ‘œμ νŠΈλ₯Ό μ§„ν–‰ν•˜λ©΄μ„œλ„ μˆ˜λ§Žμ€ μ—λŸ¬λ₯Ό λ§ˆμ£Όν–ˆμ§€λ§Œ, 이번 ν”„λ‘œμ νŠΈμ—μ„œλŠ” μ—λŸ¬λΏλ§Œ μ•„λ‹ˆλΌ μœ„μ— μž‘μ„±ν•œ νŒ€ ν˜‘μ—… 간에 μƒκΈ°λŠ” νŠΈλŸ¬λΈ”λ“€λ„ κ²ͺμ—ˆμŠ΅λ‹ˆλ‹€.

덕뢄에 문제 ν•΄κ²° λŠ₯λ ₯뿐만 μ•„λ‹ˆλΌ λ‹€μŒμ—” 이런 νŠΈλŸ¬λΈ”μ„ κ²ͺμ§€ μ•ŠκΈ° μœ„ν•΄ 문제λ₯Ό μ˜ˆλ°©ν•  수 μžˆλŠ” λŠ₯λ ₯도 κ°€μ§€κ²Œ λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

2. λ‚΄κ°€ μž‘μ„±ν•œ μ½”λ“œμ˜ 문제점 νŒŒμ•…

사싀 이번 ν”„λ‘œμ νŠΈκΉŒμ§€λŠ” μ˜€λ‘œμ§€ κΈ°λŠ₯이 μž‘λ™ν•˜λŠ” λ°μ—λ§Œ 의의λ₯Ό λ‘μ–΄μ„œ 가독성을 κ³ λ €ν•˜μ§€ λͺ»ν•˜κ³  μ½”λ“œλ₯Ό μž‘μ„±ν–ˆμŠ΅λ‹ˆλ‹€.

ν•˜μ§€λ§Œ ν”„λ‘œμ νŠΈκ°€ λλ‚˜κ³  제 μ½”λ“œλ₯Ό μ‚΄νŽ΄λ³΄λ‹ˆ ν•œλˆˆμ— λ“€μ–΄μ˜€μ§€ μ•ŠλŠ”λ‹€λŠ” 것을 μ•Œκ²Œ λ˜μ—ˆμŠ΅λ‹ˆλ‹€. κ·Έλž˜μ„œ 이 ν”„λ‘œμ νŠΈκ°€ λλ‚˜κ³  클린 μ½”λ“œλ₯Ό μž‘μ„±ν•˜λŠ” 방법을 κ³΅λΆ€ν–ˆκ³  점점 가독성도 κ³ λ €ν•˜λ©° μ½”λ”©ν•  수 μžˆλŠ” κ°œλ°œμžκ°€ λ˜μ–΄κ°€κ³  μžˆλŠ” μ€‘μž…λ‹ˆλ‹€.

0개의 λŒ“κΈ€