๋ค์จ๋ ์จ ๋ฐ๋ก๊ฐ๊ธฐ
Test ID : bc30@naver.com
Test PW : bc12345!
๋ชฉ์ฐจ
'๋ค์จ๋ ์จ'์ ๊ฐ์ ๋๋ค ํน์ ์๋ก ๋ค๋ฅธ ๋๋ค์์ ์๋ก์ด ์ฌ๋๋ค๊ณผ ํจ๊ป ๋ฌ๋ฆฌ๊ฑฐ๋ ์์์ ๊ณต์ ํ ์ ์๋ SNS/์ปค๋ฎค๋ํฐ ์๋น์ค์
๋๋ค.
- ์์ ๋กญ๊ฒ ๋ฐ๋ ๋ ์ง์ ์ฅ์๋ง ๊ฒ์ํ๋ค๋ฉด ๋๊ตฌ๋ ์ง ํจ๊ป ๋ฌ๋ฆด ์ ์์ต๋๋ค.
- ํ๋ก์ํ๋ ์ฌ์ฉ์ ๋ฟ๋ง ์๋๋ผ ์ฌ์ฉ์ ๊ฒ์์ ํตํด ํ๋ก์ํ์ง ์์ ์ฌ์ฉ์์ ์์์ ํ์ธํ ์ ์์ต๋๋ค.
- ๋ด๊ฐ ๋ฌ๋ฆฐ ๊ธฐ๋ก๊ณผ ์ฌ๋๋ค์ ์ด์๋ค์๊ฒ ๊ณต์ ํ ์ ์์ต๋๋ค.
- ์ฌ์ฉ์์ ๊ฒ์๊ธ์ ์ข์์, ๋๊ธ์ ํตํด ํ๋ฐํ๊ฒ ์ํตํ ์ ์์ต๋๋ค.
"
์ฐ๋ฆฌ๋
๊ฐ๋ฐ์๋ก ์ฑ์ฅ์ดํ์ํ๋ค
"๋ผ๋ ์๋ฏธ๋ก
์๋๋ธ๋ผ๋ ํ์ฌ์ ๋์์ ์ป๊ณ
ํจ๊ป
ํ๋ก์ ํธ๋ฅผ ์งํํ๋ฉด์ ์๋ก๊ฐํ์ํ
๋ถ๋ถ์ ์ฑ์์ฃผ๊ธฐ ์ํด
๋ค์๊ณผ ๊ฐ์ ํ๋ช ์ ์ง๊ฒ ๋์์ต๋๋ค.
๐จ UI
- ๋ง์ด ํ๋กํ ํ์ด์ง
- ์ฌ์ฉ์ ํ๋กํ ํ์ด์ง
- ํ ํผ๋ ํ์ด์ง
- ์ง๋ ์์ธ ํ์ด์ง
๐ถ ๊ณตํต ์ปดํฌ๋ํธ
- Button
- Header
- Footer
- Map
- Modal
โจ ๊ธฐ๋ฅ ๊ตฌํ
- ํํผ๋์ ๋ฌดํ ์คํฌ๋กค
- ๋ด ํ๋กํ ๋ฐ ์ฌ์ฉ์ ํ๋กํ
- ์นด์นด์ค ์ง๋ api๋ฅผ ์ด์ฉํ path ๊ทธ๋ฆฌ๊ธฐ
- ๋๊ธ ์์
- ๊ฒ์๊ธ ์ญ์ , ๊ฒ์๊ธ ์์
๐ค ๊ธฐํ
- ํ๋ก์ ํธ ์์ด๋์ด์ ๊ทผ์
- ์ง๋ api ์๋ฃ์กฐ์ฌ
๐จ UI
- ํ๋ก์ ๋ชฉ๋ก ํ์ด์ง
- ํ๋ก์ ๋ชฉ๋ก ํ์ด์ง
- ์ฑํ ํ์ด์ง
- 404 ํ์ด์ง
๐ถ ๊ณตํต ์ปดํฌ๋ํธ
- Follow
- Search
โจ ๊ธฐ๋ฅ ๊ตฌํ
- ํ๋ก์๊ณผ ํ๋ก์ ๋ฆฌ์คํธ
- ์ฑํ ๋ฆฌ์คํธ
- ์ฑํ ๋ฃธ
- ๊ฒ์ debounce๋ฅผ ํตํ ์ฑ๋ฅ ์ต์ ํ
๐ค ๊ธฐํ
- ๋ฐ์ผ๋ฆฌ ์คํฌ๋ผ, ๋ฒ๊ฐ ํ์๋ก ์์ฑ
- ๋ ธ์ ๊ด๋ฆฌ
๐จ UI
- Splash ํ์ด์ง
- ํ์๊ฐ์ ํ์ด์ง
- ๋ก๊ทธ์ธ ํ์ด์ง
- ํ๋กํ ์ค์ ๋ฐ ์์ ํ์ด์ง
๐ถ ๊ณตํต ์ปดํฌ๋ํธ
- Input
- Loading
โจ ๊ธฐ๋ฅ ๊ตฌํ
- ๋ก๊ทธ์ธ, ํ์๊ฐ์ , ํ๋กํ ์ค์ ๋ฐ ์์ ์ ์ ํจ์ฑ ๊ฒ์ฌ
- ์ฐธ์ฌํ๊ธฐ์ ์ฐธ์ฌํ๊ธฐ ์ทจ์
- ๋๊ธ ์์ฑ
- ์ด๋ฏธ์ง ์์ถ์ ํตํ ์ด๋ฏธ์ง ์ต์ ํ
- api ๋ชจ๋ํ ๋ฐ ์นด์นด์ค ์ง๋ api ์ฃผ์๊ฐ์ผ๋ก ๋ณํ
๐ค ๊ธฐํ
- ํ๋ก์ ํธ ๋์์ธ ๊ด๋ฆฌ
- ๊นํ ์ด์ ๋ฐ PR ์ ๋ฆฌ
๐จ UI
- ๊ฒ์ ํ์ด์ง
- ๊ฒ์๋ฌผ ์์ฑ ํ์ด์ง
- ๊ฒ์๋ฌผ ์์ธ ํ์ด์ง
๐ถ ๊ณตํต ์ปดํฌ๋ํธ
- Comment
- Modal
- Alert
โจ ๊ธฐ๋ฅ ๊ตฌํ
- ์ ์ ๊ฒ์
- ๊ฒ์๊ธ ์ ๋ก๋
- ๋๊ธ ์ญ์
- ์ฌ์ฉ์ ํ๋กํ ์ด๋ฏธ์ง ์ ํจ์ฑ ๊ฒ์ฌ
- ๋คํฌ๋ชจ๋ ๊ตฌํ
๐ค ๊ธฐํ
- ๋ฐ์ผ๋ฆฌ ์คํฌ๋ผ, ๋ฒ๊ฐ ํ์ ๋ฆฌ๋
- ํ๋ก์ ํธ ์ผ์ ๊ด๋ฆฌ
- ํ
๐์คํ๋์ฌ | ๐ํ์๊ฐ์ | ๐ํ๋กํ ์ค์ |
---|---|---|
๐๋ก๊ทธ์ธ | ๐ํ ํผ๋ | ๐๊ณ์ ๊ฒ์ |
---|---|---|
๐ํ๋ก์ ํ๋ก์ฐ | ๐404 | ๐์ฑํ |
---|---|---|
- ๊ฒ์๊ธ
๐๊ฒ์๊ธ ์์ฑ | ๐๊ฒ์๊ธ ์์ | ๐๊ฒ์๊ธ ์ญ์ |
---|---|---|
๐๋๊ธ ์์ฑ | ๐๋๊ธ ์ญ์ | ๐๋๊ธ ์ ๊ณ |
---|---|---|
๐๊ฒ์๊ธ ์์ธ | ๐๊ฒ์๊ธ ์ข์์ | ๐๊ฒ์๊ธ ์ข์์ ์ทจ์ |
---|---|---|
- ํ๋กํ
๐๋ด ํ๋กํ | ๐๋ด ํ๋กํ ์์ | ๐์ ์ ํ๋กํ ํ๋ก์ฐ |
---|---|---|
Emoji | Code | ๊ธฐ๋ฅ | Description |
---|---|---|---|
โจ | :sparkles: |
Feat | ์ ๊ธฐ๋ฅ |
โป๏ธ | :recycle: |
Refactor | ์ฝ๋ ๋ฆฌํฉํ ๋ง |
๐ฆ | :wrench: |
Chore | ๋ฆฌ์์ค ์์ /์ญ์ |
๐ | :bug: |
Fix | ๋ฒ๊ทธ ์์ |
๐ | :memo: |
Docs | ๋ฌธ์ ์ถ๊ฐ/์์ |
๐จ | :lipstick: |
Style | UI/์คํ์ผ ํ์ผ ์ถ๊ฐ/์์ |
๐ | :tada: |
Init | ํ๋ก์ ํธ ์์ / Init |
โ | :white_check_mark: |
Test | ํ ์คํธ ์ถ๊ฐ/์์ |
โช | :rewind: |
Rewind | ๋ณ๊ฒฝ ์ฌํญ ๋๋๋ฆฌ๊ธฐ |
๐ | :twisted_rightwards_arrows: |
Merge | ๋ธ๋์น ํฉ๋ณ |
๐ | :card_file_box: |
DB | ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ด๋ จ ์์ |
๐ก | :bulb: |
Comment | ์ฃผ์ ์ถ๊ฐ/์์ |
๐ | :rocket: |
Deploy | ๋ฐฐํฌ |
- ์์ ๋ฐ์ดํ ์ฌ์ฉ
''
์ฌ์ฉ - ์ ์ฒด๋ฅผ ๋ฌถ๋ ์คํ์ผ ์ปดํฌ๋ํธ ๋ช ์ ๋์ container ์ฌ์ฉ
- ์ด๋ฏธ์ง๋ฅผ ๊ฐ์ ธ์ค๋ ์ปดํฌ๋ํธ ๋ช ์ ํ์ค์นผ ํ๊ธฐ๋ฒ ์ฌ์ฉ
- ์ผ์น ์ฐ์ฐ์ ์ฌ์ฉ
{
"extends": ["react-app", "react-app/jest", "prettier"],
"rules": {
"react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
"linebreak-style": 0
}
}
"extends": ["react-app", "react-app/jest", "prettier"]
: ๋ค๋ฅธ ESLint ๊ตฌ์ฑ์ ํ์ฅํ๋ ์ญํ ๋ก, Create React App ํ๋ก์ ํธ์์ ์ ๊ณตํ๋ ๊ธฐ๋ณธ์ ์ธ ๊ท์น์ ์ฌ์ฉํ๊ณ , Jest ๊ด๋ จ ๊ท์น๋ ํจ๊ป ํ์ฅํ๋ฉฐ, ๋ง์ง๋ง์ผ๋ก Prettier์ ๊ด๋ จ๋ ๊ท์น๋ ์ถ๊ฐํฉ๋๋ค."rules": { ... }
****: ESLint์ ๊ท์น์ ์ง์ ํฉ๋๋ค."react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }]
****: ์ด ์ค์ ์ JSX๋ฅผ ์ฌ์ฉํ๋ React ์ปดํฌ๋ํธ ํ์ผ์ ํ์ฅ์๋ฅผ ์ง์ ํ๋ ๊ท์น์ ๋๋ค.[1, { "extensions": [".js", ".jsx"] }]
์ ๊ฒฝ๊ณ ๋ก ์ค์ ๋์ด โ.jsโ ๋๋ โ.jsxโ ํ์ฅ์๊ฐ ์๋ ํ์ผ์์ JSX๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฒฝ๊ณ ๊ฐ ํ์๋ฉ๋๋ค."linebreak-style": 0
: ๊ฐํ ๋ฌธ์ ์คํ์ผ์ ์ง์ ํ๋ ๊ท์น์ ๋๋ค.0
์ผ๋ก ์ค์ ๋์ด ์์ด, ๊ฐํ ๋ฌธ์ ์คํ์ผ์ ๋ํ ๊ฒฝ๊ณ ๋๋ ์ค๋ฅ๋ฅผ ํ์ํ์ง ์์ต๋๋ค.
{
"trailingComma": "es5",
"tabWidth": 2,
"semi": true,
"singleQuote": true
}
"trailingComma"
: ๋ง์ง๋ง ์์ ๋ค์ ์ผํ๋ฅผ ์ถ๊ฐํ ์ง ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํฉ๋๋ค.es5
๊ฐ์ ES5 ๋ฌธ๋ฒ์ ๋ฐ๋ผ ๋ง์ง๋ง ์์ ๋ค์ ์ผํ๋ฅผ ์ถ๊ฐํฉ๋๋ค."tabWidth"
: ํญ ๋ฌธ์์ ๋๋น๋ฅผ ๊ฒฐ์ ํฉ๋๋ค. ๋ค์ฌ์ฐ๊ธฐ์ ํญ ๋์ 2๊ฐ์ ๊ณต๋ฐฑ์ ์ฌ์ฉํฉ๋๋ค."semi"
: ๋ฌธ์ฅ ๋์ ์ธ๋ฏธ์ฝ๋ก ์ ์ถ๊ฐํ ์ง ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํฉ๋๋ค.true
๋ก ์ค์ ๋์ด ์์ผ๋ฏ๋ก, ์ธ๋ฏธ์ฝ๋ก ์ ์ถ๊ฐํฉ๋๋ค."singleQuote"
: ์ด ์ค์ ์ ๋ฌธ์์ด์ ์์ ๋ฐ์ดํ๋ก ๊ฐ์์ง ํฐ ๋ฐ์ดํ๋ก ๊ฐ์์ง ๊ฒฐ์ ํฉ๋๋ค.true
๋ก ์ค์ ๋์ด ์์ผ๋ฏ๋ก, ๋ฌธ์์ด์ ์์ ๋ฐ์ดํ๋ก ๊ฐ์๋๋ค.
- public/favicon/ : ํ๋น์ฝ
- src/assets/ : ์ ์ญ์์ ์ฌ์ฉํ๋ ํฐํธ, ์คํ๋ผ์ดํธ ์ด๋ฏธ์ง, ๋ก๊ณ ์ด๋ฏธ์ง
- src/atoms/ : ์ ์ญ ์ํ ๊ด๋ฆฌ๋ฅผ ์ํ ์ํฐ (UserAtom, LoginAtom)
- src/components/ : ๊ณตํต ์ปดํฌ๋ํธ์ Map ์ปดํฌํธ
- src/pages/ : ์๋น์ค์ ์ฌ์ฉ๋๋ ๊ฐ ํ์ด์ง
- src/routes/ : ํ์ด์ง ๋ผ์ฐํ
- src/styles/ : ์ ์ญ ์คํ์ผ (layout, globalstyle, theme)
๐ฌ๏ธ ๋ค์จ๋ ์จ
๐ฑpublic
โฃ ๐ฟfavicon.ico
โ ๐ฟindex.html
๐ฑsrc
โฃ ๐ฟassets
โ โฃ ๐ชดfonts
โ โฃ ๐ชดimages
โ โ ๐ชดsprite
โฃ ๐ฟatoms
โฃ ๐ฟcomponents
โ โฃ ๐ชดcommon
โ โ โฃ ๐ณAlert
โ โ โฃ ๐ณButton
โ โ โฃ ๐ณComment
โ โ โฃ ๐ณInput
โ โ โฃ ๐ณLoading
โ โ โฃ ๐ณModal
โ โ โ ๐ณUser
โ โ โ โฃ ๐ณFollow
โ โ โ โ ๐ณSearch
โ โฃ ๐ชดFooter
โ โฃ ๐ชดHeader
โ โ ๐ชดMap
โฃ ๐ฟhooks
โฃ ๐ฟpages
โ โฃ ๐ชดChatPage
โ โฃ ๐ชดFeedPage
โ โฃ ๐ชดFollowListPage
โ โฃ ๐ชดLoginPage
โ โฃ ๐ชดNotFoundPage
โ โฃ ๐ชดPostPage
โ โฃ ๐ชดProfilePage
โ โ โฃ ๐ณProfileEdit
โ โฃ ๐ชดProfileSettingPage
โ โฃ ๐ชดSearchPage
โ โฃ ๐ชดSignupPage
โ โฃ ๐ชดSnsLoginPage
โ โฃ ๐ชดSplashPage
โ โ ๐ชดUploadPage
โฃ ๐ฟroutes
โฃ ๐ฟstyles
โฃ ๐ฟutils
โฃ ๐App.js
โ ๐index.js
- ์ผ์: ํ์ผ ์ค์ 9์ (15๋ถ ๋ด์ธ)
- ์ฅ์: [ํ์์ค] ํ๋ก์ ํธ 17์กฐ ๋์ค์ฝ๋ (์นด๋ฉ๋ผOn)
- ๋ด์ฉ: ํ๊ณ ๋ฐ ์์ ๊ณํ
- ๋ํ๋ฐฉ์: ์ ๋ณด ์ ๋ฌ์ด ์๋ ๋ํ ์ฃผ์ ๊ฐ ๊ฐ์ ธ์ค๋ ํจ๊ณผ๋ ํด๊ฒฐ์ฑ ์ ํ ๋ก
Axios๋ฅผ ์ฌ์ฉํ์ฌ API ์์ฒญ์ ์ฒ๋ฆฌํ์ต๋๋ค. ์ด ๋ชจ๋์ API ์์ฒญ์ ๋ณด๋ด๊ธฐ ์ํด ์ฌ๋ฌ๊ฐ์ง ํจ์์ Axios์ ์ธ์คํด์ค๋ฅผ ๋ด๋ณด๋ ๊ฒ์ผ๋ก ๊ตฌ์ฑ๋์ด ์๊ณ ๊ฐ ํจ์๋ ํน์ ํ API์ ๋ํ ์์ฒญ์ ๋ณด๋ด๊ณ ์๋ต์ ์ฒ๋ฆฌํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๋ฐํํฉ๋๋ค.
import axios from 'axios';
const URL = 'https://api.mandarin.weniv.co.kr/';
/* ๊ธฐ๋ณธ ์ธ์คํด์ค */
export const instance = axios.create({
baseURL: URL,
headers: {
'Content-Type': 'application/json',
},
});
/* ์ด๋ฏธ์ง ์ธ์คํด์ค */
export const imgInstance = axios.create({
baseURL: URL,
headers: {
'Content-Type': 'multipart/form-data',
},
});
/* auth ์ธ์คํด์ค */
export const authInstance = axios.create({
baseURL: URL,
headers: {
Authorization: `Bearer ${localStorage.getItem('token')}`,
'Content-Type': 'application/json',
},
});
/* content ์
๋ก๋ */
export const postContentUpload = async (token, post) => {
const response = await authInstance.post(`/post/`, post, {
headers: {
Authorization: `B๋ค
Axios๋ฅผ ์ด์ฉํ์ฌ ๊ฐํธํ๊ฒ API ์์ฒญ์ ๋ณด๋ผ ์ ์์๊ณ ์์ฒญ์ ๋ด๋นํ๋ ์ธ์คํด์ค์ ๊ฐ๊ฐ์ API ์์ฒญ ํจ์๋ฅผ ๋ณ๋๋ก ๊ด๋ฆฌํ ์ ์์์ต๋๋ค. ์์ฒญ์ ํ ๋ ์ฌ์ฉํ๋ ํจ์์ ํ์๋ ํต์ผํ๊ธฐ ๋๋ฌธ์ ์ฝ๋์ ์ผ๊ด์ฑ๊ณผ ๊ฐ๋ ์ฑ์ ๋์ผ ์ ์์๋ค.
์ฌ์ฉ์๋ค์ ์ํด ์์ ์์น์ ์ข ๋ฅ ์์น๋ฅผ ์ป์ด์ค๋ ๊ธฐ๋ฅ, path๋ฅผ ๊ทธ๋ฆฌ๊ณ ๊ทธ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ฃผ์๋ฅผ ๊ฐ์ด ๋ถ๋ฌ์ฌ ์ ์๋๋ก ์ฒ๋ฆฌํ์ต๋๋ค. ์นด์นด์ค ๋งต์ ์ฌ์ฉํ ์ ์๋๋ก ๋์์ฃผ๋ ์นด์นด์ค ์ง๋ API์ React ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ฌ์ฉํ ์ ์๋๋ก ๋์์ฃผ๋ ๋ฆฌ์กํธ ์นด์นด์ค ์ง๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํจ๊ป ์ฌ์ฉํ์ต๋๋ค.
useEffect(() => {
if (data.image) {
try {
const parsing = JSON.parse(data.image);
const startLat = parsing[0].lat;
const startLng = parsing[0].lng;
const geocoder = new window.kakao.maps.services.Geocoder();
const startLatlng = new window.kakao.maps.LatLng(startLat, startLng);
geocoder.coord2Address(
startLatlng.getLng(),
startLatlng.getLat(),
(result, status) => {
if (status === window.kakao.maps.services.Status.OK) {
const startPoint = result[0].address.address_name;
setStartPoint(startPoint);
}
}
);
const endLat = parsing[parsing.length - 2].lat;
const endLng = parsing[parsing.length - 2].lng;
const endLatlng = new window.kakao.maps.LatLng(endLat, endLng);
/* ๋ง์ง๋ง ์์ = ์ด ๊ฑฐ๋ฆฌ */
geocoder.coord2Address(
endLatlng.getLng(),
endLatlng.getLat(),
(result, status) => {
if (status === window.kakao.maps.services.Status.OK) {
const endPoint = result[0].address.address_name;
setEndPoint(endPoint);
}
}
);
} catch (error) {
console.error(error);
}
}
}, [data.image]);
๋ชจ๋๊ฐ ์ง๋ API๋ฅผ ์ฒ์ ์ฌ์ฉํ๋ฉด์ ์๋ก์ด ๊ฒฝํ์ ํ ์ ์์์ต๋๋ค. ๊ธฐ์กด ์นด์นด์ค ์ง๋ API์์ ๋ฐ์์ค๋ ๋ฐ์ดํฐ(์๋, ๊ฒฝ๋)๋ฅผ ์ฌ์ฉ์์๊ฒ ๋ณด์ฌ์ฃผ๊ธฐ ์ํ ๋ฐ์ดํฐ(์ฃผ์ ๊ฐ)๋ก ๋ณํํ๋ ์์ ์ด ํ์ํ๋๋ฐ ์๋ก์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ถ๊ฐํ์ฌ ํด๊ฒฐํ์ต๋๋ค.