오늘은 기업 1차 면접에서 코드리뷰를 하게 되었는데요. 당연하게 생각했던 것들 중 인사이트를 얻게 된 것들이 많아서 좋은 경험이었던 것 같습니다. 궁금해지기도 해서 공부할 겸 포스팅을 계획하게 되었습니다.
가장 기억에 남았던 질문(내가 대답하지 못한 질문) 2가지를 가져왔습니다.
- Private final은 왜 붙이신 건가요? 안 붙인다고 Service가 바뀌나요?
- 독후감을 등록하는데 많은 기능들이 있는데 Tag등록 부분에서 오류가 나면 모두 롤백돼야 하는 게 정상 아닌가요? 이렇게 분리되어 있으면 이전의 기능들은 롤백 안되지 않나요?
리뷰 코드
@RestController
@RequiredArgsConstructor
public class ReviewController {
private final PinService pinService;
private final TaggedService taggedService;
private final VisitService visitService;
private final BookService bookService;
private final ReviewService reviewService;
private final LikesService likesService;
@PostMapping("/api/write")
@Operation(summary = "독후감 추가", description = "독후감을 새로 추가합니다.")
public CMRespDto<?> addReview(@RequestBody ReviewRespDto reviewRespDto) {
reviewService.등록또는수정전예외처리(reviewRespDto);
pinService.핀생성(reviewRespDto);
bookService.책생성(reviewRespDto);
taggedService.태그등록(reviewRespDto);
visitService.독후감쓰기전방문등록또는수정(reviewRespDto);
reviewService.독후감생성(reviewRespDto);
return new CMRespDto<>(HttpStatus.OK, null, "독후감 추가 완료");
}
}
@RequiredArgsConstructor
@Transactional(readOnly = true)
@Service
public class ReviewServiceImpl implements ReviewService {
...
}
질문 1번
private final은 왜??
사실 습관적으로 private final을 붙였었다. 내가 무엇을 쓰고 있는지도 모른 채 코드를 짜고 있었던 것이다. 그렇다고 "강의에서 하길래 따라 했다"라는 말을 할 수 없기에 불변성과 예측가능성을 이야기했지만,, 그 이후 꼬리질문에 대답하지 못했다. "그럼 안 붙이면 동작과정에서 Sevice가 바뀌나요?" 사실 private final을 붙이지 않는다고 해서 내 코드상 바뀔 일은 없다. 생각해보지 못한 주제여서 황당하였다.
그래서 왜 붙이는 건데?
먼저 필드의 불변성과 객체의 안정성을 보장하기 위한 말은 맞는 말이다. 코드로 봤을 때 존재 의의는 특히 @RequiredArgsConstructor 어노테이션에서 나타난다. 이 어노테이션 롬복에서 제공되는 기능으로, 클래스의 필드를 기반으로 생성자를 자동으로 생성한다. 이 생성자는 해당 클래스의 모든 final 필드를 매개변수로 받는 생성자를 만들어준다. 덧붙여 final은 생성자를 통한 필드 주입방법으로 대체할 수 있다.
그래서 안 바뀌면 안 붙여도 되는 거 아닌가?
바뀌는지 안 바뀌는지는 코드 상황에 따라 불분명하고 안정성을 고려하였을 때 private final을 붙이는 게 맞다고 결론이 났다. 의존성 주입을 통해 외부 서비스나 데이터에 접근하는 필드의 경우 이러한 문제가 버그를 발생시킬 수 있고 서비스가 바뀔 수 있는 경우는 정리하자면 아래와 같다고 한다.
- 의존하는 외부 서비스의 API나 인터페이스가 변경되는 경우.
- 새로운 기능이 추가되거나 기존 기능이 수정되어 의존하는 서비스의 동작이 변경되는 경우.
- 외부 환경의 변화로 인해 의존하는 서비스의 구현이 변경되는 경우.
종합하면, private final 필드를 사용함으로써 코드의 안정성과 예측 가능성을 높일 수 있으며, @RequiredArgsConstructor를 통해 자동 생성자를 생성함으로써 코드의 가독성을 향상할 수 있다. 그러나 코드 상황에 따라 적절한 판단이 필요할 수 있다. 정도로 정리가 되었다.
질문 2번
독후감을 등록하는데 많은 기능들이 있는데 Tag등록 부분에서 오류가 나면 모두 롤백되야 하는 게 정상 아닌가요?
사실 당시에는 현직 개발자 분들의 말에 대답할 수 없었다 (트랜잭션의 원자성을 지키지 못했기때문에)... 어찌 돌려 말하지도 못하고 그냥 수긍했다.. 기능적인 면에서 확실히 맞는말이기 때문에 😅
이후에 "아 코드 다 뜯어고쳐봐야겠다"라고 생각하면서 한편으론 "왜 내가 이렇게 짰을까?"라고 곰곰이 생각해 봤고 아래와 같은 결론이 났다. 지금이라면 면접 질문에 이렇게 대답할 것 같다🤔
태그 등록 부분에서 오류가 발생하여 독후감 등록 전체가 롤백되어야 하는지에 대한 의문을 제기하셨는데요. 기능적인 입장에서 아주 좋은 지적 감사드립니다. 하지만 사용자 친화적으로 생각했을때 저는 오류가 발생한 부분만 롤백되는 것이 맞다고 생각했습니다.
독후감을 등록하는 과정에서 여러 단계를 거치게 됩니다. 예를 들어, 이전 태그목록에 대한 신규 업데이트가 진행되어 태그 등록 과정에서 오류가 발생한다고 해도, 다른 단계에서는 문제가 없을 수 있습니다. 이 경우에는 태그 등록에 실패한 부분만 롤백되고, 다른 부분은 그대로 유지되는 것이 사용자 입장을 고려한 코딩방법이라고 생각합니다.
만약 태그 등록에 실패하면 전체 독후감 등록이 롤백된다면, 이미 등록된 독후감 내용도 함께 사라지게 됩니다. 결제와 같이 민감한 정보가 아니기에 모든 과정이 롤백되는 것보다는, 최대한 사용자의 노력의 결과물을 잃지 않는 것이 중요하다고 생각하고 있습니다.
그렇기 때문에, 독후감 등록 과정에서 발생한 오류가 해당 단계에만 영향을 미치도록 처리하는 것이 더 안정적이고 사용자 친화적이라고 생각됩니다.
물론 이 대답이 정답인지는 모르겠다. 나중에 더 나은 생각이 날때면 글을 추가해보도록 하자~!
다음에는 더 잘해보도록 하겠습니당, 그리고 잘 배웠습니다.😄
읽어주셔서 감사합니다.
'🥭Mango Odyssey' 카테고리의 다른 글
2024 회고 (0) | 2024.12.29 |
---|---|
[회고] 한숨 돌릴겸 회고록 (0) | 2024.08.01 |