심화과정 강의 완!
이번 심화 강의에서 대표적으로 배웠던 것은 Test와 AOP
그리고 오늘 팀프로젝트를 진행하고 피드백 받은 부분들을 수정했다. 내가 받았던 수정사항에는 응답시에 Entity를 바로 반환하는 것이 아닌, DTO로 반환해라! -> 게시글에 대한 응답을 할 때 게시글에 달린 댓글들을 응답할 때 이전에는 Comment Entity를 List에 담아서 반환했다. 이를 CommentResponseDto로 변환하고, CommentResponseListDto로 변환해서 반환!
그런데... 안된다.. 먹통이 됐다. 오류메세지를 보니
NULL이다. MenuResponseDto의 List<CommentResponseDto>가 null이다! 왜 널인지 찾아가보자 MenuResponseDto로!
제일 의심쩍은 놈이 까맣게 죽어있다. 바로 commentList가 죽어있다. 저렇게 죽어있다는건 한번도 쓰이지 않다던가, 아직 초기화가 안됐다던가?인데. 나는 그걸 몰라서 조금 고생을 했다.
내 첫번째 해결방법)
아 이거 db에 저장된 Menu Enity의 CommenetList가 비어있어서 그런가? 그게 null인가?? -> 그렇다면 Service단에서 null체크를 해야 하나? -> 근데 그러면 내 뉴스피드는 Menu를 List로 갖게 되는데, 댓글이 없는 게시글도 반드시 있다. 아니 있어야 한다. -> 댓글이 없는 게시글을 예외로 던져버리는건 말이 안됨 -> 댓글이 없는 Menu 게시글도 응답할 수 있어야함.
이 흐름을 탔다. 즉 CommentList가 비어있는 Menu도 응답해야한다.
두번째 해결방법)
답안지를 봤다. 다른 팀은 댓글을 어떻게 응답했나?? 기가막힌다. 적용하자마자 바로 작동이 됐다. 하지만 어떻게 되는지도 모르고 그냥 넘어가면? 난 또 같은 오류를 못잡겠지?
this.commentList = menu.getCommentList().stream()
.map(CommentResponseDto::new)
.toList();
도저히 몰라서 해당 팀의 팀원께 여쭤보러 갔다. 아주 친절히 설명해주셨다. 재윤님 감사합니다
stream()을 이용해서 menu가 갖고있는 commentList를 map(mapping)시켜서 CommentResponseDto로 만들어라 어떻게? 생성자를 이용해서(::new)니까. 이런식의 코딩 방법은 함수형 페러다임이라고 알려주셨다. 내가 했던건 명령형 페러다임.
그리고 내가 어떻게 했는지도 보여드리고 왜 안됐을까요? 물어봤다. 보자마자 바로 아셨다. 진짜 고수는 보법이 다르다.
stream().map()을 질문하러가서 재윤님이 해주신 짧막한 강의
[재윤님의 강의]
함수형 프로그래밍과 명령형 프로그래밍이 있다. 명령형은 처음부터 끝까지 컴퓨터에게 어떻게 해야할지 알려주는 것. 위에서 내가 했던 향상된 for문을 이용해서 Menu Entity를 MenuResponseDto로 매핑시켜주는 것을 하나하나 알려준다. 이것이 명령형 프로그래밍
함수형은 어떻게 하는지는 지정해주지 않는다. 어떤걸 할지만 정해준다. stream()은 데이터의 흐름. for문이나 while문을 대체해서 사용된다. 그러면? map을 통해 객체 두개를 mapping해준다. 어떻게는 안정해준다. 그냥 이거 하면 된다!고만 알려주는 것. 함수형 프로그래밍이 명령형 프로그래밍보다 훨씬 가독성도 좋고, 간단함을 알 수 있다.
private List<CommentResponseDto> commentList = new ArrayList<>();
위의 사진의 21번 라인에서 잘못된 점을 찾았다. 바로? 초기화를 안해줬기 때문. 아까 저렇게 까맣게 죽어있을 때
이런 메세지가 떠있었다. 왜냐하면 Collection은 저렇게 초기화를 해주지 않으면? Null로 되어있다. 아주 익숙하다. 왜냐하면? 아까 났던 에러가 NPE였다. 초기화를 안시켜줘서 그런거였다. 저걸 무시하고 했던 내가 바보긴 하다. 근데 재윤님한테 아주 새로운걸 배웠다. stream()을 이용해서 객체 두개를 mapping 시켜줄 수 있다는 것. 다음번에는 저걸 이용해서 코드를 해봐야겠다.