아치 음식거리 웹사이트의 SSM 기반 설계 및 구현

시스템 아키텍처 설계

본 시스템은 전통적인 음식 거리의 정보를 중심으로 운영되는 웹 플랫폼으로, 모듈 기반의 계층적 아키텍처를 채택하였다. 주요 구성 요소는 다음과 같다.

  • 음식점 관리 모듈: 식당 등록, 정보 수정, 위치 및 메뉴 관리
  • 사용자 인증/권한 모듈: 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를 활용해 인기 음식점 목록과 카테고리 정보 캐싱
  • 데이터베이스 최적화: categoryavg_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를 통한 자동 빌드 및 배포 파이프라인 구성
  • 서비스 장애 대응: 블루그린 배포 방식으로 안정적인 롤아웃 보장

태그: SSM Spring MyBatis MySQL Redis

6월 4일 22:41에 게시됨