- ๊ฐ์
- ์์ ๊ฐ์ด๋
- ๊ธฐ์ ์คํ
- ์ฃผ์ ๊ธฐ์ ์คํ ์ ์ ํฌ์ธํธ
- ์ฃผ์ ๊ธฐ๋ฅ
- ๋ผ์ฐํ & ์ปดํฌ๋ํธ & ์ํ๊ด๋ฆฌ
- ์ถ๊ฐ ์๊ตฌ ์ฌํญ
- Made by : ์ด๋์ค, ๊น์น์
- Development Period : From Oct 13, 2023 ~
- Github : https://github.com/2-guys-Javascript/travel-web-app
- Web Page : https://two-guys-travel-project.netlify.app/
Requirement
- Node.js 18.16.0
- NPM 9.5.1
Installation
์ฐธ๊ณ ์ฌํญ : ํด๋น ํ๋ก์ ํธ๋ฅผ ๋ก์ปฌ ๊ฐ๋ฐํ๊ฒฝ์์ ์คํ์ํค๊ธฐ ์ํด์๋ api key๋ค์ด ํ์ํฉ๋๋ค. ๋ชฉ๋ก์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
.env file
// ํ์จ ๊ด๋ จ api key
VITE_EXCHANGE_API_KEY=
// ๋ ์จ ๊ด๋ จ api key
VITE_WEATHER_API_KEY=
// firebase ๊ด๋ จ key:
VITE_FIREBASE_API_KEY=
VITE_FIREBASE_AUTH_DOMAIN=
VITE_FIREBASE_PROJECT_ID=
VITE_FIREBASE_STORAGE_BUCKET=
VITE_FIREBASE_MESSAGING_SENDER_ID=
VITE_FIREBASE_APP_ID=
VITE_FIREBASE_MEASUREMENT_ID=
VITE_GOOGLE_API_KEY=
$ git clone https://github.com/2-guys-Javascript/travel-web-app.git
$ cd travel-web-app
$ npm install // ๊ด๋ จ ์์กด์ฑ ํจํค์ง ์ค์น
$ npm run dev // ๊ฐ๋ฐ ํ๊ฒฝ์์์ ์คํ
// ํน์
$ npm run build
$ npm run preview // ๋น๋ ํ ๋ฐฐํฌ ํ๊ฒฝ์์์ ์คํ
- VITE
๊ธฐ์กด์ Create React App์ ๋ฐฉ์์ ์ฌ์ฉํ๋ฉด Webpack ๋ฒ๋ค๋ฌ์ Babel ํธ๋์คํ์ผ๋ฌ๋ฅผ ํตํด ๋น๋ํ๋๋ฐ, VITE๋ฅผ ์ด์ฉํ ๋ฐฉ์์ ESbuild ๋ฑ์ ํ์ฉํ์ฌ ์๋๊ฐ ๋ ๋น ๋ฅด๊ณ ๊ฐ๋ฐ ํ๊ฒฝ์์ ๋น๋ ๊ฒฐ๊ณผ๋ฌผ์ ๋น ๋ฅด๊ฒ ํ์ธํ ์ ์์ด ์ ํํ์ต๋๋ค. - REACT
- FIREBASE
๋ฐฑ์๋ ์๋น์ค์ ๊ตฌ์ถ์ express ํ๋ ์์ํฌ์ mongoDB๋ฅผ ์ด์ฉํ์ฌ ์งํํ ์๋ ์์ต๋๋ค. ํ์ง๋ง ํด๋น ๋ฐฉ์์ ๋ฐ๋ฅด๋ฉด ์ธ์ฆ์ ๊ตฌํํ๊ธฐ ์ํดpassport
๋ชจ๋ ๋ฑ์ ์ด์ฉํ์ฌ ์๊ฐ์ด ์๋์ ์ผ๋ก ๋ ์์๋๋ค๋ ์ , mongoDB์ firebase firestore๊ฐ ๋ชจ๋ noSQL ๊ธฐ๋ฐ์ document ๋ฐฉ์์ด๋ผ ํฐ ์ฐจ์ด๊ฐ ์๋ค๋ ์ ์ ๊ณ ๋ คํ์ฌ firebase๋ฅผ ์ด์ฉํด ๋ฐฑ์๋๋ฅผ ๊ตฌ์ถํ๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค. - NETLIFY
netlify ํธ์คํ ์๋น์ค๋ฅผ ์ด์ฉํ์ฌ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฐฐํฌ๋ฅผ ์งํํ๋ฉด Github ๋ ํฌ์งํ ๋ฆฌ์ ํ๋ก์ ํธ๋ฅผ ์๋์ผ๋ก ๋น๋ํด์ค ์ ์์ ๋ฟ๋ง ์๋๋ผ, ํด๋น ๋ธ๋์น์ ์๋กญ๊ฒ push๋ ๋ณ๊ฒฝ ์ฌํญ๊น์ง ์๋์ผ๋ก ์ ์ฉ๋๋ค๋ ์ ์ ๋งค์ฐ ๋งค๋ ฅ์ ์ผ๋ก ๋ค๊ฐ์์ต๋๋ค. - Google API
google์ Javascript Map๊ณผ places API๋ ๋ณ๊ฐ์ ๋๋ค. ํ์ง๋ง GCP์ ๊ธฐ๋ฅ์ผ๋ก ์ธํด ์ด๋ฅผ ํ๋์ api key๋ก ๊ด๋ฆฌํ๊ธฐ ํธํ๊ณ , ํด๋น ํ๋ซํผ์ ํตํด ์ ์ฝ ์ฌํญ์ ์ ํด์ค ์๋ ์๊ธฐ ๋๋ฌธ์ ๋ณด์์ฑ์ด ๋๋ค๊ณ ํ๋จํ์ต๋๋ค.
- Login & Signup ๐
๋ก๊ทธ์ธ์ ํฌ๊ฒ ๋น๋ฐ๋ฒํธ ์ธ์ฆ ๋ฐฉ์๊ณผ ๊นํ๋ธ ๊ณ์ ์ฐ๋ ๋ฐฉ์์ผ๋ก ์ด๋ฃจ์ด์ ธ ์์ต๋๋ค. ๋ ๋ฐฉ์ ๋ชจ๋ ๋ก๊ทธ์ธ๋ ์ฌ์ฉ์์ ์ ๋ณด๋ฅผ
localStorage
์ ๋ฃ์ด์ฃผ๊ณ , ๊ฐ ํ์ด์ง์ ํด๋นํ๋ ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ ๋ ๋๋ง๋ค useEffect() ํ ์ ํตํด์ ์ด๋ฅผ ๋ถ๋ฌ์ค๋ ๋ฐฉ์์ ํํ์ต๋๋ค => ์ง๋, ๋ ์จ, ํ์จ, ๋ง์ด ํ์ด์ง ํญ ๋ชจ๋ ํ์ ๊ฐ์ (Sign up)์ html form์ input์ผ๋ก๋ถํฐ ์ฌ์ฉ์์๊ฒ ์ด๋ฉ์ผ, ๋น๋ฐ ๋ฒํธ ๊ทธ๋ฆฌ๊ณ ๋๋ค์์ ์ ๋ ฅ ๋ฐ์ firebase authentication์ ๋ฑ๋กํด์ฃผ๋ ๋ฐฉ์์ ์ฌ์ฉํ์ต๋๋ค. ์ด ๊ณผ์ ์์ ๊ฐ ์ ๋ ฅ ํ๋๊ฐ ์ด๋ฉ์ผ์ด ๋ง๋์ง, ๋น๋ฐ๋ฒํธ์ ๊ธธ์ด๊ฐ ์ ๋นํ์ง๋ฅผ ์ ๊ท ํํ์ ๋ฑ์ ์ด์ฉํ์ฌ ๊ฒ์ฆํด์ฃผ์๊ณ , ์ด๋ฏธ ์กด์ฌํ๋ ๊ณ์ ์ธ์ง์ ๋ํ ์ ๋ณด๋ firebase์ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ํตํด ๋ํ๋์ต๋๋ค.
- Map ๐บ๏ธ
์ง๋๋ ๋ก๊ทธ์ธ๋ ์ฌ์ฉ์์ ๊ทธ๋ ์ง ์์ ์ฌ์ฉ์์๊ฒ ๊ฐ๊ฐ ๋ค๋ฅธ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. ์ ์๋ ํ์์ ๊ธฐ๋ฅ์ ์ถ๊ฐ์ ์ผ๋ก ๋ ์ง์ ๋ง๋ ๋ณธ์ธ์ ์ผ์ ์ ์์ฑํ๊ณ ์กฐํํ ์ ์์ผ๋ฉฐ, ํ์๋ ํน์ ์ฅ์์ ๋ํ ๊ฒ์๊ณผ ํด๋น ์ฅ์ ์ฃผ๋ณ์ ๋ช ์(์๋น, ์นดํ)์ ๋ํ ์ ๋ณด๋ฅผ ์ ๊ณตํฉ๋๋ค.
LoginMap
๋ก๊ทธ์ธ๋ ์ฌ์ฉ์๋ ๋ฒํผ์ ๋๋ฌ ์์ ์ ์์น๋ก ์ง๋๋ฅผ ์์น์ํฌ ์ ์์ผ๋ฉฐ, ํน์ ์ง์ ์ ํด๋ฆญํด ์ง๋ ํ๋จ์ ํผ์ ์ฌ์ฉํ์ฌ ์ผ์ ์ ์์ฑํ ์ ์์ต๋๋ค. ๋ํ ์์ ์ด ์์ฑํ ์ผ์ ์ ๋ํ ๋ง์ปค๋ฅผ ํด๋ฆญํ์ฌ ์ฃผ๋ณ์ ๋ช ์ ์ ๋ณด๋ฅผ ์ป์ ์ ์์ต๋๋ค.
NonLoginMap
๋น๋ก๊ทธ์ธ๋ ์ฌ์ฉ์๋ ์ง๋์ ์๋ ์์ฑ ๊ฒ์์ฐฝ์ ํน์ ์ฅ์๋ฅผ ๊ฒ์ํ์ฌ ์ด๋ํ๊ณ , ์ฃผ๋ณ์ ๋ช ์ ์ ๋ณด๋ฅผ ์ป์ ์ ์์ต๋๋ค.
- Weather ๐ฆ๏ธ
์ฌ์ฉ์๋ ๋ ์จ ํญ์์ ํ๊ตญ๊ณผ ์ผ๋ณธ์ ํน์ ๋์์ ๋ํ ๋ฐ์ค๋ฅผ ํด๋ฆญํ์ฌ ์ค๋, ๋ด์ผ, ๋ชจ๋ ์ ๋ํ ๋ ์จ ์ ๋ณด๋ฅผ ์ป์ ์ ์์ต๋๋ค.
- Currency ๐ด
์ฌ์ฉ์๋ ํ์จ ํญ์์ ํด๋ฆญ์ ํตํด ๋น์ผ์ ํ์จ ์ ๋ณด๋ฅผ ์ํ ๊ธฐ์ค, ์ํ ๊ธฐ์ค์ผ๋ก ์ป์ ์ ์์ต๋๋ค.
- Home (url :
/
) - ํ๊ตญ (url :
/korea
)
์ต์ธ๊ณฝ์๋ KrDefaultLayout์ด ๊ฐ์ธ๊ณ ์์ด ์๋จ์๋ ์ ํ๋ฆฌ์ผ์ด์ ํค๋๊ฐ, ํ๋จ์๋ ๊ฐ ํญ์ผ๋ก ์ด๋ํ ์ ์๋ ๋ค๋น๊ฒ์ด์ ๋ฐ๊ฐ ์์นํ๊ณ , ์ธ๋ถ url path์ ๋ฐ๋ผ์ Outlet ์ปดํฌ๋ํธ๊ฐ ๋ฌ๋ผ์ง๋๋ค.
- ์ผ๋ณธ (url :
/japan
)
์ผ๋ณธ ํญ๋ ํ๊ตญ ํญ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ์ต์ธ๊ณฝ์๋ JpDefaultLayout์ด ๊ฐ์ธ๊ณ ์์ด ์๋จ๊ณผ ํ๋จ์ ๊ฐ๊ฐ ์ ํ๋ฆฌ์ผ์ด์ ํค๋์ ๋ค๋น๊ฒ์ด์ ๋ฐ๊ฐ ์์นํฉ๋๋ค. ํ์ง๋ง ์ธ๋ถ Outlet ์ปดํฌ๋ํธ๊ฐ ํ์จ(
Exchange
)์ด ์ถ๊ฐ๋์๋ค๋ ํน์ง์ด ์์ต๋๋ค.
- ํ์ ๊ฐ์
(url :
/signup
) ๊ณผ ๋ก๊ทธ์ธ (url :/login
)
ํด๋น url path๋ง ์์ธ์ ์ผ๋ก ApplicationHeader๋ฅผ ์ด์ฉํ์ง ์๊ณ , ๊ฐ๋ณ์ ์ธ ํค๋๋ฅผ ์ ์ํ์ฌ UI๋ฅผ ๋ ๋๋งํฉ๋๋ค.
- ๋ง์ดํ์ด์ง (url :
/mypage
)
๋ก๊ทธ์ธ๋ ์ฌ์ฉ์์ ๊ณ์ ์ ๋ณด๋ฅผ ๋ณด์ฌ์ฃผ๋ ํญ์ด๋ฏ๋ก ApplicationHeader๋ฅผ ์ฌ์ฉํ๊ณ ๋๋จธ์ง ๋ด์ฉ์ MyPage ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ์ฌ ๋ ๋๋งํฉ๋๋ค.
-
App-Header
-
Home
-
Japan(JapanDefaultLayout)
- Japan
- Jpweather
- Exchange
- JpNavBar
-
Korea(KoreaDefaultLayout)
- Korea
- Krweather
- KrNavBar
- ์ฌ์ฉ์์ ์ผ์ ์ ๋ํ ์ญ์ ๋ฅผ ๋์ด ์์ ๊ธฐ๋ฅ
- localStorage๋ฅผ ์ด์ฉํ ๋ก๊ทธ์ธ ์ ๋ณด ์ ์ฅ์ ๋ณด์์ ์์ฌ์ด ์ ์ด ์์ผ๋ cookie๋ฅผ ์ด์ฉํ ๋ฐฉ์์ผ๋ก ๊ตฌํ
- ๋น๋ก๊ทธ์ธ๋ ์ฌ์ฉ์๋ ํน์ ์ง์ ์ ํด๋ฆญํ๊ณ , ํด๋น ์ฅ์ ์ฃผ๋ฉด์ ๋ช ์ ์ ๋ณด๋ฅผ ๋ณผ ์ ์์ผ๋ฉด ์ข์ ๊ฒ ๊ฐ์
- login๋ ์ฌ์ฉ์๊ฐ ๋ฌด๋จ์ผ๋ก
/login
,/signup
ํ์ด์ง๋ก ์ ๊ทผํ๋ ์ด์ - ๋ง์ด ํ์ด์ง์์ sns ๋ก๊ทธ์ธ๋ ์ฌ์ฉ์๋ ๋๋์ฒด ๋ฌด์จ ๋น๋ฐ ๋ฒํธ ๋ณ๊ฒฝ์ ํ๋ผ๋ ๊ฒ์ธ๊ฐ?
- App ์ปดํฌ๋ํธ์์ ๋ก๊ทธ์ธ, ์ฌ์ฉ์ id, ์ด๋ฆ์ ๋ํ ์ํ๋ฅผ ๊ฐ์ต๋๋ค. ์ ์ญ ์ํ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ๊ด๋ จ hook์ผ๋ก ์ ์ญ ์ํ๋ก ๋ก๊ทธ์ธ ์ฌ๋ถ๋ฅผ ๋์ด์์ ๊ด๋ จ UI๋ฅผ ๋ณด์ฌ์ค ์ ์๊ฒ ์ง๋ง ํ๋ก์ ํธ ๊ตฌ์ฑ์ ์ด์ ๋ฌ๋ฆฌ ํ๊ธฐ ๋๋ฌธ์
header
,footer
,content
๋ฅผ ๊ณตํต์ ์ผ๋ก wrapping ํ๋ App ์ปดํฌ๋ํธ์์ ์ํ๋ฅผ ์ ์ธํ๊ณ , ํน์ ํ์ด์ง์ ์ง์ํ ๋๋ง๋คuseEffect()
ํ ์ ์ด์ฉํด ๋ก์ปฌ ์คํ ๋ฆฌ์ง๋ฅผ ๊ฒ์ฌํฉ๋๋ค.
ํด๋น ํ์ด์ฆ๋ korea์ japan ํญ์ผ๋ก ์ด๋ํ ์ ์๋ ๋งํฌ๊ฐ fadeIn ํจ๊ณผ๋ฅผ ํตํด ๋ํ๋ฉ๋๋ค. ์ด๋ ์ค๊ฐ์ opening
์ด๋ฏธ์ง๊ฐ ํญ์ ๊ฐ๋ฆฌ๋ ํ์์ pointer-events : none
์์ฑ์ผ๋ก ํด์ ์์ผ๋ฒ๋ฆผ
๊ธฐ๋ณธ์ ์ผ๋ก KoreaDefaultLayout
์ด ํ์ ์ธ๋ถ ์ธ๊ทธ๋จผํธ๋ค์ ๊ฐ์ธ๋ฉฐ, ์ด๋ outlet
์ปดํฌ๋ํธ๋ฅผ ํตํด ์ฐจ๋ณํ๋๋ค.
weather
์ธ๋ถ ๊ฒฝ๋ก : ๋ ์จ api๋ฅผ ๋ฐ์์์ ๊ตญ๋ด ๋ ์จ ์ ๋ณด๋ฅผ ๋์ ๋ณ๋ก ๋ ๋๋ง
๊ธฐ๋ณธ์ ์ผ๋ก JapanDefaultLayout
์ด ํ์ ์ธ๋ถ ์ธ๊ทธ๋จผํธ๋ค์ ๊ฐ์ธ๋ฉฐ, ์ด๋ outlet
์ปดํฌ๋ํธ๋ฅผ ํตํด ์ฐจ๋ณํ๋๋ค.
weather
์ธ๋ถ ๊ฒฝ๋ก : ๋ ์จ api๋ฅผ ๋ฐ์์์ ์ผ๋ณธ ๋์ ๋ ์จ ์ ๋ณด๋ฅผ ๋์ ๋ณ๋ก ๋ ๋๋งexchange
์ธ๋ถ ๊ฒฝ๋ก : ํํ, ์ผํ ๊ฐ์ ํ์จ ์ ๋ณด๋ฅผ ๊ฐ๊ฐ ๋ฐ์์์ ์ฌ์ฉ์์๊ฒ ๋ ๋๋งํด์ค๋ค.
ํ์ ๊ฐ์
์ ์ด๋ฉ์ผ๊ณผ ํจ์ค์๋ ๊ธฐ๋ฐ์ ๋ก์ง์ผ๋ก ์งํํ๋ค. sns ๋ฐฉ์์ ๋ฐ๋ก ํ์ ๊ฐ์
์ ์งํํ ํ์๋ ์๊ณ , ๋ฐ๋ก ๋ก๊ทธ์ธ ํ์ด์ง์์ ์๋น์ค ์ด์ฉ์ ์งํํ๋ฉด ๋๋ค.
ํ์ ๊ฐ์
์ ์ ์ฐจ๋ ๋ค์๊ณผ ๊ฐ๋ค.
- ์ฌ์ฉ์๊ฐ form์ ์ด๋ฉ์ผ, ํจ์ค์๋, ์ฌ์ฉํ ๋๋ค์์ ์ ๋ ฅํ๋ค. ์ด๋ ๊ณผ๋ํ ํ์ด์ง ๋ฆฌ๋ ๋๋ง์ ๋ง๊ธฐ ์ํด form์ ์๋ฐฉํฅ ๋ฐ์ธ๋ฉ์ ํ์ง ์๊ณ ๋จ์ง form์ด ์ ์ถ๋ ๋์๋ง ํด๋น ๊ฐ์ ์ฐธ์กฐํ์ฌ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ์งํํ๋ค.
- ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ํต๊ณผํ ์ด๋ฉ์ผ๊ณผ ํจ์ค์๋๋
createUserWithEmailAndPassword
ํจ์๋ฅผ ํตํด credential์ ๊ฐ์ ธ์ค๊ณ ,updateProfile
ํจ์๋ฅผ ํตํด displayName๊น์ง ๋๋ค์์ผ๋ก ๋ฑ๋กํด์ค๋ค. - ์ ์์ ์ด๋ผ๋ฉด ๋ก๊ทธ์ธ ํ์ด์ง๋ก ์ด๋ํ์ฌ ๋ค์ ๊ณผ์ ์ ์งํํ๊ณ , ๊ทธ๋ ์ง ์๋ค๋ฉด ๋ถ์ ๊ธ์จ๋ก ์๋ฌ ๋ฉ์์ง๋ฅผ ๋ณด์ฌ์ค๋ค.
๋ก๊ทธ์ธ์ ๋ก์ง์ Oauth 2.0 ํ๋กํ ์ฝ์ ์น ์๋ฒ์์ ๋ฐ๋ก ๊ตฌํํ๊ธฐ๋ณด๋ค๋, firebase์์ ์ ๊ณตํ๋ API๋ฅผ ์ด์ฉํ๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค.
๋ก๊ทธ์ธ ๋ฐฉ์์ ํฌ๊ฒ facebook, google, gitub, ๊ทธ๋ฆฌ๊ณ ์ด๋ฉ์ผ & ํจ์ค์๋ ๋ฐฉ์์ผ๋ก ๋๋๋๋ฐ, ๊ธฐ๋ณธ ์๋ฆฌ๋ ๋์ผํฉ๋๋ค.
- auth๋ชจ๋๊ณผ ์ธ์ฆ ๊ด๋ จ ์ ๋ณด(์ด๋ฉ์ผ & ํจ์ค์๋ ํน์ sns provider) : ๊ด๋ จ ์ค์ ์ firebaseConfig.js ๋ชจ๋์์ ์์ฑ
- 1์ ๋น๋๊ธฐ ํจ์๋ฅผ async ~ await ๋ฐฉ์์ผ๋ก ์คํํ์ฌ ๋ฆฌํดํ credential์์ uid์ displayName์ ๋ฐ์ ์ํ์ ๋ก์ปฌ ์คํ ๋ฆฌ์ง์ ๋ฐ์ํ๊ธฐ
- 2์ ๊ณผ์ ์์ ์ค๋ฅ๊ฐ ์๋ค๋ฉด ์๋ฌ ํธ๋ค๋ง์ ํ๊ณ , ์ฑ๊ณต์ ์ด๋ผ๋ฉด ๋ฃจํธ ๋๋ฉ ํ์ด์ง๋ก ๋ค๋น๊ฒ์ดํธ