์ฝ๋์บ ํ
https://developer.mozilla.org/ko/docs/Web/HTTP/Overview
HTTP๋โ ๋ ์ปดํจํฐ ๊ฐ(ํ๋ก ํธ <-> ๋ฐฑ์๋)์ ํ ์คํธ ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ณ ๋ฐ๋ ๊ธธ์ด๋ค.
ํด๋ผ์ด์ธํธ(ex: ๋ธ๋ผ์ฐ์ )์ ์๋ฒ๊ฐ HTTP ๋ผ๋ ๊ธธ๋ก ์์ฒญ(request)๊ณผ ์๋ต(response) 2๊ฐ์ง๋ฅผ ์๋ก ์ฃผ๊ณ ๋ฐ์ ์ ์๋ค.
โ HTTP ์์ฒญ(Request)
์น๋ธ๋ผ์ฐ์ ์์ ํํ์ด์ง(Front-end)๊ฐ ์คํ์ค์ด๋ผ๋ฉด, ์์ฑํ ๊ฒ์๋ฌผ
ํ ์คํธ ๋ฐ์ดํฐ
๋ฅผ HTTP๋ฅผ ํตํด Back-end ์ปดํจํฐ๋ก ๋ณด๋ด๊ณ Back-end ์ปดํจํฐ์๊ฒ ์ด ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅ ํด๋ฌ๋ผ๊ณ์์ฒญ
ํ๋ค.
โ HTTP ์๋ต(Response)
์์ฒญ์ ๋ฐ์ Back-end ์ปดํจํฐ๋ ์ฑ๊ณต, ์คํจ ๋ฑ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ
์๋ต
ํ๋ค.
Back-end ์ปดํจํฐ๋ ์๋ตํ ๋ ์๋ต ์ํ์ฝ๋ ๋ผ๋ ๊ฒ๋ ํจ๊ป ๋ณด๋ด์ฃผ๋๋ฐ,
์๋ต ์ํ์ฝ๋๋ 100~ 599๊น์ง์ ์ซ์๋ก ๊ตฌ์ฑ๋์ด ์๋ค.
์์ฃผ ๋ณผ ์ ์๋ ์๋ต ์ํ์ฝ๋๋ ์ฑ๊ณต(200), Front-end ์๋ฌ(400), Back-end ์๋ฌ(500) ๋ฑ์ด ์๋ค.
์๋ฅผ ๋ค์ด, ์์ฒญ์ ์ฑ๊ณตํ์์ผ๋ฉด ์ฑ๊ณต ๋ฉ์์ง์ ์๋ต ์ํ์ฝ๋ 200์ ํจ๊ป ๋ณด๋ด์ฃผ๊ฒ ๋๋ ๊ฒ!
โ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ฐ๋ก ์์ฒญํ๋ฉด ์๋๋ ๊ฑธ๊นโ
๋ณด์ ๋ฐ ๋ฐ์ดํฐ ์ ์ ๋ฑ์ ์ด์ ๋ก Back-end์์ ๊ฒ์ฆ ๊ณผ์ ์ ๊ฑฐ์ณ์ผ ํ๊ธฐ ๋๋ฌธ์, ์๋ฌด๋ ํจ๋ถ๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์์ฒญํ ์ ์๋ค!
โ API๋โ
HTTP ์์ฒญ์ Back-end ์ปดํจํฐ์ ๋ณด๋์๋ ์คํ๋๋ Back-end ๊ธฐ๋ฅ์ด๋ค.
Front-end์์ HTTP๋ผ๋ ๊ธธ์ ํตํด ๊ฒ์๋ฌผ ๋ฐ์ดํฐ๋ฅผ Back-end์ ๋ณด๋ด ์ ์ฅ์ํค๋๋ฐ,
๋ง์ฝ ๊ฒ์๋ฌผ์ด ์๋ ํ๋กํ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ณ ์ถ์ผ๋ฉด ์ด๋ป๊ฒ ํด์ผ ํ ๊นโ
๊ทธ๋ฌ๊ธฐ ์ํด์ ,์ฌ๋ฌ๊ฐ์ HTTP ๋ผ๋ ๊ธธ์ด ์กด์ฌ
ํด์ผ ํ๊ณ , ๊ฐ๊ฐ์ ์์ฒญ๋ง๋ค ๋ด๋น์๊ฐ ํ์ํ๊ฒ ๋๋๋ฐ ์ด ๋ด๋น์๋ฅผAPI
๋ผ๊ณ ๋ถ๋ฅด๋ ๊ฒ์ด๋ค.
API๊ฐ ๊ธฐ๋ฅ์ด๋ผ๋ฉด ๊ธฐ๋ฅ์ ๊ณง ํจ์๊ฐ ์๋๊น โ
API๋ Back-end ๊ฐ๋ฐ์๊ฐ ๋ง๋ ํจ์์ด๋ค! ํจ์๋ ์ธ์์ return ๋ฐ์ดํฐ๊ฐ ์๊ณ , API์ ์์ฒญํ ๋ ๋ณด๋ด๋ ๋ฐ์ดํฐ๊ฐ ๊ณง API ํจ์๋ก ๋ค์ด๊ฐ ์ธ์์ด๋ฉฐ
์๋ต์ผ๋ก ๋ฐ๊ฒ๋๋ ๋ฐ์ดํฐ๊ฐ API ํจ์์ return ๋ฐ์ดํฐ ์ธ ๊ฒ์ด๋ค.
HTTP ํ๋กํ ์ฝ์ ์ฌ์ฉํด ์ธํฐ๋ท์ ์๋ ๋ฐ์ดํฐ๋ฅผ ์์ฒญํ๊ณ , ์ฃผ์(URL, URI)๋ฅผ ํตํด API ์ ์ ๊ทผํ ์ ์๋ค.
API์ ์ข ๋ฅ๋ ํฌ๊ฒrest-API
,graphql-API
2๊ฐ์ง๋ก,
๋ช๊ฐ์ง ์ฐจ์ด์ ์ด ์๋ค.โ rest-API์ graphql์ ์ฐจ์ด์
1. ํจ์ ์ด๋ฆ์ ์ฐจ์ด
2. ์๋ต ๊ฒฐ๊ณผ๋ฌผ์ ์ฐจ์ด
rest-API๋ ์๋ต ๊ฒฐ๊ณผ๋ก back-end ๊ฐ๋ฐ์๊ฐ ๋ง๋ ํจ์์์ ๋ณด๋ด์ฃผ๋ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ผ๋ง ํ๋ค.
๋ฐ๋ฉด์, graphql-API๋ back-end ๊ฐ๋ฐ์๊ฐ ๋ง๋ ํจ์์์ ํ์ํ ๋ฐ์ดํฐ๋ง ๊ณจ๋ผ ๋ฐ์ ์ ์๋ค.
์ด๋ฌํ ์ด์ ๋ก, ๊ฐ API์ ์ ์ก์ ์์ฒญํ๋ ๋ด๋น์๋ ๋ค๋ฅด๋ค.
rest-API์ ์์ฒญํ๋ ์์ฒญ๋ด๋น์๋ axios์ด๊ณ
graphql-API์ ์์ฒญํ๋ ์์ฒญ๋ด๋น์๋ apollo-client์ด๋ค.
(์ฌ๊ธฐ์ ๋งํ๋ ์์ฒญ๋ด๋น์๋ Front-end ์์ ์ค์นํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ค.)
์ด๋ ๋ฏ ๋ด๋น์๊ฐ graphql์ธ์ง rest์ธ์ง์ ๋ฐ๋ผ์ ๋ค๋ฅธ๋ฐ,
rest์ ๊ฒฝ์ฐ ์์ฒญ ์์ ๋ฐฑ์๋๊ฐ ๋ฏธ๋ฆฌ ๋ง๋ค์ด๋๊ณ ์ธํ ํด๋์ผ๋ฉด
๋๋น์์ ์ฐพ์์ ๊ฐ์ฒด๋ก ๋ง๋ค์ด ์๋ตํด์ฃผ๊ธฐ ๋๋ฌธ์,
ํ์ํ ๊ฒ๋ง ์ํ ๋๋ ๋ค๋ฅธ ์ ๋ณด๋ค์ด ํจ๊ป ๋ฌ๋ ค์จ๋ค.
๋ฐ๋ผ์ ์ฉ๋์ด ๋ง์ ๋๋ ค์ง๋ค.
๋ฐ๋ฉด์ graphql์ ์์ฒญ์ ์ ํํ ์ด๋ค ๊ฒ์ด๋ผ๊ณ ํ๋ค๋ฉด ํ์ํ ๋ฐ์ดํฐ๋ง ๊ณจ๋ผ ๋ฐ์ ์ ์๋ ์ฅ์ ์ด ์๊ธฐ ๋๋ฌธ์,
๋ถํ์ํ ๊ฒ๋ค์ ์๋ต๋ฐ์ง ์์ ์ ์์ด ํจ์จ์ ์ธ ํต์ ์ ํ ์ ์๊ฒ ๋๋ค.
ํต์ฌ์, ์ฃผ๋๋๋ก ๋ฐ๋๋ ๊ณจ๋ผ์ ๋ฐ๋๋ ์ด๋ค.
graphql์ํ์ด์ค๋ถ
์์ ๋ฐ์ํ๋ ์๋ง์ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด ํ์ด์ค๋ถ ๊ฐ๋ฐํ์์ ๋ง๋ค์์ผ๋ฉฐ,
facebook, airbnb, github
๋ฑ ์ ๋ช ํ ์ฌ์ดํธ์์ ์ฌ์ฉ์ค์ธ ํต์ ๋ฐฉ๋ฒ์ด๋ค.3. ์ค์นํด์ผ ํ ํ๋ก๊ทธ๋จ์ ์ฐจ์ด
rest-API ์ graphql API๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ ๊ฐ๊ฐ ํ๋ก๊ทธ๋จ์ ์ค์นํด์ผํ๋ค.
์ฌ์ดํธ
ํฌ์คํธ๋งจ
์ค์จ๊ฑฐ
[GRAPHQL-API]์ ์ฅ์
- ์ํ๋ ๋ฐ์ดํฐ๋ง ๊ณจ๋ผ์ ๋ฐ๊ธฐ ๊ฐ๋ฅ
- ๋ชจ๋ ๋ฐ๋ ๊ฒ๋ณด๋ค ์ฉ๋์ด ์์์ ๋น ๋ฆ
- ํ์ด์ค๋ถ, ๊นํ๋ธ, ์์ด๋น์ค๋น ๋ฑ ๊ธ๋ก๋ฒ ์๋น์ค ์ฌ์ฉ
[REST-API]๋ฅผ ์์์ผ๋ง ํ๋ ์ด์
- ๋ง์ ํ์ฌ๊ฐ REST API๋ฅผ ์ฌ์ฉ
- ์ทจ์ ํ ํ์ฌ์์ REST๋ฅผ ์ฌ์ฉํ ์ ์์.
- OPEN-API(= PUBLIC API)์์ ์ผ๋ฐ์ ์ผ๋ก REST๋ฅผ ์ ๊ณต
ex) ์นด์นด์ค๋ก ๋ก๊ทธ์ธํ๊ธฐ ๊ธฐ๋ฅ์ ์นด์นด์ค์์ ์ ๊ณตํด์ฃผ๋ API๋ฅผ ์ฌ์ฉํด์ผํ๋๋ฐ, ์ด๋ฌํ ๊ธฐ๋ฅ๋ค์ ๋๋ถ๋ถ rest-API๋ก ์ ๊ณต๋๊ณ ์๋ค.
โ JSON์ด๋โ
๋ฐฑ์๋์์ ์๋ต์ ๋ฐ์ ๋, ์ฒ์์ ๋ฌธ์์ดํํ์ ๊ฐ์ฒดํํ์ด๋ค -> {""}
ํ์ง๋ง ๊ทธ ๊ฐ์ "ํ ์คํธ"๋ก ๋ฐ์ ์ฃผ๊ณ ๋ฐ์ ์ ์๊ธฐ ๋๋ฌธ์ ๊ฐ์ฒด ์์ฒด๋ก๋ ๋ฐ์ ์๋ ์๋ค.
๋ฐ๋ผ์ ๊ฐ์ฒด๋ฅผ "๋ฌธ์์ด"๋ก ๋ฌถ์ด ์์ ์ ํ ๋ค ๊ฐ์ฒด๋ฅผ ๋ด์ ๋ฌธ์์ด "{""}" ์ ๋ณด๋ด๊ฒ ๋๋๋ฐ
์ด ๋๊ฐ์ฒด๋ฅผ ๋ด์ ๋ฌธ์์ด
์ ๊ฐ์ฒด ํ๊ธฐ๋ฒ ์ด๋ผ๊ณ ํ๋ฉฐ JSON ์ด๋ผ๊ณ ํ๋ค!
๊ทธ ๊ฐ์ฒด๋ฅผ ๋ฐ์ดํฐ์ ์ ์ฅ์ ํ๊ณ ๋ฐ์ดํฐ๋ฅผ ์ถ๋ ฅํ๋ฉด ๊ฐ์ฒด๋ด์ฉ์ด ๋์จ๋ค.
์ฆ, ๋ฐฑ์๋์์ ์๋ต์ ๊ฒฐ๊ณผ๋ฌผ๋ก ๋๊ฒจ์ฃผ๋ ๊ฒ์ด JSON์ด๊ณ ,
๋ฐ์์จ JSON ๋ฐ์ดํฐ๋ ํ๋ก ํธ์์ ๋ฌธ์์ด์ ๋ฒ๊ฒจ ๊ฐ์ฒด๋ก ์ฌ์ฉํ๊ฒ ๋๋ ๊ฒ์ด๋ค.โ JSON์ ํน์ง๊ณผ ์๋ตํค๋
์๋ต์ header์ body๋ถ๋ถ์ผ๋ก ๋๋๊ฒ ๋๋ค.
์๋ต์ผ๋ก ์ฃผ๊ณ ๋ฐ์ JSON์ ์๋ต์ body ๋ถ๋ถ์ด๊ณ ,
header์๋ body์ ๊ด๋ จ๋ ์์ฝ์ ๋ณด๊ฐ ๋ค์ด๊ฐ๊ฒ ๋๋ค.
์ฌ๊ธฐ์ ์์ฝ์ ๋ณด๋ผ ํจ์ ์๋ต์ ๋ณด๋ด๋ ์ฌ์ดํธ๊ฐ ์ด๋์ธ์ง,
๋ฐ๋์ ํํ๋ JSON์ธ์ง ๋ฑ๋ฑ์ ํฌํจํ๊ณ ์๋ค.
์๋ฅผ ๋ค์ด, ์๋ต์ ํธ์ง๋ดํฌ๋ผ๊ณ ์น๋ฉด
ํธ์ง๋ดํฌ๋ (์์ฒญ)ํค๋์ ๋ฐ๋๋ก ๊ตฌ์ฑ๋์ด ์๊ณ
์์ฒญํค๋์ ๋ณด๋ด๋ ์ด๋ ๋ธ๋ผ์ฐ์ , ๋ณด๋ด๋ ํํ๋ ์์ฝํ ๊ฐ์ฒด์.
๋ฐฑ์๋๋ ์์ฒญ์ ๋ํ ์๋ต์ ํ๋ค.
๋ธ๋ผ์ฐ์ ๋ ์ฑ๊ณตํ๋์ง ์คํจํ๋์ง ์์์ผ ํ๋ค.
์ฌ์ดํธ
-> ํ์ง๋ง ๋งค๋ฒ ๋ฐ์๋๋ง๋ค ๋ฌธ์์ด์ ๊ฐ์ฒด๋ก ๋ง๋ค์ด์ค์ผ ํ๋๋ฐ
๊ทธ๊ฑด ๊ท์ฐฎ์ผ๋๊น ์์์ค์ค ์์ฒด์์ ์ฒ๋ฆฌํด์ค.
์ํ๋ ค์ ๋์ค๋ ๋ฌธ์๋ค์ ์ง์ ๋ฐ๊ฟ์ ์ฌ์ฉํด์ผํ๋ค!
๋ฌธ์์ด ์ง์ฐ๋ ๋ช ๋ น์ด Json.parse
โ API์ 4๊ฐ์ง ๋ฐฉ์
- ์๋ก์ด ๊ฒ์
์์ฑํ๋ API
โ CREATE- ๊ธฐ์กด์ ๊ฒ์
์กฐํํ๋ API
โ READ- ๊ธฐ์กด์ ๊ฒ์
์์ ํ๋ API
โ UPDATE- ๊ธฐ์กด์ ๊ฒ์
์ญ์ ํ๋ API
โ DELETE
-> DB๋ฅผ ๋ฐ๊ฟ๊ฒ์ธ์ง ๊ทธ๋๋ก ๋๋๊ฒ์ธ์ง ํ๊ธฐ ์ํด mutation๊ณผ query๋ก ๋๋๊ฒ ๋์์.โ ์ฌ์ฉ๋ฐฉ๋ฒ
โ ํ ๋ ์ ๋ฆฌ
API ๋ช ์ธ์๋
API ์ฌ์ฉ ์ค๋ช ์
๋ก,
ํํ์ด์ง๋ฅผ ๋ง๋ค๊ธฐ ์ , Back-end ๊ฐ๋ฐ์๊ฐ ๋ง๋ค์ด ๋์ API ๊ฐ ๋ช ๊ฐ ์๊ณ ,
์ด๋ป๊ฒ ๊ตฌ์ฑ๋์ด์๋์ง ํ์ธํ๊ธฐ ์ํด ํ์๋ก ํ๋ค.
`API๋ช ์ธ์๋ Back-end ๊ฐ๋ฐ์์๊ฒ ๋ฐ์์ผ ํ๋๋ฐ,
Back-end ๊ฐ๋ฐ์๋ ์์ ์ด ๋ง๋ API๋ฅผ ์ง์ ๋ฌธ์ ํํ๋ก ์์ฑํ๊ฑฐ๋,
swagger ๋ผ๋ ํ๋ก๊ทธ๋จ์ ์ค์นํด์ ๋ง๋ ๋ค.
โ graphQl docs์ ํ์๊ฐ
! ๋ ๋ฌด์กฐ๊ฑด ๋ณด๋ด์ค์ผํ๋ ํ์๊ฐ
[!]๋ ์๋ค๋ฉด ๋ฌด์กฐ๊ฑด ๋ณด๋ด์ค์ผํ๋ ์กฐ๊ฑดํ์๊ฐ
โ Mutation
: ์๋ก์ด data๋ฅผ ๋ง๋ค๋ mutation์ ์ฌ์ฉํ๋ค.
->์์ฑ, ์์ , ์ญ์ , ์กฐํ์ ๋ฐ๋ฅธ ์์ฒญ ๋ช ๋ น์ด๊ฐ ์๋๋ฐ
GRAPHQL์ ์์ฑ, ์์ , ์ญ์ ๋ฅผ ํ๋๋ก ํตํฉํ๋ค.
๊ทธ๋ฌ๊ธฐ์ MUTATION์ ์ ์คํด์ผ ๋๋ค.โ Query
: ๋ฐ์ดํฐ๋ฅผ ์กฐํ ์ query๋ฌธ์ ์ฌ์ฉ
1. HTTP ์๋ต ์ํ์ฝ๋ 404๋ ๋ฌด์์ ์๋ฏธํ๋๊ฐ?
http://yoonbumtae.com/?p=4932
2. HTTP๋ฉ์๋ PUT๊ณผ PATCH๋์ ์ฐจ์ด๋?
https://programmer93.tistory.com/39
3. rest-API์ ์ธ๋ํ์นญ, ์ค๋ฒํ์นญ์ด๋?https://ivvve.github.io/2019/07/24/server/graphql/over-under-fetching/
https://stackoverflow.com/questions/44564905/what-is-over-fetching-or-under-fetching
JSX
// import { Header } from "antd/es/layout/layout"; import { Wrapper, Title, Wrapper_input, Wrapper_info, Name, Input, Password, Wrapper_title, Subtitle, Sub_Input, Wrapper_content, Content, Content_input, Wrapper_address, Address_title, AddressZip, Address_Input, Search_btn, Address, Wrapper_youtube, Youtube_title, Youtube_Input, Wrapper_image, Img_title, UploadBox, UploadBtn, Box, Plus, Text, Wrapper_mainSet, Main_title, Radio, RadioButton, RadioLabel, Wrapper_register, RegisterBtn, Color, } from "./css"; import { useState } from "react"; export default function freeBoardFrom() { const [TheName, setName] = useState(""); const [ThePassword, setPassword] = useState(""); const [TheSubtitle, setSubtitle] = useState(""); const [TheContent, setContent] = useState(""); const [NameError, setNameError] = useState(""); const [PasswordError, setPasswordError] = useState(""); const [SubtitleError, setSubtitleError] = useState(""); const [ContentError, setContentError] = useState(""); function onChangeName(event) { setName(event.target.value); } function onChangePassword(event) { setPassword(event.target.value); } function onChangeSubtitle(event) { setSubtitle(event.target.value); } function onChangeContent(event) { setContent(event.target.value); } function Signup() { //๊ฐ์ ํ๊ธฐ if (TheName === "") { //์ด๋ฆ์ด ๋น๊ฐ์ด๋ผ๋ฉด setNameError("์ด๋ฆ์ ์ ๋ ฅํด์ฃผ์ธ์"); } else { setNameError(""); } if (ThePassword === "") { setPasswordError("๋น๋ฐ๋ฒํธ๋ฅผ ์ ๋ ฅํด์ฃผ์ธ์"); } else { setPasswordError(""); } if (TheSubtitle === "") { setSubtitleError("์ ๋ชฉ์ ์ ๋ ฅํด์ฃผ์ธ์"); } else { setSubtitleError(""); } if (TheContent === "") { setContentError("๋ด์ฉ์ ์ ๋ ฅํด์ฃผ์ธ์"); } else { setContentError(""); } if ( TheName !== "" && ThePassword !== "" && TheSubtitle !== "" && TheContent !== "" ) { alert("๊ฒ์๊ธ์ด ๋ฑ๋ก๋์์ต๋๋ค."); } } return ( <Wrapper> <Title>๊ฒ์๋ฌผ๋ฑ๋ก</Title> <Wrapper_input> <Wrapper_info> <Name>์์ฑ์</Name> <Input type="text" placeholder="์ด๋ฆ์ ์ ์ด์ฃผ์ธ์" onChange={onChangeName} /> <Color>{NameError}</Color> </Wrapper_info> <Wrapper_info> <Password>๋น๋ฐ๋ฒํธ</Password> <Input type="password" placeholder="๋น๋ฐ๋ฒํธ๋ฅผ ์ ๋ ฅํด์ฃผ์ธ์" onChange={onChangePassword} /> <Color>{PasswordError}</Color> </Wrapper_info> </Wrapper_input> <Wrapper_title> <Subtitle>์ ๋ชฉ</Subtitle> <Sub_Input type="text" placeholder="์ ๋ชฉ์ ์์ฑํด์ฃผ์ธ์" onChange={onChangeSubtitle} /> <Color>{SubtitleError}</Color> </Wrapper_title> <Wrapper_content> <Content>๋ด์ฉ</Content> <Content_input type="text" placeholder="์ ๋ชฉ์ ์์ฑํด์ฃผ์ธ์" onChange={onChangeContent} /> <Color>{ContentError}</Color> </Wrapper_content> <Wrapper_address> <Address_title>์ฃผ์</Address_title> <AddressZip> <Address_Input type="text" placeholder="07250"></Address_Input> <Search_btn>์ฐํธ๋ฒํธ ๊ฒ์</Search_btn> </AddressZip> <Address /> <Address /> </Wrapper_address> <Wrapper_youtube> <Youtube_title>์ ํ๋ธ</Youtube_title> <Youtube_Input type="text" placeholder="๋งํฌ๋ฅผ ๋ณต์ฌํด์ฃผ์ธ์." </Youtube_Input> </Wrapper_youtube> <Wrapper_image> <Img_title>์ฌ์ง์ฒจ๋ถ</Img_title> <UploadBox> <UploadBtn> <Box> <Plus>+</Plus> <Text>Upload</Text> </Box> </UploadBtn> <UploadBtn> <Box> <Plus>+</Plus> <Text>Upload</Text> </Box> </UploadBtn> <UploadBtn> <Box> <Plus>+</Plus> <Text>Upload</Text> </Box> </UploadBtn> </UploadBox> </Wrapper_image> <Wrapper_mainSet> <Main_title>๋ฉ์ธ์ค์ </Main_title> <Radio> <RadioButton type="radio" id="youtube" name="radio-button" /> <RadioLabel>์ ํ๋ธ</RadioLabel> <RadioButton type="radio" id="image" name="radio-button" /> <RadioLabel>์ฌ์ง</RadioLabel> </Radio> </Wrapper_mainSet> <Wrapper_register> <RegisterBtn onClick={Signup}>๋ฑ๋กํ๊ธฐ</RegisterBtn> </Wrapper_register> </Wrapper> ); }
CSS
import styled from "@emotion/styled"; export const Wrapper = styled.div` width: 1200px; /* height: 1847px; */ background: #ffffff; box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.2); border: none; display: flex; flex-direction: column; align-items: center; padding-left: 102px; padding-right: 102px; `; export const Title = styled.div` width: 100%; font-style: normal; font-weight: 700; font-size: 36px; text-align: center; color: #000000; padding-top: 60px; padding-bottom: 80px; `; export const Wrapper_input = styled.div` width: 100%; display: flex; flex-direction: row; justify-content: space-between; `; export const Wrapper_info = styled.div` width: calc(50% - 24px); position: relative; `; export const Name = styled.div` font-family: "Noto Sans CJK KR"; font-style: normal; font-weight: 500; font-size: 16px; line-height: 24px; color: #000000; padding-bottom: 16px; `; export const Input = styled.input` width: 100%; height: 52px; background: #ffffff; border: 1px solid #bdbdbd; padding-left: 10px; &::placeholder { color: #c4c4c4; font-size: 16px; line-height: 24px; } `; export const Password = styled.div` font-family: "Noto Sans CJK KR"; font-style: normal; font-weight: 500; font-size: 16px; line-height: 24px; color: #000000; padding-bottom: 16px; `; export const Wrapper_title = styled.div` width: 100%; margin-top: 40px; /* padding-top: 40px; */ display: flex; flex-direction: column; justify-content: center; position: relative; //error `; export const Subtitle = styled.div` font-family: "Noto Sans CJK KR"; font-style: normal; font-weight: 500; font-size: 16px; line-height: 24px; color: #000000; padding-bottom: 16px; `; export const Sub_Input = styled.input` width: 100%; height: 52px; background: #ffffff; border: 1px solid #bdbdbd; padding-left: 10px; &::placeholder { color: #c4c4c4; font-size: 16px; line-height: 24px; } `; export const Wrapper_content = styled.div` width: 100%; /* margin-top:40px; */ padding-top: 40px; display: flex; flex-direction: column; justify-content: center; position: relative; //error `; export const Content = styled.div` font-family: "Noto Sans CJK KR"; font-style: normal; font-weight: 500; font-size: 16px; color: #000000; padding-bottom: 16px; `; export const Content_input = styled.textarea` width: 100%; height: 480px; background: #ffffff; border: 1px solid #bdbdbd; padding-left: 10px; &::placeholder { color: #c4c4c4; font-size: 16px; line-height: 24px; padding-top: 10px; } `; export const Wrapper_address = styled.div` padding-top: 40px; display: flex; flex-direction: column; width: 100%; display: flex; `; export const Address_title = styled.div` font-family: "Noto Sans CJK KR"; font-style: normal; font-weight: 500; font-size: 16px; color: #000000; padding-bottom: 16px; `; export const AddressZip = styled.div` display: flex; flex-direction: row; `; export const Address_Input = styled.input` width: 77px; height: 52px; background: #ffffff; border: 1px solid #bdbdbd; text-align: center; margin-right: 10px; &::placeholder { color: #c4c4c4; font-size: 16px; line-height: 24px; padding-top: 10px; } `; export const Search_btn = styled.button` width: 124px; background: #000000; border: 1px solid #bdbdbd; text-align: center; color: white; `; export const Address = styled.div` width: 100%; height: 52px; background: #ffffff; border: 1px solid #bdbdbd; padding-left: 10px; margin-top: 15px; `; export const Wrapper_youtube = styled.div` width: 100%; padding-top: 40px; display: flex; flex-direction: column; justify-content: center; `; export const Youtube_title = styled.div` font-family: "Noto Sans CJK KR"; font-style: normal; font-weight: 500; font-size: 16px; color: #000000; padding-bottom: 16px; `; export const Youtube_Input = styled.input` width: 100%; height: 52px; background: #ffffff; border: 1px solid #bdbdbd; padding-left: 10px; &::placeholder { color: #c4c4c4; font-size: 16px; line-height: 24px; padding-top: 10px; } `; export const Wrapper_image = styled.div` width: 100%; padding-top: 40px; display: flex; flex-direction: column; justify-content: center; `; export const Img_title = styled.div` font-family: "Noto Sans CJK KR"; font-style: normal; font-weight: 500; font-size: 16px; color: #000000; padding-bottom: 16px; `; export const UploadBox = styled.div` display: flex; flex-direction: row; `; export const UploadBtn = styled.div` display: flex; flex-direction: column; `; export const Box = styled.button` display: flex; flex-direction: column; background-color: black; width: 78px; height: 78px; background-color: #bdbdbd; margin-right: 24px; outline: none; border: none; cursor: pointer; align-items: center; justify-content: center; `; export const Plus = styled.div` font-size: 25px; color: #4f4f4f; font-weight: 500; `; export const Text = styled.div` color: #4f4f4f; `; export const Wrapper_mainSet = styled.div` width: 100%; padding-top: 40px; display: flex; flex-direction: column; justify-content: center; `; export const Main_title = styled.div` font-family: "Noto Sans CJK KR"; font-style: normal; font-weight: 500; font-size: 16px; color: #000000; padding-bottom: 16px; `; export const Radio = styled.div` display: flex; flex-direction: row; border: none; background-color: white; `; export const RadioButton = styled.input` cursor: pointer; `; export const RadioLabel = styled.label` margin-left: 8px; margin-right: 20px; font-weight: 500; cursor: pointer; `; export const Wrapper_register = styled.div` width: 100%; padding-top: 40px; display: flex; flex-direction: column; justify-content: center; align-items: center; `; export const RegisterBtn = styled.button` width: 179px; height: 52px; border: none; font-size: 16px; font-weight: 500; cursor: pointer; background-color: yellow; margin-bottom: 80px; `; export const Color = styled.div` color: red; display: block; position: absolute; top: calc(100% + 6px); `;
Image
- ๋ฑ๋ก,์์ ,์กฐํ,์ญ์ ๋ฅผ ์ํ ๊ฐ API๊ฐ ํ์ํ๋ค
API๋ ํ๋ํ๋์ ๊ธฐ๋ฅ๋ง๋ค ๋ฐ๋ผ๋ค๋๋ ํ์ํ ๋ช ์ธ์์ด๋ค.- ํ์ด์ง๋ ํ๋์ ํฐ ์ปดํฌ๋ํธ๋ผ๋ ๊ฒ ๊ธฐ์ตํ์!
์ด์ ๊ณผ์ ์ค ๋ฏธ์์ฑ ๋ ๋ถ๋ถ์ ์ฝ๋๋ฆฌ๋ทฐ ์๊ฐ์ ํตํด ํด๊ฒฐํ ์ ์์๋ค.
Q. ์์ฑ์์ ๋น๋ฐ๋ฒํธ ์์ญ ์ฌ์ด์ ๊ฐญ์ฒ๋ฆฌ ๋ฐฉ๋ฒ
A. ๋ถ๋ชจ์์์ ๋๋น๋ฅผ 100%๋ก ์ฃผ๊ณ ์์์์๋ค์ ๊ฐ์ผ ์์ญ์
calcํจ์๋ฅผ ์จ์50% - ์ฃผ๊ณ ์ถ์ ๊ฐญ ์ฌ์ด์ฆ
๋ฅผ ์ค์ ํด๊ฒฐ
Q. input์์ญ์ placeholder์ ํจ๋ฉ์ ์ฃผ์๋๋ ์์ญ ๋ฐ์ผ๋ก
์์ ธ๋๊ฐ๋ ํ์์ด ๋ฐ์ํจ.
A. &::placeholder ์ฒ๋ฆฌ๋ฅผ ํด์ค์ input ์์ฒด๊ฐ ์๋,
placeholder์๋ง ์คํ์ผ์ ์ ์ฉํ๋๋ก ํจ.
Q. contents์์ญ์ placeholder๊ฐ ์ค๊ฐ์ ๋จธ๋ฌผ๋ฌ ์๋ ํ์
A. textareaํ๊ทธ๋ก ๋ฐ๊ฟ์ ํด๊ฒฐ.
Q. ๊ฐ ์ธํ์ error๋ฉ์์ง๊ฐ ๋จ๋ฉด ์๋๋ก ๋ฐ๋ฆฌ๋ ํ์
A. error๋ฉ์์ง ์์์๋ display:block; position: absolute;์ ์ฃผ๊ณ ,
์์์์์ position: relative๋ฅผ ์ค์ ํด๊ฒฐ
๋ํ, calc(100% + 6px)ํจ์๋ก ์๋จ์์ 6px๋งํผ ๋จ์ด์ง๋๋ก ์ถ๊ฐํด์ค.
์ดํ ๋์ ์ ์ 7์๊ฐ ์ค๋๋ฐ๋ ๋ถ๊ตฌํ๊ณ ์์นจ์ ๋์ด ๋ฒ์ฉ ๋ ์ก๋ค.
์๋ฉด ์๊ฐ์ด ๋ถ์กฑํด์ ์์ ์๊ฐ์ ํน์ฌ๋ ์กธ์ง ์์๊น ์ถ์์ง๋ง,
๋คํํ ์์ ์ ์ ๋ฐ๋ผ๊ฐ ๊ฒ ๊ฐ๋ค.
CS ๊ณต๋ถ๋ ๋ฌด์ ๊ถ ํด์ผํ๋ค๋ ๊ฒ์ ์๊ธฐ์,
์ฒ์ "HTTP ํต์ " ์ด๋ผ๋ ๋จ์ด๋ฅผ ๋ค์์ ๋
๋๋ ๋ฉํ ๋์ด ๋ง์ํ์ จ๋ ๊ฒ์ฒ๋ผ ๋ญ๊ฐ ๋๊ฒ ์ด๋ ค์ธ ๊ฒ ๊ฐ๊ณ
์์ํด๋ณด๊ธฐ๋ ์ ์ ์กฐ๊ธ ๊ฑฑ์ ๋๋ ๊ฒ์ด ์์๋ค.
์ผ๋ ค์๋ ๋ฌ๋ฆฌ ๋จ์ง ์ฐ๋ฆฌ ๋์ ๋ณด์ฌ์ง๊ธฐ๊น์ง ์ด๋ ํ ๊ณผ์ ์ผ๋ก
์ปดํจํฐ ๊ฐ์ ์ํต์ ํ๋์ง์ ๊ดํ ๋ด์ฉ์ด์๊ณ
ํนํ ํธ์ง๋ดํฌ์ ๋น๋์ด ์๊ฐ์ ํ๋ ์ดํดํ๊ธฐ๊ฐ ๋ ์์ํ๋ค.
ํ๋ฉด ๋ท ๋จ์์๋ ์ด๋ ๊ฒ ์์ ์ด ์ด๋ค์ง๊ณ ์์๊ตฌ๋ ํ๋ ์๊ฐ์
์์ผ ๋ด๊ฐ ํ๋ ค๊ณ ํ๋ ์ผ์ด ๊ฐzl๋๊ฒ ๋๊ปด์ง๋,,ใ ใ
์๋ง ๊ฐ์๋ก ๋ ๋ณต์กํ๊ณ ์ด๋ ค์ด ์ธ๊ณ๊ฐ ํผ์ณ์ง๊ฒ ์ฅ
์ดํด๊ฐ ์๊ฐ๋ฉด ๋ ๋ฒ๋ณด๊ณ ์ธ ๋ฒ๋ณด๊ณ ๋ค์ฏ ๋ฒ๋ ๋ณด๊ณ ํ๋ ์๋ฐ์!
๊ทธ๋ฌ๋ค๋ณด๋ฉด ์ต๋๋ ฅ๋ ์์นํ๊ฒ ์ง,,?
์ธ์ ๊ฐ ํ ๋ฒ ์๋ ค์ฃผ๋ฉด ๋ฐ๋ก ์~ํ๊ณ ์ดํดํ๊ณ ์ ์ฉํ ์ ์๋ ๋ ์ด ์ค๊ธฐ๋ฅผ!!