SpringBoot와 Vue 기반 농산물 온라인 판매 시스템 설계 및 구현

디지털 경제의 발전과 함께 전자상거래 플랫폼은 전통적인 농산물 유통 방식을 혁신하고 있다. 본 시스템은 생산자와 소비자를 직접 연결하는 온라인 거래 플랫폼으로, 정보 비대칭 문제를 해소하고 유통 효율성을 제고하는 것을 목표로 한다. 시스템은 신선 농산물의 실시간 판매 관리, 주문 처리 자동화, 안전한 결제 연동 기능을 제공하여 사용자 경험을 향상시킨다.

백엔드는 SpringBoot 프레임워크를 기반으로 개발되었으며, Java 언어와 MySQL 데이터베이스를 사용한다. MyBatis-Plus를 활용한 ORM 설계를 통해 데이터 접근 계층의 개발 생산성을 극대화하였고, Redis 캐싱 메커니즘을 도입하여 고빈도 조회 요청에 대한 응답 속도를 개선했다. 프론트엔드는 Vue.js 3와 Composition API를 적용하여 구성하였으며, Element Plus UI 컴포넌트 라이브러리를 기반으로 반응형 인터페이스를 구현하였다.

주요 데이터 모델

사용자 정보 테이블 (user_info)

필드명 데이터 타입 설명
user_id BIGINT 사용자 고유 식별자 (기본키)
login_id VARCHAR(50) 로그인 아이디
pwd_hash VARCHAR(128) SHA-256 기반 암호화된 비밀번호
full_name VARCHAR(50) 실명
mobile VARCHAR(15) 휴대폰 번호
email_addr VARCHAR(60) 이메일 주소
reg_date DATETIME 가입 일시 (자동 생성)
last_access DATETIME 최종 접속 시간
role_type TINYINT 권한 등급 (1: 일반, 2: 관리자)

상품 정보 테이블 (product_info)

필드명 데이터 타입 설명
item_id BIGINT 상품 고유 ID (기본키)
item_name VARCHAR(120) 상품명
category_code INT 카테고리 코드
unit_price DECIMAL(12,2) 단가 (원)
stock_count INT 재고 수량
item_desc TEXT 상세 설명
thumbnail_url VARCHAR(255) 썸네일 이미지 경로
listing_date DATETIME 등록 일시 (자동 생성)
sale_status BOOLEAN 판매 상태 (true: 판매중)

주문 정보 테이블 (order_record)

필드명 데이터 타입 설명
order_no BIGINT 주문 번호 (기본키)
customer_id BIGINT 구매자 ID
product_id BIGINT 상품 ID
purchase_qty INT 구매 수량
total_price DECIMAL(12,2) 총 금액
order_timestamp DATETIME 주문 시각 (자동 생성)
payment_state TINYINT 결제 상태 (0: 대기, 1: 완료)
delivery_phase TINYINT 배송 단계 (0: 준비, 1: 출고, 2: 완료)

기술 아키텍처

시스템은 RESTful API 기반의 전후방 분리 구조를 채택하였다. 백엔드 서버는 Spring Security를 통한 인증/인가 체계를 구축하고 JWT(JSON Web Token) 기반 세션 관리를 구현하였다. 파일 업로드 기능은 클라우드 스토리지 연동을 고려하여 설계되었으며, 결제 모듈은 가상계좌 및 카드 결제를 지원하는 PG사 API와 연동된다.

핵심 구현 코드

package com.agro.platform;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@ComponentScan(basePackages = "com.agro")
@EnableScheduling
public class AgroMarketApplication {
    public static void main(String[] args) {
        SpringApplication.run(AgroMarketApplication.class, args);
    }
}
package com.agro.controller;

import com.agro.entity.UserInfo;
import com.agro.service.UserService;
import com.agro.util.JwtUtil;
import com.agro.util.ResultResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/api/auth")
@CrossOrigin(origins = "*")
public class AuthController {

    @Autowired
    private UserService userService;

    @Autowired
    private JwtUtil jwtUtil;

    @PostMapping("/signin")
    public ResultResponse login(@RequestBody Map credentials) {
        String userId = credentials.get("username");
        String password = credentials.get("password");

        UserInfo user = userService.authenticateUser(userId, password);
        if (user != null) {
            String token = jwtUtil.generateToken(userId, user.getRoleType());
            Map result = new HashMap<>();
            result.put("token", token);
            result.put("userInfo", user);
            return ResultResponse.success("로그인 성공", result);
        } else {
            return ResultResponse.error("아이디 또는 비밀번호가 잘못되었습니다.");
        }
    }

    @PostMapping("/signup")
    public ResultResponse register(@RequestBody UserInfo userInfo) {
        if (userService.existsByLoginId(userInfo.getLoginId())) {
            return ResultResponse.error("이미 존재하는 사용자입니다.");
        }
        
        userInfo.setRegDate(new java.util.Date());
        userInfo.setLastAccess(new java.util.Date());
        userService.createUser(userInfo);
        
        return ResultResponse.success("회원가입이 완료되었습니다.");
    }
}

태그: SpringBoot Vue.js MyBatis-Plus MySQL Redis

6월 11일 21:09에 게시됨