[React + Spring Boot] 쇼핑몰 클론 코딩 : part1. 개요 및 설계

이지연·2025년 7월 22일
post-thumbnail

개요

쇼핑몰 프로젝트를 통해 React로 프론트엔드와 백엔드를 직접 구현해보고자 한다.
먼저 프로젝트의 방향성, 서비스 페이지 구성 등을 정리하고, 아주 기본적인 설계까지 진행예정!

프로젝트 방향성 및 대상 선정

프로젝트의 기본적인 틀은 클론코딩이다
우선 어떤 사이트를 클론할지 결정하는 과정이 필요했음

  1. 자사몰
  2. 오픈마켓/소셜커머스
  3. 백화점 등 대형 몰형 플랫폼

쇼핑몰이라는 큰 카테고리에서 여러 선택지 중, 1. 자사몰을 택했고, 실제 클론 참고 사이트로는 파르티멘토(partimento.com)라는 의류 브랜드를 선정함

서비스 개요

해당 사이트를 바탕으로 시스템적으로 기획의 방향을 정리해보았다

서비스 주요 페이지 (쇼핑몰)

  1. 메인 페이지
  2. 리스트 페이지
  3. 상세(뷰) 페이지

구체적인 컴포넌트 단위는 기획서를 토대로 진행 예정

어드민 페이지

어드민 페이지 역시 기획 구체화 후 진행 예정

설계

대상 선정과 서비스 개요를 잡은 뒤, 구조를 시각화하고 주요 산출물을 정리해보았음

part.1 기획 및 설계 (서비스 페이지)

역할 및 산출물 정리

정확히 어떤 서비스를 구현할지 정의하고, 개발 착수 이전에 아래와 같이 업무와 산출물을 정리함
(실제 작업 진행 및 일정에 따라 변경될 수 있음. 구체적인 실행 계획 이전의 큰 틀만 잡은 상태임)

역할주요 업무 내용산출물
기획1. 대상 선정 및 분석사용자 시나리오 플로우 다이어그램(figma), 페이지단 화면 목록(notion), 와이어프레임(figma)
2. 화면 플로우 설계(와이어프레임)
2-1. 사용자 시나리오 파악(로그인/비로그인)
2-2. 페이지 목록 정리
2-3. 페이지 간 이동/흐름 관계 정의(Screen Flow)
2-4. 와이어프레임 설계
2-5. 액션 명세 주석(각 UI별 동작 및 요청 설명)
3. 목표 기능 및 비기능 요건 정리
디자인1. 디자인 시스템 정의(반응형 포함)디자인 시스템, 화면 디자인(figma)
2. 페이지별 디자인 설계
프론트엔드1. 화면 설계서 기반 컴포넌트 구조 설계기술 스택, 협업 규칙(notion)
2. 라이브러리 선정
2-1. 상태관리(Redux, Zustand 등)
2-2. 스타일 관리(Tailwind, styled-components 등)
3. 라우팅 구조 설계
백엔드1. DB 모델링ERD, API 명세서
1-1. MySQL 테이블 설계
2. API 명세서 작성
3. 인프라 구조 기획

세팅

git 저장소 및 프로젝트 생성

  • 프론트엔드는 React + Vite + TypeScript 기반으로 app-front 프로젝트를 생성
  • 백엔드는 Java, Spring Boot 기반으로 shop.template 프로젝트를 생성

프론트엔드 세팅 회고

  • Vite 공식 문서를 참고해 TypeScript 기반 프로젝트를 생성

백엔드 세팅 회고

  1. DB 생성
  • Datagrip 내 쿼리 콘솔에서 shop_db 생성
  • shop_db 내 test 테이블 생성
CREATE DATABASE shop_db;

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,     -- 고유 사용자 ID
    username VARCHAR(50) NOT NULL UNIQUE,  -- 사용자 이름 (중복 불가)
    email VARCHAR(100) NOT NULL UNIQUE,    -- 이메일 (중복 불가)
    password VARCHAR(255) NOT NULL,        -- 비밀번호 (암호화된 상태로 저장)
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP, -- 생성 시간
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP -- 수정 시간
);
  1. Spring Initializr로 프로젝트 생성
    (유료 인텔리제이 사용 시 자체적으로도 생성 가능, 차후 직접 적용 예정)
  • Project : Gradle-Groovy
  • Language : Java
  • Spring Boot : 3.5.3
  • Project Metadata : 이미지 참고
  • Dependencies : Spring Web, Spring Boot DevTools
  1. 백엔드 기본 구조 세팅
  • 디렉터리 구조 참조 : main/java/com.study.shop.template
  • BasicController.java 추가 후 개발서버 주소로 통신 테스트
package com.study.shop.template;

import org.springframework.web.bind.annotation.CrossOrigin; // ✅ CORS 설정을 통해 다른 출처에서의 요청 허용
import org.springframework.web.bind.annotation.GetMapping; // ✅ HTTP GET 요청을 처리하는 메서드 사용
import org.springframework.web.bind.annotation.RestController; // ✅ 컨트롤러 클래스 명시

@RestController // ✅ RESTful 방식으로 응답을 반환
public class BasicController {

    @CrossOrigin(origins = "http://localhost:5174") // ✅ React 개발 서버 주소에서 오는 요청을 허용
    @GetMapping("/") // ✅ localhost:8080/ 경로로 GET 요청이 들어왔을 때 아래 메서드를 실행
    public String hello() {
        return "안녕하세요"; // ✅ HTTP 응답 본문(Response Body) 으로 그대로 전송
    }
}

  • application.properties에서 DB 연결을 위한 설정 작업 (Spring Boot 프로젝트에서 전역 설정을 정의하는 곳)
# 애플리케이션 이름
spring.application.name=shop.template

# 데이터베이스 연결 설정 (MySQL)
spring.datasource.url=jdbc:mysql://localhost:3306/shop_db?serverTimezone=UTC&useSSL=false
spring.datasource.username=your_db_username   # ← 여기에 DB 사용자 이름 입력
spring.datasource.password=your_db_password   # ← 여기에 DB 비밀번호 입력
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# JPA 설정
spring.jpa.hibernate.ddl-auto=update          # 엔티티 변경 시 테이블 자동 수정
spring.jpa.show-sql=true                      # 실행되는 SQL 로그 출력
  • Test.java: DB의 test 테이블과 매핑되는 Entity 클래스 추가
package com.study.shop.template;

import jakarta.persistence.*;
import java.time.LocalDateTime;

@Entity
@Table(name = "test") // 매핑될 테이블 이름
public class Test {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) // auto increment
    private Integer id;

    @Column(nullable = false, length = 100) // null 허용 X, 최대 길이 100
    private String name;

    @Column(length = 100) // null 허용 O (기본값), 최대 길이 100
    private String email;

    @Column(name = "created_at", columnDefinition = "DATETIME") // 컬럼명 지정 + 타입 정의
    private LocalDateTime createdAt;

    // Getter & Setter
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public LocalDateTime getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(LocalDateTime createdAt) {
        this.createdAt = createdAt;
    }
}
  • TestController.java: Test 엔티티의 조회 및 생성 API를 제공하는 컨트롤러
package com.study.shop.template;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;

@RestController
@RequestMapping("/test") // 공통 URI prefix
public class TestController {

    @Autowired
    private TestRepository testRepository;

    @CrossOrigin(origins = "http://localhost:5174") // React 개발 서버 CORS 허용
    @GetMapping
    public List<Test> getAll() {
        return testRepository.findAll(); // 모든 데이터 조회
    }

    @PostMapping
    public Test create(@RequestBody Test test) {
        return testRepository.save(test); // 전달받은 JSON을 DB에 저장
    }
}
  • TestRepository.java: Test 엔티티의 데이터 접근을 위한 JPA 레포지토리 인터페이스
package com.study.shop.template; // Controller와 동일하게 패키지 선언

import org.springframework.data.jpa.repository.JpaRepository;

public interface TestRepository extends JpaRepository<Test, Integer> {
    // 추가 메서드는 이곳에
}
  1. 프론트에서 백엔드 데이터 출력 확인
  • App.tsx 내 아래 코드 추가 후 화면 출력 확인
const [testData, setTestData] = useState<Test[]>([]);
const [message, setMessage] = useState('');
const [error, setError] = useState<string | null>(null);

// ① 단순 텍스트 데이터 백엔드에서 받기
useEffect(() => {
    fetch('http://localhost:8080/')
        .then(res => res.text())
        .then(data => setMessage(data))
        .catch(err => setMessage('Error: ' + err.message))
}, [])

// ② DB 데이터(JSON 배열) 받기
useEffect(() => {
    fetch('http://localhost:8080/test')
        .then(res => {
            if (!res.ok) throw new Error('Network response was not ok');
            return res.json();
        })
        .then(data => setTestData(data))
        .catch(err => setError(err.message))
}, [])

return (
    <>
        <h1>React + Spring Boot 연결 테스트</h1>
        <p>백엔드에서 온 메시지: {message}</p>

        <h2>DB 데이터 목록</h2>
        {error && <div style={{ color: 'red' }}>DB 요청 오류: {error}</div>}
        {testData.length === 0 ? (
            <p>데이터 로딩 중...</p>
        ) : (
            <table>
                <thead>
                    <tr>
                        <th>ID</th>
                        <th>Name</th>
                        <th>Email</th>
                        <th>Created At</th>
                    </tr>
                </thead>
                <tbody>
                    {testData.map(row => (
                        <tr key={row.id}>
                            <td>{row.id}</td>
                            <td>{row.name}</td>
                            <td>{row.email}</td>
                            <td>{row.createdAt}</td>
                        </tr>
                    ))}
                </tbody>
            </table>
        )}
    </>
);


마치며

이후에는 본격적인 DB 모델링/화면설계 및 확장 개발을 진행할 예정이다!!!

profile
Eazy하게

4개의 댓글

comment-user-thumbnail
2025년 7월 24일

spring boot 프로젝트 서버 실행 단계 및 기본 설정 내용 누락 (추가하셈)

1개의 답글
comment-user-thumbnail
2025년 7월 24일

BasicController 작업 시 build.gradle도 수정진행 해야만 통신이 확인 가능함 수정

답글 달기