포스트

REST API(2) Event 생성 API 구현 - Event 도메인 구현

구현 Package 및 Class

image


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") : EqualsOfHashCodeOf는 사용할때 기본적으로 모든 필드를 사용한다. 그러나 나중에 Entity간의 연관관계가 있을 때 ,연관관계가 상호 참조하는 관계가 되어버리면 EqualsOfHashCodeOf를 구현한 코드 안에서 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을 사용하는 이유

  1. 코드의 단순화로 가독성을 향상시킨다.
  2. 인스턴스의 생성과 상속을 방지한다.
  3. enum 키워드를 사용함으로써 구현의 의도가 열거임을 분명히 나타낼 수 있다.

EventTest

InteliJ의 Ctrl+Shift+T 단축키를 이용하여 테스트 클래스를 생성한다. 이는 해당 테스트 클래스로 이동하는 데에도 사용될 수 있다.
그리고 테스트함에 있어서 assertThat1을 사용할 건데, 테스트 클래스를 생성하면 기본적으로 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 : 최대 참가 인원

basePricemaxPrice 경우의 수와 각각의 로직

basePricemaxPrice 
0100선착순 등록
00무료
1000무제한 경매
(높은 금액 낸 사람이 등록)
100200제한가 선착순 등록
처음 부터 200을 낸 사람은 선 등록

100을 내고 등록할 수 있으나,
낸 사람에 의해 밀려날 수 있음

결과값

  • id : 이벤트 id (이벤트를 고유하게 식별할 수 있는 식별자)
  • name
  • eventStatus : 기본적으로 DRAFT 상태 (다른 유저들한테 이 이벤트에 대한 정보가 보이지는 않는 상태, 본인에게만 보임)
  • offline : location이 있으면 offline
  • _links : 여러 HATEOAS 정보들
    • profile : 메시지 자체에 대한 정보를 담고 있는 문서의 링크 (self-descriptive message 충족)
    • self : 자신에게 돌아가는 링크
    • publish : 생성한 이벤트를 조회할 수 있는 링크
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.