오늘 오후 1시에는 예비군 훈련이 예정되어있었다. 그래서 오전에는 개발보다는, 독서와 강의를 보고서 공부했다. 원래는 프로젝트를 먼저 하고, 여유롭게(?) 독서와 강의를 보려고했는데, 프로젝트 개발하다가 중간에 끊고 가면 이거 진짜 계속 생각날 것 같아서 순서를 뒤집었다.
TestContainer
친 누나에게 생일선물로 부탁했던, "더 자바, 애플리케이션을 테스트하는 다양한 방법" 강의 중, 가장 궁금하고 지금 내게 가장 필요한 부분이라 생각했던 TestContainer 에 대하여 강의를 공부했다.
나는 최근 가장 큰 고민이었던, 카프카를 사용하는 부분에 있어 통합테스트 부분에 대하여 고민이 많았다. 어떻게 실제카프카 클러스터와 정상적인 상호작용을 안정적으로 검증할 수 있을까? 하는 고민을 했고, 나는 spring-kafka-test 를 통해 EmbededKafka 를 사용하여 해당 문제를 해결했다.
하지만 지금은 카프카와의 통합테스트만 이렇게 진행이 된것이고.. 아픙로 계속해서 개선해나갈 현 프로젝트에서 외부 서비스를 사용한다면..? 나는 또 다시 이런 고민을 계속해서 해야한다.. 이것은 솔직하게 나에게 피할수 없는 부담이 된다.
그런데 이 고민을 풀어줄 수 있는 TestContainer 을 사용한 통합테스트 진행 방법을 알게되었다. 기본적으로 Docker 를 사용하여 진행하는 방법이었는데, 기존에 내가 사용하던 방식과 차이점이라고 한다면, 테스트를 실행할 때, 테스트에 사용할 컨테이너를 직접 관리하지 않아도 된다는 것이었다. 테스트가 실행되면, 설정한 컨테이너가 자동으로 생성되고, 테스트가 종료되면 자동으로 컨테이너의 사용을 중지했다.
이를 잘 공부하고 정리해두면 분명 지금 뿐만아니라 실무에가서도 큰 도움이 될 것 같다.
예측 가능한 코드: 매직 값을 사용하지 말자
오늘 오전 독서는 좋은코드 나쁜코드의 chapter.6 예측 가능한 코드를 작성하라 를 독서했다. 해당 챕터는 아직 모두 다 보지는 못했지만, 이전 챕터 들에서의 고민(?)을 어떻게 해결 할 수 있을지 힌트를 얻을 수 있었다.
일반화를 할 수 없지만, 대부분의 개발자들은 다른 개발자가 개발한 코드를 기반으로 개발을하고, 또 다른개발자는 내가 작성한 코드를 기반으로 자신의 코드를 작성할것이다. 그리고 이는 무한의 굴레처럼 반복되겠지..
내가 작성한 코드를 다른사람이 오해하지 않고 잘 사용할 수 있도록 하는 것은 작성자의 책임일까? 나는 이에대해서 그렇다고 생각한다. 그래서 나는 코드를 개발할 때, 해당 클래스에서 하고자 하는 바를 명확하게 표현하고 싶었다. 그렇지 못한다면, 주석, 문서화를 진행했었다.
하지만 코드 문서, 주석은 생각보다 무시될 경우가 많다는 것을 알게되었다. 이전 회사의 사수조차도 문서를 작성하라 했지만, 정작 내가 작성한 문서는 한번도 보지 않았다.(대문짝하게 작성되있는걸 몰랐으니, 말다했다.) 주석을 달면 지저분하다. 코드만 봐도 이해할 수 있다. 라는 피드백을 해주었었다. 이것 관련하여 이야기하면 하소연이 될 것 같고, 무튼 내가 하고싶었던 말은 코드문서, 주석은 무시가 될 확률이 매우 높다. 그리고 책에서도 같은 의견이었다.
하지만 나는 어떻게하면 주석없이, 코드문서없이 해당 클래스를 어떻게 제대로 이해할 수 있을까?(혹은 시킬 수 있을까?) 에 대한 방법을 몰랐다. 관련해서 같은 고민을 하는 사람을 찾을 수도 없었고, 이 고민을 공유할 사람이 없었다.. 그리고 시간이 흘러 지금, 책을 통해 그 답의 힌트를 얻었다.
예측 가능한 코드를 작성하는 것은 무언가를 분명하게 하는 것일 때가 많다. - 책의 일부분-
나는 이 부분을 보고서 처음에는 무슨 당연한말을하는거지? 하는 생각이 가장 먼저 들었다. 그런데 시간이 조금 지나고, 책을 계속 읽으면서 나는 과연 분명하게 했나?하는 생각이 들기 시작했다.
책에서는 매직 값을 반환하지 말아야한다고 한다. 매직값(magic value)는 함수의 정상적인 반환 유형에 적합하지만 특별한 의미를 갖고 있는 값을 말하며, 값이 없거나 오류가 발생했음을 나타내기 위해 -1 을 반환하는 경우를 예시로 이야기 할 수 있다.
나는 지금까지 타입을 명시해야하는 것이 의무가 아닌 언어(파이썬, PHP) 를 사용한 개발을 해왔었기에, 매직값에 대한 경험이 없지않나? 하는 생각을 했었다. 하지만 이는 아니었다.
Default Value 의 사용
분명 default value 와 mgaic value 는 다르다. 그런데 책을 보다보니, 내가 default value 로 사용한 것이 올바르게 사용한 것일까? 그리고 default value 값을 사용하는 것이 좋을까? 하는 생각이 들었다.
이에 대한 고민은 GPT와도 이야기를 해보았다.
GPT 는 magic value 는 프로그래밍 컨텍스트에서 default value 를 의미할 수 있다고 한다. 그런데 이후로 답변이 조금 이상해서 다시 물어보았다.
GPT 는 기본값과 마법 값은 동일하지는 않지만, 적절한 맥락과 설명이 부족할 경우 기본값이 마법 값이 될 수 있다고 한다.
다시 내 지난 상황들을 회고해보면, 나는 값이 제공되지 않을 때, 사용되는 값으로 Default value 를 사용해왔다. 이것이 제대로된 default value 로서의 가치를 했는가? 라고 스스로 물어본다면, 그렇기도하고 아닌 것 같기도 하다. 왜냐하면 이는 내 주관적인 견해로 작성했기 때문이다.
작성한 코드를 함께 리뷰하는 과정이 있었다면, 제대로 사용했건 잘못사용했건 내 주관에 객관 한방을을 첨가할 수 있었을텐데 아쉽다.
책에서는 magic value 사용 문제의 해결책으로 Null 과 Optional 을 반환하라 조언해 주었지만, 나는 default value 사용 또한 해당 조언에 포함되면 좋을 것 같다는 생각이 들었다. default value 가 예측가능한 결과를 항상 유도할까? 하는 생각이 들었기 때문이다.
이 책을 읽으면서, 점점 좋은코드에 대한 조건이 점점 생기는 것 같다. 처음에는 가독성이 좋은 코드가 좋은 코드라고 생각했는데, 이제는 예측가능해야한다.
- 가독성이 좋다: 코드의 논리가 글 처럼 쉽게 읽혀야한다. 중간에 물음표없이 해당 코드의 로직이 그려진다면 가독성이 좋다 이야기 할 수 있을 것 같다.
- 예측 가능하다: 작성자의 추측(가정)이 아닌, 다른 어떤 사람이 보아도 해당 기능을 하도록 예측 가능해야한다.
Message 계층 개발 간 발생한, 참조오류
지난 EmbededKafka 를 통해 카프카 통합테스트를 진행하면서, 관련 마지막 클래스인 Listner 테스트를 위한 코드를 작성하는데 오류가 발생했다. 해당 에러의 원인은 다음과 같았다.
Caused by: java.lang.ClassCastException: class com.shoes.ordering.system.PaymentResponseAvroModel cannot be cast to class com.shoes.ordering.system.common.kafka.model.PaymentResponseAvroModel (com.shoes.ordering.system.PaymentResponseAvroModel and com.shoes.ordering.system.common.kafka.model.PaymentResponseAvroModel are in unnamed module of loader 'app')
에러메시지를 확인해보면, 클래스 캐스팅에서 문제가 발생했다. 해당 에러를 보고, 내가 클래스 참조를 잘못한 것인지 바로 경로를 확인해보았다.
정말 이상했다. 같은 경로의 PaymentResponseAvroModel 을 바라보는데 왜 이런 에러가 발생하는거지? 하는 의문이 지워지지 않았다. 그래서 하나하나 확인해보기 시작했다.
com.shoes.ordering.system.PaymentAvroModel 에 대하여
PaymentAvroModel 은 프로젝트가 실행될 때, 자동으로 생성된다. 그리고 나는 생성된 클래스를 com.shoes.ordering.system.common.kafka.model 로 옮겨 사용하고 있다.
나는 가장 먼저 com.shoes.ordering.system.PaymentAvroModel 을 사용하는 클래스가 있는지 먼저 확인을 했다. 그리고 결과는 당연하게도 없었다.
그렇다면, 어떻게 해당 경로의 파일을 바라본다는 것인지 이해가 가지 않았다. 그래서 테스트 하는 클래스의 경로를 com.shoes.ordering.system.PaymentAvroModel 으로 변경을 해보았다.
- Test 에서의 경로는 com.shoes.ordering.system.common.kafka.medel.PaymentAvroModel 으로 변경하지 않았다.
그리고 정말 놀랍게도, 해당 오류가 사라졌다. 이로 인해, 원인은 줄여졌다. 테스트가 실행될 때 캐스팅이 잘못된다는 것이다.
원인은 파악을 했는데, 이를 어떻게 수정해야할지 모르겠다.. 그리고 이 문제가 해결되면, 다음 문제로 지금 클래스를 어떻게 검증해야할지도 의문이다.. 나는 메시지를 정상적으로 수신했다는 것을 기록하지 않아서 어떻게 해야할지 모르겠다...
내일은 승원이를 만나서 같이 모각코를 하기로했는데, 가면 코딩보다는 개발관련된 질문과 피드백, 그리고 이력서 수정을 할 것 같다. 가능하면 밀린 정리도 할 수 있다면 해봐야겠다. 개발은 외부 모니터가 없으면 못해...
'회고 > TIL' 카테고리의 다른 글
Order Messaging 계층 1차 마무리, DataAccess 계층 개발 시작, 독서 (0) | 2023.08.23 |
---|---|
이력서 업데이트, 친구와 모각코 (0) | 2023.08.22 |
테스트 개선과 깨지기 쉬운 테스트?, 신규 이슈 등록 (0) | 2023.08.20 |
드디어 메시징 테스트 진행, 거의 다 온 것 같다(?)[ 3AM, 문제해결 ] (0) | 2023.08.19 |
Application 계층 완료, Adapter 개발시작, 디자인패턴공부 (0) | 2023.08.17 |