티스토리 뷰
1편 강의에서 간단한 스프링부트 웹서버를 띄우는거까지 했으니
이번에는 특정 도메인 모델에 대한 CRUD 기능을 제공하는 API 를 만들어보겠습니다.
도서관리 기능을 제공하는 예제로 진행하겠습니다.
우선, 도서관리의 기본이 될 Book 클래스를 생성해 보겠습니다.
위와같은 패키지와 클래스 파일을 생성해주세요.
Book 클래스
도서관리 API 를 만드는 예제이기 때문에 저희 예제의 도메인 모델은 '책' 입니다.
소스는 다음과 같습니다.
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
|
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@Setter
@Entity
public class Book {
@Id
@GeneratedValue
private Long id;
@Column(length = 300, nullable = false)
private String title;
@Column(nullable = false)
private String author;
@Column
private int price;
@Builder
public Book(String title, String author, int price) {
this.title = title;
this.author = author;
this.price = price;
}
}
|
cs |
어노테이션들에 대한 간단한 설명을 해드리겠습니다.
@Entity
해당 클래스가 엔티티 클래스임을 나타냅니다.
엔티티 클래스는 테이블과 매핑되는 클래스입니다.
JPA 에서는 기존 JDBC 방식처럼 쿼리를 사용하지 않고, 엔티티 클래스를 활용하여 데이터를 관리합니다. (물론 필요에 따라 쿼리도 사용합니다.)
어플리케이션이 실행될 때, JPA는 이 클래스들을 엔티티 빈에 등록합니다.
@Id
해당 필드가 PK임을 명시. 하나의 엔티티 클래스에는 반드시 하나가 필요합니다.
@GeneratedValue
PK의 생성 규칙을 나타냅니다. 기본값으로는 데이터 추가시, 값이 자동으로 증가하는 정수형 입니다.
@Column
해당 필드를 테이블의 컬럼과 매핑시켜줍니다.
생략하게 되면, 해당 필드명이 테이블의 컬럼명으로 자동으로 매핑됩니다.
위의 소스와 같이, 컬럼의 규칙 등을 명시할 수 있습니다.
이 밖에도 JPA에서 사용하는 어노테이션들이 더 존재하지만, 이번 예제에서는 이정도만 다루어보겠습니다.
나머지 어노테이션들은 JPA 의 어노테이션이 아닌, lombok 의 어노테이션 입니다.
@NoArgsConstructor
기본 생성자를 자동으로 생성합니다.
위의 코드에서는 생성자의 접근 권한을 protected로 제한한 것입니다. (코드상에서의 Entity 생성은 제한하고, JPA에서 Entity를 생성하는 것만 허용.)
@Getter @Setter
클래스 내에 있는 필드들에 대해서 getter, setter 메소드를 자동생성.
@Builder
해당 클래스의 빌더 패턴 클래스를 생성.
클래스가 아닌 생성자에 명시했을 경우, 해당 생성자에 명시된 필드에 대해서만 빌더를 생성.
(빌더 패턴에 대한 설명은 여기를 참조하세요.)
lombok 라이브러리는 프로젝트를 생성하면서 dependency를 추가했지만, IDE에서 추가적인 환경구성이 필요합니다.
인텔리제이 기준,
1. Preferences > Plugins > Browse repositories.. > Lombok 검색 > Install > restart
2. Preferences > Compiler > Annotation Processors > Enable annotaion processing 체크를 통해 구성을 완료할 수 있습니다.
자, 이걸로 Entity 클래스인 Book 클래스에 대한 설명을 마쳤습니다.
(사실 이 강의에서는 간단한 API 구축을 위해 굳이 Builder를 사용하지는 않았습니다. 참고만 해주세요.)
BookRepository 인터페이스
다음으로는 Repository 입니다. 같은 패키지에 아래와 같은 파일을 생성해주세요.
1
2
3
|
public interface BookRepository extends JpaRepository<Book, Long> {
}
|
cs |
스프링부트에서 Repository는 기본적으로 MyBatis의 DAO와 같은 역할을 합니다. 실제로 DB에 접근하는 객체입니다.
Repository 를 상속한 JpaRepository는 CRUD 기능을 포함하여 Entity 에 대한 기본적인 메소드를 제공합니다.
(정확히는 CrudRepository를 상속받았기에 CRUD 기능을 포함하고 있습니다.)
JpaRepository<Entity 클래스, PK 타입> 을 명시해주면 Repository에 대한 준비가 끝납니다.
실제로 CRUD 구현에 앞서, 원하는 데이터를 찾지 못했을 때 exception 을 발생시키기 위해,
커스터마이징된 exception 클래스를 만들어보겠습니다.
ResourceNotFoundExceptrion 클래스
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
@Getter
@ResponseStatus(value = HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
private String resourceName;
private String fieldName;
private Long fieldValue;
public ResourceNotFoundException(String resourceName, String fieldName, Long fieldValue) {
super(String.format("%s not found with %s : '%s'", resourceName, fieldName, fieldValue));
this.resourceName = resourceName;
this.fieldName = fieldName;
this.fieldValue = fieldValue;
}
}
|
cs |
소스를 보시면 아시겠지만 굉장히 간단합니다.
특정 id로 Book를 찾지 못했을 때, 예외를 발생시키는 클래스입니다.
자, 이제 컨트롤러와 서비스만 만들면 될 것 같습니다.
설명에 앞서 컨트롤러와 서비스의 간단한 차이를 미리 말씀드리자면,
컨트롤러는 클라이언트의 요청을 받고, 결과를 (화면이든 JSON 등의 데이터든) 되돌려주는 역할.
서비스는 컨트롤러가 받은 요청에 대한 비즈니스 로직을 수행하는 부분으로 역할을 나누었습니다.
PostsService 클래스
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
34
35
36
37
|
@AllArgsConstructor
@Service
public class BookService {
private BookRepository bookRepository;
public List<Book> findAll() {
return bookRepository.findAll();
}
public Book findOne(Long id) {
return bookRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("Book", "id", id));
}
@Transactional
public Book save(Book book) {
return bookRepository.save(book);
}
@Transactional
public Book update(Long id, Book newBook) {
Book book = bookRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("Book", "id", id));
book.setTitle(newBook.getTitle());
book.setAuthor(newBook.getAuthor());
book.setPrice(newBook.getPrice());
return bookRepository.save(book);
}
@Transactional
public void delete(Long id) {
Book book = bookRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("Book", "id", id));
bookRepository.delete(book);
}
}
|
cs |
소스를 보시면 아시겠지만 JpaRepository 를 상속받아 만든 postRepository 에는 이미 CRUD 기능이 구현되어 있습니다.
단지 파라미터로 id를 받아 처리하는 메소드에서는 저희가 만든 예외를 발생시키는 부분을 추가한 것 뿐입니다.
@Transactional 어노테이션은 이름에서 알 수 있듯 트랜잭션을 설정해주는 기능인데요,
트랜잭션에 대해 간단히 설명하자면... 해당 메소드에서 일어나는 로직이 모두 정상적으로 수행이 되어야만
최종적으로 DB에 commit을 하는 기능이라고 생각하시면 될 것 같습니다. 일반적으로 CUD 기능에 트랜잭션을 설정을 합니다.
MainController 클래스
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
|
@RestController
@AllArgsConstructor
public class MainController {
private BookService bookService;
@GetMapping("/book")
public List<Book> getBookList() {
return bookService.findAll();
}
@GetMapping("/book/{id}")
public Book getBook(@PathVariable("id") Long id) {
return bookService.findOne(id);
}
@PostMapping("/book")
public Book saveBook(@RequestBody Book book) {
return bookService.save(book);
}
@PutMapping("/book/{id}")
public Book updateBook(@RequestBody Book book, @PathVariable("id") Long id) {
return bookService.update(id, book);
}
@DeleteMapping("/book/{id}")
public void deleteBook(@PathVariable("id") Long id) {
bookService.delete(id);
}
}
|
cs |
서비스에서 정의한 메소드들을 단순히 호출만 하는 구조입니다. 간단하죵?
각 메소드는 HTTP 요청의 메소드별로 어노테이션을 추가해주었습니다. (REST API 이므로)
@RequestBody 어노테이션을 통해 HTTP 요청의 body 에 들어있는 값을 Book 클래스로 매핑할 수 있습니다.
@PathVariable 어노테이션은 클라이언트의 요청 url 에서 파라미터를 가져올 수 있는 어노테이션입니다.
이것으로 소스상의 준비는 모두 끝났네요.
다음 강좌에서 H2 를 활용하여 웹서버를 동작시키고, Rest Client 툴을 통하여 실제로 잘 동작하는지 확인해보겠습니다.
(이 강좌에 모두 작성하려니 내용이 다소 길어지는거 같아서요 😭)
'개발 > Java' 카테고리의 다른 글
[스프링부트 기초3] Postman과 H2 를 이용한 CRUD API 확인 (2) | 2019.03.10 |
---|---|
[디자인패턴] 빌더 패턴 Builder Pattern (객체 생성 방법) (3) | 2019.02.14 |
[스프링부트 기초1] 스프링부트(Spring Boot) 시작하기 (IntelliJ) (4) | 2019.02.10 |
- Total
- Today
- Yesterday
- vue.js
- event loop
- 인텔리제이
- 근본설
- 프로미스
- 근본
- 이벤트루프
- es6
- 빌더패턴
- nuxtjs
- promise
- Builder
- 자바스크립트
- vuejs
- 자바스크립트 엔진
- jest
- springboot
- javascript engine
- CommonJs
- javascript
- nuxt
- KCD
- intellij
- KCD2019
- await
- 야누자이
- 모듈시스템
- vue
- 스프링부트
- 테스트코드
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |