안녕하세요. 제 인생 최초의 코드 리뷰를 받아보았습니다.
카카오 테크 캠퍼스를 신청하게 된 계기가 내가 옳은 방향으로 나아가고 있는지 코드는 잘 짜고 있는지를 확인할 수 있는 코드 리뷰가 있다는 것이었는데 드디어 받게 되었습니다. 그 결과를 기록해보려 합니다.
아래의 pr을 통해 제가 받은 코드 리뷰를 확인할 수 있습니다.
https://github.com/kakao-tech-campus-2nd-step2/spring-gift-product/pull/50
구현한 기능 📄
일단 구현한 기능은 아래와 같습니다.
처음에는 HashMap 자료구조를 통해 db를 대신하여 api를 구현하였는데 3번째 과제에서 jdbc를 통해 데이터베이스와 연동 작업을 진행했습니다. 항상 jpa를 사용해왔기에 처음 사용하는 jdbc는 쉽지만은 않았습니다.
# spring-gift-product 🎁
## 기능 목록 📄
### api 기능
- [x] 상품 조회 api 구현
- [x] 상품 추가 api 구현
- [x] 상품 수정 api 구현
- [x] 상품 삭제 api 구현
### 관리자 페이지
- [x] 모든 상품 조회된 페이지
- [x] 상품 추가 버튼 및 기능
- [x] 상품 삭제 버튼 및 기능
- [x] 상품 수정 버튼 및 기능
### 상품 api jdbc
- [x] 모든 api를 jdbc를 이용하여 데이터베이스에 저장하도록 수정
- [x] 상품 생성
- [x] 상품 조회
- [x] 상품 수정
- [x] 상품 삭제
받은 피드백 🎯
생성자의 위치
대부분 필드 작성 후에 생성자를 작성합니다.
객체를 생성할 때, 생성자를 호출하기에 상단에 작성했었는데 이런 코드 스타일을 주로 사용한다는 것을 알게되었습니다.
public class Product {
private Long id;
private String name;
private int price;
private String imageUrl;
public Product() {}
public Product(Long id, String name, int price, String imageUrl) {
this.id = id;
this.name = name;
this.price = price;
this.imageUrl = imageUrl;
}
}
부정보다는 긍정을
!= 로 if문을 사용하기 보다는 == 로 사용한다고 합니다.
if (product != null) {
return new ResponseEntity(HttpStatus.CREATED);
}
return new ResponseEntity(HttpStatus.CONFLICT);
if (product == null) {
return new ResponseEntity(HttpStatus.CONFLICT);
}
return new ResponseEntity(HttpStatus.CREATED);
select -> find 네이밍
select 라는 단어는 자주 나올 수 있는 단어여서 객체를 조회할 때는 find로 주로 사용한다고 합니다.
따라서, find와 findAll로 수정해주었습니다.
public Product select(Long id) {
String sql = "SELECT id, name, price, imageUrl from products WHERE id = ?";
try {
return jdbcTemplate.queryForObject(sql, productRowMapper(), id);
} catch (Exception e) {
return null;
}
}
ResponseEntity의 팩토리 패턴 지향
위의 생성자를 통한 ResponseEntity 객체의 생성보다는 정적 팩토리 패턴으로 작성하는 게 좋다고 합니다.
그 이유는 메서드 체이닝으로 연결된 빌더 패턴을 사용하는 것이 의미가 직관적이며 유지보수에 좋기 때문입니다.
이후, 이펙티브 자바의 아이템 2를 읽어보라고 권하셨습니다.
return new ResponseEntity<>(product, HttpStatus.OK);
return ResponseEntity.ok().body(product);
null 반환 지양 -> ExceptionHandler로 에러 처리
다른 프로젝트에서도 제가 사용한 코드 방식이었는데 특정 id로 객체를 조회했을 때 없는 경우에 Repository, Service에서 null을 반환하여 Controller에서 null 인지 확인 후에 다른 응답 값을 주곤 했습니다.
그런데 Service에서 에러를 반환하면 controller가 그 에러를 잡아서 ExceptioHandler에서 처리하면 더 좋겠다는 피드백을 받았습니다.
이 글을 읽어보라고 권하셨습니다.
https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc
그래서, 상품이 이미 존재한다는 에러 ProductAlreadyExistsException 에러와 상품을 찾을 수 없다는ProductNotFoundException 에러를 만들었습니다.
public class ProductAlreadyExistsException extends RuntimeException {
public ProductAlreadyExistsException(String message) {
super(message);
}
}
public class ProductNotFoundException extends RuntimeException {
public ProductNotFoundException(String message) {
super(message);
}
그리고 Service 단에서 해당 에러를 던졌고, 컨트롤러에서 ExceptionHandler를 통해 에러 처리를 해주었습니다.
@ExceptionHandler(ProductNotFoundException.class)
public ResponseEntity<String> handleProductNotFoundException(ProductNotFoundException e) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(e.getMessage());
}
@ExceptionHandler(ProductAlreadyExistsException.class)
public ResponseEntity<String> handleProductAlreadyExistsException(ProductAlreadyExistsException e) {
return ResponseEntity.status(HttpStatus.CONFLICT).body(e.getMessage());
}
@Autowired 생략 가능한 경우
생성자를 통해 의존 관계가 호출되는 경우, 호출 시점에 1회 호출되는 것이 보장됩니다. 그래서 주입받은 객체가 변하지 않는다면 @Autowired를 생략할 수 있습니다.
public ProductController {
private ProductService productService;
@Autowired
public ProductController(ProductService productService) {
this.productService = productService;
}
}
public ProductController {
private final ProductService productService;
public ProductController(ProductService productService) {
this.productService = productService;
}
}
후기🎓
코드 리뷰를 통해 코드를 더 깔끔하게 작성할 수 있게 된 것 같습니다. 이제껏 알지 못해서 사용하지 못한 것들, 제대로 코드를 짜고 있는 지 들었던 의문점들이 해결될 수 있는 시간인 것 같습니다. 앞으로의 카테캠의 기간동안 코드 리뷰의 시간을 소중히 여기고 잘 배워야겠다고 생각했습니다.
'🍫카카오 테크 캠퍼스 2기 BE' 카테고리의 다른 글
[카카오 테크 캠퍼스 / BE] 2단계 세 번째 코드 리뷰 (1) | 2024.07.14 |
---|---|
[카카오 테크 캠퍼스 / BE] 2단계 두 번째 코드 리뷰 (0) | 2024.07.14 |
[카카오 테크 캠퍼스 / BE] 두 번째 미니과제, 자동차 경주🚗 (0) | 2024.06.10 |
[카카오 테크 캠퍼스 / BE] 첫 번째 미니과제, 숫자 야구 게임⚾ (0) | 2024.05.27 |
[카카오 테크 캠퍼스 / 2기] '웰컴 키트' 라는 것을 받다 (0) | 2024.05.14 |