티스토리 뷰

300x250

API를 만들기 위해서는 총 3개의 클래스가 필요하다고 한다.

1. Request 데이터를 받을 Dto

2. API 요청을 받을 Controller

3. 트랜잭션, 도메인 기능 간의 순서를 보장하는 Service

나는 기존에 알고 있었던 지식으로는 항상 Service 에서 비지니스 로직을 처리해야 한다고 들었었고

그렇게 했었다.

하지만 이 저자 분 께서는 Service에선 트랜잭션, 도메인간 순서 보장의 역할만 한다고 한다.

"그럼 비지니스 로직은 누가 처리하냐?"라고 반문 한다면

각 영역의 소개를 잠깐 봐야 한다.

1. Web Layer

- 흔히 사용하는 컨트롤러와 JSP등의 뷰 템플릿 영역이다.

- 이외에도 필터, 인터셉터, 컨트롤러 어드바이스등 외부 요청과 응답에 대한 전반적인 영역을 이야기 한다.

2. Service Layer

- @Service에 사용되는 서비스 영역이다.

- 일반적으로 Controller와 Dao의 중간 영역에서 사용된다.

- @Transaction이 사용되어야 하는 영역이기도 하다.

3. Repository Layer

- Database와 같이 데이터 저장소에 접근하는 영역이다

- 기존에 개발했던 Dao영역과 같다고 생각하면 된다.

4. Dtos

- Dto(Data Transfer Object) 는 계층 간에 데이터 교환을 위한 객체를 이야기하며Dtos는 이들의

영역을 이야기 한다.

5. Domain Model

- 도메인이라 불리는 개발 대상을 모든 사람이 동일한 관점에서 이해할 수 있고 공유할 수 있도록

단순화시킨 것을 도메인 모델이라 일컫는다.

- 이를테면 택시 앱이라고 하면 배차, 탑승, 요금등이 모두 도메인이 될 수 있다.

- @Entity를 사용해 봤다면@Entity가 사용된 영역 역시 도메인 모델이라고 이해하면된다.

- 다만 무조건 데이터베이스의 테이블과 관계가 있어야만 하는 것은 아니다.

- Vo처럼 값 객체들도 이 영역에 해당하기 때문이다.

이 다섯가지 레이어에서 비지니스 처리를 담당해야 하는 곳이 바로 Domain영역이다.

%참고%

스프링에서는 빈을 주입받는 방식들은 총 3가지가 잇따

- @Autowired , setter, Constructor

이 중 가장 권하는 방식이 생성자로 주입받는 방식이다. @Autowired는 권장하지 않는다고 한다.

자세하게 보려면 아래에 블로그를 참고해서 나중에 한번 더 봐야겠다.

https://madplay.github.io/post/why-constructor-injection-is-better-than-field-injection

 

생성자 주입을 @Autowired를 사용하는 필드 주입보다 권장하는 하는 이유

@Autowired를 사용하는 의존성 주입보다 생성자 주입(Constructor Injection)을 더 권장하는 이유는 무엇일까?

madplay.github.io

 

 

이제 테스트 클래스들을 만들고 호출을 해보자

1. PostsApiControllerTest

package com.jojodu.book.springboot.web;

import com.jojodu.book.springboot.domain.posts.Posts;
import com.jojodu.book.springboot.domain.posts.PostsRepository;
import com.jojodu.book.springboot.web.dto.PostsSaveRequestDto;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;

import static org.assertj.core.api.Assertions.*;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class PostsApiControllerTest {

    @LocalServerPort
    private int port;

    @Autowired
    private PostsRepository postsRepository;

    @Autowired
    private TestRestTemplate restTemplate;

    @After
    public void tearDown(){
        postsRepository.deleteAll();
    }

    @Test
    public void Posts_insert() throws Exception{
        //given
        String title = "title";
        String content = "content";
        PostsSaveRequestDto requestDto = PostsSaveRequestDto.builder()
                .title(title)
                .content(content)
                .author("author")
                .build();

        String url = "http://localhost:" + port + "/api/v1/posts";


        //when
        ResponseEntity<Long> responseEntity = restTemplate.postForEntity(url, requestDto, Long.class);

        //then
        assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
        assertThat(responseEntity.getBody()).isGreaterThan(0L);

        List<Posts> all = postsRepository.findAll();
        assertThat(all.get(0).getTitle()).isEqualTo(title);
        assertThat(all.get(0).getContent()).isEqualTo(content);


    }



}

2.PostsSaveRequestDto

package com.jojodu.book.springboot.web.dto;

import com.jojodu.book.springboot.domain.posts.Posts;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
public class PostsSaveRequestDto {

    private String title;
    private String content;
    private String author;

    @Builder
    public PostsSaveRequestDto(String title, String content, String author){

        this.title = title;
        this.content = content;
        this.author = author;

    }

    public Posts toEntity() {
        return Posts.builder().title(title).content(content).author(author).build();
    }
}

 

참고

이전 HelloController와 달리 @WebMvcTest를 사용하지 않는다. @WebMvcTest 같은 경우는

JPA 기능이 작동하지 않는다고 한다. Controller와 ControllerAdvice 등 외부 연동과 관련된 부분만

활성화 되니 지금 같이 JPA 기능까지 한번에 테스트 할 때는 @SpringBootTest 와 TestRestTemplate을

사용하면 된다고 한다.

 
728x90

'Framework > Springboot' 카테고리의 다른 글

JWT(Json Web Token)완전 정복  (0) 2023.06.28
Spring Data JPA적용하기  (0) 2023.06.19
머스테치로 화면 구성하기  (0) 2023.06.19
250x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/05   »
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
글 보관함