시스템 아키텍처 설계
본 시스템은 전통적인 음식 거리의 정보를 중심으로 운영되는 웹 플랫폼으로, 모듈 기반의 계층적 아키텍처를 채택하였다. 주요 구성 요소는 다음과 같다.
- 음식점 관리 모듈: 식당 등록, 정보 수정, 위치 및 메뉴 관리
- 사용자 인증/권한 모듈: RBAC 기반의 역할 기반 접근 제어 시스템
- 리뷰 및 평점 시스템: 사용자 리뷰 수집 및 평균 점수 산출 기능
- 검색 및 필터링 엔진: 지역, 가격대, 음식 종류별 실시간 검색 지원
- 통계 분석 대시보드: 인기 음식점, 방문 패턴, 평균 평점 등의 데이터 시각화
기술 스택 선택
백엔드 기술
- 프레임워크: Spring 5.x + MyBatis 3.5 + Spring MVC
- 인증: JWT + Spring Security
- 데이터베이스: MySQL 8.0 + MyBatis-Plus
- 캐싱: Redis 6.x (세션 및 정적 데이터 캐싱)
- 메시징: RabbitMQ 3.9 (알림 및 비동기 처리)
프론트엔드 기술
- 프레임워크: Vue 3.x + Vite 개발 환경
- UI 라이브러리: Element Plus
- 차트 라이브러리: ECharts 5.0 (지역별 인기 맵, 평점 추이 그래프)
- HTTP 클라이언트: Axios
데이터베이스 설계
주요 테이블 구조는 다음과 같다.
CREATE TABLE food_vendor (
vendor_id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
category VARCHAR(50),
location VARCHAR(200),
phone VARCHAR(20),
avg_rating DECIMAL(3,2) DEFAULT 0.00,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE menu_item (
item_id BIGINT PRIMARY KEY AUTO_INCREMENT,
vendor_id BIGINT,
dish_name VARCHAR(100) NOT NULL,
price INT NOT NULL,
description TEXT,
is_available BOOLEAN DEFAULT TRUE,
FOREIGN KEY (vendor_id) REFERENCES food_vendor(vendor_id)
);
CREATE TABLE user_review (
review_id BIGINT PRIMARY KEY AUTO_INCREMENT,
vendor_id BIGINT,
user_id BIGINT,
rating TINYINT CHECK (rating BETWEEN 1 AND 5),
comment TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (vendor_id) REFERENCES food_vendor(vendor_id),
FOREIGN KEY (user_id) REFERENCES users(user_id)
);
핵심 기능 구현
음식점 추천 알고리즘 예제
public List<FoodVendor> recommendVendors(List<FoodVendor> vendors, User currentUser, String preference) {
return vendors.stream()
.filter(v -> v.getCategory().equals(preference))
.sorted(Comparator.comparingDouble(FoodVendor::getAvgRating).reversed())
.limit(10)
.collect(Collectors.toList());
}
검색 조건 동적 쿼리 생성 예시
public Page<FoodVendor> searchVendors(SearchCriteria criteria, Pageable pageable) {
return queryFactory.selectFrom(qVendor)
.where(
qVendor.category.eq(criteria.getCategory()),
qVendor.avgRating.goe(criteria.getMinRating()),
qVendor.location.contains(criteria.getLocation())
)
.orderBy(qVendor.avgRating.desc())
.fetchResults(pageable)
.getResults();
}
성능 최적화 전략
- 캐시 전략: Redis를 활용해 인기 음식점 목록과 카테고리 정보 캐싱
- 데이터베이스 최적화:
category와avg_rating에 대한 복합 인덱스 생성 - 쿼리 성능 개선: JOIN 연산 최소화, 필요 시 서브쿼리 활용
- 정적 자원 분리: 이미지 및 스타일 파일을 CDN 또는 MinIO로 외부 저장
보안 방어 전략
- JWT 기반 세션 인증 및 만료 시간 설정
- Spring Security의
@PreAuthorize("hasAuthority('ROLE_USER')")를 통한 권한 체크 - 비밀번호 암호화: BCrypt 알고리즘 적용
- SQL 인젝션 방지: 파라미터화된 쿼리 사용
- 로그 기록: 모든 사용자 리뷰 등록/삭제 작업에 대해 이벤트 로그 남김
외부 시스템 연동
- 지도 서비스: Google Maps API 또는 네이버 지도 연동
- 소셜 로그인: 카카오, 네이버, 구글 계정 연동
- 푸시 알림: Firebase Cloud Messaging (FCM) 통합
- 결제 연동: 카카오페이 또는 네이버페이 결제 시스템 연계
운영 및 모니터링
- 모니터링 도구: Prometheus + Grafana로 서버 리소스 및 요청 지표 감시
- 로그 시스템: ELK 스택 (Elasticsearch, Logstash, Kibana)을 이용한 로그 분석
- 배포 전략: Docker 컨테이너화 + Kubernetes 기반의 클러스터 배포
- CI/CD: GitHub Actions 또는 Jenkins를 통한 자동 빌드 및 배포 파이프라인 구성
- 서비스 장애 대응: 블루그린 배포 방식으로 안정적인 롤아웃 보장