REST API(2) Event 생성 API 구현 - Event 도메인 구현
구현 Package 및 Class
Event 도메인
Event 생성 API를 구현하기에 앞서, Event domain을 구현해보자 events
패키지(package)를 만들어 주고 Event
클래스(class)를 생성한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package me.hantomas.restapi.events;
import lombok.*;
import java.time.LocalDateTime;
@Builder @AllArgsConstructor @NoArgsConstructor
@Getter @Setter @EqualsAndHashCode(of = "id")
public class Event {
private Integer id;
private String name;
private String description;
private LocalDateTime beginEnrollmentDateTime;
private LocalDateTime closeEnrollmentDateTime;
private LocalDateTime beginEventDateTime;
private LocalDateTime endEventDateTime;
private String location;
private int basePrice;
private int maxPrice;
private int limitOfEnrollment;
private boolean offline;
private boolean free;
private EventStatus eventStatus = EventStatus.DRAFT;
}
@Builder
: Builder Pattern으로 객체를 생성할 수 있게 해주는 어노테이션이다.@AllArgsConstructor
: 클래스의 모든 필드 값을 파라미터로 받는 생성자를 자동으로 생성하는 어노테이션이다.@NoArgsConstructor
: 파라미터가 없는 디폴트 생성자를 자동으로 생성하는 어노테이션이다.@Getter
,@Setter
: Getter/Setter 자동 생성 어노테이션.@EqualsAndHashCode(of = "id")
:EqualsOf
와HashCodeOf
는 사용할때 기본적으로 모든 필드를 사용한다. 그러나 나중에 Entity간의 연관관계가 있을 때 ,연관관계가 상호 참조하는 관계가 되어버리면EqualsOf
와HashCodeOf
를 구현한 코드 안에서StackOverFlow
가 발생할 수 있다. 따라서id
의 값만 가지고 Equals와 HashCode를 비교하도록 만들어서 사용한다. 몇 가지 필드를 더 추가해서 사용도 가능하다.
ex)@EqualsAndHashCode(of = {"","",""})
❗ @Data
어노테이션을 사용하지 않는 이유
@Data
는 위의 어노테이션들을 자동으로 구현해 주지만, @EqualsAndHashCode
를 구현할 때, 모든 Property를 다 써서 구현하기 때문에, 이 역시 상호 참조 문제로 StackOverFlow
가 발생한다. 따라서 최소한 Entity에는 사용하는 것을 권장하지 않는다.
EventStatus enum
EventStatus
이늄(enum)을 추가해 준다.
1
2
3
4
5
6
package me.hantomas.restapi.events;
public enum EventStatus {
DRAFT, PUBLISHED, BEGAN_ENROLLMEND, CLOSED_ENROLLMENT, STARTED, ENDED
}
Enum의 의미와 개념
Enum이란 Enumeration ‘열거’라는 의미로 관련 있는 상수들의 집합을 나타내는 클래스이다. 대표적으로 요일이나, 계절 처럼 서로 의미있고 한정적인 데이터 집합들을 나타낼 때 사용한다. 클래스 내 선언하는 상수가 많아질 수록 네이밍이 겹치는 것을 막고 상수값 관리를 용이하게 하기 위해 Class 대신 Enum을 사용한다. Enum은 단순히 데이터의 집합이 아니라 온전한 클래스 형태로 보며 상태와 행위를 한 곳에서 관리할수 있다는 특징이 있다. enum 생성자는 private
으로 선언한다.
Enum을 사용하는 이유
- 코드의 단순화로 가독성을 향상시킨다.
- 인스턴스의 생성과 상속을 방지한다.
- enum 키워드를 사용함으로써 구현의 의도가 열거임을 분명히 나타낼 수 있다.
EventTest
InteliJ의 Ctrl
+Shift
+T
단축키를 이용하여 테스트 클래스를 생성한다. 이는 해당 테스트 클래스로 이동하는 데에도 사용될 수 있다.
그리고 테스트함에 있어서 assertThat
1을 사용할 건데, 테스트 클래스를 생성하면 기본적으로 Junit의 Assert가 import 되어있는데, 우리는 assertj의 것을 사용할 것이다.(assertj가 자동완성, Assertion 분류, 확장성면에서 성능이 좋다고한다.)
Ctrl
+Alt
+O
단축키를 사용하여 사용하지 않을 import를 제거하고(최적화) import static org.assertj.core.api.Assertions.assertThat
를 해준다.
1: assertThat(T actual, Matcher<? super T> matcher) 의 형태로 메서드를 사용하여 두 값을 비교할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package me.hantomas.restapi.events;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class EventTest {
@Test
public void builder(){
Event event = Event.builder()
.name("Inflearn Spring REST API")
.description("REST API development with Spring")
.build();
assertThat(event).isNotNull();
}
@Test
public void javaBean(){
// Given
String name = "Event";
String description = "Spring";
// When
Event event = new Event();
event.setName(name);
event.setDescription(description);
// Then
assertThat(event.getName()).isEqualTo(name);
assertThat(event.getDescription()).isEqualTo(description);
}
}
위의 첫번째 Test는 Builder 패턴을 이용한 방법이고, 아래의 Test는 Default 생성자를 사용해서 만든 방법이다.
이벤트 비지니스 로직
다음을 입력값으로 받는다.
name
: 이벤트 이름description
: 설명beginEnrollmentDateTime
: 이벤트 등록 시작 시간closeEnrollmentDateTime
: 이벤트 등록 종료 시간beginEventDateTime
: 이벤트 시작 일시endEventDateTime
: 이벤트 종료 일시location
: optional, 이벤트 위치 (장소가 없으면 온라인 이벤트)basePrice
: optional, 모임 등록비maxPrice
: optional, 모임 등록비limitOfEnrollment
: 최대 참가 인원
basePrice
와 maxPrice
경우의 수와 각각의 로직
basePrice | maxPrice | |
---|---|---|
0 | 100 | 선착순 등록 |
0 | 0 | 무료 |
100 | 0 | 무제한 경매 (높은 금액 낸 사람이 등록) |
100 | 200 | 제한가 선착순 등록 처음 부터 200을 낸 사람은 선 등록 100을 내고 등록할 수 있으나, 낸 사람에 의해 밀려날 수 있음 |
결과값
id
: 이벤트 id (이벤트를 고유하게 식별할 수 있는 식별자)name
- …
eventStatus
: 기본적으로 DRAFT 상태 (다른 유저들한테 이 이벤트에 대한 정보가 보이지는 않는 상태, 본인에게만 보임)offline
: location이 있으면 offline_links
: 여러 HATEOAS 정보들profile
: 메시지 자체에 대한 정보를 담고 있는 문서의 링크 (self-descriptive message 충족)self
: 자신에게 돌아가는 링크publish
: 생성한 이벤트를 조회할 수 있는 링크