최근에 업무상 필요한 API를 만들게 되었습니다. API 자체는 간단히 조회를 통해서 특정 주문 데이터를 가져오는 것인데 문제는 Spring에 대해서는 완전 기초적인 것만 알고 있는 상태였습니다. 이번에 API를 만들면서 배웠던 것들을 정리하려고 합니다.
개발 환경은 다음과 같았습니다.
- Spring Boot
- Hibernate
- Swagger
- PostgreSQL
- AWS
저는 Spring MVC Architecture에 맞게 Controller
, Service
, Repository
작업만 하면 되었습니다. API 동작 여부는 Swagger
가 있어서 Swagger를 통해서 데이터가 제대로 들어오는지 확인하였습니다.
🔰 ApiController.java
@RequestMapping(value = "/getOneItem", method = RequestMethod.POST)
public ResponseEntity getOneItem(@RequestHeader(name = "param1", defaultValue = "") String param1,
@RequestHeader(name = "param2", defaultValue = "") String param2,
@RequestHeader(name = "param3", defaultValue = "") String param3){
logger.info("param1 : " + param1 + "....");
return ResponseEntity.ok(ApiService.getOneItem(param1, param2, param3));
}
일단 ResponseEntity
는 처음 보기에 무엇인지 찾아보았습니다.
ResponseEntity는
Spring Framework에서 제공하는 클래스 중 HttpEntity
를 상속받아 구현한 클래스입니다. 해당 객체는 HTTP 응답을 빠르게 만들어주기 위해 사용한다고 합니다. 이 객체를 사용하면 응답으로 변환될 정보를 모두 담은 요소들을 객체로 만들어 반환해준다고 합니다. 그리고 ResponseEntity
를 사용 시, 숫자로 된 상태 코드를 넣을 때 실수를 할 수 있기 때문에 Constructor 보다는 Builder를 활용하기를 권장하고 있습니다.
log4j
를 통해서 로그를 남기게 하였습니다.
🔰 ApiService.java
@Transactional
public Item getOneItem(String param1, String param2, String param3){
List<Item> items = ApiRepository.findAllByParam1AndParam2(param1, param2);
SimpleDateFormat dateForm = new SimpleDateFormat("yyMMdd");
Date now = new Date();
return items.stream()
.filter(s -> s.getDate().contains(dateForm.format(now)))
.filter(s-> s.getNum().substring(0,s.getNum().length() - 16).substring(6).equals(param3))
.findFirst()
.orElse(null);
}
@Transactional
은 Spring에서 JPA기술을 쓸 때 다음과 같은 이점이 있어 사용한다고 합니다.
- transaction
begin
,commit
을 자동 수행 - 예외를 발생시키면,
rollback
처리를 자동 수행
이를 통해 많은 보일러 코드를 줄일 수 있다고 합니다.
Query에서 like 구문을 사용하면 느려지는 경우가 있다고 하여 데이터를 가져오고 filter를 통해 원하는 데이터를 가져오는 방식을 사용했습니다.
Debug 시 filter 후 중간 값을 확인할 수가 없어서 아래와 같이 peek()
함수를 사용해서 확인했습니다.
return items.stream()
.filter(s -> s.getDate().contains(dateForm.format(now)))
.peek(s -> System.out.println(s.getNum() + " " + s.getParam()))
🔰 ApiRepository.java
@Query(value="SELECT " +
"\"I\".* " +
"FROM " +
"\"default$default\".\"Items\" AS \"I\" " +
"WHERE \"I\".\"param1\" = ?1 " +
"AND \"I\".\"param2\" = ?2 ", nativeQuery = true)
List<Item> findAllByParam1AndParam2(String param1, String param2);
일단 Repository
를 통해 DB에 접근하여 데이터를 가져오는 것은 알고 있었지만 정확히 사용법을 몰랐는데 이번 기회에 어떤 방식으로 데이터를 조회하고 가져오는지 알게 되었습니다.
@Query
annotation을 통해서 쿼리문을 작성하고 return 값으로 List<Item>
을 받습니다. 처음에 매개변수를 어떻게 사용할까? 고민을 했는데 ? + 순번
으로 사용한다는 것을 알았습니다. 예를 들어 첫 번째 파라미터를 쿼리문에 사용하겠다고 하면 ?1
라고 쓰면 됩니다. 여기서는 ?1 => param1
이 될 것입니다.
그리고 Native Query를 사용하기 위해 nativeQuery = true
를 사용해야 합니다. 일반적으로 대용량 데이터를 처리할 때 Native Query를 사용하는 게 더 좋다고 합니다. Native Query는 사용하는 DB engine에 맞는 SQL문으로 작성을 하면 됩니다.
'개발 > Spring' 카테고리의 다른 글
[Spring] REST API 리턴 시 원하는 JSON 데이터 반환하기 (0) | 2021.10.08 |
---|---|
[Spring] Repository와 Service 구현하기 (0) | 2021.10.06 |
[Spring] 단위 테스트를 위한 JUnit (0) | 2021.08.26 |
[Spring] Spring 웹 개발 기초 (0) | 2021.08.16 |
[Spring] 프로젝트 생성 (0) | 2021.08.12 |
댓글