레벨1에서는 미션마다 회고를 작성했는데, 레벨2에서는 미션에 치여서 정신없게 지내다 보니 블로그 포스팅이 어려웠다.. 준호(제이)님과 점심식사 자리에서 준호님이 “미션당 회고 어려울거에요 ㅋㅋ” 라고 하셨었는데, 현실이 되었다.. (미션당 회고는 고사하고, 레벨당 회고만 진행해도 잘 하는게 아닐까 합리화가 시작된다 😅)
레벨 막바지에 진행한 테코톡이 일정 대부분을 잡아먹은 주범이었다. 그래도 언젠가는 발목을 붙잡을 녀석이었는데 나름 잘 넘긴거 같아서 후련하고 좋다.
레벨2는 ‘기술에 대한 학습’보다 ‘어떻게 공부할 것인지, 나만의 공부방법이 무엇인지 학습’하는 기간이었다. 개개인마다 잘 맞는 학습법들이 있겠지만 나는 역시나 누군가에게 풀어내는게 가장 즐겁고 학습효과도 좋았기 때문에, 글로 적어내는 방식을 계속 유지하고자 했다.
그러나 블로그에 일일히 학습 내용을 적어내기가 힘들었다. 단순하게 적어내기엔 다른 사람들이 읽는다는 부담이 있었고, 정성스럽게 공들이자니 너무 많은 시간이 소요되었다. 그러던 중 파즈, 마크, 조엘 등 많은 크루들이 작성하는 TIL을 보고 영감을 받아 WIL(What-I-Learned)를 개설해서 학습한 내용을 기록하기 시작했다. 여기서 괜찮은 글감이 뽑히면 정제해서 블로그에 포스팅하는 식으로 WIL과 블로그를 관리 중이다.
그렇지만 역시 미션 피드백 회고를 빼놓을 순 없지!
- [1, 2단계 - Spring 적용하기] 현구막(최현구) 미션 제출합니다.
- [Spring 체스 - 3단계, 추가미션] 현구막(최현구) 미션 제출합니다.
- [Spring 지하철 노선도 관리 - 1, 2단계] 현구막(최현구) 미션 제출합니다.
- [Spring 지하철 노선도 관리 - 3단계] 현구막(최현구) 미션 제출합니다.
- [Spring 지하철 경로 조회 - 1,2단계] 현구막(최현구) 미션 제출합니다.
- [Spring 지하철 경로 조회 3단계] 현구막(최현구) 미션 제출합니다.
- [스프링 - 협업 미션] 현구막(최현구) 미션 제출합니다.
레벨1 미션에선 ‘정답과 컨벤션이 정해져있는 부분’들에 대해 피드백을 받았다면, 레벨2 미션부터는 전반적으로 ‘정답이 없고 고민하기 나름인’ 피드백들이 주를 이루었다.
📎 사용하지 않는 프로덕션 코드는 지우자
사용되지 않는 프로덕션 코드에 의미를 부여하고 남겨두지 말자. 그 의미는 오로지 ‘나 자신만’ 알고 있으며, 다른 사람은 의도를 이해하지 못하고 괜한 오해를 하게 된다.
📎 테스트도 유지보수 대상
테스트는 프로젝트를 설명하는 설명서다. 프로덕션 코드가 변경되었다면 테스트도 덩달아서 유지보수를 진행해주어야 한다.
대부분의(특히 한국) 사람들은 설명서를 읽지 않는다. 읽기 귀찮다. 설명서를 읽는 것도 시간을 소비하는 일이다. 너무 길고 많은, 불필요한 테스트들로 읽기 싫은 설명서를 만드는 것도 위험하다. 필요한 검증만 명확하게, 프로덕션 코드처럼 유지보수하자.
📎 DTO의 동등성
DTO(Data Transfer Object)도 결국 Data가 중요하기 때문에, VO(Value Object) 처럼 동등성 비교가 필요하다면 equals를 구현해줄 수 있다. 그러나 VO와 달리 불변성을 보장해주지 않기 때문에 (보통 DTO에 기본생성자를 구현해서 필드의 final 키워드를 붙이지 못함) 그 값 자체를 완전히 신뢰하기엔 부담이 있다.
때문에 굳이 동등성을 비교하고자 한다면 사용되는 그 시점에서만 명확하게 비교하고 사용해야할 것 같다.
📎 비즈니스 로직 예외는 비즈니스 계층에서 처리
비즈니스 로직 상에서 DAO에게 기대하는 예외 상황(ex. 이메일이 중복인지 확인하기 위해 DB를 찔러봤는데, 데이터를 찾지 못한 경우)이 발생할 경우, 해당 예외는 비즈니스 계층(ex. service layer)에서 처리해야한다.
DAO는 온전히 데이터베이스에 관련한 예외만 처리해야하며, 개발자가 기대한 예외상황을 처리하기 시작하면 계층간 경계가 무너진다. 웹 MVC 패턴에서 계층을 나누는 이유는? 유지보수를 편하게 하기 위해서. 즉 유지보수가 점차 어려워진다.
📎 HTTP 상태코드는 ‘서버의 상태’
API 서버는 보통 특정 사용처에서만 사용할 걸 의도해서 만들지 않습니다. 실제 테스트 코드 또한 프론트엔드 사이트가 아닌데 API 호출을 하고 있죠. 마찬가지로 Postman, 다른 API 서버 등이 요청 할 수도 있답니다. 그래서 상태코드도 서버가 중심이 되어야 하지 클라이언트의 상태를 고려할 필요는 없답니다.
HTTP 상태코드는 서버의 상태를 명확하게 전달하기 위함이지, 클라이언트에게 도움을 주기 위한 코드가 아니다. 클라이언트(프론트엔드)가 어떻게 구축되어있는지 모르는 시점에서 백엔드 개발을 진행하면서 HTTP 상태코드를 결정한다고 생각하면 쉽게 이해할 수 있다.
클라이언트에게는 상태코드가 아닌 에러 메세지로 도움을 줄 수 있다.
📎 CRUD Transactional
Create/Update/Delete 는 테이블에 변화를 일으키기 때문에 트랜잭션을 거는 것이 추천된다. 그러나 Read는 트랜잭션을 거는 것에 신중해야한다. (거의 걸면 안된다.)
예를 들어 1개의 서비스에서 2개의 데이터베이스(A, B)를 조회하려고 할 때, B 데이터베이스에 문제가 발생했을 경우 서비스는 트랜잭션을 지키기 위해서 B 데이터베이스의 문제가 해결될 때 까지 기다리려고 한다. (트랜잭션을 걸지 않았을 경우 바로 예외를 던지며 실패할 수 있다.)
이 때문에 Read 쪽에는 트랜잭션을 거는 것에 신중해야한다. (나중에 현업 단계에서는 더 많은 고려사항이 존재하지만, 현재는 이렇게 이해하고 넘어가자)
📎 사소한 네이밍도 인터페이스처럼
자바에서 ArrayList
를 선언할 떄 ArrayList<Integer> numbers
로 선언하지 않는다.
numbers
를 사용할 때 형태와 방식을 노출한다는 점과, 다른 리스트로 대체가 불가능 하기 때문이다.
이 때문에 우리는 List<Integer> numbers
형태로 ArrayList
를 선언한다.
사소한 변수 네이밍 또한 인터페이스처럼 여기고 지으면 좋다!
📎 서로 다른 엔티티-DAO 간 의존관계 주의
엔티티 객체와 DAO 객체는 Section-SectionDao
, Line-LineDao
와 같이 서로 1:1 매칭되어야 한다.
Line-SectionDao
식으로 직접 의존되는 경우 유지보수에 큰 어려움이 따른다.
Line
객체의 필드 값을 직접 꺼내서 사용하는 식으로 의존 관계를 최소화 해야 한다.
📎 Request Valid는 있지만 Response Valid는 없는 이유
‘왜 Response 방향의 Validation 어노테이션을 붙일 곳이 없을까’ 라는 생각에 고민중이었는데, 재연링이 해주신 말씀을 읽고 보니 ‘굳이 할 필요가 없으니까 없겠구나’ 라는 결론에 도달했어요. 문제가 발생할거라면 RequestDTO - 도메인으로 변환 과정에서 먼저 발생했어야하니, 그 이후의 데이터는 믿고 쓴다는 느낌인거 같아요.
즉, 도메인(엔티티)와 DAO가 최후의 예외 확인 지점이다. ResponseDTO에는 검증 로직이 담기지 않기 떄문에, RequestDTO(Controller), Service, Domain(Entity), DAO에서 최선을 다해 검증해야 한다.
📎 패키지 구조에 따른 중복 코드
io.github.hyeon9mak.modulename1.id
io.github.hyeon9mak.modulename1.name
io.github.hyeon9mak.modulename2.id
io.github.hyeon9mak.modulename2.color
모듈을 우선시 하는 패키지 구조의 경우 중복된 코드가 발생할 수 있다.
이 때 중복 코드를 허용할 것인지, 별도의 common
패키지를 개설해서 한 번에 관리할 것인지 고민이 생긴다.
“같은 이름을 가진 VO더라도 도메인에 따라 다른 기능을 갖을 수도 있기 때문에 중복코드라고 보지 않는 시선도 있다.”
위와 같은 의견을 떠올려 보면 충분히 중복 코드를 허용할 수 있다.
📎 DAO에서의 Optional
DAO 단에서 데이터 조회에 실패했을 때 예외처리를 어떻게 하느냐에 대해 크루들과 토론이 있었다. 나는 크게 2가지 이유로 DAO에서 Optional 사용을 지양하는 편이었다.
- 데이터 조회에 실패했다면 곧장 예외 상황으로 넘기면 될 걸, Optional이 추가 로직 가능성을 제공한다.
- 추가 로직이 수행되는지 별도로 확인 작업을 거쳐야한다.
- JPA가 Optional을 사용한다.
- JPA를 모방하기 위함인지, 실제로 조회 실패시 별도 로직을 수행하기 위함인지 구별하기 어렵다.
그러나 준호님(제이)와 이야기를 나눠본 후 ‘조회 값이 없는것 자체가 예외가 아니다. Optional을 통해 비즈니스 로직에게 선택권을 준다.’ 라고 생각할 수 있게 되었다. 게다가 Optional이 DAO 조회 결과가 Null 일수도 있다는 걸 표현해준다는 장점도 있다. (try-catch 문이 줄어드는 부가적인 효과도 누릴 수 있다!)
페어 회고
🏀 에어
정리왕 섹시에어 😂. 새로운 기능을 학습할 때마다 빠짐없이 기록하고, 그걸 검색해서 사용하는 모습에 감명 받았다. 잘 정리된 에어 블로그 글 덕분에 “이게 뭐였지..?” 하는 상황에서 바로바로 Ctrl + F 검색으로 필요한 기능을 찾아내서 사용할 수 있었다. 인간 백과사전. ‘WIL을 작성해야겠다’ 라고 마음먹게 된 첫 계기가 에어였다. 그 후 파즈, 마크, 조엘의 TIL을 보면서 구체화 되었고…
잘했다 생각이 드는 점은 에어와 페어를 기점으로, 미션 외적으로도 최대한 많이 이야기하고 취미를 즐기려 했다. “미션 완성이 페어 프로그래밍의 전부가 아닌데… 레벨2부턴 정말 포비에게 도전한다는 마인드로 임해야겠다. 내쫒으려면 내쫒으라지.” 레벨1 마지막 회고 때 다짐을 지키기 시작했다. 에어도 그게 인상적이었는지, 인상적이었던 페어로 나를 뽑아줬다😆😆😆!
아쉬웠던 점은 에어의 코드로 미션을 진행하다보니 코드 이해가 다소 어려웠던 점. 에어는 ‘다른 사람의 코드를 빠르게 이해하고 미션에 참여한 점이 인상적이었다.’ 라고 칭찬 해줬지만, 사실 꽤 많이 애를 먹었다. 자주자주 다른 사람의 코드를 읽어보면서 빠르게 이해하는 스킬을 키워야 될 것 같다.
🍺 와이비
가장 오랜 페어기간을 지낸 크루이자, 가장 많이 맥주를 마신 크루. 😅
계층별 분리나 단위 테스트 등 여러가지 이론적인 부분들을 실제로 적용하고자하는 의지가 강한 참된 지식인이다. 본인이 아는 것과 모르는 것이 명확한데, 와이비는 나무위키 식으로 WIL를 작성한다고 한다. 자신이 명확하게 아는 것에 대해 설명할 땐
눈빛이 돌변하면서 말투가 냉철해지는데, 이 땐 정말 바짝 긴장하고 와이비에 말에 집중해서 하나라도 얻어가야 한다.
와이비는 긍정적인 방향으로 대화가 이어져 나가게끔 하는 소프트 스킬이 돋보인다. 항상 긍정적인 방향으로 디펜스 해주는 느낌이 있다. 자신 뿐만 아니라 상대까지도. 기술 뿐만 아니라 사람 대 사람으로서 많이 배운다.
페어 기간 동안 잘한 점은 곧장 미션을 진행하지 않고 이론적인 부분들에 대해 끊임없이 대화했던 점. 아무래도 곧장 미션을 진행하면 좌/우 시야를 가린 경주마처럼 미션의 끝만을 향해서 달리게 된다. 그게 싫어 미션 시작을 계속 미루며 전체적인 설계에 대해 와이비와 이야기를 나누고, 취미활동을 즐겼다. 와이비 역시 그 활동들이 인상적이었는지 인상적인 페어로 나를 뽑아줬다! 😆😆😆
아쉬웠던 점은 그 취미활동을 너무 즐긴 나머지, 막바지에 들어서 시간이 부족했다는 점이다. 게다가 와이비가 페어 마지막 즈음에 ‘그 날 하루 아무것도 한게 없으면 현타가 온다’ 라고 이야기하는데, 너무 미안했다…😰 뭐든지 적당히!!
💪 마크
TIL 정리 장인.
아는 정보도 굉장히 많고 풍부한 모습에서 찰리가 연상됐다. 그 근원은 역시 TIL을 꼼꼼하게 정리하는 습관인거 같다.
코드를 짤 때도 자기만의 신념과 색깔을 갖고 있다. 그런데 마크의 배경지식이 두텁다보니, 그 신념과 색깔에 무한한 신뢰가 가게 된다.
마크와 진행한 미션은 크게 난이도가 높지 않았어서, 각자 개인 공부시간을 충분히 가지고 미션을 진행했다.
잘했다고 생각이 드는 점은 그 개인공부 시간 동안 스프링5 책을 최대한 열심히 읽은 덕분에 마크가 쏟아내는 지식들을 이해하고 의견을 나눈 것!
아쉬운 점은 둘 다 자바스크립트에 잼병이라 멘붕하는 상황이 잦았다. 프론트도 공부 좀 해야겠다고 절실히 느꼈다. 😱 그리고 미션기간이 짧았다보니 미션 외적으로 교감이 적었던게 아쉽다. 요즘도 DM으로 기술적인 이야기를 나누곤 하지만… 레벨3엔 그 외적으로 술도 한 잔하고 더 많이 친해집시다 마크…🥺🙏
🦒 파즈
첫 페어주차에 내가 테코톡, 그 다음주에 파즈가 테코톡이라 실제 페어기간이 가장 짧았던 크루.
be-positive 라는 본인 닉네임 유례답게 굉장히 긍정적인 사고의 소유자다! 덕분에 많이 웃으면서 미션을 진행했던거 같다.😆
새로운 것을 배우고자 하는 의욕이 강했고, 모르는 것을 물어봤을 때 하나하나 그림 그리면서 알려준 것도 고마웠다.
파즈와 잘했다고 생각이 드는 점은 인프라 미션을 진행하는 동안 궁금증이 생기는 부분을 놓치지 않고 그 자리에서 곧장
파고들어 학습을 진행했던 점. 덕분에 리버스프록시 - WAS - DB
인스턴스 3개를 연결하는 하나의 시나리오에 대해서도 정리할 수 있었다!
아쉬웠던 점은 역시나 서로 격주 걸린 테코톡 때문에 더 많이 붙어있지 못한 점…🥺 지하철 프로젝트 자바코드도 페어프로그래밍을 거의 못했고, 미션 외적으로도 함께한 시간이 적었다. 그래도 파즈와 DM으로 소소한 일상 이야기를 나누면서 조금이나마 가까워진거 같아서 다행이다!
레벨2는 전반적으로 짧게 끝나는 미션들이 많아서 페어활동 기간도 짧았지만, 그래서 더욱 페어와 미션 외 시간을 함께하려고 노력했다. 그 결과는? 에어와 와이비한테 인상적인 크루로 선정되는 영광을 누렸다! 미션만 하려고 우테코 왔나? 개발 좋아하는 사람들이랑 함께 웃고 떠드는 것도 우테코 활동 중 하나지! 레벨1 때의 다짐을 실천하고 좋은 결과까지 만든게 너무 행복한 시간이었다.
레벨2 기간동안 크루들과 더 많이 친해진거 같고, 레벨3 팀 프로젝트가 더욱 기대된다. 너무 신내서 까불다가 관계를 망치지 않게, 너무 열내서 진행하다 번아웃이 오지 않게. 레벨3 기간도 딱 2가지만 주의해서 성공적으로 마무리 지었으면 좋겠다!
끗!
댓글남기기