์ด ๋ฌธ์๋ ํ๋ก ํธ์๋ ๊ฐ๋ฐ์๊ฐ IsItempty ๋ฐฑ์๋ API์ ์ฐ๋ํ์ฌ ๊ฐ๋ฐํ๋ ๋ฐฉ๋ฒ์ ์๋ดํฉ๋๋ค.
- ๋ฐฑ์๋ API ์ฐ๊ฒฐ ์ ๋ณด
- API ์๋ํฌ์ธํธ
- ์ฃผ์ฐจ์ฅ ๋ฐ์ดํฐ ๋ชจ๋ธ
- API ํ ์คํธ ๋ฐฉ๋ฒ
- ํ๋ก ํธ์๋ ๊ฐ๋ฐ ์ ๊ณ ๋ ค์ฌํญ
- ๋ฐฑ์๋ ๊ฐ๋ฐ ํ๊ฒฝ ์ค์
- ํ๋ก ํธ์๋ ๊ฐ๋ฐ ํ๊ฒฝ ์ค์
- ๋ฌธ์ ํด๊ฒฐ
๋ฐฑ์๋ ์๋ฒ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ค์ URL์์ ์คํ๋ฉ๋๋ค:
http://localhost:8080
ํ์ฌ ์ฌ์ฉ ๊ฐ๋ฅํ API ์๋ํฌ์ธํธ:
| ์๋ํฌ์ธํธ | ๋ฉ์๋ | ์ค๋ช | ์๋ต ์์ |
|---|---|---|---|
/api/hello |
GET | ํ ์คํธ์ฉ API | "Hello, World!" |
/api/parking-lots |
GET | ๋ชจ๋ ์ฃผ์ฐจ์ฅ ๋ชฉ๋ก ์กฐํ | ์ฃผ์ฐจ์ฅ ๊ฐ์ฒด ๋ฐฐ์ด |
/api/parking-lots/{id} |
GET | ํน์ ์ฃผ์ฐจ์ฅ ์กฐํ | ์ฃผ์ฐจ์ฅ ๊ฐ์ฒด |
/api/parking-lots |
POST | ์ ์ฃผ์ฐจ์ฅ ์ถ๊ฐ | ์์ฑ๋ ์ฃผ์ฐจ์ฅ ๊ฐ์ฒด |
/api/parking-lots/{id} |
PUT | ์ฃผ์ฐจ์ฅ ์ ๋ณด ์์ | ์์ ๋ ์ฃผ์ฐจ์ฅ ๊ฐ์ฒด |
/api/parking-lots/{id} |
DELETE | ์ฃผ์ฐจ์ฅ ์ญ์ | ์ํ ์ฝ๋ |
์ฃผ์ฐจ์ฅ ๊ฐ์ฒด์ ๊ตฌ์กฐ:
{
"id": 1,
"name": "๊ฐ๋จ์ญ ์ฃผ์ฐจ์ฅ",
"address": "์์ธ์ ๊ฐ๋จ๊ตฌ ๊ฐ๋จ๋๋ก 396",
"totalSpaces": 200,
"availableSpaces": 120,
"isOpen": true,
"hourlyRate": 3000,
"latitude": 37.498095,
"longitude": 127.027610,
"description": "๊ฐ๋จ์ญ ๊ทผ์ฒ 24์๊ฐ ์ฃผ์ฐจ์ฅ",
"lastUpdated": "2025-04-06T18:30:00"
}- Postman ๋ค์ด๋ก๋ ๋ฐ ์ค์น: https://www.postman.com/downloads/
- ์ ์์ฒญ ์์ฑ ๋ฐ URL ์ค์ (์:
http://localhost:8080/api/parking-lots) - ์์ฒญ ๋ฉ์๋ ์ ํ (GET, POST ๋ฑ)
- POST/PUT ์์ฒญ์ ๊ฒฝ์ฐ Body ํญ์์ JSON ๋ฐ์ดํฐ ์ ๋ ฅ
- Send ๋ฒํผ ํด๋ฆญํ์ฌ ์์ฒญ ์ ์ก
GET http://localhost:8080/api/parking-lotsPOST http://localhost:8080/api/parking-lots
Content-Type: application/json
{
"name": "ํ
์คํธ ์ฃผ์ฐจ์ฅ",
"address": "์์ธ์ ๊ฐ๋จ๊ตฌ",
"totalSpaces": 100,
"isOpen": true,
"hourlyRate": 2000,
"latitude": 37.5665,
"longitude": 126.9780,
"description": "ํ
์คํธ ์ฃผ์ฐจ์ฅ์
๋๋ค."
}๋ฐฑ์๋๋ CORS๋ฅผ ํ์ฉํ๋๋ก ์ค์ ๋์ด ์์ต๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก localhost์์์ ์์ฒญ์ ํ์ฉํฉ๋๋ค.
ํ์ฌ๋ ์ธ์ฆ์ด ๊ตฌํ๋์ด ์์ง ์์ต๋๋ค. ํฅํ JWT ๊ธฐ๋ฐ ์ธ์ฆ์ด ์ถ๊ฐ๋ ์์ ์ ๋๋ค.
์ฃผ์ฐจ์ฅ ๊ฐ์ฉ ๊ณต๊ฐ์ ์ค์๊ฐ์ผ๋ก ๋ณ๊ฒฝ๋ ์ ์์ต๋๋ค. ์ฃผ๊ธฐ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๊ฐฑ์ ํ๋ ๋ก์ง์ ๊ตฌํํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
// ์์: 30์ด๋ง๋ค ์ฃผ์ฐจ์ฅ ๋ฐ์ดํฐ ๊ฐฑ์
setInterval(async () => {
const response = await fetch('http://localhost:8080/api/parking-lots');
const parkingLots = await response.json();
updateParkingLotDisplay(parkingLots);
}, 30000);ํ๋ก ํธ์๋ ๊ฐ๋ฐ์๋ ํ์ํ ๊ฒฝ์ฐ ๋ฐฑ์๋๋ฅผ ๋ก์ปฌ์์ ์คํํ ์ ์์ต๋๋ค:
-
๋ฐฑ์๋ ์ ์ฅ์ ํด๋ก :
git clone https://github.com/isitempty/backend.git cd backend -
SSH ํฐ๋ ์ค์ :
./scripts/setup-ssh-tunnel.sh
-
๋ฐฑ์๋ ์ ํ๋ฆฌ์ผ์ด์ ์คํ:
./gradlew bootRun
์์ธํ ๋ด์ฉ์ ๋ฐฑ์๋ ์ ์ฅ์์ README.md๋ฅผ ์ฐธ์กฐํ์ธ์.
- Node.js 18 ์ด์
- npm ๋๋ yarn
- ํ๋ก์ ํธ ํด๋ก :
git clone https://github.com/isitempty/frontend.git
cd frontend- ์์กด์ฑ ์ค์น:
npm install
# ๋๋
yarn install- ๊ฐ๋ฐ ์๋ฒ ์คํ:
npm run dev
# ๋๋
yarn dev- ๋ธ๋ผ์ฐ์ ์์
http://localhost:3000์ ์
.env.local ํ์ผ์ ํ๋ก์ ํธ ๋ฃจํธ์ ์์ฑํ๊ณ ๋ค์ ๋ด์ฉ์ ์ถ๊ฐํฉ๋๋ค:
NEXT_PUBLIC_API_URL=http://localhost:8080/api
- ๋ฐฑ์๋ ์๋ฒ๊ฐ ์คํ ์ค์ธ์ง ํ์ธ
- ์ฌ๋ฐ๋ฅธ URL๊ณผ ํฌํธ๋ฅผ ์ฌ์ฉํ๊ณ ์๋์ง ํ์ธ
- ๋คํธ์ํฌ ์ฐ๊ฒฐ ์ํ ํ์ธ
์ค๋ฅ ๋ฉ์์ง: Access to fetch at 'http://localhost:8080/api/parking-lots' from origin 'http://localhost:3000' has been blocked by CORS policy
[ํด๊ฒฐ ๋ฐฉ๋ฒ]
- ๋ฐฑ์๋ ๊ฐ๋ฐ์์๊ฒ CORS ์ค์ ํ์ธ ์์ฒญ
- ๊ฐ๋ฐ ํ๊ฒฝ์์ CORS ํ๋ก์ ์ฌ์ฉ:
๊ทธ๋ฆฌ๊ณ
npm install -g local-cors-proxy lcp --proxyUrl http://localhost:8080
http://localhost:8010/proxy์๋ํฌ์ธํธ ์ฌ์ฉ
- Redux DevTools ๋๋ React DevTools๋ฅผ ์ฌ์ฉํ์ฌ ์ํ ๋ณํ ๋๋ฒ๊น
- ์ปดํฌ๋ํธ ๋ฆฌ๋ ๋๋ง ์ด์๋ React.memo ๋๋ useMemo ๊ณ ๋ ค
IsItempty ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ค์ ํ๋ฉด ํฌ๊ธฐ๋ฅผ ์ง์ํด์ผ ํฉ๋๋ค:
- ๋ชจ๋ฐ์ผ: 320px ~ 480px
- ํ๋ธ๋ฆฟ: 481px ~ 768px
- ๋ฐ์คํฌํฑ: 769px ์ด์
/* ๋ฐ์ํ ๋์์ธ ์์ */
@media (max-width: 480px) {
.parking-lot-card {
width: 100%;
}
}
@media (min-width: 481px) and (max-width: 768px) {
.parking-lot-card {
width: 48%;
}
}
@media (min-width: 769px) {
.parking-lot-card {
width: 30%;
}
}ยฉ 2025 IsItempty Team