인프런에서 주최하는 Warming-up 클럽 0기 백엔드 스터디에 참여하고 있다.
스터디에 참여하면서 배우게 된 내용을 전체적으로 정리하고, 참여하면서 느낀 부분을 회고해 보고자 한다.
(1) 4일 차 : 2024-02-22(Thu)
1. 사용자 업데이트, 삭제 API
1-1. 사용자 업데이트 API 명세
(1) HTTP Method : PUT
(2) HTTP Path : /user
(3) HTTP Body : JSON
(4) 업데이트 후 별도의 결과는 반환하지 않는다. (서버로부터 200 OK 응답코드만 받을 것)
1-2. 사용자 삭제 API 명세
(1) HTTP Method : DELETE
(2) HTTP Path : /user
(3) HTTP Body : Query parameter
(4) 삭제 후 별도의 결과는 반환하지 않는다. (서버로부터 200 OK 응답코드만 받을 것)
1-3. UserController.java (사용자 업데이트, 삭제 API 추가)
@RestController
@RequiredArgsConstructor
public class UserController {
private final JdbcTemplate jdbcTemplate;
@GetMapping("/user")
public List<UserListResponseDto> getAllUsers() {
String sql = "select * from user";
return jdbcTemplate.query(sql, (rs, rowNum) -> {
long id = rs.getLong("id");
String name = rs.getString("name");
int age = rs.getInt("age");
return new UserListResponseDto(id, name, age);
});
}
@PostMapping("/user")
public void saveUser(@RequestBody UserCreateRequestDto request) {
String sql = "insert into user(name, age) values(?, ?)";
jdbcTemplate.update(sql, request.getName(), request.getAge());
}
@PutMapping("/user")
public void updateUser(@RequestBody UserUpdateRequestDto request) {
String selectSql = "select * from user where id = ?";
boolean isUserNotExist = jdbcTemplate.query(selectSql, (rs, rowNum) -> 0, request.getId()).isEmpty();
if (isUserNotExist) {
throw new IllegalStateException("존재하지 않는 회원입니다.");
}
String sql = "update user set name = ? where id = ?";
jdbcTemplate.update(sql, request.getName(), request.getId());
}
@DeleteMapping("/user")
public void deleteUser(UserDeleteRequestDto request) {
String selectSql = "select * from user where name = ?";
boolean isUserNotExist = jdbcTemplate.query(selectSql, (rs, rowNum) -> 0, request.getName()).isEmpty();
if (isUserNotExist) {
throw new IllegalStateException("존재하지 않는 회원은 삭제할 수 없습니다.");
}
String sql = "delete from user where name = ?";
jdbcTemplate.update(sql, request.getName());
}
}
(1) 현재 생성, 조회, 수정, 삭제에 대한 API 코드가 모두 나열되어 있다.
(2) 수정(업데이트), 삭제에 대한 부분만 따로 빼서 확인해 보자.
1-4. UserController - 사용자 업데이트
@RestController
@RequiredArgsConstructor
public class UserController {
private final JdbcTemplate jdbcTemplate;
@PutMapping("/user")
public void updateUser(@RequestBody UserUpdateRequestDto request) {
String selectSql = "select * from user where id = ?";
boolean isUserNotExist = jdbcTemplate.query(selectSql, (rs, rowNum) -> 0, request.getId()).isEmpty();
if (isUserNotExist) {
throw new IllegalStateException("존재하지 않는 회원입니다.");
}
String sql = "update user set name = ? where id = ?";
jdbcTemplate.update(sql, request.getName(), request.getId());
}
}
(1) 새롭게 추가된 코드들이 보이는데 하나씩 확인해 보자.
(2) 단순히 업데이트, 수정만 하는 코드의 경우는 문제가 있다.
- 바로 존재하지 않는 회원에 대한 아이디 값을 주더라도 200 OK를 반환한다.
(3) 이 부분을 해결해 주기 위해 존재하지 않는 회원에 대한 예외 상황에 대해서는 업데이트가 불가능하도록 예외를 만들어 주어야 한다.
String selectSql = "select * from user where id = ?";
boolean isUserNotExist = jdbcTemplate.query(selectSql, (rs, rowNum) -> 0, request.getId()).isEmpty();
(4) 조회용 selectSql를 따로 만든다.
(5) query()를 사용해 만약 selectSql로 인해 조회되는 결과가 있다면 0이 담긴 리스트를 반환하게 하고, 만약 없다면 빈 리스트를 반환하도록 한다
(6) request.getId()의 경우 selectSql의 와일드 카드 부분을 매핑해서 바디로 넘어온 아이디 값을 전달해준다.
(7) 따라서 (5)의 결과를 빈 리스트가 반환된다면 해당 회원은 존재하지 않는다는 뜻이다. 그러므로 isUserNotExist 변수는 true가 되므로 IllegalStateException 예외를 던지게 된다.
(8) 결국 존재하지 않는 회원에 대한 업데이트는 실패하게 된다.
(9) 사용자 삭제도 위와 비슷하다 한 번 살펴보자.
1-5. UserController - 사용자 삭제
@RestController
@RequiredArgsConstructor
public class UserController {
private final JdbcTemplate jdbcTemplate;
@DeleteMapping("/user")
public void deleteUser(UserDeleteRequestDto request) {
String selectSql = "select * from user where name = ?";
boolean isUserNotExist = jdbcTemplate.query(selectSql, (rs, rowNum) -> 0, request.getName()).isEmpty();
if (isUserNotExist) {
throw new IllegalStateException("존재하지 않는 회원은 삭제할 수 없습니다.");
}
String sql = "delete from user where name = ?";
jdbcTemplate.update(sql, request.getName());
}
}
(1) 회원 삭제의 경우 아이디가 아닌 이름 값을 넘겨서 판단하도록 하고 있다.
(2) 위의 업데이트 로직과 동일하게 쿼리 파라미터로 넘어온 이름을 조회했을 때 빈 리스트가 반환된다면, 해당 이름을 가진 회원은 존재하지 않는 것이다 따라서 isUserNotExist 값이 true가 되므로 IllegalStateException 예외를 던지게 되면서 회원 삭제에 실패하게 된다.
2. 문제점
(1) 위의 회원 컨트롤러를 확인해 봤을 때 문제점이 하나 있다.
(2) 바로 하나의 컨트롤러가 너무 많은 작업을 수행하고 있다.
- 조회, 예외 처리, 실질적인 쿼리 수행 등 다양한 일을 하나의 컨트롤러 레벨에서 모두 처리하고 있다.
(3) 현재 기능이 단순해서 코드를 읽는데 그렇게 어렵지 않지만 조금만 요구사항이 추가되면 코드가 바로 복잡해질 것이다.
(4) 이 부분을 해결이 필요하다.
3. 개인 회고
(1) 현재 하나의 컨트롤러에서 너무 많은 역할을 수행하도록 코드가 작성되어 있다. 좋은 컨트롤러는 들어온 요청에 대해 적절한 처리를 다른 계층에서 수행해 주고 응답만을 돌려받아 다시 클라이언트측으로 반환하는 역할을 수행해야 한다.
(2) 너무 많은 기능을 담당하는 코드가 컨트롤러에 존재하면 가독성은 물론 유지보수가 매우 어려워진다
(3) 이 부분을 빠르게 개선해 보고 싶다.
※ 해당 포스팅에 대해 내용 추가가 필요하다고 생각되면 기존 포스팅 내용에 다른 내용이 추가될 수 있습니다.
개인적으로 공부하며 정리한 내용이기에 오타나 틀린 부분이 있을 수 있으며, 이에 대해 댓글로 알려주시면 감사하겠습니다.
'기록, 회고 > InFlearn Warming-up 0기 BE' 카테고리의 다른 글
[5일 차] - 내용 정리, 개인 회고 (0) | 2024.02.21 |
---|---|
[4일 차] - 과제 수행 : API 개발 연습 (0) | 2024.02.21 |
[3일 차] - 과제 수행 : 익명 클래스, 함수형 프로그래밍(람다식), Stream API, 메서드 참조(Method Reference) (4) | 2024.02.20 |
[3일 차] - 내용 정리, 개인 회고 (0) | 2024.02.20 |
[2일 차] - 과제 수행 : GET, POST API 설계 (4) | 2024.02.19 |
댓글