어느덧 10주차가 되었다. 감회가 새롭네 ㅎㅎ
두 번째 데모데이
두 번째 데모데이를 실시하였다. 이 말은 즉 벌써 프로젝트를 시작한지 4주가 되었다는 것이다. 시간이 너무 빠름을 느끼며 얼른 계획했던대로 개발할 수 있도록 해야겠다. 일단 1차 배포로는 스프린트에서 기획한대로 진행하였다. 개발을 진행 하면서 조금씩 다른 의견을 조율하는 것이 어렵다고 느껴진다. 이런 점은 충분한 대화가 필요함을 다시 한 번 느끼게 된다. 또한 이전에 얘기했던 기능과 조금씩 차이가 발생함을 느꼈는데 이래서 api에 대해서도 버전을 나누는 것인가 생각이 들며, 확실히 문서화를 잘해야겠음을 느꼈다.
api 버전의 필요성을 느낀 예시는 다음과 같다.
가령 스타터밸리 서비스는 유데미의 부트캠프의 전 기수가 사용할 수 있도록 하자는 목표를 가지고 있는데, 우리 기수는 현재 구글 폼을 통해서 출석을 확인하고 있다. 그렇다면 아래 이미지의 출석체크를 눌렀을 시 구글 폼과 출석체크를 동시에 진행함이 필요할 수 있다. 그렇게 되면 로직이 조금은 달라질 수도 있다는 것이다.
만약 이 서비스가 잘 되어서 정말로 이 이후의 기수들과 매니저님들이 사용하게 되면 더 이상의 구글 폼으로 보내는 로직은 필요없게 되는 것이다. 이럴 때 로직을 뜯어고친다는 것은 ocp 과정에 위배되지 않을까 싶다.(이때 말하는게 맞으려나? ㅎㅎ) 그러면 api만 v2로 업해서 구글 폼에 안 보내게끔 하면 되지 않을까 싶은 것이다. 이런 점은 질문을 통해서 더 확실 시 해봐야겠다.
아직은 수동으로 배포하고 있는데, 얼른 CI/CD도 구축하여 편안하게 테스트할 수 있도록 해야겠다. 그래도 돈 걱정 없이 aws를 마음껏 누려보고 있다는 점은 아주 마음에 든다 ㅎㅎ (그래도 안전하게 사용토록 하자!)
멘토링
이번주는 멘토님이 우리의 코드를 봐주시면서 안티패턴이나 주의할 점을 설명해주셨다.
- optional.get()은 웬만하면 쓰지 말자. 나같은 경우엔 다음과 같이 코드를 짠다.
Optional<User> optional = findById(userId);
if (optaional.isEmpty()) {
throw new xxxException();
}
User user = optional.get();
이렇게 짜면 Optional로 감싸야 하니 추가 비용이 발생한다는 것이다. 또한 코드 라인도 불필요하게 생기고, 그렇기에 orElseThrow()를 활용하라고 해주셨다. 그렇다면 다음과 같이 적용할 수 있겠다.
User user = findById(userId).orElseThrow(RuntimeException::new)
이렇게 하면 한줄을 통해 예외도 던지고 있으면 엔티티도 구해올 수 있게 된다.
- 메서드의 이름은 더 의미있게 지어보자.
나는 유저 구하는 메서드를 다음과 같이 해두었다.
public User getUser(Long userId) {
return userRepository.findById(userId).orElseThrow(() -> new RuntimeException());
}
이렇게 해두니 나는 알겠지만, 다른 개발자분이 저 메서드만 갖다 쓴다는 가정하에 이 메서드를 호출햇을 때 값이 없으면 예외가 터질지 아니면 null로 반환될지 알 턱이 없는 것이다. 그렇기에 이름을 좀 더 유의미하게 짓는게 좋다고 하셨다. 예로들면 위에서 예외가 터지니 getUserOrElseThrow 같이 해두면 "아 예외가 발생하는 메서드구"나 판단할 수도 있다는 것이다. 아니면 저대로 쓸거면 그냥 null을 반환토록 해주어도 될 것이라 하셨다. 다른 사람과 협업할 때를 대비해서 이름도 잘 짓도록 해야할 거 같다.
- flatMap 활용하기
지금 우리 코드 중에 삼중 for문이 들어간 곳이 있다.
@Test
@DisplayName("유저들 강아지 사진 갖고오기")
@Transactional
void getPetImages() {
List<User> userList = userRepository.findAll();
for (User user : userList) {
List<Pet> pets = user.getPets();
for (Pet pet : pets) {
List<PetImg> petImg = pet.getPetImg();
for (PetImg img : petImg) {
System.out.println(img.getOriImgName());
}
}
}
}
봤을 때 크게 어려움은 없다만, 가독성 면에서도 indent 면에서도 안 좋기에 이런 것은 stream으로 잘 풀어주는 것이 좋다.
List<User> userList = userRepository.findAll();
List<String> petImageNames = userList.stream()
.map(User::getPets)
.flatMap(Collection::stream)
.map(Pet::getPetImg)
.flatMap(Collection::stream)
.map(PetImg::getOriImgName)
.collect(Collectors.toList());
for (String name : petImageNames) {
System.out.println(name);
}
이 방식도 좋은 방법인진 모르겠으나 indent가 하나로 해결되는 것을 볼 수 있다 ㅎㅎ. flatMap이 되게 헷갈리는데, stream과 함께 더 공부해볼만한 요소인 거 같다.
- Code smell
냄새나는 코드를 발견해주셔서 고쳤다 ㅋㅋㅋ 순서 같은 것도 관례적으로 쓰는 것으로 잘 바꿔주자
private final static // X
private static final // O
- @Transaction(readOnly = true) 같은 것을 전체 클래스로 달아줄지는 고민해보자.
나같은 경우에 서비스 클래스에다 습관적으로 위 어노테이션을 달아주는데, write가 더 빈번히 일어나는 곳에 쓰면 비효율적이지 않을까 하는 지적을 해주셨다. 차라리 조회용 서비스를 따로 만드는 것도 하나의 방법이라고 해주셨다.
- 자바의 안티패턴들도 더 찾아보자!
삽질을 통한 성장
이번 스프린트에서는 이것저것 삽질을 많이 하였다. 요즘은 문서화 하는 것이 얼추 습관화가 되어서 노션에다가 적어두고 있다.
간단할 수도 있는 이 정리들이 내가 잊어먹었을 때 다시금 도움이 되지 않을까 싶다.
CS 스터디도 열심히
CS 스터디, SQL 공부도 계속 열심히 문제를 풀고 있다. 나 뿐만 아니라 팀원들도 계속 성장하는 모습이 보이기에 주최한 입장에서 굉장히 뿌듯하다. 지금은 자바 기초도 좀 익힐까 싶사 상속에 대해서도 내주었다. 같이 많은 결과물을 얻어갔으면 하는 바람이다.
* 유데미 바로가기 : https://bit.ly/3SFlXDy * 유데미 STARTERS 취업 부트캠프 공식 블로그 보러가기 : https://blog.naver.com/udemy-wjtb 본 후기는 유데미-웅진씽크빅 취업 부트캠프 2기 - 프론트엔드&백엔드 과정 학습 일지 리뷰로 작성되었습니다.
'유데미 부트캠프' 카테고리의 다른 글
유데미 스타터스 취업 부트캠프 2기 - 백엔드(java, 자바) 12주차 학습 일지 (0) | 2023.01.01 |
---|---|
유데미 스타터스 취업 부트캠프 2기 - 백엔드(java, 자바) 11주차 학습 일지 (0) | 2022.12.25 |
유데미 스타터스 취업 부트캠프 2기 - 백엔드(java, 자바) 9주차 학습 일지 (0) | 2022.12.11 |
유데미 스타터스 취업 부트캠프 2기 - 백엔드(java, 자바) 8주차 학습 일지 (0) | 2022.12.04 |
유데미 스타터스 취업 부트캠프 2기 - 백엔드(java, 자바) 7주차 학습 일지 (0) | 2022.11.27 |
댓글