요즘 박재성(a.k.a자바지기)님의 강의를 들으며 부쩍 TDD를 사용하려고 노력중이다.
그래서 회사일을 하면서도 최대한 테스트 코드를 적용중이다.
진행 도중 기존 코드에서 인자값으로 받는 API 주소와 리턴타입만 다른 여러 메소드들이 있어 이를 리팩토링 하는 과정에서 테스트 코드를 작성하다가 이상함을 발견하였다. 의도한 바와 다르게 데이터 형변환이 되는 것이다.
회사 코드를 직접 올린순 없어서 대충 비슷하게 코드를 작성해 보았다. 블로그에는 사진으로 코드를 설명하겠다.
(자세한 코드는 Github에 올려놓았다.)
아래와 같은 json 데이터가 있다고 가정하자.
위 데이터를 받아서 처리 하기 위해 2개의 POJO를 만들었다.
그리고 이를 시험할 테스트 코드는 아래와 같다.
보다시피 DataResponse<Book>이냐 DataResponse<다른 타입의 POJO> 냐의 차이라서 당연히 Book 자리를 제네릭 T가 들어가야할 자리라고 생각하여 코드를 작성하였는데..... 테스크 코드가 실패하는것이였다.
으잉? 왜 실패하는지 궁금하여 debug 모드로 전환하여 확인해보았다.
실패의 원인은 놀랍게도 result의 타입이 LinkedHashMap으로 되어있는 것이다.
이게 좀 이해가 안되서 여러방법들을 다 사용해보았는데 내가 원하는대로 Book으로 형변환이 되지 않았다.
고민고민하다가 부끄럽지만 dosaTv 슬랙에 질문을 올렸다. 채널의 Jace Shim 님과 이것저것 얘기하면서도 뭔가 풀리지가 않아 고민고민 하고 있었는데!! 바로 그때!!
토비님(토비의 스프링의 그 토비님이 맞으십니다!!) 께서 아주아주 친절하게 그 원인과 해결책을 알려주셨다!!!
영광입니다 ㅠㅠㅠ
즉, 제네릭은 소거자(effective java 번역에선 소거자 라고 표현하더라 원문에선 erasure)에 의해 구현되어 컴파일시에만 자신의 타입 제약을 지키게 하고 런타임시에는 자신의 타입정보를 소거해버린다. 이로인해 런타임시에 기존의 코드로는 T 타입이 뭔지 알수없어서 Object로 판정 후 json 데이터의 여러 속성들을 보고 Map으로 추론해버려서 형변환을 시킨것이다.
이를 해결하려면 컴파일시에 어떤 타입이 될지 명시해주면 된다.
아래는 해결한 코드다
사실 요즘 리우 올림픽이라는 아주아주 빅 이벤트가 코앞에 다가와서 일정 압박이 장난아니다.
그래서 기존에 익숙하지 않은 테스트코드 작성 & 제네릭을 사용해볼까 말까 고민이 정말 많았다.
망설인 이유는 당연히 일정을 못지킬까봐이긴 한데 (실제로 위 테스트 코드때문에 반나절 넘게 사용했었다. 개발 진행에 크게 많은 부분을 차지하지도 않는 부분인데 말이다)
그래도 해보길 잘했다.
거의 자정이 다되서 토비님이 답변주신것 보고 어서빨리 회사가서 테스트코드 수정해보고 싶다는 생각밖에 없었다.
배우는 맛이 뭔지 하루하루 느끼고 있다.
Java Generic이나 Java 고급 기술 ( 이를테면 리플렉션 ) 이런 쪽 공부 하기 좋은 책 혹은 사이트 추천 좀 해주 실 수 있을까요?
답글
안녕하세요 seungdols님!
리플렉션에 한해서는 자바 기본서중에는 잘 표현하고 있는게 없는것 같습니다.
자바 고급은 "이펙티브 자바"를 꼭꼭 읽어보시길 추천드립니다.
자바 기본은 "소설같은 자바"를 추천드립니다. 기본서에는 없는 내용들을 상세하게 잘 설명해주고 있습니다.
Spring이나 Serlvet에 대한 이해도를 높이기 위해서는 토비의 스프링을 보기 보다는 엄진영님의 "자바 웹 개발 워크북" 읅 읽어보시길 추천드립니다.
직접 웹 프레임워크를 만들어가면서 Java와 웹에 대한 이해도를 높이는데 정말 좋습니다.
창천향로님 상세한 답변 감사합니다!!ㅎㅎ
토비 스프링은 입문용으로는 사실 너무 난해합니다...ㅠㅠ 그런데 추천해주신 서적으로 한 번 도전해보겠습니다.
이펙티브는 1독 했지만 아직은 이해도 제대로 했는지 모르기에 다시 읽어 봐야 할 것 같습니다.
소설 같은 자바는 빌려 꼭 읽어 보도록 하겠습니다.
(제가 또 스프링 공부하는지 어찌 아시고..;;
감사합니다. ^^
갓천향로님 감사합니다..!
답글
덜덜... 갓은 kingbbode님이시죠!