Skip to content

Josh5519/Watcher-Habit-Server

This branch is up to date with Last-Survivors-3-8/Watcher-Habit-Server:dev.

Folders and files

NameName
Last commit message
Last commit date
Sep 12, 2023
Sep 11, 2023
Sep 25, 2023
Sep 13, 2023
Sep 9, 2023
Sep 9, 2023
Sep 9, 2023
Oct 11, 2023
Sep 15, 2023
Sep 15, 2023

Repository files navigation

Watcher Habit: μŠ΅κ΄€ 곡유 ν”Œλž«νΌ 🌱

πŸ’β€β™€οΈ μ†Œκ°œ

Watcher Habit은 개인의 μŠ΅κ΄€μ„ 효과적으둜 κ΄€λ¦¬ν•˜κ³ , μ†Œκ·œλͺ¨ κ·Έλ£Ήκ³Ό μŠ΅κ΄€μ„ κ³΅μœ ν•˜λŠ” ν”Œλž«νΌμž…λ‹ˆλ‹€. μ‚¬μš©μžλ“€μ΄ μ„œλ‘œμ˜ μŠ΅κ΄€μ„ κ³΅μœ ν•˜λ©°, μ„œλ‘œλ₯Ό μ§€μΌœλ³΄λ©΄μ„œ 동기뢀여λ₯Ό 얻을 수 μžˆμŠ΅λ‹ˆλ‹€. 이λ₯Ό 톡해 μŠ΅κ΄€μ˜ 지속성을 높이고, κ·Έλ£Ή λ‚΄μ˜ λ™λ£Œλ“€κ³Ό ν•¨κ»˜ μ„±μž₯ν•˜λŠ” κ²½ν—˜μ„ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

πŸ“Ή μ‹œμ—° μ˜μƒ: Watcher Habit μ‹œμ—° μ˜μƒ 유튜브 링크


πŸ‘€ λͺ©μ°¨


πŸ’‘ ν”„λ‘œμ νŠΈ 동기

1. 개인의 기술적 ν₯미와 ν•™μŠ΅ μ˜μ§€

ν”„λ‘œμ νŠΈ 기획 λ‹¨κ³„μ—μ„œ Last-Survivors 3/8 νŒ€μ›μ€ μ„œλ‘œ λ‹€λ₯Έ 기술적 ν₯미와 ν•™μŠ΅ λͺ©ν‘œλ₯Ό 가지고 μžˆμ—ˆμŠ΅λ‹ˆλ‹€.

μ§€ν˜„
  • λ¦¬μ•‘νŠΈ ν™œμš© 및 μƒνƒœ 관리 툴 λ„μž…
  • λ°˜μ‘ν˜• μ›Ή μ•± κ΅¬ν˜„
  • μ‚¬μš©μž μ€‘μ‹¬μ˜ UI/UX 섀계
  • 초기 기획 λ‹¨κ³„μ—μ„œμ˜ λ°©ν–₯μ„± λͺ…ν™•ν™”
μ‹œν™˜
  • μ‹€μ‹œκ°„ μ„œλ²„ 처리 κ²½ν—˜
  • μžλ°”μŠ€ν¬λ¦½νŠΈ μ€‘μ‹¬μ˜ μ„œλ²„ μž‘μ—…λ°©μ‹ κΉŠμ€ 탐ꡬ
지은
  • μ‹ κ·œ 기술과 라이브러리 λ„μž… κ²½ν—˜
  • μ•ˆμ •μ μΈ 기술 μŠ€νƒ ν™œμš© 및 ν”„λ‘œμ νŠΈ νš¨μœ¨μ„± ν–₯상

2. μŠ΅κ΄€ 기둝 아이디어

μ‹œν™˜λ‹˜μ€ ν‰μ†Œ λ…Έμ…˜μœΌλ‘œ 슀슀둜의 μŠ΅κ΄€ ν˜•μ„±μ„ κΈ°λ‘ν•˜κ³  μžˆμ—ˆλŠ”λ°, 혼자만의 기둝은 동기 뢀여에 ν•œκ³„κ°€ μžˆμ—ˆμŠ΅λ‹ˆλ‹€. μ΄λŸ¬ν•œ λ¬Έμ œμ μ„ ν•΄κ²°ν•˜κΈ° μœ„ν•΄ μŠ΅κ΄€ 기둝을 μ„œλ‘œ κ³΅μœ ν•˜κ³  확인할 수 μžˆλŠ” μ†Œκ·œλͺ¨ 그룹을 ν˜•μ„±ν•˜λŠ” 아이디어가 μ œμ‹œλ˜μ—ˆμŠ΅λ‹ˆλ‹€. 이 μ•„μ΄λ””μ–΄λŠ” κ·Έλ™μ•ˆ κ³΅λΆ€ν•΄μ˜¨ λ¦¬μ•‘νŠΈλ‘œλ„ μΆ©λΆ„νžˆ κ΅¬ν˜„ κ°€λŠ₯ν•˜λ©΄μ„œ, 관리할 μƒνƒœκ°€ λ§Žμ„ κ²ƒμœΌλ‘œ μ˜ˆμƒλ˜μ—ˆκΈ° λ•Œλ¬Έμ— μƒνƒœ 관리 툴의 ν•„μš”μ„±μ΄ λ†’λ‹€κ³  μƒκ°λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 또, 이전 ν”„λ‘œμ νŠΈμ™€λŠ” λ‹€λ₯΄κ²Œ μ„œλ²„μ™€ ν΄λΌμ΄μ–ΈνŠΈλ₯Ό λΆ„λ¦¬ν•˜μ—¬ μž‘μ—…ν•˜λŠ” λ“± λ‹€μ–‘ν•œ 기술적 도전을 ν¬ν•¨ν•˜κ³  μžˆμ—ˆμŠ΅λ‹ˆλ‹€.


3. μ›Ή μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 'Watcher Habit'

λͺ¨λ“  νŒ€μ›μ˜ 기술적 ν₯미와 μ‹œν™˜λ‹˜μ˜ μŠ΅κ΄€ 기둝 아이디어가 합쳐져, μ‚¬μš©μžλ“€μ΄ μ„œλ‘œμ˜ μŠ΅κ΄€μ„ μ§€μΌœλ³΄λ©° μ„œλ‘œλ₯Ό λ„μ™€μ£ΌλŠ” μ›Ή μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 'Watcher Habit'이 νƒ„μƒν•˜κ²Œ λ˜μ—ˆμŠ΅λ‹ˆλ‹€. μ‚¬μš©μžλ“€μ—κ²Œ μ„œλ‘œμ˜ μŠ΅κ΄€μ„ λͺ¨λ‹ˆν„°λ§ν•˜λ©° 동기λ₯Ό λΆ€μ—¬ν•˜λŠ” μ„œλΉ„μŠ€μž…λ‹ˆλ‹€.


🚧 도전 및 문제 ν•΄κ²°

3μ£Ό λ™μ•ˆ κ°œλ°œμ„ μ§„ν–‰ν•˜λ©΄μ„œ κ²ͺμ—ˆλ˜ μ„œλ²„μ™€ ν΄λΌμ΄μ–ΈνŠΈμ—μ„œ λ°œμƒν•œ 핡심적인 λ¬Έμ œλ“€μ„ 정리해 λ³΄μ•˜μŠ΅λ‹ˆλ‹€.

1. ν΄λΌμ΄μ–ΈνŠΈ μƒνƒœ 관리

1) ν΄λΌμ΄μ–ΈνŠΈ μƒνƒœ κ΄€λ¦¬μ˜ μ€‘μš”μ„±κ³Ό ν•„μš”μ„±

ν”„λ‘ νŠΈμ—”λ“œ 개발 쀑 μƒνƒœ κ΄€λ¦¬μ˜ μ€‘μš”μ„±μ„ κΉ¨λ‹¬μ•˜μŠ΅λ‹ˆλ‹€. μ—¬λŸ¬ μ»΄ν¬λ„ŒνŠΈμ—μ„œ μƒνƒœλ₯Ό κ³΅μœ ν•˜κ³ , μ„œλ²„ λ°μ΄ν„°μ™€μ˜ 동기화 및 μƒνƒœ μ—…λ°μ΄νŠΈκ°€ ν•„μš”ν–ˆμŠ΅λ‹ˆλ‹€. 특히, μ•Œλ¦Όμ„ μ‘°νšŒν•˜κ±°λ‚˜ μŠ΅κ΄€ 정보λ₯Ό 쑰회, μˆ˜μ •, μΆ”κ°€ν•  λ•Œλ§ˆλ‹€ μ‹€μ‹œκ°„μœΌλ‘œ μœ μ €μ—κ²Œ λ³΄μ—¬μ£ΌλŠ” λΆ€λΆ„μ—μ„œ μƒνƒœ 관리λ₯Ό 톡해 μ½”λ“œλ₯Ό κ°„κ²°ν•˜κ²Œ λ§Œλ“€μ–΄μ•Ό ν–ˆμŠ΅λ‹ˆλ‹€.

2) props drilling λ¬Έμ œμ™€ μƒνƒœ 관리 툴의 선택

μ»΄ν¬λ„ŒνŠΈ 뢄리 κ³Όμ •μ—μ„œ props drilling ν˜„μƒμ΄ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€. 이λ₯Ό ν•΄κ²°ν•˜κ³  μƒνƒœλ₯Ό 효율적으둜 κ΄€λ¦¬ν•˜κΈ° μœ„ν•΄ λ‹€μ–‘ν•œ μƒνƒœ 관리 νˆ΄μ„ μ‘°μ‚¬ν•˜κ³  μ μš©ν•  ν•„μš”κ°€ μžˆμ—ˆμŠ΅λ‹ˆλ‹€.

3) μƒνƒœ 관리 μ΅œμ ν™” 적용

(a) React λ‚΄μž₯ Hook: useState

React λ‚΄μž₯ Hook 쀑 useStateλŠ” 비ꡐ적 κ°„λ‹¨ν•œ 둜컬 μƒνƒœ 관리에 μ ν•©ν•˜λ―€λ‘œ, λ‘œλ”© μƒνƒœ, λͺ¨λ‹¬μ˜ μ—΄λ¦Ό 및 λ‹«νž˜, κ·Έλ£Ή λͺ©λ‘μ˜ ν‘œμ‹œ 여뢀와 같은 κ°„λ‹¨ν•œ UI μƒνƒœλ₯Ό κ΄€λ¦¬ν•˜λŠ” 데 μ‚¬μš©λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

(b) μ „μ—­ μƒνƒœ 관리: Redux와 Redux Toolkit

μ „μ—­ μƒνƒœ κ΄€λ¦¬μ—λŠ” Redux와 Redux Toolkit을 μ‚¬μš©ν•˜μ—¬ μŠ΅κ΄€ 정보, μ•Œλ¦Ό 정보 λ“±μ˜ μ „μ—­ μƒνƒœλ₯Ό μ€‘μ•™μ—μ„œ κ΄€λ¦¬ν•˜μ˜€μŠ΅λ‹ˆλ‹€. 이λ₯Ό 톡해 μŠ΅κ΄€μ΄λ‚˜ μ•Œλ¦Ό 정보가 변경될 λ•Œλ§ˆλ‹€ μ‹€μ‹œκ°„μœΌλ‘œ μƒνƒœλ₯Ό μ—…λ°μ΄νŠΈν•˜κ³  μ‚¬μš©μžμ—κ²Œ λ°˜μ˜ν•  수 있게 λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

(c) μ„œλ²„ 데이터 관리: react-query

μ„œλ²„μ™€μ˜ 데이터 동기화λ₯Ό μœ„ν•΄ react-queryλ₯Ό μ‚¬μš©ν•˜μ˜€μŠ΅λ‹ˆλ‹€. 특히, 쒌츑 μ‚¬μ΄λ“œλ°” μ»΄ν¬λ„ŒνŠΈμ—μ„œ 그룹을 μƒμ„±ν•˜λ©΄ μƒμ„±λœ 그룹의 νŽ˜μ΄μ§€λ‘œ μ΄λ™λ˜λ©΄μ„œ λ™μ‹œμ— κ·Έλ£Ή λ¦¬μŠ€νŠΈμ— μ‹€μ‹œκ°„μœΌλ‘œ μƒˆλ‘œμš΄ 그룹의 이름이 λ‚˜νƒ€λ‚˜μ•Ό ν–ˆμŠ΅λ‹ˆλ‹€. 이λ₯Ό μœ„ν•΄ μ•„λž˜μ˜ μ»€μŠ€ν…€ 훅을 κ΅¬ν˜„ν•˜μ—¬ μ„œλ²„μ—μ„œ μ΅œμ‹ μ˜ μ‚¬μš©μž 데이터λ₯Ό κ°€μ Έμ˜€λ„λ‘ ν–ˆμŠ΅λ‹ˆλ‹€. λ˜ν•œ react-query의 데이터 캐싱 κΈ°λŠ₯을 ν™œμš©ν•˜μ—¬ μ„±λŠ₯을 ν–₯μƒμ‹œμΌ°μŠ΅λ‹ˆλ‹€.

react-queryλ₯Ό μ μš©ν•œ μ»€μŠ€ν…€ ν›… μ˜ˆμ‹œ 이 μ»€μŠ€ν…€ ν›…μ—μ„œλŠ” react-query 라이브러리의 useQuery 훅을 μ‚¬μš©ν•˜μ—¬ μœ μ € 쑰회 APIλ₯Ό 톡해 μ‚¬μš©μž 데이터λ₯Ό μš”μ²­ν•©λ‹ˆλ‹€. 이 λ•Œ, useQuery의 enabled μ˜΅μ…˜μ„ μ‚¬μš©ν•˜μ—¬ 쑰건에 따라 데이터 μš”μ²­μ„ ν™œμ„±ν™”ν•˜κ±°λ‚˜ λΉ„ν™œμ„±ν™”ν•  수 μžˆμœΌλ―€λ‘œ μœ μ € IDκ°€ μœ νš¨ν•œ κ²½μš°μ—λ§Œ μ‚¬μš©μž 데이터λ₯Ό μš”μ²­ν•˜λ„λ‘ μ„€κ³„ν•˜μ˜€μŠ΅λ‹ˆλ‹€. useQueryλŠ” μš”μ²­ν•œ 데이터λ₯Ό μžλ™μœΌλ‘œ μΊμ‹œν•˜λ―€λ‘œ 같은 데이터에 λŒ€ν•œ μž¬μš”μ²­ μ‹œ λΆˆν•„μš”ν•œ μ„œλ²„ ν˜ΈμΆœμ„ μ€„μ—¬μ€λ‹ˆλ‹€. μΆ”κ°€λ‘œ 그룹이 생성될 λ•Œλ§ˆλ‹€ μ΅œμ‹ μ˜ κ·Έλ£Ή 리슀트λ₯Ό λ‹€μ‹œ κ°€μ Έμ˜€κΈ° μœ„ν•΄μ„œ 쒌츑 μ‚¬μ΄λ“œλ°”μ™€ κ°€μž…ν•œ κ·Έλ£Ή 리슀트 μ»΄ν¬λ„ŒνŠΈμ—μ„œ refetchλ₯Ό μ‚¬μš©ν•˜μ˜€μŠ΅λ‹ˆλ‹€.
import { useQuery } from 'react-query';
import userGetAPI from '../services/api/userGet';

export const useFetchUserData = (userId) => {
  const fetchUserData = async () => {
    const response = await userGetAPI(userId, 'group', true);

    return response.groups.map((group) => ({
      groupId: group._id,
      groupName: group.groupName,
    }));
  };

  const {
    data: groupList,
    refetch,
    isLoading,
  } = useQuery(['userData', userId], fetchUserData, {
    enabled: !!userId,
  });

  return { groupList, refetch, isLoading };
};

4) μƒνƒœ κ΄€λ¦¬μ˜ νš¨κ³Όμ™€ ν–₯μƒλœ κ²°κ³Ό

Redux Toolkitκ³Ό react-queryλ₯Ό 효과적으둜 μ‘°ν•©ν•˜μ—¬ μ‚¬μš©ν•˜λ €κ³  λ…Έλ ₯ν–ˆμŠ΅λ‹ˆλ‹€. 그리고 μ»€μŠ€ν…€ ν›…μ˜ λ„μž…μœΌλ‘œ μ»΄ν¬λ„ŒνŠΈ λ‚΄μ˜ 둜직과 μƒνƒœ 관리 λ‘œμ§μ„ λͺ…ν™•ν•˜κ²Œ λΆ„λ¦¬ν•¨μœΌλ‘œμ¨ ν”„λ‘œμ νŠΈ λ‚΄μ˜ μƒνƒœ 관리 λ³΅μž‘μ„±μ„ 크게 μ€„μ˜€μŠ΅λ‹ˆλ‹€. μ΄λŸ¬ν•œ 접근은 μ½”λ“œμ˜ 가독성, μœ μ§€ λ³΄μˆ˜μ„±μ„ ν–₯μƒμ‹œμΌ°μŠ΅λ‹ˆλ‹€. λ˜ν•œ μ‹€μ‹œκ°„ μƒνƒœ μ—…λ°μ΄νŠΈμ™€ 데이터 캐싱 κΈ°λŠ₯을 톡해 μ‚¬μš©μžμ—κ²Œ λ”μš± λΉ λ₯΄λ©΄μ„œλ„ λΆ€λ“œλŸ¬μš΄ 응닡을 μ œκ³΅ν•  수 있게 λ˜μ—ˆμœΌλ―€λ‘œ μ‚¬μš©μž κ²½ν—˜μ„ ν–₯μƒμ‹œμΌ°μŠ΅λ‹ˆλ‹€.


2. μŠ΅κ΄€ νžˆμŠ€ν† λ¦¬ μ €μž₯을 μœ„ν•œ ν…Œμ΄λΈ” 섀계

1) 데이터 λ³΄κ΄€μ˜ ν•„μš”μ„±

μŠ΅κ΄€ 곡유 ν”Œλž«νΌμ„ κ°œλ°œν•˜λ©΄μ„œ λ°œκ²¬ν•œ ν•œκ°€μ§€ λ¬Έμ œμ μ€ ν˜„μž¬ λ‚ μ§œμ— ν•΄λ‹Ήν•˜λŠ” μŠ΅κ΄€λ“€λ§Œ μœ μ €μ—κ²Œ λ³΄μ—¬μ§€κ²Œ λ˜μ–΄ μžˆμ–΄ 이전에 ν–‰ν–ˆλ˜ μŠ΅κ΄€ 기둝을 ν™•μΈν•˜κΈ° μ–΄λ ΅λ‹€λŠ” κ²ƒμ΄μ—ˆμŠ΅λ‹ˆλ‹€. μœ μ €κ°€ κΎΈμ€€νžˆ ν•΄μ˜¨ μŠ΅κ΄€μ„ ν™•μΈν•˜κΈ° μœ„ν•΄μ„œ 이전 기둝 μ €μž₯은 저희 ν”„λ‘œμ νŠΈμ— λ°˜λ“œμ‹œ ν•„μš”ν•œ κΈ°λŠ₯μ΄μ—ˆμŠ΅λ‹ˆλ‹€.

2) μŠ΅κ΄€ νžˆμŠ€ν† λ¦¬ ν…Œμ΄λΈ” μ„€κ³„μ˜ 고렀사항

λ”°λΌμ„œ 이미 μ§„ν–‰ν•œ μŠ΅κ΄€ 내역을 μ €μž₯ν•˜λŠ” ν…Œμ΄λΈ”μ΄ ν•„μš”ν–ˆμŠ΅λ‹ˆλ‹€. λ‹€λ§Œ λ‹€λ₯Έ μž‘μ—…μ— 영ν–₯을 μ£Όλ©΄ μ•ˆλ˜μ—ˆκΈ°μ— 배치λ₯Ό 톡해 μ²˜λ¦¬ν•  ν•„μš”κ°€ μžˆμ—ˆμŠ΅λ‹ˆλ‹€. 그리고 μŠ΅κ΄€μ˜ νžˆμŠ€ν† λ¦¬ λ°μ΄ν„°λŠ” κ³„μ†ν•΄μ„œ μŒ“μ΄κ²Œ λ˜λ―€λ‘œ 데이터 쑰회 μ‹œ 응닡 속도 μ΅œμ ν™”μ—λ„ 주의λ₯Ό κΈ°μšΈμ—¬μ•Ό ν–ˆμŠ΅λ‹ˆλ‹€.

3) 초기 진행 λ°©ν–₯κ³Ό 문제점, ν•΄κ²° 방법

μ΄ˆκΈ°μ—λŠ” 쑰회의 μš©μ΄ν•¨μ„ μœ„ν•΄ ν•˜λ£¨μ— ν•œλ²ˆ λ‚ μ§œλ³„, μœ μ €λ³„λ‘œ ν•œλ²ˆμ— 데이터λ₯Ό λͺ¨μ•„μ„œ μ €μž₯ν•˜λŠ” 방식을 μƒκ°ν–ˆμŠ΅λ‹ˆλ‹€.

문제점
1. λ‚ μ§œλ₯Ό κΈ°μ€€μœΌλ‘œ μœ μ € λ³„λ‘œ μ €μž₯ν•˜λ©΄ 쑰회 μ‹œ λΉ λ₯΄κ³  κ°„νŽΈν•˜κ²Œ μ‘°νšŒν•  수 μžˆλ‹€λŠ” μž₯점이 μžˆμ§€λ§Œ mongodb document의 μ œμ•½μƒ 15mb μ΄ν•˜λ‘œλ§Œ μ €μž₯ν•  수 μžˆμ—ˆμŠ΅λ‹ˆλ‹€. 계산해 λ³΄λ‹ˆ ν•˜λ£¨ μœ μ € 1λͺ…이 평균 5개의 μŠ΅κ΄€μ„ ν•œλ‹€λŠ” κ°€μ • ν•˜μ— λŒ€λž΅ 3천λͺ…λΆ„λ§Œ μ €μž₯ν•  수 μžˆμ—ˆμŠ΅λ‹ˆλ‹€. μ΄λŠ” λ§Žμ€ μœ μ €κ°€ μ‚¬μš©ν•΄μ•Όν•˜λŠ” μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ— μ•…μ˜ν–₯을 주기에 데이터λ₯Ό ν•˜λ‚˜λ‘œ λ¬ΆκΈ°λŠ” μ–΄λ €μ› μŠ΅λ‹ˆλ‹€.
2. μŠ΅κ΄€λ“€μ„ μ €μž₯ν•˜λ €κ³  ν• λ•Œ 아직 λλ‚˜μ§€ μ•Šμ€ μŠ΅κ΄€μ΄ μžˆλ‹€λ©΄ 이 μŠ΅κ΄€μ„ 기둝해두기가 μ–΄λ €μ› μŠ΅λ‹ˆλ‹€. μ„œλ²„ μ„±λŠ₯에 영ν–₯을 주지 μ•ŠκΈ° μœ„ν•΄ μƒˆλ²½μ— ν•˜λ €κ³  해도 μƒˆλ²½μ— μˆ˜ν–‰ν•˜λŠ” μŠ΅κ΄€μ΄ μžˆλŠ” 경우 배치 μ‹œκ°„λ³΄λ‹€ 뒀에 μ’…λ£Œλ  μš°λ €κ°€ μžˆμ—ˆμŠ΅λ‹ˆλ‹€.
ν•΄κ²° 방법
각각의 μŠ΅κ΄€λ§ˆλ‹€ λ‚ μ§œμ™€ μœ μ € idλ₯Ό 컬럼으둜 κ°–λŠ” document둜 μ €μž₯ν•˜λŠ” 방식을 μ‚¬μš©ν–ˆμŠ΅λ‹ˆλ‹€.
const mongoose = require('mongoose');
const HabitSchema = require('./Habit').schema;

const HabitHistorySchema = new mongoose.Schema(
  {
    date: {
      type: String,
      required: true,
      validate: {
        validator(v) {
          return /^(\d{4})-(\d{2})-(\d{2})$/.test(v);
        },
        message: 'Invalid date format',
      },
    },
    userId: {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'User',
      required: true,
    },
    habitId: {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'Habit',
      required: true,
    },
    habitDetails: HabitSchema,
  },
  {
    timestamps: true,
  },
);

module.exports = mongoose.model('HabitHistory', HabitHistorySchema);

4) 섀계 κ²°κ³Ό

κ·Έ κ²°κ³Ό μœ μ €κ°€ 이전에 ν–‰ν–ˆλ˜ μŠ΅κ΄€μ˜ κ²°κ³Όλ₯Ό λ³΄μ—¬μ£ΌλŠ” μ£Όκ°„ μŠ΅κ΄€ νŽ˜μ΄μ§€μ—μ„œ μœ μ €μ˜ 이전 기둝을 κ°€μ Έμ˜¬ 수 있게 λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 그리고 mongodb의 document μš©λŸ‰ μ œν•œ 초과 문제 ν•΄κ²°. μ–΄λ–€ μ‹œκ°„μ— 배치λ₯Ό μˆ˜ν–‰ν•΄λ„ μ •μƒμ μœΌλ‘œ 데이터λ₯Ό μ €μž₯ν•  수 μžˆμ—ˆμŠ΅λ‹ˆλ‹€. 쑰회 μ‹œμ˜ μ„±λŠ₯ λ¬Έμ œλŠ” 인덱슀둜 쿼리 νŠœλ‹μ„ ν•˜μ—¬ λ³΄μ™„ν•˜μ˜€μŠ΅λ‹ˆλ‹€.


3. μ‹€μ‹œκ°„ μ•Œλ¦Ό

1) μ‹€μ‹œκ°„ μ•Œλ¦Όμ˜ μ€‘μš”μ„±κ³Ό ν•„μš”μ„±

ν”„λ‘œμ νŠΈμ˜ 핡심 κΈ°λŠ₯ 쀑 ν•˜λ‚˜λŠ” μ‚¬μš©μžκ°€ μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜ λ‚΄μ—μ„œ λ°œμƒν•˜λŠ” λ‹€μ–‘ν•œ μ΄λ²€νŠΈλ“€μ— λŒ€ν•΄ μ‹€μ‹œκ°„μœΌλ‘œ μ•Œλ¦Όμ„ λ°›λŠ” κ²ƒμ΄μ—ˆμŠ΅λ‹ˆλ‹€. 이λ₯Ό 톡해 μ‚¬μš©μžλŠ” μƒˆλ‘œμš΄ κ·Έλ£Ή μ΄ˆλŒ€, μŠ΅κ΄€ 확인 μš”μ²­, μ•Œλ¦Ό 승인 μš”μ²­ λ“±μ˜ 이벀트λ₯Ό μ¦‰κ°μ μœΌλ‘œ μΈμ§€ν•˜κ³  λ°˜μ‘ν•  수 μžˆμ–΄μ•Ό ν–ˆμŠ΅λ‹ˆλ‹€.

2) μ•Œλ¦Ό 전솑 λ°©λ²•μ˜ 선택과 SSE의 λ„μž…

μ‹€μ‹œκ°„ μ•Œλ¦Όμ„ κ΅¬ν˜„ν•˜κΈ° μœ„ν•œ μ—¬λŸ¬ 방법 쀑, Server-Sent Events (SSE)λ₯Ό μ„ νƒν•œ μ΄μœ λŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:

  • κ°„λ‹¨ν•œ κ΅¬ν˜„: SSEλŠ” μ›Ή ν‘œμ€€ κΈ°μˆ λ‘œμ„œ κ΅¬ν˜„μ΄ κ°„λ‹¨ν•˜λ©°, 좔가적인 λΌμ΄λΈŒλŸ¬λ¦¬λ‚˜ ν”„λ ˆμž„μ›Œν¬ 없이도 μ›Ή μ„œλ²„μ™€ λΈŒλΌμš°μ €μ—μ„œ μ§€μ›λ©λ‹ˆλ‹€.
  • μžλ™ μž¬μ—°κ²°: λ§Œμ•½ λ„€νŠΈμ›Œν¬ 문제둜 연결이 λŠμ–΄μ‘Œμ„ λ•Œ, SSEλŠ” μžλ™μœΌλ‘œ μž¬μ—°κ²°ν•˜λŠ” κΈ°λŠ₯을 λ‚΄μž₯ν•˜κ³  μžˆμ–΄, λ³„λ„μ˜ μž¬μ—°κ²° λ‘œμ§μ„ κ΅¬ν˜„ν•  ν•„μš”κ°€ μ—†μ—ˆμŠ΅λ‹ˆλ‹€.
  • 단방ν–₯ ν†΅μ‹ μœΌλ‘œ μΆ©λΆ„νžˆ κ΅¬ν˜„ κ°€λŠ₯ν•˜λ‹€κ³  νŒλ‹¨: ν”„λ‘œμ νŠΈμ—μ„œ ν•„μš”ν•œ μ•Œλ¦Όμ€ λ°›κΈ°λ§Œ ν•˜λ©΄ μ„œλ²„μ—μ„œ λ‹€λ₯Έ μž‘μ—…μ„ 해주지 μ•Šμ•„λ„ λ˜λŠ” κ²ƒμœΌλ‘œ κΈ°νšν–ˆκΈ° λ•Œλ¬Έμ—, 단방ν–₯ 전솑 방법인 SSE둜 μΆ©λΆ„νžˆ κ΅¬ν˜„μ΄ κ°€λŠ₯ν–ˆμŠ΅λ‹ˆλ‹€.

SSE

3) μ‹€μ‹œκ°„ μ•Œλ¦Ό κ΅¬ν˜„ 상세

ν”„λ‘œμ νŠΈμ—μ„œλŠ” initEventSource ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ SSE 연결을 μ΄ˆκΈ°ν™”ν•˜μ˜€κ³ , 연결이 μ„±κ³΅μ μœΌλ‘œ 이루어지면 μ„œλ²„μ—μ„œ ν΄λΌμ΄μ–ΈνŠΈλ‘œ μ•Œλ¦Ό 데이터λ₯Ό μ „μ†‘ν•©λ‹ˆλ‹€. 이λ₯Ό μˆ˜μ‹ ν•œ ν΄λΌμ΄μ–ΈνŠΈλŠ” μ•Œλ¦Ό λ©”μ‹œμ§€λ₯Ό 화면에 ν‘œμ‹œν•˜λ©°, 일정 μ‹œκ°„ ν›„μ—λŠ” μžλ™μœΌλ‘œ μ•Œλ¦Όμ„ ν™”λ©΄μ—μ„œ μ œκ±°ν•©λ‹ˆλ‹€.

4) μ‹€μ‹œκ°„ μ•Œλ¦Ό κΈ°λŠ₯ κ΅¬ν˜„ κ²°κ³Ό

SSEλ₯Ό λ„μž…ν•¨μœΌλ‘œμ¨ μ‚¬μš©μžλŠ” μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ λ°œμƒν•˜λŠ” μ€‘μš”ν•œ μ΄λ²€νŠΈλ“€μ„ μ‹€μ‹œκ°„μœΌλ‘œ 확인할 수 있게 λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 이λ₯Ό 톡해 μ‚¬μš©μžλŠ” ν•„μš”ν•œ μ •λ³΄λ‚˜ μš”μ²­μ„ μ¦‰μ‹œ ν™•μΈν•˜κ³  μ²˜λ¦¬ν•  수 있게 λ˜μ–΄ μ‚¬μš©μž κ²½ν—˜μ˜ ν–₯상을 이룰 수 μžˆμ—ˆμŠ΅λ‹ˆλ‹€.

λ˜ν•œ, μ„œλ²„μ—μ„œ ν΄λΌμ΄μ–ΈνŠΈλ‘œμ˜ μ‹€μ‹œκ°„ 톡신 κ΅¬ν˜„μœΌλ‘œ 인해 ν”„λ‘œμ νŠΈμ˜ 동적인 μƒν˜Έμž‘μš©μ΄ ν™•λŒ€λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

5) SSE의 ν•œκ³„μ™€ μ›Ήμ†ŒμΌ“μ„ μ‚¬μš©ν•˜μ§€ μ•Šμ•„μ„œ 생긴 μ•„μ‰¬μš΄ 점

우리 ν”„λ‘œμ νŠΈμ—μ„œλŠ” SSEλ₯Ό μ‚¬μš©ν•˜μ—¬ μ‹€μ‹œκ°„ μ•Œλ¦Ό κΈ°λŠ₯을 κ΅¬ν˜„ν•˜μ˜€μŠ΅λ‹ˆλ‹€. SSEμ—λŠ” λ‹€μ–‘ν•œ μž₯점이 μžˆμ§€λ§Œ, λ™μ‹œμ— μ›Ήμ†ŒμΌ“μ— λΉ„ν•΄ λͺ‡ 가지 ν•œκ³„μ μ΄ μžˆμŠ΅λ‹ˆλ‹€.

SSE의 ν•œκ³„

  • 단방ν–₯ 톡신: SSEλŠ” μ„œλ²„μ—μ„œ ν΄λΌμ΄μ–ΈνŠΈλ‘œμ˜ 단방ν–₯ ν†΅μ‹ λ§Œ μ§€μ›ν•©λ‹ˆλ‹€. 이둜 인해 ν΄λΌμ΄μ–ΈνŠΈμ—μ„œμ˜ λ™μž‘μ΄ μ„œλ²„μ— μ‹€μ‹œκ°„μœΌλ‘œ 반영되기 μ–΄λ ΅μŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€λ©΄, μ•Œλ¦Όμ—μ„œμ˜ νŠΉμ • μ•‘μ…˜μ„ μ„œλ²„μ— μ¦‰κ°μ μœΌλ‘œ λ°˜μ˜ν•˜λŠ” 것이 μ–΄λ ΅μŠ΅λ‹ˆλ‹€.

  • 지속적 μ—°κ²° μœ μ§€: λ§Žμ€ μ‚¬μš©μžκ°€ λ™μ‹œμ— SSE 연결을 μœ μ§€ν•  경우 μ„œλ²„μ— λΆ€ν•˜κ°€ μ¦κ°€ν•˜κ²Œ λ©λ‹ˆλ‹€. ν˜„μž¬ μ—°κ²°λœ μœ μ € idλ₯Ό λͺ¨λ‘ connection으둜 λͺ¨μ•„놓고 μžˆλŠ”λ° 이 크기가 컀지면 μ„œλ²„ λ‚΄μ—μ„œ λ©”λͺ¨λ¦¬λ₯Ό κ³„μ†ν•΄μ„œ 많이 차지할 수 있기 λ•Œλ¬Έμ— λΆ€ν•˜κ°€ μ¦κ°€ν•˜λŠ” μš”μΈμ΄ λ©λ‹ˆλ‹€.

μ›Ήμ†ŒμΌ“μ˜ μž₯점 및 ν”„λ‘œμ νŠΈμ—μ„œμ˜ 아쉬움

  • μ–‘λ°©ν–₯ 톡신: μ›Ήμ†ŒμΌ“μ€ μ„œλ²„μ™€ ν΄λΌμ΄μ–ΈνŠΈ κ°„μ˜ μ–‘λ°©ν–₯ 톡신을 μ§€μ›ν•©λ‹ˆλ‹€. 이둜 인해 μ•Œλ¦Όμ°½μ˜ μ‹€μ‹œκ°„ κ°±μ‹ κ³Ό 같은 κΈ°λŠ₯을 더 효율적으둜 κ΅¬ν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

  • μ•Œλ¦Όμ°½ μ‹€μ‹œκ°„ κ°±μ‹ : ν”„λ‘œμ νŠΈμ—μ„œλŠ” λ¦¬μ•‘νŠΈ 쿼리λ₯Ό μ‚¬μš©ν•˜μ—¬ 10μ΄ˆλ§ˆλ‹€ μ•Œλ¦Όμ„ μ‘°νšŒν•˜λŠ” 방식을 μ±„νƒν•˜μ˜€μŠ΅λ‹ˆλ‹€. μ›Ήμ†ŒμΌ“μ„ μ‚¬μš©ν–ˆλ‹€λ©΄, μ„œλ²„μ—μ„œ μ‹ κ·œ μ•Œλ¦Ό λ°œμƒ μ‹œ ν΄λΌμ΄μ–ΈνŠΈμ— μ¦‰μ‹œ μ „μ†‘ν•˜μ—¬ μ•Œλ¦Όμ°½μ„ μ‹€μ‹œκ°„μœΌλ‘œ κ°±μ‹ ν•˜λŠ” 것이 κ°€λŠ₯ν–ˆμ„ κ²ƒμž…λ‹ˆλ‹€.

  • νš¨μœ¨μ„± 및 λ„€νŠΈμ›Œν¬ μ΅œμ ν™”: μ›Ήμ†ŒμΌ“μ€ 데이터λ₯Ό 전솑할 λ•Œ 헀더가 λΆˆν•„μš”ν•˜μ—¬, λ„€νŠΈμ›Œν¬μ˜ μ˜€λ²„ν—€λ“œκ°€ μ μŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ, μ‹€μ œλ‘œ μ•Œλ¦Όμ΄ λ°œμƒν–ˆμ„ λ•Œλ§Œ 데이터λ₯Ό μ „μ†‘ν•˜κ²Œ λ˜μ–΄ λ„€νŠΈμ›Œν¬ λ¦¬μ†ŒμŠ€λ₯Ό 보닀 효율적으둜 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

  • ν™•μž₯μ„±: μ›Ήμ†ŒμΌ“μ€ λ‹€μ–‘ν•œ μ‹€μ‹œκ°„ κΈ°λŠ₯에 λŒ€ν•œ ν™•μž₯성이 λ†’μŠ΅λ‹ˆλ‹€. ν”„λ‘œμ νŠΈμ˜ λ°œμ „μ— 따라 λ‹€μ–‘ν•œ μ‹€μ‹œκ°„ μƒν˜Έμž‘μš© κΈ°λŠ₯을 μΆ”κ°€ν•  λ•Œ, μ›Ήμ†ŒμΌ“μ˜ μ–‘λ°©ν–₯ 톡신 λŠ₯λ ₯을 ν™œμš©ν•˜λ©΄ 보닀 효과적으둜 κ΅¬ν˜„ν•  수 μžˆμ—ˆμ„ κ²ƒμž…λ‹ˆλ‹€.

결둠적으둜, SSEλŠ” ν˜„μž¬ 저희 ν”„λ‘œμ νŠΈμ—μ„œ ν•„μš”ν•œ κΈ°λŠ₯을 λΉ λ₯΄κ³  κ°„νŽΈν•˜κ²Œ κ΅¬ν˜„ν•˜λŠ” λ°μ—λŠ” μΆ©λΆ„ν•˜μ˜€μŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ 미래의 ν”„λ‘œμ νŠΈ ν™•μž₯성을 κ³ λ €ν•œλ‹€λ©΄, μ›Ήμ†ŒμΌ“μ€ λ§Žμ€ κΈ°λŠ₯을 보닀 효과적으둜 κ΅¬ν˜„ν•  수 μžˆλŠ” κ°•λ ₯ν•œ λ„κ΅¬λ‘œ μž‘μš©ν•  것 κ°™μŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ, λ‹€μŒ λ‹¨κ³„μ˜ κ°œλ°œμ—μ„œλŠ” μ›Ήμ†ŒμΌ“μ˜ λ„μž… 및 ν™œμš©μ„ κ³ λ €ν•΄λ³Ό ν•„μš”κ°€ μžˆλ‹€κ³  μƒκ°λ©λ‹ˆλ‹€. 이λ₯Ό 톡해 μ‚¬μš©μž κ²½ν—˜μ„ λ”μš± ν–₯μƒμ‹œν‚€κ³ , ν”„λ‘œμ νŠΈμ˜ 기술적 ν•œκ³„λ₯Ό λ„“νž 수 μžˆμ„ κ²ƒμœΌλ‘œ κΈ°λŒ€λ©λ‹ˆλ‹€.


4. 둜그인 κ³Όμ •μ—μ„œμ˜ λ³΄μ•ˆ 고렀사항

1) μ‚¬μš©μžμ˜ 데이터λ₯Ό μ•ˆμ „ν•˜κ²Œ μ €μž₯

μ™“μ²˜ν•΄λΉ—μ—μ„œλŠ” λ‘œκ·ΈμΈμ„ 톡해 μ‚¬μš©μžμ˜ 데이터λ₯Ό μ„œλ²„μ— μ•ˆμ „ν•˜κ²Œ μ €μž₯ν•˜λ©°, μ–΄λŠ κΈ°κΈ°μ—μ„œλ‚˜ μ–Έμ œλ“  μ ‘κ·Όν•  수 μžˆλ„λ‘ JWT 토큰 기반의 λ‘œκ·ΈμΈμ„ κ΅¬ν˜„ν–ˆμŠ΅λ‹ˆλ‹€. μ΄λ•Œ μ£Όμš” 고렀사항은 ν΄λΌμ΄μ–ΈνŠΈ μΈ‘μ—μ„œ 토큰을 μ–΄λ–»κ²Œ μ•ˆμ „ν•˜κ²Œ μ €μž₯ν•˜λ©°, ν† ν°μ˜ κ°±μ‹ κ³Ό 만료 처리λ₯Ό μ–΄λ–»κ²Œ 진행할 κ²ƒμΈμ§€μ˜€μŠ΅λ‹ˆλ‹€.

2) μ‚¬μš©μžμ˜ 데이터 관리λ₯Ό ν† ν°μœΌλ‘œ 선택

  1. XSS κ³΅κ²©μœΌλ‘œλΆ€ν„° λ³΄ν˜Έν•  수 μžˆλŠ” 토큰 μ €μž₯ 방법
  2. μ‚¬μš©μžμ˜ 토큰이 νƒˆμ·¨λ‹Ήν•˜λŠ” μ•…μš©μ„ λ§‰λŠ” 방법

3) ν† ν°μœΌλ‘œ μ•ˆμ „ν•˜κ²Œ 관리

(a) μ•ˆμ „ν•œ 토큰 μ €μž₯ 방법

  • JavaScript 접근을 μ°¨λ‹¨ν•˜λŠ” HttpOnly μΏ ν‚€ 선택

(b) 토큰 κ°±μ‹  λ©”μ»€λ‹ˆμ¦˜

token

  • μ•‘μ„ΈμŠ€ ν† ν°μ˜ 수λͺ…을 짧게 ν•˜κ³ , λ¦¬ν”„λ ˆμ‹œ 토큰을 μ‚¬μš©ν•˜μ—¬ 만료된 μ•‘μ„ΈμŠ€ 토큰을 μž¬λ°œκΈ‰
    • Axios Interceptorsλ₯Ό ν™œμš©ν•œ 토큰 μž¬λ°œκΈ‰ λ©”μ»€λ‹ˆμ¦˜ Axios의 Interceptors κΈ°λŠ₯을 ν™œμš©ν•˜μ—¬ API 호좜 전에 ν† ν°μ˜ μœ νš¨μ„±μ„ κ²€μ¦ν•˜κ³ , λ§Œμ•½ 토큰이 λ§Œλ£Œλ˜μ—ˆμ„ 경우, λ¦¬ν”„λ ˆμ‹œ 토큰을 톡해 μƒˆλ‘œμš΄ μ•‘μ„ΈμŠ€ 토큰을 λ°›μ•„μ™€μ„œ API ν˜ΈμΆœμ„ μˆ˜ν–‰ν•˜λ„λ‘ κ΅¬ν˜„ν•˜μ˜€μŠ΅λ‹ˆλ‹€.
api.interceptors.response.use(
  (response) => response,
  async (error) => {
    if (error.response.status === 401) {
      const res = await api.post(
        `${process.env.REACT_APP_SERVER_DOMAIN}/api/auth/refreshToken`,
        {},
        { withCredentials: true },
      );

      const newAccessToken = res.data.accessToken;
      api.defaults.headers.common['Authorization'] = `Bearer ${newAccessToken}`;
      error.config.headers['Authorization'] = `Bearer ${newAccessToken}`;

      return api(error.config);
    }
    return Promise.reject(error);
  },
);

(c) λ¦¬ν”„λ ˆμ‹œ 토큰 만료 처리

  • λ¦¬ν”„λ ˆμ‹œ 토큰 만료 μ‹œ μ‚¬μš©μžλ₯Ό 둜그인 νŽ˜μ΄μ§€λ‘œ λ¦¬λ‹€μ΄λ ‰νŠΈ

(d) μΏ ν‚€λ₯Ό μ΄μš©ν•œ 토큰 전달 μ΄μŠˆμ™€ ν•΄κ²°

  • 이슈: λ‘œμ»¬μ—μ„œ μΏ ν‚€λ₯Ό ν†΅ν•œ 토큰 전달 문제 λ°œμƒ
  • ν•΄κ²°: CORS μ„€μ • μˆ˜μ • 및 withCredentials μ˜΅μ…˜ ν™œμ„±ν™”

4) κ΅¬ν˜„ κ²°κ³Ό

쿠킀와 CORS μ„€μ •μ˜ μ€‘μš”μ„±μ„ μΈμ‹ν•˜κ³ , 이λ₯Ό 톡해 ν΄λΌμ΄μ–ΈνŠΈμ™€ μ„œλ²„ κ°„μ˜ λ³΄μ•ˆ 문제λ₯Ό ν•΄κ²°ν•˜μ˜€μŠ΅λ‹ˆλ‹€.


πŸ“… 일정

1μ£Όμ°¨
  • 아이디어 회의
  • 기술 μŠ€νƒ 쑰사 및 μ„ μ •
  • Git μž‘μ—… ν”Œλ‘œμš° κ²°μ •
  • ν˜‘μ—… κ·œμΉ™ 정립
  • Mockup μ œμž‘ 및 λ””μžμΈ 섀계
  • DB μŠ€ν‚€λ§ˆ 섀계
  • API Docs μž‘μ—…
  • 개발 일정 칸반 λ³΄λ“œ μž‘μ„±
  • 개발 초기 μ„ΈνŒ…
2μ£Όμ°¨ ~
  • ν”„λ‘ νŠΈμ—”λ“œ μ›Ή μ‚¬μ΄νŠΈ κ΅¬ν˜„
  • λ°±μ—”λ“œ μ„œλ²„ κ΅¬ν˜„
  • λ¦¬νŒ©ν† λ§ 및 버그 ν”½μŠ€
  • ν…ŒμŠ€νŠΈ μ½”λ“œ μž‘μ„±
  • νŒ€ ν”„λ‘œμ νŠΈ λ°œν‘œ
  • λ¦¬λ“œλ―Έ μž‘μ„±
  • 배포

πŸ› οΈ 기술 μŠ€νƒ

ν”„λ‘ νŠΈμ—”λ“œ

React React Router Dom React Query Redux JWT Decode AWS SDK Axios TailwindCSS ESLint Prettier


λ°±μ—”λ“œ

Node.js Express Express Validator MongoDB AWS SDK Cron jsonwebtoken Server Http Errors ESLint Prettier


πŸ— μ„ΈνŒ… 방법

μ‹œμž‘ν•˜κΈ° 전에, 루트 디렉토리에 .env νŒŒμΌμ„ λ§Œλ“€κ³  μ•„λž˜μ™€ 같이 μ„€μ •ν•΄μ£Όμ„Έμš”.

# ν΄λΌμ΄μ–ΈνŠΈ
REACT_APP_SERVER_DOMAIN=                 # λ°±μ—”λ“œ API μ„œλ²„ μ£Όμ†Œ
REACT_APP_GOOGLE_CLIENT_ID=              # Google OAuth 2.0 인증을 μœ„ν•œ κ°’
REACT_APP_AWS_ACCESS_KEY_ID=             # AWS μ„œλΉ„μŠ€μ— ν”„λ‘œκ·Έλž˜λ° λ°©μ‹μœΌλ‘œ μ•‘μ„ΈμŠ€ν•˜κΈ° μœ„ν•œ κ°’
REACT_APP_AWS_SECRET_ACCESS_KEY=         # AWS μ„œλΉ„μŠ€μ— ν”„λ‘œκ·Έλž˜λ° λ°©μ‹μœΌλ‘œ μ•‘μ„ΈμŠ€ν•˜κΈ° μœ„ν•œ κ°’
REACT_APP_REDIRECT_URI=                  # OAuth 인증 κ³Όμ • 쀑 μ‚¬μš©μžλ₯Ό λ¦¬λ‹€μ΄λ ‰νŠΈμ‹œν‚€λŠ” URI

# μ„œλ²„
MONGODB_URI=                             # MongoDB λ°μ΄ν„°λ² μ΄μŠ€ 연결을 μœ„ν•œ URI
ACCESS_TOKEN_SECRET=                     # JWT 생성 및 검증을 μœ„ν•œ λΉ„λ°€ ν‚€
REFRESH_TOKEN_SECRET=                    # JWT 생성 및 검증을 μœ„ν•œ λΉ„λ°€ ν‚€
CLIENT_DOMAIN=                           # ν”„λ‘ νŠΈμ—”λ“œ ν΄λΌμ΄μ–ΈνŠΈμ˜ 도메인 μ£Όμ†Œλ‚˜ IP μ£Όμ†Œ
AWS_ACCESS_KEY_ID=                       # AWS μ„œλΉ„μŠ€μ— ν”„λ‘œκ·Έλž˜λ° λ°©μ‹μœΌλ‘œ μ•‘μ„ΈμŠ€ν•˜κΈ° μœ„ν•œ κ°’
AWS_SECRET_ACCESS_KEY=                   # AWS μ„œλΉ„μŠ€μ— ν”„λ‘œκ·Έλž˜λ° λ°©μ‹μœΌλ‘œ μ•‘μ„ΈμŠ€ν•˜κΈ° μœ„ν•œ κ°’

πŸ‘₯ νŒ€ 멀버

문의 사항이 μžˆμœΌμ‹œλ‹€λ©΄, μ•„λž˜μ˜ μ΄λ©”μΌλ‘œ μ—°λ½μ£Όμ„Έμš”.


πŸ”— Repository Link


πŸ“Œ 기타 사항

  • λΌμ΄μ„ΌμŠ€

    이 ν”„λ‘œμ νŠΈλŠ” MIT λΌμ΄μ„ΌμŠ€λ₯Ό λ”°λ¦…λ‹ˆλ‹€. 더 μžμ„Έν•œ λ‚΄μš©μ€ LICENSE νŒŒμΌμ„ μ°Έκ³ ν•΄μ£Όμ„Έμš”.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • JavaScript 100.0%