๋น๊ฑด ํ๋ ์ฌ ์ฝ์ค๋ฉํฑ ๋ธ๋๋ - ๋ฌ์ฌ(LUSH) ์ฌ์ดํธ ํด๋ก .
๐ ์ ํ๋ธ ์์ ๋งํฌ
๐ Front-end Github
๐ Back-end Github
โ๏ธ Front-End : React, SASS, JSX
โ๏ธ Back-End : Django, Python, MySQL, jwt, bcypt, AWS RDS, AWS EC2
โ๏ธ Common : Git, Github, Slack, Trello, Postman
state
์ ๋ฐ๋ฅธ ๊ฐ๊ฒฉ ๋ณํstate
์ ์ํ id๋ฅผ ์ฅ๋ฐ๊ตฌ๋ ๋ฐฑ์๋ API๋ก ์ ์กmap
๋ฉ์๋๋ก ๋๋ฆผ๊ฐ์ธ์ ์ผ๋ก ์ฐ๋ฆฌ ํ์ ์์ฌ์ํต์ด ํ๋ฐํ์๊ณ ํ์ํฌ๊ฐ ์ข์๋ ํ์ด๋ผ๊ณ ์๋ถํ ์ ์๋ค. ๊ธฐ์ ๋ธ๋ก๊ทธ์ ์ฌ์ ์ธ ์น๋ชฉ ํ๋์ ๋ํ ํฌ์คํ ์ ์ง์ํ๋ ํธ์ด์ง๋ง, ์ด๋ฒ ํ๋ก์ ํธ๋ฅผ ํ๋ฉด์ ๊ธฐ์ตํ๊ณ ์ถ์ ๋ด์ฉ๋ค์ด ์๋ ๋ง์๊ธฐ์, ์์ด๋ฒ๋ฆฌ๊ธฐ ์ ์ ์ ~๋ถ ๊ธฐ๋กํ๊ณ ์ ํ๋ค.
๋งค์ผ ์์นจ ์คํ๋ฆฐํธ๋ฅผ ํ๋ฉด์ ๊ฐ์ ์ด๋ ํ์ด์ง๋ฅผ ๊ฐ๋ฐํ๊ณ ์๋์ง, ์ด๋ค ์ํฉ์ ์ด๋ ๋ถ๋ถ์์ ๋งํ๋์ง ๊ณต์ ๋ฅผ ํ์๋ค. ์ ์ฐํ ๋ถ์๊ธฐ ์์์ ๊ณํ์ ์ด๊ณ ํจ์จ์ ์ผ๋ก ๊ฐ๋ฐํ๊ณ ์ถ์ ๋ง์์ด ์์๋ค ๋ณด๋, ๋๊ฐ ์ํค์ง ์์๋๋ฐ๋ ๋ด๊ฐ ์ฃผ๋์ ์ผ๋ก ํธ๋ ๋ก ๊ด๋ฆฌ๋ฅผ ํ๊ฒ ๋์๋ค. (๊ทธ๋ ๊ฒ ์ด์ฉ๋ค ์ ๊ฐ PM์ด ๋์์ต๋๋ค.)
์ด์ ํ์ฌ์์ ํธ๋ ๋ก๋ก ์ผ์ ๊ด๋ฆฌ๋ฅผ ํด ๋ณธ ๊ฒฝํ์ด ์์๋๋ฐ, ์ ๋ฌด์ ์ธ ๋ด์ฉ๋ค๋ง ์นด๋๋ก ์ผ์ผ์ด ๋์ด์ ํด ๋์ผ๋ ๋ด์ฉ์ด ๋จ์กฐ๋ก์ ๋ ๊ธฐ์ต์ด ๋ฌ์๋ค. ์ฐ๋ฆฌ ํ๋ก ํธ์๋ ํ์๋ค์ ํ๋ก์ ํธ์ ๋ํ ๋ถ๋ด๊ฐ์ด ์๋ค๋ ๊ฑธ ์๊ณ ์์๊ธฐ์, ๋๊น์ง ์ผ์ ์ฒดํฌ๋ก ์๋ฐ๊ฐ์ ์ฃผ๊ธฐ ์ซ์๋ค.
๊ทธ๋์ ์ผ์ ์นด๋ ๋ฑ๋ก๊ณผ ๋์์, ์น๋ฐ๊ฐ์ ์ ๋ํ๋ ์น๋ชฉ ํ๋ ์ฌ์ง๊ณผ ํ๋ก ํธ์ ๋ฐฑ์๋์ ์ฒซ ๋ฒ์งธ ํต์ ์บก์ฒ๋ณธ์ ์ฌ๋ ค ํธ๋ ๋ก์ ์ ์ํ ๋๋ง๋ค ๋ณผ ์ ์๊ฒ ํ๋ค. ์ง๊ธ ์๊ฐํ๋ฉด, ์ฌ์ ์ผ๋ก ํ๋ ์์ค์๋ ํธ๋ ๋ก๋ฅผ ๋ณด๋ฉด์ ํ์ํฌ๋ฅผ ๋์๋ ๋ฐฉ๋ฒ์ด ์๋๊น ์ถ๋ค.
๊ฐ์ธ์ ์ผ๋ก ํ๋ก์ ํธ๋ฅผ ํ๋ฉด์ ๊ฐ์ฅ ๊ฐ๋๋ฐ์๊ณ ์ข์๋ ๋ถ๋ถ์ด๋ค.
์ด ๊ธ์ ์ฝ๋ ์ฌ๋ฌ๋ถ๋ ๋ง์ด ๊ฒฝํํ์ ๊ฒ์ด๋ค. ๋ชจ์ฌ ์์ ๋๋ ์ด์ฌํ ์ํตํ๋ค๊ฐ, ๊ฐ์ ๊ท๊ฐ ํ์๋ ์ฐ๋ฝ์ด ๋์ ๋๋ ๊ฒฝํ์...... ๐ญ
๊ทธ๋ฌ๋ ์ฐ๋ฆฌ ํ์๋ถ๋ค์ ๊ท๊ฐ ํ์๋ Slack์ผ๋ก ๊ฐ๋ฐ ์ํฉ์ ๋ํ ์ํต์ ๋ง์ด ํด์ฃผ์ จ๋ค. ๋ชจ๋๊ฐ ๊ฐ์ ํ์ด์ง์ ๋งก์ ๋ฐ์ ์ถฉ์คํ๊ฒ ์ํฉ ๊ณต์ ๋ฅผ ํด์ฃผ์ จ๊ณ , ์ฌ์ง์ด ์๋ฒฝ 2-3์๊น์ง ์ฃผ๋ฌด์์ง ์๊ณ ์ด์ฌํ ๊ฐ๋ฐ์ ํด ์ฃผ์ จ๋ค. ํนํ ๋์ ๊ฐ์ด ์ํ ๊ด๋ จ ๊ฐ๋ฐ์ ๋งก์ ๋ฐฑ์๋ ์นํ๋์ด ๋ฐค ๋ฆ๊ฒ๊น์ง ๊ถ๊ธ์ฆ์ ๋ํด, ํ๋ก ํธ์ ์ ์ฅ์์ ์น์ ํ๊ฒ ์ค๋ช ํด ์ฃผ์ จ๋ ๊ฒ ์ธ์์ด ๋๋ฌด๋๋ ๊น์๋ค. ๋ค์ ํ๋ฒ ๊ฐ์ฌ๋๋ฆฝ๋๋ค. ๐
ํ๋ก ํธ์ ๋ฐฑ์๋์ ์ํต์ ์ค์์ฑ
์์ ์บก์ฒ๋ณธ์๋ ๋์์๋ ๋ด์ฉ์ด์ง๋ง, ํ๋ก ํธ์ ๋ฐฑ์๋๋ ๊ฐ์ ํ๊ตญ์ด๋ฅผ ์ฐ์ง๋ง ์๋ก ๋ฌด์จ ๋ง์ ํ๋์ง ์ดํดํ๊ธฐ ์ฝ์ง ์๋ค. ๋ฌด์จ ์๋๋ก ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ์ด๋ ๊ฒ ์ง์ จ๋์ง, ํ๋ก ํธ ์ ์ฅ์์ ๋ฐฑ์๋์ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ์ด๋ป๊ฒ ์ ๊ทผํด์ผ ํ๋์ง ๋ฑ์ ๋ํ ์ด์ผ๊ธฐ๋ฅผ ๋ง์ด ์ฃผ๊ณ ๋ฐ๋ ๊ฒ์ด ์ค์ํ๋ค. ๊ทธ๋ ๊ธฐ์ ์ํต์๋ง ์ฐ์ธ ์๊ฐ์ด ํ๋ฃจ ์ค 3๋ถ์ 1์ ์ฐจ์งํ์๋ค.
์ฐ๋ฆฌ ํ์ ๊ฐ ์ํต์ ๊ณผ์ ์์๋ ์ ํ ๋ฌธ์ ๊ฐ ์์์ง๋ง, ์ํต์ผ๋ก ์ฐ์ด๋ ์๊ฐ์ด ๋ง์๋ ํฐ๋ผ ์๊ฐ ๋ฐฐ๋ถ์ ๋ํ ๊ณ ๋ฏผ์ ๋ง์ด ํ์๋ค. ์ง๊ธ ์๊ฐํด ๋ณด๋ฉด ํ๋ฐํ ์ํต์ ๊ธด ์๊ฐ์ ํฌ์ํ ๋๋ถ์ ์ฐ๋ฆฌ ํ์ ๋ฐฑ์๋์ ํ๋ก ํธ์ API ์ฐ๊ฒฐ์ด ๋น๊ต์ ๋นจ๋ฆฌ, ์ํํ๊ฒ ์ฐ๊ฒฐ์ด ๋์๋ ๊ฒ ๊ฐ๋ค.
React SASS์ nesting์ ์ค์์ฑ
๋ฆฌ์กํธ๋ SPA์ด๋ค. ํ๋์ ํ์ด์ง๊ฐ ์ฌ๋ฌ ๊ฐ์ง ํ์ด์ง๋ฅผ ๋ณด์ฌ ์ฃผ๋ ํํ์ด๋ค. ๋๋ฌธ์, ๋ค๋ฅธ ํ์์ด ๋ง๋ ํ์ด์ง๊ฐ ๋์ ํ์ด์ง์ ์ํฅ์ ์ค ์ ์์ผ๋ฉฐ ๋ฐ๋๋ก ๋ด๊ฐ ๋ง๋ ํ์ด์ง๊ฐ ๋ค๋ฅธ ํ์์ด ๋ง๋ ํ์ด์ง์ ์ํฅ์ ์ค ์๋ ์๋ค.
ํ์ฌ, sass์์ nesting์ ํ์คํ ํด์ผ ํ๋๋ฐ ๋ ํฌํจ ์ฐ๋ฆฌ ํ๋ก ํธ์๋ ํ์๋ค ๋ชจ๋๊ฐ ๋ฏธ์ณ ์ ๊ฒฝ์ฐ์ง ๋ชปํ๋ค. ๋ ์ด์์์ ์คํ์ผ๋งํ๋ฉด์ "๊ณผ์ฐ ๋ด๊ฐ ์๋ช ํ class๋ช ์ ๋ค๋ฅธ ํ์๋ class๋ช ์ผ๋ก ์ธ๊น?" ๋ผ๊ณ ๊ณ ๋ฏผํ์๋๋ฐ.. ์ญ์๋ ์ฐ๋๋ผ. nesting์ ์ ๊ฒฝ์ ์ฐ์ง ์์๋ค๋ ์ ์ ๋ํด ๋ผ์ ๋ฆฌ๊ฒ ๋ฐ์ฑํ๋ค.
์ด ๋ถ๋ถ์์ ํผ๋๋ฐฑ์ ๋ฐ์ ์ ์ด ์๋ค. ํฐ ํ์ธ Tag์ class๋ช ์ ํ์ค์นผ ์ผ์ด์ค๋ก ์ ์ผ๋๊น, sass์์ nesting์ ํ ๋ ํฐ ํ์ธ Tag์ class๋ช ์ ํฌ๊ฒ ๋ฌถ์ด ์ค์ผ ํ๋ค๋ ์ ์ ๋ช ์ฌํ๊ณ ๋ ๋ช ์ฌํ์. ์ด๋ฒ์ ์ค์๋ฅผ ํด๋ดค์ผ๋ ๋ค์์๋ ์ ๋ ์ค์๋ฅผ ํ์ง ์์ ๊ฒ์ด๋ค.
Github์ ๋ํ ์ํ ๊ธฐ์ต..
๋ด๊ฐ Github์ ์ฝํ๋ค๋ ๊ฒ์ ๋ ์ค์ค๋ก๋ ์๊ณ ์์๋ ํฐ๋ผ, ํ๋ก์ ํธ ์์ ์ ์ฃผ๋ง์ Github ๊ณต๋ถ๋ฅผ ์ด์ฌํ ํ๊ณ ๊ฐ์๋ค. ์ผํ ๊ณต๋ถํ์๋ ๊ฑด์ง ์์ฒญ๋ ์ค์๋ฅผ ํ๊ณ ๋ง์๋ค.
master -> A ๋ธ๋์น ์์ฑ ๋ฐ ์ด๋ -> B ๋ธ๋์น ์์ฑ ๋ฐ ์ด๋ -> C ๋ธ๋์น ์์ฑ ๋ฐ ์ด๋ -> B ๋ธ๋์น ์ด๋ ํ ์์ ์์ -> A ๋ธ๋์น ์ด๋ ํ ์์ ์์ -> C ๋ธ๋์น ์ด๋ ํ ์์ ์์
ํ.. ์ง๊ธ ์๊ฐํด๋ ์ ๋ ํ์ง ๋ง์์ผ ํ ์ค์์๋๋ฐ, ์ฐ๋ฆฌ ํ์๋คํํ ๋๋ฌด ๋ฏธ์ํด์ ์ธ์์ ์ฐธ์๋ ๊ธฐ์ต์ด ๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ฒ์ ํ๋ ์ค์ ๋๋ถ์ ๋ธ๋์น๋ฅผ ํ์ธํ๊ณ ๋ธ๋์น๋ฅผ ์์ฑํ๋ ์ต๊ด์ด ์๊ฒผ๊ณ , ์ ๋ฐ์ ์ธ Github ํ๋ฆ์ ๋ํด ์ดํดํ ์ ์์๋ค.
master์์ branch ์์ฑ ํ ์ด๋
$ git branch <๋ธ๋์น ์ด๋ฆ>
: ๋ธ๋์น ์์ฑ$ git checkout -b <๋ธ๋์น ์ด๋ฆ>
: ๋ธ๋์น ์์ฑ ํ ์ด๋$ git add .
or $ git add <ํ์ผ๋ช
>
$ git commit -m "์ปค๋ฐ ๋ฉ์์ง"
$ git push origin "๋ธ๋์น"
$ git checkout master
$ git pull origin master
์ถฉ๋์ด ์๊ฒผ๋ค๋ฉด, $ git checkout <1๋ฒ์ ๋ธ๋์น>
๋ก ์ด๋ํ์ฌ $ git merge master
๋ช
๋ น์ด ํ ๋ค์ ์ฝ๋ ๋ฎ์ด์์ฐ๊ธฐ
์ถฉ๋์ด ์๋ค๋ฉด, $ git checkout -b <์๋ก์ด ๋ธ๋์น>
๋ก ์ด๋ํ์ฌ $ git merge master
ํ ๋ค์ ์๋ก์ด ์์
์์
๋ํ Git์ ๊ธฐ๋ณธ์ ์ผ๋ก ํ์ผ๋ช or ํด๋๋ช ์ ๋์๋ฌธ์๋ฅผ ๊ตฌ๋ถํ์ง ๋ชปํ๋ค. ๊ทธ๋ฌ๋๊น ๋์๋ฌธ์ ๊ตฌ๋ถ ์ํด์ mergy๋ฅผ ํ๋๋ก ํ์..
๋นํฉ์ค๋ฌ์ ๋ ๋์ error..
์๋ฒฝ์ ์ปดํฌ๋ํธํ๋ฅผ ํ๋ค๊ฐ ๋ณด์๋ ์๋ฌ์ด๋ค. ํํ๊ณ ํด์๊ธฐ๋ก ๋๋ ค๋ด๋.. ํด์๋ ๋ด์ฉ์ ์๋ฌด๋ฆฌ ์ฝ์ด๋ ๋ฌด์จ ๋ง์ธ์ง ๋ชฐ๋ผ์ ์๋ฒฝ์ ๋ ์๊ฐ๋์ ์ด ์๋ฌ๋ฅผ ํด๊ฒฐํ๋๋ผ ์ ๋ ๋ชป ์๊ณ ๊ณ ์ํ๋ ๊ธฐ์ต์ด ๋๋ ทํ๋ค.
์๋ฌ์ ์ด์ ๋ ํฐ๋ฌด๋์์ด ๊ฐ๋จํ๋ค. ๋ถ๋ชจ ์ปดํฌ๋ํธ์์ ์์ ์ปดํฌ๋ํธ๋ฅผ ํธ์ถํ์ผ๋ฉด์, ๋ง์ ์์ ์ปดํฌ๋ํธ์ ์ฝ๋๋ฅผ ๋ค ์ฃผ์์ฒ๋ฆฌ ํ์๊ธฐ ๋๋ฌธ์ ์ด ์๋ฌ๊ฐ ๋ด๋ ๊ฒ์ด๋ค. ์ปดํฌ๋ํธ ๋๋ฌธ์ธ ์ค ๋ชจ๋ฅด๊ณ , ๋ด๊ฐ ์๋ก ๋ง๋ ๋ฉ์๋๊ฐ ์ด๋๊ฐ์์ ๊ผฌ์ธ ๊ฑด ์๋์ง ๊ณ์ ๊ณ ์น๊ณ ๊ณ ์ณค์๋ค. ์ด ์๋ฌ๋ ๋ด ๊ธฐ์ต์ ํ์คํ ๋จ์์ผ๋, ๋ค์์ ์ด ์๋ฌ๊ฐ ๋ค์ ๋ฌ๋ค๋ฉด 1๋ถ๋ง์ ํด๊ฒฐํ ์ ์์ ๊ฒ ๊ฐ๋ค.
ํ์๋ถ๋ค์ ์ค์ ์ฌ์ง์ผ๋ก ํฌํ ๋ฆฌ๋ทฐ ์ฌ์ง์ ๊พธ๋ช์๋ค. ๋ด๊ฐ ๋จผ์ ์ค์ ๋ฌ์ฌ ํฉ์ ํด์ ์ ์นด ์ฌ์ง์ ๋ณด๋ด๊ณ , ํฌํ ๋ฆฌ๋ทฐ๋ก ๊พธ๋ฏธ์๊ณ ์ ์ํ์๋๋ฐ ๋ค๋ค ์ ์พํ๊ณ ํ์พํ ๋ฐ์์ฃผ์ ์ ๋๋ฌด ๊ฐ์ฌํ๋ค. ์ด๋ ์ก์ฒด์ ์ผ๋ก ๋ค๋ค ํผ๊ณคํ์ ํ ๋ฐ, ์ด img ๋ฐ์ดํฐ๋ฅผ ๋ง๋ค๊ณ ๋ง์ถฐ ๋ณด๋ ๊ณผ์ ์์ ์๋ก์ ์ผ๊ตด ์ฌ์ง์ด ๋ณด์ด๋ ๋ค๋ค ๋นต ํฐ์ ธ์ ์์๋ ๊ธฐ์ต์ด ๊น๊ฒ ๋จ๋๋ค.
componentDidMount() {
fetch(`${API.PRODUCT_DETAIL}/${this.props.match.params.id}`)
.then(res => res.json())
.then(productInfo =>
this.setState({
productData: productInfo.product_info,
})
);
}
// ๋ถ๋ชจ(์ํ ์์ธ) ์ปดํฌ๋ํธ์ ์์(ํฌํ ๋ฆฌ๋ทฐ) ์ปดํฌ๋ํธ ํธ์ถ
<span className="photoWrap">
{productData.photo_reviews?.map(imgData => (
<PhotoReviewImg key={imgData.review_id}
imgSrc={imgData.image_url}
imgID={imgData.review_id} />
))}
</span>
[ํฌํ ๋ฆฌ๋ทฐ ๋ชจ์๋ณด๊ธฐ]์ ์์ img ์ฌ์ง์, ์ํ ์์ธ ๋ฐ์ดํฐ API์ ์ํด์์ผ๋ฏ๋ก ๋ถ๋ชจ ์ปดํฌ๋ํธ์์ ํธ์ถํ๋ค.
์์ img ์ฌ์ง์ ํด๋ฆญํ๋ฉด ๋จ๋ ํด๋น ๋ฆฌ๋ทฐ์ ๋ด์ฉ์ ๋ฆฌ๋ทฐ API์ ์ํด์์ผ๋ฏ๋ก, ์์ ์ปดํฌ๋ํธ์์ ํ์
์ฐฝ์ด ์ผ์ง๋ ์์ (ํ์
class state
์ธ imgClick๊ฐ ๋ณ๊ฒฝ๋๋) ๋ฉ์๋ ์์ ๋์์ API๋ฅผ ํธ์ถํด ์ฃผ์๋ค.
// ์์(ํฌํ ๋ฆฌ๋ทฐ) ์ปดํฌ๋ํธ
class PhotoReviewImg extends Component {
constructor() {
super();
this.state = {
closeBtnOFF: false,
imgClick: false,
photo: {},
};
}
reviewImgClick = () => {
const { imgClick } = this.state;
const { imgID } = this.props;
this.setState({
imgClick: !imgClick,
});
fetch(`${API.BASE_URL}/reviews/${imgID}`)
.then(res => res.json())
.then(info =>
this.setState({
photo: info.review_info,
})
);
// ์ฌ์ง IMG ํ์ผ ํด๋ฆญ์, ์ฌ์ง ํ์ผ์ ๋ฐ์์ค๋ API
};
AverageToStars = average => {
const num = Math.floor(average);
switch (num) {
case 1:
return 'โ
';
case 2:
return 'โ
โ
';
case 3:
return 'โ
โ
โ
';
case 4:
return 'โ
โ
โ
โ
';
case 5:
return 'โ
โ
โ
โ
โ
';
default:
return 'โ
โ
โ
โ
โ
';
}
};
render() {
const { imgSrc } = this.props;
const { imgClick, photo } = this.state;
return (
<>
<article className={imgClick ? 'imgPopUpON' : 'imgPopUpOFF'}>
<div className="imgSection">
<img className="photo" alt="photoReview_IMG" src={photo.image} />
</div>
<div className="bottomWrap">
<div className="reviewUserInfo">
<p className="userName">{photo.user_name}</p>
<p className="userStar">{this.AverageToStars(photo.rating)}</p>
</div>
<div className="reviewContentWrap">
<p className="reviewProductName">{photo.product_name}</p>
<div className="reviewProductContent">{photo.content}</div>
<p className="likeCount">
<span className="countNumber">
์ถ์ฒ ์ : {photo.like_count}
</span>
</p>
</div>
</div>
</article>
<img
alt="photoReview_IMG"
className="photoReviewIMG"
src={imgSrc}
onClick={this.reviewImgClick}
/>
</>
);
}
}
export default PhotoReviewImg;
};
์ฆ, ๋ฆฌ๋ทฐ ๊ฒ์๊ธ์ id๋ฅผ ๊ธฐ์ค์ผ๋ก API๋ฅผ ํธ์ถํ์ฌ ๋ฆฌ๋ทฐ ๋ฐ์ดํฐ๋ฅผ state๋ก ๋ฐ์ ํด๋น ๋ฆฌ๋ทฐ์ ๋ด์ฉ์ ๋ณด์ฌ์ฃผ์๋ค.
์ฒ์์๋ ๋ฆฌ๋ทฐ ๊ฒ์๊ธ์ id๊ฐ ์๋ ๊ฐ๊ฐ์ index ๊ฐ์ผ๋ก ์ ๊ทผํด์ผ ํ๋ ๊ตฌ์กฐ๋ก ์ง์ฌ์ ธ ์์ด ์ด๋ป๊ฒ ์ง์ ์ด๋ค ์ ๊ทผํด์ผ ํ ์ง ๊ฐ์ด ์กํ์ง ์์๋ค. ๊ทธ๋ฌ๋ ๋ฐฑ์๋ ๊ตฌ์กฐ๊ฐ ์๋ชป ์ง์ฌ์ ธ ์๋ค๋ ํผ๋๋ฐฑ์ ๋ฐ์ ๋ค, ๋ฐฑ์๋ ๋ถ์ด ์ผ์ฌ์ฒ๋ฆฌ๋ก ๋ฐ๊ฟ์ฃผ์ ๋๋ถ์ ์ฑ๊ณต์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ํธ์ถํ ์ ์์๋ค.
// before API ๊ตฌ์กฐ
{ ...
ReviewID : [1, 2, 3, 4],
Review_img : ["http://~/abc.png", "http://~/cde.png", "http://~/fgsdd.png"],
...
}
// after API ๊ตฌ์กฐ
{ ...
photo_reviews: [{review_id: 7, review_img: "http://~/abc.png"},
{review_id: 6, review_img: "http://~/cde.png"}]
...
}
์ฌ์ฉ์๊ฐ ์ฅ๋ฐ๊ตฌ๋ ๋ฒํผ์ ํด๋ฆญํ๋ฉด, ํด๋น ์ํ์ id์ ์ํ ์๋์ ์ ์ฅํ์ฌ ์ฅ๋ฐ๊ตฌ๋ API๋ฅผ POST๋ก ๋ณด๋ด๋ ๊ณผ์ ์ด๋ค.
goToCart = () => {
const ID = this.state.productData.options[0].option_id;
// ํด๋น ์ํ์ id๋ฅผ goToCart ๋ฉ์๋ ์์์ ๋ณ์๋ก ์ ์ฅํ๋ค.
fetch(`${API.CART}`, {
method: 'POST',
// ํด๋น ์ํ์ ๋ฐฑ์๋ ๋ฐ์ดํฐ๊ตฌ์กฐ์ ์๋ก ์ถ๊ฐํ๋ ๊ณผ์ ์ด๋ฏ๋ก POST
headers: {
Authorization: localStorage.getItem('token'),
},
// ๋ธ๋ผ์ฐ์ localStorage๋ก๋ถํฐ token ๋ฐ์์ค๊ธฐ - token์ ๋ฐ์ ์ฌ๋ = ๋ก๊ทธ์ธํ ํ์์ผ ๋๋ง ์ฅ๋ฐ๊ตฌ๋์ ๋ด์ ์ ์์.
body: JSON.stringify({
option_id: `${ID}`,
quantity: this.state.quantity,
}),
// ์ํ id์ ํ์ฌ ์ํ ์๋์ ๋ฐฑ์๋์ JSONํํ์ฌ ์ ์กํจ.
})
.then(response => response.json())
.then(response => {
alert(
'์ฅ๋ฐ๊ตฌ๋์ ์ฑ๊ณต์ ์ผ๋ก ๋ด๊ฒจ์ก์ต๋๋ค! ์ ์ ํ ํ์ด์ง๊ฐ ์ด๋๋ฉ๋๋ค.'
);
this.props.history.push('/cart');
});
};
์ด๋ fetch ๋ฉ์๋์ ์ต์ํ์ง ์์๋ ํฐ๋ผ ์ํต ์ค ์ดํด๋ฅผ ๋ชปํ ๋ถ๋ถ์ด ์์๋ค. ๋ฐฑ์๋๋ถ์ด ๋ง์ํ์๋ "ํค๋"์ ๋ด๊ฐ ์์๋ฃ๋ "ํค๋"์ ์ ์๊ฐ ๋ฌ๋๊ธฐ ๋๋ฌธ์ด๋ค.
ํค๋์ ํ ํฐ๊ฐ์ ์ ์ฅํด์ผ ํ๋ค๋ ์ฃผ์ ๋ ๋๊ฐ์๋๋ฐ, ๋ฐฑ์๋๋ถ์ด ๋ง์ํ์๋ "ํค๋"๋ fetch ๋ฉ์๋์ headers
์๊ณ , ๋ด๊ฐ ์์๋ค์ "ํค๋"๋ ์ฌ์ดํธ์ <head>
์๋ค. ๊ทธ๋์ "์ฌ์ดํธ์ <head>
์ ํ ํฐ๊ฐ์ ๋ฐ์์ ์ ์งํด์ผ ํ๋ค๊ณ ..?" ์ ๊ฝํ์ ํ๋์ ์ดํด๋ฅผ ๋ชปํ๋ ๊ฒฝํ์ด ์์๋ค. ๋๋ ๋ผ์๊น์ง ํ๋ก ํธ์๋์ธ๊ฐ ๋ณด๋ค. ๐
์ํ ๋ชฉ๋ก ํ์ด์ง์์ ๋์ ๋ผ์ฐํฐ๋ฅผ ์ ์ฉํด์ผ ํ๋ ๋จ๊ณ์๋ค.
componentDidMount()
๋ ํ์ด์ง๊ฐ ๋ก๋๋ ๋ ๋จ ํ ๋ฒ ํธ์ถ๋๋ค. ํ๋,componentDidUpdate()
๋ ํ์ด์ง๊ฐ ๋ก๋๋ ๋๋ง๋ค ๊ณ์ ํธ์ถ๋๋๋ฐ.......
componentDidUpdate(prevProps) {
if (prevProps.match.params.id !== this.props.match.params.id) {
fetch(
`${API.PRODUCT_DETAIL}?category=${this.props.match.params.id}&offset=0&limit=10`
)
.then(res => res.json())
.then(listData =>
this.setState({
headerTitle: listData.category_info,
productsData: listData.products_list,
})
);
}
}
์ฒ์์๋ if ์กฐ๊ฑด๋ฌธ์ ๊ฑธ์ด์ฃผ์ง ์์๋๋, ๋ฐฑ์๋๋ถ์ ๊ฒ์ ํ๋ฉด์ ์์ฒญ๋ log๊ฐ ์ค์๊ฐ์ผ๋ก ๋ฐ์์ ธ์ค๋ ์์ฒญ๋ ๊ฒฝํ์ ํ์๋ค.
๊ทธ ์ด์ ๋ this.setState
๋ฅผ ํ ๋๋ง๋ค ๋ฆฌ๋ ๋๋ง์ด ๋๋๋ฐ, componentDidUpdate
๋ฉ์๋์์ this.setState
๋ฅผ ๊ณ์ ํธ์ถํ๋ componentDidUpdate
๋ ๊ณ์ ํธ์ถ๋๋ ์ํฉ.. ์ฆ, ๋ฌดํ๋ฃจํ์ ๋น ์ง ๊ฒ์ด๋ค.
์ํ ๋ชฉ๋ก ํ์ด์ง์ ์ด์ path ํ๋ผ๋ฏธํฐ์ ํ์ฌ path ํ๋ผ๋ฏธํฐ๊ฐ ๋ค๋ฅด๋ค๋ฉด, ์ฆ ์ด์ ํ์ด์ง์ ํ์ฌ ํ์ด์ง๊ฐ ๋ค๋ฅด๋ค๋ฉด ํ์ฌ ํ์ด์ง์ ์ํ ๋ชฉ๋ก API ๋ฐ์ดํฐ๋ฅผ ํธ์ถํ ์ ์๋๋ก ์ฝ๋๋ฅผ ์งฐ๋ค.
ํ๋ก ํธ์ ๋ฐฑ์๋๊ฐ ์๋ก ํต์ ์ ํ๋ ค๋ฉด ๊ฐ์ ์์ดํ์ด์ ์ ์์ ํด์ผ ํ๋ ์ํฉ์ด์๋ค. ๋ง๊ฐ์ผ์ด ์ผ๋ง ๋จ์ง ์์์ ๋, ๋ฐฑ์๋ ๋ถ๋ค์ด ๋น๊ต์ ๋น ๋ฅด๊ฒ AWS ๋ฐฐํฌ๊น์ง ํด์ฃผ์ ๋๋ถ์ ์ฐ๋ฆฌ ํ๋ก ํธ๊ฐ ๊ท๊ฐ ํ ์๋ฒฝ ๋ด๋ด ํธํ๊ฒ ํต์ ํ๋ฉด์ ์์ ์ ํ ์ ์์๋ค. ์ ๋ฐ์ ์ผ๋ก ๊ฐ๋ฐ ์๋๋ฅผ ๋ฐฐ๋ คํด ์ฃผ์ ์ ๋๋ฌด ๊ฐ์ฌํ๋ ๋ถ๋ค์ด์๋ค. ํ์ํฌ๊ฐ ์ด๋ ๊ฒ๋ ์ค์ํ ๋๋ชฉ์ด์๋์ง ์ฒ์ ๊นจ๋ฌ์๋ค. ํ์๋ค ๋ชจ๋, ์ฌํ์ ๋๊ฐ์๋ ํจ๊ป ๊ฐ๋ฐํ๊ณ ์ถ์ ๋ถ๋ค์ด์๋ค. ๐ค
๊ตฌํํ๊ณ ์ถ์ ๊ธฐ๋ฅ์ ๋ง์๋ฐ ๊ฐ์์ ์๋๊ฐ ๋ฌ๋๋ค. ์ฒ์ ์งํํด ๋ณธ ํ๋ก์ ํธ๋ผ ์ผ์ ์คํ๋ฆฐํธ๋ฅผ ๋ ์ง์ ๋ง์ถฐ์ ์งํํ์ง ๋ชปํ๋๋ฐ, ์ด๋ฒ ๊ธฐํ๋ฅผ ํตํด ๋ด ์๋๋ฅผ ์์์ผ๋ ๋ค์ ํ๋ก์ ํธ ๋๋ ๋ด ์๋์ ๋ง์ถฐ ์ผ์ ๊ด๋ฆฌ๋ฅผ ๋ ์ํ ์ ์์ ๊ฒ ๊ฐ๋ค.
ํ์ ์ค ์ ์ผ ๋์ด๊ฐ ์ด๋ฆฌ๊ณ ์ ์ด์ ๋ฆฌ๋ํ๋ ์ฑ๊ฒฉ์ด ์๋ ํฐ๋ผ, ์ฒ์ ๋งก๋ PM์ด๋ผ๋ ์ญํ ์ด ๋ํํ ๊ณผ๋ถํ๊ณ ๋ถ๋ด์ค๋ฌ์ ๋ค. PM์ด๋ผ๋ ์ญํ ์ด ์ข ๋ฌด๊ฒ๊ฒ ๋๊ปด์ก์๋๋ฐ, ๋ค๋ฅธ ํ์๋ถ๊ป์ ์ธ์ ๋ด๊ฐ์ด์ ํ์ ์ธ ๊ฒ ๊ฐ๋ค๊ณ ๋ง์ํด ์ฃผ์ ๋๋ถ์ ํ์ด ๋ง์ด ๋ฌ์๋ค. ๊ทธ ๊ฒฐ๊ณผ ์ฃผ๋์ ์ผ๋ก ํ์ ์ด๋๊ณ ๊ฐ๋ฐํ ์ ์์๋ ๊ฒ ๊ฐ๋ค. ๊ทธ๋๋ ํ๊ณ ํ ์ ์, ์์ง์ ์ฌ๋๋ค ์์์ ๋ฐํํ๋ ๊ฒ์ด ๋ฏ์ค๋ค๋ ๊ฒ์ด๋ค. ์ฐจ๋ผ๋ฆฌ ๋ง๋ณด๋ค ์ฝ๋๋ก ์ณ์, ์ฝ๋๋ก ๋ณด์ฌ์ฃผ๋ ๊ฒ์ด ํจ์ฌ ์ฌ์ด ๊ฒ ๊ฐ์ง๋ง.. ๊ทธ๋๋ PM์ผ๋ก์จ ๋ฐํ๋ฅผ ๋ฌด๋ ค ์ธ ๋ฒ์ด๋ ํ ์ ์์๋ ๊ฐ์ง ๊ฒฝํ์ ํ๋ค. ํ๋ถ ๋๋ณด๋ค ๋ ๊ฑด๊ฐํ๊ณ , ๋ ์ฑ์ํ๊ฒ ํ๋ก์ ํธ๋ฅผ ๋ง๋ฌด๋ฆฌํ ์ ์์๋ค๋ ์ ์์ ๋ ์์ ์ค์ค๋ก๊ฐ ์ฑ์ฅํ์์ ๋๊ผ๋ค.
ํ์ ์ ์ด๋์ด์ฃผ์ ๋ฏธ์ฐ๋.!
๋๋ถ์ ์ฒซ ํ๋ก์ ํธ๋ฅผ ์ ๋ง๋ฌด๋ฆฌํ๊ณ ๋๋ฌด๋๋ ์ข์๊ธฐ์ต์ผ๋ก ๋จ๊ฒ ํด ์ฃผ์ จ์ด์!
๋ฐฑ์๋์ ์ํต๋ ์ ๊ทน์ ์ผ๋ก ํด์ฃผ์๊ณ , ํ๋ก ํธ์๋์์๋ ์ํต์ ์ ํด์ฃผ์ ์ ์ฑ๊ณต์ ์ผ๋ก ๋ง๋ฌด๋ฆฌ๊ฐ ๋๋ ๊ฒ ๊ฐ์์.
ํญ์ ๊ณ ๋ง์ ๊ณ ์์ผ๋ก๋ ์ํ๋ ๊ฐ๋ฐ์๋ก ์ฑ๊ณตํ์๊ธธ ์์ํ๊ฒ ์ต๋๋ค.
๋ง๋ด์์ ค๋ฏธ์ฐ์ฐ~ ํ์ ์ํ๊ตฌ ์ค์ธ์๐๐๐๐ฅ๐