[개발] Rest API, Spring으로 Category 구현하기 (1)

 

 

 

지난 3개월동안의 프로젝트


개발팀 4인은 1주일단위의 스프린트를 계획하여 오늘까지 개발을 진행했다

겨울동안 코드베이스를 맡은 선배가 Spring Security/JWT, 자체 알고리즘 제작, Swagger Docs, 로그인/회원가입등을 구현하였다. 그리고 min-0 동생이 같이 Oauth2와 docker환경의 서버를 준비했다.

그리고 JHJ는 각종 테이블설계와 TDD를 위한 사전조사, API 설계를 도맡았다. 나같은 경우는 log(log4j2)쪽과 이에 대한 mongoDB를 연동을 위해 JPA 이해를 기반으로 CRUD구현과 테스트, rest 원칙을 기반으로 API를 설계하기 등을 맡았다.

 

우리의 목적은 크게 주서비스에 대한 만족도 높은 큐레이팅인데, 그 전에 기본적인 API구현을 다 끝내는 것이 level1이며 지금까지 진행되고 있다.

 

 

총 개발활동 요약 정리


초반 한달

  • User/System requirement 작성과 각각의 맵핑 + 프로젝트 내의 Glossary 정리
  • Project Managing Plan, Git branch 전략 설정 / sprint, story, issue, PR, codeReview...
    • project에 사용될 기술 선정- Spring 공부 시작
  • Database 설계
  • ERD 제작

두 번째 달~현재

  • Spring Security, 자체알고리즘, Swagger Docs, login/sign-up
  • DataTable 설계, rest API 설계, crud API 구현, TDD진행
  • Frontend 아키텍처 설계

 

그렇게 당장은 깅기리가 카테고리의 구현을 맡고 있다는 이야기 ㅎㅎ

( 테이블 설계 -> API 설계 -> (Spring) domain, dto, service, controller 개발 -> TDD 진행(Junit5) )

 

 

 

카테고리에 대한 설계부터 점검해보기


1️⃣ 데이터 테이블

  Attribute Data Type NN Key   Description  
1 category_id long NN PK   카테고리 id  
2 category_parent_id long       상위 카테고리 id  
3 category_name String NN     카테고리명  
4 depth Integer NN     깊이  

요구사항

  • depth를 통해서 데이터를 조회하라
    • id == a && depth == 2 일 때 하위 카테고리를 찾는 법 ⇒ parent_id == a && depth == 3 검색

  • 완전탐색 구현해와라

 

2️⃣ API 설계

POST: api/categories   //create
GET: api/categoreis   //read-list
GET: api/categories/{id}   // read
** GET: api/categories/child/{id}  // additional
** GET: api/categories/child-full/{id} //additinoal
PATCH: api/categories/{id}   //update
DELETE: api/categories/{id}   // delete

POST, GET으로 하나씩만 보자면, 다음의 내용을 기대하고 있다

POST api/category
//input
{
	"category-parent-id": 0,
	"category-name": "name",
}

//output
{
	"response":"생성"
}
GET api/categories/{id}
//input
{
	"category-id": 1,
}

//output
{
	"category-id": 1,
	"category-up-id": 0,
	"category-name": "name"
  	"depth": 0	
}

내가 맡은 category기준으론 Domain은 스스로를 참조하게 된다. 무한으로 늘어나는 depth를 이용하게 되는 것도 특징이고, 이에 대해서 구현된 것을 오늘은 거의 확정된 domain만 살펴보자.

 

 

Domain

@Id
@Column(name = "category_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; // PK

@ManyToOne(fetch = FetchType.LAZY )
@JoinColumn(name = "category_id")
private Category categoryParent;

@Column(name = "category_name")
private String categoryName;

@Column(nullable = false)
private Integer depth;
  • 자기순환(셀프참조, 셀프조인)으로 부모를 가지게 하자
    • 보통, 부모 엔티티 정의시보다 자식 에티티 정의가 더 간단하다고 하지만.
  • @ManyToOne
    • 연관관계 어노테이션
    • fetch속성 : lazy로 통일. 참조하는 그 시점에 사용하도록 지정
      • 으로 할 뻔했으나, 내장 데이터베이스(h2)로 테스트 하는 과정중에 fetch는 EAGER을 사용하기로 함.
    • cascade, targetEntity 속성도 있음
      • 그러나, cascade은 따로 구현하자.
  • @JoinColumn
    • 외래키를 매핑할 때 사용하는 어노테이션
    • name 속성: 매핑할 외래 키의 이름 지정
    • referencedColumnName속성: 참조하길 원하는 필드 이름 지정
      • 지정하지 않을시, 기본값은 PK로 된다
    • unique, nullable insertable, updatable, columnDefinition, table 등의 속성도 있음