사용자의 위치와 취향에 맞는 식당을 탐색하고, 리뷰와 찜을 통해 경험을 공유하는 BGS(배고파) 서비스의 웹 클라이언트입니다.
HTML, CSS, Vanilla JavaScript로 화면과 상태 흐름을 직접 구성했으며, Naver Maps JavaScript API와 브라우저 Geolocation을 활용해 목록·지도·상세·마이페이지·관리자 기능을 하나의 서비스 흐름으로 연결했습니다.
- Live Demo
- Frontend Repository: BGS-client
- Backend Repository: BGS-server
- Backend API
Demo account
- ID: demouser
- Password: a1234567!
관리자 계정 정보는 README에 공개하지 않습니다.
- Project Overview
- Frontend Highlights
- User Flow
- Pages
- Tech Stack
- Architecture
- Directory Structure
- Local Setup
- Deployment
- Screenshots
- Troubleshooting
- Security Notes
- Remaining Work
| Item | Description |
|---|---|
| Development Period | 2025.07 ~ 2026.06 |
| Release | 2026.07.02 |
| Team | 개인 프로젝트 (1명) |
| Role | UI 설계, 프론트엔드 구현, API 연동, Naver Maps 연동, Netlify 배포 |
BGS 프론트엔드는 서버의 추천·검색·리뷰 API를 사용자가 자연스럽게 탐색할 수 있는 화면으로 제공하는 데 집중했습니다.
- 위치·지역·검색어·정렬 조건을 조합한 식당 탐색
- 지도 이동 영역과 현재 위치를 활용한 주변 식당 조회
- 식당 상세 정보, 메뉴, 영업시간, 리뷰 확인
- 회원가입·로그인·계정 찾기와 로그인 유지 선택
- 리뷰 작성·수정·삭제, 이미지 관리, 반응 처리
- 찜·방문 식당·차단 사용자·식당 요청을 모은 마이페이지
- 점주의 식당 정보·메뉴·영업시간·이미지 수정
- 관리자의 사용자·리뷰·식당·등록 요청 관리
추천 점수, 데이터 모델, 트랜잭션 및 API 성능 개선에 관한 내용은 백엔드 README에서 확인할 수 있습니다.
- 검색어, 지역, 정렬 방식을 URL query string에 반영해 목록과 상세 화면을 오가도 탐색 조건 유지
- 추천순·평점순·조회순·찜순·리뷰순·거리순 UI 제공
- 최근 검색어를 Local Storage에 저장하고 개별 삭제 지원
IntersectionObserver로 다음 cursor를 요청해 목록을 점진적으로 추가- 현재 위치 사용이 불가능한 경우 서비스 기본 위치를 기준으로 목록 제공
- Naver Maps JavaScript API로 식당 및 사용자 위치 마커 표시
- 브라우저 Geolocation으로 현재 위치 이동
- 지도 drag·zoom 이후 현재 영역을 기준으로 식당 데이터 갱신
- 식당 마커 선택 시 요약 정보와 상세 페이지 이동 제공
- Geocoder를 활용한 주소 검색과 좌표 선택
- 식당 등록·수정 화면에서도 지도 클릭으로 위치 지정
지도 렌더링과 사용자 상호작용은 프론트엔드에서 담당하고, 백엔드는 좌표·검색어·반경 조건에 맞는 식당 데이터를 제공합니다.
- 공통
AppAuth모듈에서 JWT 저장·조회·삭제 처리 - 로그인 유지 선택 시 Local Storage, 미선택 시 Session Storage 사용
- 인증이 필요한 페이지에서 로그인 화면으로 이동하고
next경로로 원래 화면 복귀 401 Unauthorized응답 시 만료된 토큰 제거 및 재로그인 유도
- 서버의 상대 이미지 URL을 배포 API Origin과 결합해 일관된 경로 생성
- 허용된 API Origin의 HTTP(S) 이미지만 표시해 임의 외부 URL 차단
- 이미지가 없거나 로드에 실패하면 식당·프로필 기본 이미지로 대체
- 리뷰 작성·수정 및 식당 수정 화면에서 기존 이미지와 새 이미지 상태를 분리 관리
- 데스크톱과 모바일 화면을 위한 반응형 레이아웃
- 사용자·점주·관리자 역할에 따라 필요한 화면과 작업 동선 제공
- 마이페이지의 리뷰·방문·찜·차단 목록에 cursor 기반 추가 조회 적용
- 식당 영업 상태와 등록 요청 승인·반려 상태를 화면에 반영
flowchart LR
Guest[Guest] --> Search[Search and Filters]
Search --> Map[Naver Map Discovery]
Search --> Detail[Restaurant Detail]
Detail --> View[View Info and Reviews]
Guest --> Login[Login]
Login --> Member[Authenticated User]
Member --> Review[Write Review]
Member --> Like[Like Restaurant]
Member --> MyPage[My Page]
MyPage --> Request[Submit Restaurant Request]
Request --> Approval[Admin Approval]
Approval --> Owner[Restaurant Owner]
Owner --> Edit[Restaurant Management]
| Page | File | Description |
|---|---|---|
| Main | index.html |
식당 검색·필터·정렬 및 추천 목록 |
| Map | map.html |
현재 위치와 지도 영역 기반 식당 탐색 |
| Restaurant Detail | restaurant.html |
식당 정보·메뉴·영업시간·리뷰 조회 |
| Review Editor | review_write.html |
리뷰 및 이미지 작성·수정 |
| My Page | mypage.html |
프로필과 사용자 활동 내역 관리 |
| Restaurant Request | restaurant_request.html |
지도·주소를 이용한 식당 등록 요청 |
| Restaurant Editor | restaurant_edit.html |
점주의 식당 정보·메뉴·영업시간 관리 |
| Admin | admin.html |
사용자·리뷰·식당·등록 요청 관리 |
| Authentication | login.html, sign-up.html |
로그인·회원가입 |
| Account Recovery | findId.html, findPw.html |
아이디·비밀번호 찾기 |
| Category | Technology |
|---|---|
| Markup | HTML5 |
| Styling | CSS3, Bootstrap 5, Bootstrap Icons |
| Language | Vanilla JavaScript |
| Map | Naver Maps JavaScript API, Geocoder |
| Browser API | Geolocation, Local Storage, Session Storage, Intersection Observer |
| API Communication | Fetch API 기반 REST API 연동 |
| Deployment | Netlify |
flowchart LR
User[Browser] --> Netlify[Netlify Static Hosting]
Netlify --> App[HTML, CSS and JavaScript]
App --> State[Auth and Browser Storage]
App --> API[BGS REST API]
App --> Maps[Naver Maps API]
API --> Images[Railway Image URLs]
프론트엔드는 화면 렌더링과 브라우저 상태를 담당하고, 인증 검증·권한·추천·데이터 일관성은 서버가 최종 책임을 갖도록 역할을 분리했습니다.
client/
├── assets/ # 아이콘과 Bootstrap 정적 파일
├── css/ # 페이지별 스타일과 반응형 레이아웃
├── images/ # 기본 식당·프로필 이미지
├── js/ # 페이지 로직과 공통 인증·이미지·위치 모듈
├── scripts/
│ └── generate-config.js # Netlify 환경변수 기반 API 설정 생성
├── *.html # 페이지별 진입 문서
├── netlify.toml # Netlify 빌드·배포 설정
└── README.md
별도의 프론트엔드 프레임워크나 번들 설치 없이 정적 파일 서버로 실행할 수 있습니다.
git clone https://github.com/JJeSeok/BGS-client.git
cd BGS-client로컬 API 기본 주소는 js/config.js에서 확인할 수 있습니다.
window.APP_CONFIG = {
API_BASE: 'http://localhost:8080',
};백엔드 서버를 http://localhost:8080에서 실행한 뒤 VS Code Live Server 등으로 index.html을 엽니다.
브라우저에서 http://127.0.0.1:5500으로 접속합니다.
백엔드의 CORS_ALLOW_ORIGIN에는 위 프론트엔드 Origin을 등록해야 합니다.
Netlify는 저장소의 정적 파일을 배포하며, 빌드 과정에서 환경변수를 사용해 운영 API 주소를 생성합니다.
[build]
publish = '.'
command = 'node scripts/generate-config.js'Netlify 환경변수:
API_BASE=https://bgs.up.railway.appscripts/generate-config.js는 빌드 시 이 값을 js/config.js에 기록하며, 운영 환경에서 값이 없으면 빌드를 실패시켜 잘못된 API 주소로 배포되는 것을 방지합니다.
Naver Maps JavaScript API는 허용된 Web 서비스 URL에서만 호출되도록 설정했습니다.
- Local:
http://127.0.0.1:5500 - Production:
https://baegopa-eats.netlify.app
검색과 지역·정렬 조건을 바탕으로 식당을 탐색할 수 있습니다.
Naver Map에서 주변 식당의 위치와 요약 정보를 확인할 수 있습니다.
식당 이미지, 평점, 위치, 영업시간과 메뉴를 한 화면에서 확인할 수 있습니다.
평가 유형과 별점, 리뷰 내용 및 이미지를 함께 등록할 수 있습니다.
관리자는 식당 등록 요청을 조회하고 승인하거나 반려할 수 있습니다.
- 문제: 로컬 API 주소가 포함된
config.js를 그대로 배포하면 운영 프론트엔드가localhost를 호출할 수 있었습니다. - 해결: Netlify 빌드에서
API_BASE환경변수로config.js를 생성하고, 운영 빌드에서 변수가 누락되면 실패하도록 구성했습니다. - 결과: 로컬·배포 환경의 API 주소를 코드 수정 없이 분리하고 잘못된 설정의 배포를 차단했습니다.
- 문제: 프론트엔드와 서버의 Origin이 달라 상대 이미지 경로를 그대로 사용하면 프론트엔드 주소에서 파일을 찾았습니다.
- 해결:
/uploads/경로를 운영 API Origin과 결합하는 공통 이미지 모듈을 만들고, 로드 실패 시 기본 이미지로 대체했습니다. - 결과: 페이지마다 중복되던 이미지 URL 처리를 통일하고 배포 환경에서도 이미지를 안정적으로 표시했습니다.
- 문제: 로그인 유지 선택 여부와 관계없이 토큰을 하나의 저장소에 보관하면 브라우저 종료 후 세션 정책을 구분할 수 없었습니다.
- 해결: 로그인 유지 시 Local Storage, 미선택 시 Session Storage를 사용하고 공통
AppAuth모듈에서 우선순위와 삭제를 관리했습니다. - 결과: 사용자가 선택한 로그인 유지 정책을 화면 전반에서 일관되게 적용했습니다.
- 문제: 식당·리뷰 등 사용자 입력값을
innerHTML로 렌더링하면 악의적인 HTML이나 스크립트가 DOM에 삽입될 수 있었습니다. - 해결: 동적 화면 생성에서
innerHTML사용을 줄이고, DOM API의createElement와textContent를 사용해 입력값을 텍스트로 렌더링했습니다. - 결과: 신뢰할 수 없는 입력이 HTML로 해석되는 경로를 줄여 DOM 기반 XSS 공격 위험을 완화했습니다.
- 사용자 입력은 화면에서 검증하되 서버 검증을 최종 기준으로 사용합니다.
- 인증 토큰은 로그인 유지 선택에 따라 Local Storage 또는 Session Storage에 저장됩니다.
- 이미지 URL은 배포 API와 동일한 Origin만 허용하고 잘못된 URL은 기본 이미지로 대체합니다.
- Netlify 환경변수에는 공개 가능한 API Base URL만 저장하며 서버 비밀값은 포함하지 않습니다.
- Naver Maps Client ID에는 허용 Web 서비스 URL을 제한합니다.
- 접근성 검사와 키보드 탐색 개선
- 초기 마이페이지 요청 병렬화 및 화면별 지연 로딩
- 사용자 업로드 이미지의 목록용 썸네일 적용
- 반복되는 DOM 생성 로직과 API 요청·오류 처리의 공통 모듈화




