SpringBoot, JPA, H2를 이용한 간단한 RESTful API를 만들어 보자.
1. 요구사항 분석
계정에 관한 기본적인 CRUD API를 만들어 보자.
- 생성 - POST /api/account/
- 목록조회 - GET /api/account/
- 단건조회 - GET /api/account/{id}
- 수정 - PUT /api/account/{id}
- 삭제 - DELETE /api/account/{id}
2. 프로젝트 구성
2.1. 의존성 추가
pom.xml 파일에 web
, lombok
외에 spring-data-jpa
, h2
모듈을 추가했습니다.
h2데이터베이스는 인메모리 DB로 scope를 런타임으로 지정해서 사용하고 있다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.197</version>
<scope>runtime</scope>
</dependency>
2.2. application.properties 설정
# JPA 관련 옵션
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
# h2 db 셋팅
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
#h2 url path로 접근하도록 설정
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
- ddl-auto 옵션은
create-drop
으로 설정( 반드시 local환경에서만 해당 옵션을 사용해야함 ‼️‼️)- none: 아무것도 하지 않음
- create-drop: SessionFactory 시작 지점에 drop후 create를 실행하고, SessionFactory종료시 drop을 실행함.
- create: SessionFactory 시작지점에 drop실행하고 create (종료시점에 아무것도 안한다.)
- update: 변경된 스키마만 적용
- validate: 변경된 스키마가 존재하면 변경사항을 출력하고 앱 종료
2.3. AccountRepsotiroy 추가
@Repository
public interface AccountRepository extends JpaRepository<Account, Long> {
}
JpaRepository 인터페이스를 상속받는 AccountRepository를 만들어 줍니다.
JpaRepository는 인터페이스로 구현체는 SimpleJpaRepository 입니다.
이 말인 즉슨, 기본 CRUD는 이미 구현을 해 놨습니다. 그렇기 때문에
엔티티
에 대한 CRUD는 따로 만들어주지 않아도 됩니다.
2.4. AccountController 추가
@RestController
@RequestMapping("/api")
@RequiredArgsConstructor
public class AccountApiController {
//생성자 주입으로 AccountRepository를 주입시켜줍니다.
private final AccountRepository accountRepository;
// 생성
@PostMapping("/account")
public ResponseEntity<?> saveAccount(@RequestBody Account account) {
Account savedAccount = accountRepository.save(account);
return ResponseEntity.ok(savedAccount);
}
// 목록 조회
@GetMapping("/account")
public List<Account> all() {
return accountRepository.findAll();
}
// 단건 조회
@GetMapping("/account/{id}")
public Account getAccount(@PathVariable Long id) {
return accountRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("illegal argument :" + id));
}
// 수정
@PutMapping("/{id}")
public void updateAccount(@PathVariable Long id, @RequestBody Account newAccount) {
accountRepository.findById(id)
.map(account -> {
account.setName(newAccount.getName());
account.setPassword(newAccount.getPassword());
return accountRepository.save(account);
})
.orElseGet(() -> {
newAccount.setId(id);
return accountRepository.save(newAccount);
});
}
// 삭제
@DeleteMapping("/{id}")
public void deleteAccount(@PathVariable Long id) {
accountRepository.deleteById(id);
}
-
@RestController
:@Controller
+@ResponseBody
입니다. 기존의 @Controller는 return 값을 ViewResolverName을 통해서 View단의 이름이랑 매핑했습니다. 하지만, RESTful API는 응답형태를 (보통은 Json) 으로 내보내야 하기 때문에 간편하게 @RestController를 통해서 API관련 코드를 작성할 수 있습니다. 이름에서도 AccountApiController라고 지었습니다. -
@RequiredArgsConstructor
: 롬복의 애노테이션으로, 필드에 대한 클래스 생성자를 자동으로 해줍니다. 이것을 사용하는 이유는 보통은@Autowired
를 통해서 AccountRepository 빈을 주입 받아서 사용하는데, 스프링에서는, IntelliJ에서도 Field Injection은 추천하지 않습니다. 여러 가지 이유가 있지만 Circular dependencies(빈 순환 참조) 이슈가 발생할 수 있기 때문입니다. 나중에 자세한 포스팅은 따로 하겠습니다. 그런 이유에서 필드 주입이 아닌, 생성자 주입을 통해서 빈을 사용합니다. 롬복은 그것을 조금 더 쉽게 만들어 줍니다. -
POST Account 는 @RequestBody를 메서드 파라미터에 붙여주고, save()메서드를 호출합니다. 보통은 저장한 엔티티 그 자체를 return 받아서 ResponseEntity의 body에 담아서 응답을 합니다.
2.5. PostMan API 테스트
PostMan으로 POST요청을 날리면 Status 200 과 저장에 성공한 Account정보를 Body에 담아서 보내줍니다. 요청을 보낼때는 Id에 값을 따로 입력하지 않습니다. 자동으로 @GeneratedValue 를 통해서 자동증감으로 값을 할당해 줍니다. 반면에 ResponseBody에는 해당 Id값이 1로 할당되어 돌아오는 것을 확인했습니다.
3. 정리
지금까지 SpringBoot, JPA, H2를 통한 간단한 RestfulAPI 를 만들어 봤습니다.
📚 Related Posts
- Spring WebFlux 테스트 방법
- Spring과 MongoDB 연동 실전 가이드
- SpringBoot, MongoDB 시작하기
- Spring Boot 서버 타임존 설정 방법
- SpringBoot CommandLineRunner, ApplicationRunner 초기화 방법
- Jackson, LocalDateTime Serialization, Deserialization 이슈
- Spring Boot, Dockerfile로 이미지 생성, 배포하기
- SpringBoot RabbitMQ 연동하기
- Junit5 정리
- Spring Sentry(에러 트래킹 서비스) 적용하기
- [Spring] 빈 주입하는 방법 && Best Practice
- Thymeleaf 실무에서 자주 사용하는 것들
- Thymeleaf Collection 정보 화면에 렌더링하기
- Spring, JPA를 이용한 REST API 만들기
- [Spring] MultipartFile을 이용한 파일 업로드
- [Spring] 모델 검증(validation)
- [Spring]HandlerMethodArgumentResolver 인터페이스
- [Spring] DispatcherServlet에 대해서 알아보자
- [Spring] MVC 만들어 보기
- [Spring] 메세지 컨버터
- [Spring] MVC 살펴보기
- [Spring] @ConfigurationProperties를 이용해서 properties값들을 클래스로 관리하기
- [Spring] Profile 설정하기
- [Spring] SpringApplication를 통한 코딩
- [Spring Boot] 스프링 부트 3가지 특징
- [Spring] @SpringBootAppllication 어노테이션에 대한 고찰
- [Spring] bean circular dependencies (빈 순환 참조)
- [Spring]Bean에 대해서 알아보자
- SpringBoot, JPA, H2를 이용한 간단한API 작성
- [Spring] Spring Data Common 프로젝트 살펴보기