프로젝트 개요
프로젝트 명 : 스프링을 이용한 오디오스토어 웹
진행 기간 : 2023.12.10 – 2024.01.27
개발 인원 : 1명
프로젝트 선정 이유 :
스피커, 헤드폰, 턴테이블 등 오디오 기기에 대한 관심이 증가하는 추세.
국내 오디오 콘텐츠 시장 규모는 2019년 약 259억, 2024년에는 약 4.4배 증가한 약 1,115 억원 규모로 증가할 것이라는 통계가 이를 뒷받침.
보통 해외 기업이 많아서인지 해외에서 사용하는 사이트를 그대로 한국어로 번역만 한 쇼핑몰은 UI 등 이용하기에 불편하다고 느껴져, 직접 오디오 스토어를 구현함.
프로젝트 주요 내용
- 회원
고객 : 회원가입, 로그인, 회원정보 수정, 회원 탈퇴
관리자 : 회원 목록 조회
- 상품
고객 : 상품 조회
관리자 : 고객기능 + 상품 등록, 수정, 삭제, 조회
- 장바구니
여러 상품과 각 수량을 선택하여 장바구니 담기, 각 상품 삭제
- 주문
장바구니 전체 주문하기 (배송지 변경가능, 배송메시지, 결제방법)
개발 환경
Database | MySql |
프레임워크 | 이클립스 STS4 (Gradle) |
사용 언어 | Java, Html, JavaScript, CSS |
템플릿 엔진 | Thymeleaf |
부트스트랩 출처
로그인 폼 디자인
https://inpa.tistory.com/entry/CSS-💍-로그인-회원가입-페이지-스타일-🖌️-모음
쇼핑몰 웹 디자인
https://themewagon.com/themes/free-html5-ecommerce-website-template/
마이페이지
https://www.bootdey.com/snippets/view/bs4-edit-profile-page
관리자 페이지
https://codepen.io/jasonhowmans/pen/DBdjNM?editors=1111
프로젝트 구조
- ERD 다이어그램
- 스프링 구조
웹 어플리케이션 ) 사용자가 주소 or 데이터 입력 등을 컨트롤러로 요청
컨트롤러 ) 사용자 요청 처리, 응답 생성하며 웹의 데이터를 매개변수로 서비스 함수 호출
서비스 ) 로그인 등 비즈니스 로직 수행, 매퍼 함수 호출
매퍼 ) 데이터베이스의 create, select, update, delete문 등의 sql 쿼리 작성
① 메인/자바
configuration (설정 패키지)
- DBConfiguration : 외부 property 파일의 설정값 읽어오기, MyBatis 매퍼 파일의 위치, 도메인 클래스의 패키지 등 설정
- SecurityConfig : 스프링 시큐리티 설정, 비밀번호 암호화 인코더
* HikariCP : JDBC(Java Database Connectivity)를 사용하여, 자바 어플리케이션에서 데이터베이스에 접속할 때 발생하는 연결 관리를 효과적으로 수행하는 커넥션 풀 라이브러리
* 커넥션 풀 : 데이터베이스 연결 생성 및 해제, 연결 재사용 등 관리
constant (enum 패키지)
- Method : http 요청 메서드
domain (의도는 DTO 패키지, 웹과 서비스 간의 데이터 전송을 위한 객체 포함 패키지)
- MemberDTO : 유효성 검사 + 회원 테이블 속성
- ProductDTO : 상품 테이블 속성 + 카테고리 이름 (테이블에는 카테고리 번호만 있기 때문)
- ProductImgDTO : 상품이미지 테이블 속성
- CategoryDTO : 카테고리 테이블 속성
- OrdersDTO : 주문 테이블 속성
- OrderDetailDTO : 상세 주문 테이블 속성 + (회원id, 상품이름, 주문날짜, 상품별가격, 결제방법, 배송지, 배송메모, 주문상태, 수정일, 상품이미지명, 상품이미지경로)
- CartDTO : 장바구니 테이블 속성 + (상품이름, 상품가격, 상품이미지명, 상품이미지경로)
controller (웹 어플리케이션의 사용자 요청을 처리, 응답 생성하는 패키지)
- AdminController : 관리자 컨트롤러
의존성 주입 : 회원서비스, 상품서비스
모든 메서드는 관리자인지 확인
@GetMapping | @PostMapping | ||
/admin /registerItem |
상품 등록/수정 페이지 열기 * new ProductDTO(), 특정 ProductDTO(), 카테고리 Model에 추가 |
/admin /registerItem |
상품 등록하기 * 썸네일 이미지 저장, 이미지 목록 저장, 상품 정보 저장 |
/admin /itemList |
상품 목록, 삭제된 상품 목록 페이지 열기 |
/admin /updateItem |
상품 정보 수정 |
/admin/list | 회원 목록 페이지 열기 | /admin /itemDelete |
상품 내리기 |
- MemberController : 회원 컨트롤러
의존성 주입 : 회원서비스
@PostMapping | |
/member /register |
회원 등록 * 유효성 검사, 아이디 중복 검사 |
/member /update |
회원 정보 수정 * 유효성 검사 |
/member /delete |
회원 탈퇴 |
- LoginController : 로그인 컨트롤러
의존성 주입 : 회원서비스
@GetMapping | @PostMapping | ||
/member /login |
로그인, 회원가입 페이지 열기 * 로그인 상태 아닌지 확인, new MemberDTO() |
/member /signin |
로그인 요청 * 존재 회원 & 비밀번호 일치 시 HttpSession 생성 |
/member /checkLoginStatus |
로그인 상태 -> 마이페이지 로그아웃 상태 -> 로그인페이지 |
/member /logout |
로그아웃 * HttpSession 제거 |
- HomeController : 홈페이지 이동 컨트롤러
의존성 주입 : 회원서비스, 상품서비스, 이미지서비스, 주문서비스
페이지 상단에 회원 이름이 출력되므로 모든 메서드는 회원 정보를 불러옴
@GetMapping | |
/home | 메인 홈페이지 열기 |
/admin | 관리자 페이지 열기 * 관리자인지 확인 |
/member /myaccount |
마이페이지 열기 * 로그인 상태 확인, 회원정보 전달 |
/member /myOrder |
주문 목록 페이지 열기 * 로그인 상태 확인 |
/product | 상품 목록 페이지 열기 * 상품리스트 Model에 추가 |
/product-detail | 상세 상품 페이지 열기 * 상품 정보, 이미지리스트, new CartDTO() Model에 추가 * 조회 수 증가 |
- CartController : 장바구니, 주문 컨트롤러
의존성 주입 : 회원서비스, 장바구니서비스, 주문서비스
모든 메서드는 로그인 상태인지 확인, 회원 정보를 불러옴 (HomeController와 동일메서드)
@GetMapping | @PostMapping | ||
/cart | 장바구니 페이지 열기 * 장바구니리스트, new OrderDTO Model에 추가 |
/add-to-cart | 장바구니 추가하기 |
/cart /delete |
장바구니 상품 삭제하기 | ||
/cart /order |
주문하기 * 주문 & 상세주문추가 |
mapper (매퍼.xml 인터페이스)
- MemberMapper : 회원
등록, 조회(by 회원번호, 회원아이디), 수정, 삭제, 탈퇴회원 장바구니 비우기, 목록 - ProductMapper : 상품
등록, 이미지등록, 카테고리list, 조회, 수정, 삭제, 삭제 상품 장바구니에서 제외, 목록, 삭제 상품 목록,이미지수정, 조회수 증가, 재고 감소, 주문수 증가 - ProductImgMapper : 상품 이미지
등록, 한 이미지 정보, 수정, 삭제, 목록, 개수 세기 - CartMapper : 장바구니
등록, 수량만 수정, 삭제,탈퇴 시 장바구니 삭제, 조회, 목록, 장바구니 개수 세기 - OrderMapper : 주문
등록, 상세주문 조회. 주문 시 장바구니 비우기, 목록
service (비즈니스 로직 패키지 : 각 매퍼함수 호출로 내용은 매퍼와 유사)
- MemberService 인터페이스 & 구현체
- ProductService 인터페이스 & 구현체
- ProductImgService 인터페이스 & 구현체
- CartService 인터페이스 & 구현체
- OrderService 인터페이스 & 구현체
UiUtils (알림 메시지 alert, 페이지 이동)
② 메인 / 리소스
매퍼 쿼리 xml : 매퍼 구현체, sql 쿼리
템플릿 : html
- cart > shopping-cart
- fragment > common
- home > index
- item > product, product-detail
- manage > admin, itemList, memberList, registerItem
- member > my_orderList, myaccount, signup
- utils > message-redirect, success-false
static
- css
- fonts
- images
- js
- vendor
- 화면 흐름도
실행 결과
- 홈페이지
- 회원가입, 로그인
- 관리자 페이지
- 마이 페이지 (정보 수정)
- 마이페이지 (주문 조회)
- 상품 목록
- 상품 상세 정보 (로그인 상태)
- 상품 상세 정보 (로그아웃 상태)
- 재고보다 많은 수량 선택 불가
- 품절 시 장바구니 담기 불가
- 장바구니
- 담아둔 상품의 재고 부족 시, 주문 방지를 위해 자동 삭제
진행 중 문제 사항과 해결
문제 사항 | 해결 방안 |
회원가입에 대한 유효성 검사 클래스를 따로 만들어서 컨트롤러에서 호출하였는데, 의존성 주입이 되지 않아 Mapper나 Service가 null로 받아와짐. @Component로 시도해도 동일 | DTO에서 jakarta.validation.constraints를 이용하여 유효성 조건을 정하고, 컨트롤러에서 스프링의 유효성 기능인 @Valid를 이용하여 간단하게 구현 |
상세 상품 목록에서 카테고리 이름을 띄우려 했으나, 상품 테이블에는 카테고리 번호 속성만 있어서 어쩔 수 없이 카테고리 번호를 출력했음. | DTO의 변수와 테이블 속성 외에 다른 변수 추가가 가능함을 알고, ProductDTO에 CateName 변수를 추가하여, mapper의 쿼리에서 조인을 통해 category 테이블의 cateName도 함께 데이터에 담음 |
html의 한 태그 내에 타임리프의 th:field와 th:value를 동시에 사용하니 null이 들어감 | field가 아닌 name과 th:value를 사용하여 해결 |
스프링 시큐리티를 로그인에 test한 후로 꺼두었다가 기능을 모두 구현하고 활성을 했는데, post와 delete 요청에서 에러와 함께 동작하지 않음 | 토큰을 추가하여 해결 |
문제점 및 한계
- 고정적인 이미지 경로
이미지가 저장되어 있는 경로와 상관없이 이미지를 선택하면, 해당 이미지를 프로젝트 폴더 내에 “product-01.jpg“와 같이 새롭게 저장하기를 의도하였으나, 에러가 해결되지 않아, 이미 프로젝트 폴더 내에 저장이 되어 있어야 정상적으로 이미지가 불러와짐.
즉, 이미지를 부를 때 static/images/products 폴더 내에서만 찾는데 해당 폴더에 이미지가 존재하지 않을 수도 있음.
- SOLID 원칙 x
기능을 최대한 구현하는 것을 우선으로 하여 SOLID 원칙을 고려하지 않음.
즉, 유지보수에 대해 고려하지 않음.
* SOLID 원칙 : 객체지향 소프트웨어 설계의 기본원리로서 다음의 5가지 원칙을 제공하여 코드의 가독성, 확장성, 유지보수성을 향상시키고, 객체 간의 결합을 낮춰 유연하고 재사용 가능한 코드를 작성하도록 한다. 단일 책임 원칙, 개방/폐쇄원칙, 리스코프 치환 원칙, 인터페이스 분리 원칙, 의존 역전 원칙 - 비즈니스 로직을 컨트롤러에 구현
스프링 구조에서는 보통 서비스에 예외처리와 비즈니스 로직을 구현하는데, 본 프로젝트에서는 수업 자료를 참고하여 컨트롤러에 예외처리와 비즈니스 로직을 구현함.
고찰
본 프로젝트를 진행할 때, 기능과 구조만 계획하고 페이지에 대한 흐름은 한 페이지를 완성하며 세워나갔다. 계획이 부실하여 진행하다가 어떤 흐름으로 가야할지 고민하느라 생각이 꼬이기도 했었다. 다음 프로젝트에서는 pigma 사이트를 이용하여 웹 디자인과 페이지 흐름에 대해 미리 계획할 필요성을 느꼈다.
프로젝트 진행 이유 중 하나였던 스프링 MVC 패턴의 CRUD에 대한 흐름을 이해할 수 있었다. 데이터가 어떻게 흘러가고, 매퍼, 서비스, 컨트롤러, 웹 어플리케이션의 연결 구조를 완벽히 이해하였다. 하지만, 한 가지 방법을 위주로 사용하여 각 클래스의 내부 함수를 효율적으로 구성하였다고는 생각하지 않았다. @ResponseBody나 AJax 방식 등 여러 방법에 대해 공부할 필요와 SOLID 원칙을 잘 지킬 필요성을 느꼈다.
1차 계획에서는 기간이 부족하면 장바구니와 주문 기능까지는 어려울 수도 있다고 생각했지만, 두 기능을 모두 구현하였고, 기대했던 것보다 완성도가 있는 웹 어플리케이션을 제작하여, 스프링을 이용한 웹 프로젝트에 대해 자신감을 얻었고, 더 완벽히 할 수 있지 않을까 욕심이 생겼다.
'백엔드(Back-End) > Spring Boot' 카테고리의 다른 글
[STS4-Spring Boot] 게시판 검색 기능 (0) | 2024.02.12 |
---|---|
[sts4-Spring Boot] 18. 게시글 조회수 기능 구현 (0) | 2023.12.07 |
[sts4-Spring Boot] 17. REST 방식의 댓글 리스트, 작성, 삭제 (1) | 2023.12.07 |
[sts4-Spring Boot] 16. REST 방식으로 댓글 CRUD (0) | 2023.12.07 |
[sts4-Spring Boot] 15. REST API 사용해보기 (0) | 2023.12.07 |