Skip to content

Last-Survivors-3-8/Watcher-Habit-Server

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

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

Contributors 3

  •  
  •  
  •