justsicklife
Spring boot Rest Api Web 프로젝트 따라하기 (2) Rest API 설계 본문
GitHub - justsicklife/springboot_RestApi_Web_Project
Contribute to justsicklife/springboot_RestApi_Web_Project development by creating an account on GitHub.
github.com
spring boot REST API Web 프로젝트 (4) - Http 메소드를 기준으로 API 설계 (Controller, Service)
스프링 부트 REST API WEB 프로젝트 깃헙 링크 https://github.com/choiwoonsik/springboot_RestApi_App_Project/tree/main/restApiSpringBootApp 수행 목록 환경구성 및 helloworld 출력 H2 DB 연동 Swagger API 문서 연동 REST API 설계 Re
ws-pace.tistory.com
API를 구현할 때 확장 가능하도록 REST API를 구현하기 위해서는 아래 단계를 따르자
- Entity를 그대로 반환해서는 안된다 (dto) 를 사용
- 리소스의 맞게 HTTP METHOD 를 사용해야 한다.
- 반환 시 객체로 반환하지 말고 JSON 형태로 맞게 data로 넣어줘야 한다 (확장성을 위해)
조회
- GET /v1/users : 모든 회원을 조회
- GET /v1/users/{}
등록
POST /v1/user : 회원등록
수정
PUT /v1/user : 회원정보 수정
삭제
DELETE /v1/user : 회원 삭제
2. 결과 데이터의 구조를 표준화해서 정의
기존 User 정보를 바탕으로 응답 데이터 구조를 만들자
기존 User 데이터
{
"userId": 1,
"email": "abc@gmail.com"
"name": "구슬탈출"
}
기존 User 데이터
{
"data": {
"userId": 1,
"email": "abc@gmail.com"
"name": "구슬탈출"
},
"success":true,
"code": 0,
"message": "성공하였습니다."
}
응답 모델 3가지 구현
com.restApi.restApiSpring.demo 하위에 model.response 폴더를 만들고 응답할 답을 3 가지 모델을 만들자
공통 응답 모델
전달된 데이터와 별개로 API의 처리여부, 상태, 메시지가 담긴 데이터이다. 이 응답은 다른 모든 응답이 상속받아서 갖도록 한다.
@Getter
@Setter
public class CommonResult {
@Schema(name = "응답 성공 여부 T/F")
private boolean success;
@Schema(name = "응답 코드: >= 0 정상, < 0 비정상")
private int code;
@Schema(name = "응답 메시지")
private String msg;
}
단일 응답 모델
API 반환값이 단일 객체일 경우 해당 데이터 모델로 처리하고 공통 응답모델도 상속받았으므로 API응답 관련 정보도 포함되어있다. 또한 타입을 제네릭 타입인 <T> 로 선언 해서 User dto 말고 다른 dto 도 적용이 가능하도록 설계했다.
@Setter
@Getter
public class SingleResult<T> extends CommonResult{
T data;
}
다중 응답 모델
@Getter
@Setter
public class ListResult<T> extends CommonResult {
private List<T> list;
}
3. API가 반환할 모델을 처리할 Service 구현
결과 모델에 데이터를 넣어주는 Service를 구현한다. ResponseService 클래스를 service 패키지를 생성하서 안에 생성한다.
1. 공통 응답 모델을 Success / Fail로 처리하기 위해 Enum 클래스를 생성한다.
@Getter
@AllArgsConstructor
public enum CommonResponse {
SUCCESS(0,"성공하였습니다."),
FAIL(-1,"실패하였습니다.");
private int code;
private String msg;
}
2. 유형별로 ResponseService를 구현해준다.
@Service
public class ResponseService {
// 단일건 결과 처리 메서드
public <T> SingleResult<T> getSingleResult(T data) {
SingleResult<T> result = new SingleResult<>();
result.setData(data);
setSuccessResult(result);
return result;
}
// 복수건 결과 처리 메서드
public <T> ListResult<T> getListResult(List<T> list) {
ListResult<T> result = new ListResult<>();
result.setList(list);
setSuccessResult(result);
return result;
}
// 성공 결과만 처리
public CommonResult getSuccessResult() {
CommonResult result = new CommonResult();
setSuccessResult(result);
return result;
}
// 실패 결과만 처리
public CommonResult getFailResult() {
CommonResult result = new CommonResult();
setFailResult(result);
return result;
}
// API 요청 성공 시 응답 모델을 성공 데이터로 세팅
private void setSuccessResult(CommonResult result) {
result.setSuccess(true);
result.setCode(CommonResponse.SUCCESS.getCode());
result.setMsg(CommonResponse.SUCCESS.getMsg());
}
// API 요청 실패 시 응답 모델을 실패 데이터로 세팅
private void setFailResult(CommonResult result) {
result.setSuccess(false);
result.setCode(CommonResponse.FAIL.getCode());
result.setMsg(CommonResponse.FAIL.getMsg());
}
}
- 단일 응답, 복수 응답 별로 나눠서 API 응답을 받고, 공통 응답 부분을 성공 여부에 따라 T/F 로 처리해준다.
- 성공여부 실패 여부 만을 반환하는 메서드도 선언해준다.
- 회원 삭제 시 삭제가 성공하면 성공응답을 반환하는 용도로 사용된다.
4. Mapper, userService,mapper.xml 파일 수정하기
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTO Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.restApi.restApiSpring.demo.repository.UserMapper">
<select id="findById" resultType="com.restApi.restApiSpring.demo.dto.User">
SELECT * FROM user where userId = #{userId}
</select>
<select id="findByName" resultType="com.restApi.restApiSpring.demo.dto.User">
SELECT * FROM user where name = #{name}
</select>
<select id="findAll" resultType="com.restApi.restApiSpring.demo.dto.User">
SELECT * FROM user
</select>
<select id="findByEmail" resultType="com.restApi.restApiSpring.demo.dto.User">
SELECT * FROM user where email = #{email}
</select>
<insert id="save" parameterType="com.restApi.restApiSpring.demo.dto.User">
insert into user values(USER_ID_SEQ.nextval,#{name},#{email})
</insert>
<update id="updateById" parameterType="com.restApi.restApiSpring.demo.dto.User">
update user set
userId = #{userId}, email = #{email}, name = #{name}
where userId = #{userId}
</update>
<delete id="deleteById" parameterType="Long">
delete from user where userId = #{userId}
</delete>
</mapper>
userService
public interface UserService {
public Optional<User> findById(Long userId);
public List<User> findByName(String name);
public User findByEmail(String email);
public int save(User user);
public List<User> findAll();
int updateById(User user);
int deleteById(Long userId);
}
userServiceImpl
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService{
final UserMapper userMapper;
@Override
public Optional<User> findById(Long userId) {
return userMapper.findById(userId);
}
@Override
public List<User> findByName(String name) {
return userMapper.findByName(name);
}
@Override
public User findByEmail(String email) {
return userMapper.findByEmail(email);
}
@Override
public int save(User user) {
return userMapper.save(user);
}
@Override
public List<User> findAll() {
return userMapper.findAll();
}
@Override
public int updateById(User user) {
return userMapper.updateById(user);
}
@Override
public int deleteById(Long userId) {
return userMapper.deleteById(userId);
}
}
5. Http Method와 정형화된 주소 체계로 Controller 구현
위에서 정의한 GET,POST,PUT,DELETE에 맞춰서 Mapping 테이블을 완성한다.
@Tag(name= "예제 APi", description = "Swagger 테스트용 API")
@RestController
@RequiredArgsConstructor
public class UserController {
final UserService userService;
final ResponseService responseService;
@Operation(summary = "회원 단검 검색", description = "userId로 회원을 조회합니다.")
@GetMapping("/user/{userId}")
public SingleResult<User> findUserByKey(@Parameter(name = "userId",required = true) @PathVariable Long userId) {
return responseService.getSingleResult(userService.findById(userId).orElse(null));
}
@Operation(summary = "회원 검색 (이름)" , description = "이름으로 회원을 검색합니다.")
@GetMapping("/users/{name}")
public ListResult<User> findUserByName(@Parameter(name = "name",required = true) @PathVariable String name) {
return responseService.getListResult(userService.findByName(name));
}
// @Operation(summary = "회원 검색 (이메일)",description = "이메일로 회원 검색합니다.")
// @GetMapping("/users/{email}")
// public User findUserByEmail(@Parameter(name = "email",required = true) @PathVariable String email) {
// return userService.findByEmail(email);
// }
@Operation(summary = "모든 회원 조회", description = "모든 회원 목록을 조회합니다.")
@GetMapping("/users")
public ListResult<User> findAllUser() {
return responseService.getListResult(userService.findAll());
}
@Operation(summary = "회원 저장" ,description = "이름 과 이메일을 받아 저장합니다.")
@PostMapping("/user")
public SingleResult<Integer> save(@Parameter(name = "email",required = true)
@RequestParam String email,
@Parameter(name = "name", required = true)
@RequestParam String name) {
User user = User.builder()
.email(email)
.name(name)
.build();
return responseService.getSingleResult(userService.save(user));
}
@Operation(summary = "회원 수정", description = "회원 정보를 수정합니다.")
@PutMapping("/user")
public CommonResult modify(
@Parameter(name = "userId",required = true) @RequestParam Long userId,
@Parameter(name = "email",required = true) @RequestParam String email,
@Parameter(name = "name",required = true) @RequestParam String name
) {
User user = User.builder()
.userId(userId)
.email(email)
.name(name)
.build();
return responseService.getOperatorResult(userService.updateById(user));
}
@Operation(summary = "회원 삭제",description = "회원 정보를 수정합니다.")
@DeleteMapping("/user/{userId}")
public CommonResult delete(@Parameter(name = "userId",required = true)
@PathVariable Long userId) {
userService.deleteById(userId);
return responseService.getSuccessResult();
}
}
기존의 블로그에서는 JPA를 써서 save 만하면 저장,수정이 다됬지만 mybatis 에는 그런 기능이 없어서 수정을 했다.
'프로젝트' 카테고리의 다른 글
Spring boot Rest Api Web 프로젝트 따라하기 (1) swagger 연동 (0) | 2024.04.20 |
---|---|
Spring boot Rest Api Web 프로젝트 따라하기 (1) 환경 구성 (0) | 2024.04.18 |
React + Spring Boot 다키스트 던전 공략 사이트 제작기 (1) | 2024.04.14 |
spring boot + react 로 게시판 만들기 세팅편 (0) | 2024.01.20 |