감 잃지말고 개발하기

[JSP][MVC][MySQL] 도서 사이트에서 다중 카테고리 구현하기 #1. 구현 틀 잡기 본문

JSP/MVC

[JSP][MVC][MySQL] 도서 사이트에서 다중 카테고리 구현하기 #1. 구현 틀 잡기

persii 2023. 6. 12. 11:27

"도서 등록 페이지 카테고리 구현하기" 포스팅에서는 클라 딴 페이지에서 카테고리 1개를 구현하는 로직을 정리해 보았다(아래 포스팅 참고).

 

이번 포스팅에서는 이것을 조금 더 응용해 다중 카테고리를 구현해 보도록 하겠다.

늘 그렇듯, 교보문고의 도서 상세 페이지를 참고해 나름대로 구현해 보았다.

 

카테고리를 구현하는 기본적인 로직 및 DB 테이블은 아래 포스팅을 참고하기 바란다.

 


♠ 기본 카테고리 구현 로직이 궁금하면 아래 포스팅을 참고하세요 ♠

 

2023.05.31 - [JSP/MVC] - [JSP][MVC][MySQL] 도서 등록 페이지 카테고리 구현하기 #1. 기본 세팅

 

[JSP][MVC][MySQL] 도서 등록 페이지 카테고리 구현하기 #1. 기본 세팅

도서 등록 페이지에서 박스로 카테고리를 설정하는 로직을 기록하고자 한다. 이번 포스팅에서는 구현에 필요한 기본 세팅을 정리해 보도록 하겠다. 목표 ♠ 카테고리를 위한 DB 테이블을 생성할

persimmon-ary-stepbystep.tistory.com


 

목표

♠ 다중 카테고리를 구현할 수 있다.

♠ 셀프 조인 및 이너 조인을 자유롭게 사용할 수 있다.

 

 

참고 모델 살펴보기

이번 구현에 있어 모델이 된 교보문고 사이트의 도서 상세 페이지를 한번 살펴보자.

 

아래 이미지를 보면 도서 정보의 가장 상단에 해당 도서의 메인 분야(카테고리)가,

도서 상세 설명란의 "이 책이 속한 분야" 부분에 2개의 분야가 나와있음을 확인할 수 있다(빨간 박스).  

 

나는 가장 상단 부분의 분야(카테고리)를 "메인 분류"로, 그 외의 분야를 "서브 분류"로 구분해 구현할 것이다.

 

참고 - 교보문고

 

참고 - 교보문고

 

 

DB 테이블 생성

위에서 메인 분류와 서브 분류를 따로 구분했으므로 그에 필요한 테이블을 생성하고 기존 테이블을 수정한다.

필요한 테이블은 총 3개이다.

 

1. bookcatgycode 테이블

도서를 분류하는 코드가 저장되는 계층형 테이블이다.

 

소분류 데이터를 기준으로 생각하면 이해하기 쉽다(가장 중요한 테이블이므로 이해가 안되면 위에 링크한 포스팅을 보고 오길 바란다).

 

CREATE TABLE `bookcatgycode` (
  `bc_code` int NOT NULL COMMENT '카테고리 코드',
  `bc_name` varchar(45) NOT NULL COMMENT '카테고리 코드명',
  `bc_code_ref_md` int DEFAULT NULL COMMENT '해당 카테고리의 중분류 코드',
  `bc_code_ref_mn` int DEFAULT NULL COMMENT '해당 카테고리의 대분류 코드',
  PRIMARY KEY (`bc_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='도서 카테고리 테이블'

 

2. book 테이블

도서 한 권의 정보가 저장되는 테이블로, 서브 분류를 제외한 데이터가 저장된다. 

 

"b_bc_code"는 해당 도서의 메인 분류 코드가 저장되는 칼럼이다.

 

CREATE TABLE `book` (
  `b_id` int NOT NULL AUTO_INCREMENT COMMENT '책 아이디',
  `b_name` varchar(100) NOT NULL COMMENT '책 제목',
  `b_writer` varchar(100) NOT NULL COMMENT '책 저자',
  `b_translator` varchar(100) DEFAULT NULL COMMENT '책 옮긴이',
  `b_publisher` varchar(100) NOT NULL COMMENT '책 출판사',
  `b_bc_code` int NOT NULL COMMENT '책 카테고리 코드(메인)',
  `b_price` int NOT NULL COMMENT '책 가격',
  `b_image` varchar(45) NOT NULL COMMENT '책 대표 이미지',
  `b_page` bigint NOT NULL COMMENT '책 쪽수',
  `b_publish_date` varchar(15) NOT NULL COMMENT '책 출판일',
  `b_content` text COMMENT '책 설명',
  `b_readcount` int DEFAULT NULL COMMENT '조회수',
  PRIMARY KEY (`b_id`),
  KEY `fk_b_bs_code_idx` (`b_bc_code`),
  CONSTRAINT `fk_b_bc_code` FOREIGN KEY (`b_bc_code`) REFERENCES `bookcatgycode` (`bc_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='도서를 저장하는 테이블'

 

3. booksubcatgy 테이블

도서 한 권의 서브 분류 코드가 저장되는 테이블이다.

 

"bsc_b_id" 칼럼이 book 테이블의 "b_id" 칼럼을 참조하기 때문에 해당 도서의 서브 분류 코드를 가져올 수 있다.

마찬가지로 "bsc_bc_code" 칼럼이 bookcatgycode 테이블의 "bc_code" 칼럼을 참조하므로 해당 코드의 대/중분류 코드를 가져올 수 있다.

 

CREATE TABLE `booksubcatgy` (
  `bsc_id` int NOT NULL AUTO_INCREMENT COMMENT 'PK',
  `bsc_b_id` int NOT NULL COMMENT '해당 도서 아이디',
  `bsc_bc_code` int NOT NULL COMMENT '해당 도서의 서브 카테고리 코드',
  PRIMARY KEY (`bsc_id`),
  KEY `fk_bsc_bc_code_idx` (`bsc_bc_code`),
  KEY `fk_bsc_b_id_idx` (`bsc_b_id`),
  CONSTRAINT `fk_bsc_b_id` FOREIGN KEY (`bsc_b_id`) REFERENCES `book` (`b_id`),
  CONSTRAINT `fk_bsc_bc_code` FOREIGN KEY (`bsc_bc_code`) REFERENCES `bookcatgycode` (`bc_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='등록된 도서 한 권의 서브 카테고리(메인이 아닌) 정보를 담는 테이블'

 

4. ERD

위 3개의 테이블의 관계도는 아래와 같다.

4-1. ▼ book - bookcatgycode 테이블

book - bookcatgycode 테이블

 

4-2. ▼ booksubcatgy - book & bookcatgycode 테이블

booksubcatgy - book & bookcatgycode

 

 

VO 클래스

DB 테이블을 JSP에서 사용하기 위한 VO 클래스를 생성해 보자.

 

1. Bookcatgycode 클래스

도서 분류 코드 정보를 저장할 VO 클래스이다.

 

☞ 변수 code_ref_md_name, code_ref_mn_name

bookcatgycode 테이블이 계층형인 것을 감안해 해당 분류 코드의 대 / 중분류 코드명을 가져오기 위해 생성한 변수이다.

 

package vo;

/** 도서 분류 VO */
@Getter
@Setter
public class BookCatgyCode {

	private int code;		// 해당 카테고리 코드(소분류 코드)
	private String name;		// 해당 카테고리 코드명
	private int code_ref_md;	// 해당 카테고리 중분류 코드
	private int code_ref_mn;	// 해당 카테고리 대분류 코드
	
	private String code_ref_md_name; // 해당 카테고리 중분류 코드명
	private String code_ref_mn_name; // 해당 카테고리 대분류 코드명
	
	public BookCatgyCode() {
		super();
	}
	
	public BookCatgyCode(int code, String name, int code_ref_md, int code_ref_mn, String code_ref_md_name,
			String code_ref_mn_name) {
		super();
		this.code = code;
		this.name = name;
		this.code_ref_md = code_ref_md;
		this.code_ref_mn = code_ref_mn;
		this.code_ref_md_name = code_ref_md_name;
		this.code_ref_mn_name = code_ref_mn_name;
	}
	
	// alt shift s s
	@Override
	public String toString() {
		return "BookCatgyCode [code=" + code + ", name=" + name + ", 
                            code_ref_md=" + code_ref_md + ", code_ref_mn="
                            + code_ref_mn + ", code_ref_md_name=" + code_ref_md_name + ", 
                            code_ref_mn_name=" + code_ref_mn_name
                            + "]";
	}
}

 

2. Book 클래스

도서 한 권의 정보를 저장할 VO 클래스이다.

 

☞ List<BookCatgyCode> bookSubCatgyList

해당 도서의 서브 분류를 저장하는 변수이다.

1개 이상 존재할 수 있으므로 List형으로 저장하며, BookCatgyCode 클래스 타입으로 저장되도록 한다. 

 

package vo;

import java.util.List;

/** 책 하나의 정보를 저장하는 클래스*/
@Getter
@Setter
public class Book {

	private int b_id;			// 책 아이디
	private String b_name;			// 책 제목
	private String b_writer;		// 책 저자
	private String b_translator;		// 책 옮긴이
	private String b_publisher;		// 책 출판사
	private int b_bc_code; 			// 책 메인 분류
	private int b_price;			// 책 가격
	private String b_image;			// 책 대표 이미지
	private int b_page;			// 책 쪽수
	private String b_publish_date;		// 책 출판일
	private String b_content;		// 책 설명
	private int b_readcount;		// 책 조회수
	
	private int b_main_catgy;		// 책 대분류
	
	private List<BookCatgyCode> bookSubCatgyList;	// 책 서브 분류를 저장할 VO
	
	public Book(int b_id, String b_name, String b_writer, String b_translator, 
                    String b_publisher, int b_bc_code, int b_price, String b_image, 
                    int b_page, String b_publish_date, String b_content, int b_readcount, 
                    List<BookCatgyCode> bookSubCatgyList) {
		this.b_id = b_id;
		this.b_name = b_name;
		this.b_writer = b_writer;
		this.b_translator = b_translator;
		this.b_publisher = b_publisher;
		this.b_bc_code = b_bc_code;
		this.b_price = b_price;
		this.b_image = b_image;
		this.b_page = b_page;
		this.b_publish_date = b_publish_date;
		this.b_content = b_content;
		this.b_readcount = b_readcount;
		this.setBookSubCatgyList(bookSubCatgyList);
	}

	public Book(int b_id, String b_name, String b_writer, String b_translator, 
                    String b_publisher, int b_bc_code, int b_price, String b_image, 
                    int b_page, String b_publish_date, String b_content, int b_readcount) {
		this.b_id = b_id;
		this.b_name = b_name;
		this.b_writer = b_writer;
		this.b_translator = b_translator;
		this.b_publisher = b_publisher;
		this.b_bc_code = b_bc_code;
		this.b_price = b_price;
		this.b_image = b_image;
		this.b_page = b_page;
		this.b_publish_date = b_publish_date;
		this.b_content = b_content;
		this.b_readcount = b_readcount;
	}
	
	public Book() {
		// TODO Auto-generated constructor stub
	}

	// alt shift s + s
	@Override
	public String toString() {
		return "Book [b_id=" + b_id + ", b_name=" + b_name + ", b_writer=" + b_writer + ", 
                        b_translator=" + b_translator + ", b_publisher=" + b_publisher + ", 
                        b_bc_code=" + b_bc_code + ", b_price=" + b_price + ", 
                        b_image="+ b_image + ", b_page=" + b_page + ", 
                        b_publish_date=" + b_publish_date + ", b_content=" + b_content+ ", 
                        b_readcount=" + b_readcount + ", b_main_catgy=" + b_main_catgy + ", 
                        bookSubCatgyList="+ bookSubCatgyList + "]";
	}
}

 

 


 

 

이렇게 다중 카테고리를 구현하기 위한 기본 세팅이 끝났다.

다음 포스팅부턴 클라 딴부터 하여 본격적으로 구현해 보도록 하겠다.

 

 

끝.