브라이언이 모의 면접을 해주셨다. 사실 잘 생각해보면 준비가 하나도 안 되어서 면접이 의미 없을 수도 있었는데, 면접을 제대로 본 적이 없기에 일단 신청해봤었다. 사실 많은 분들이 지원하실줄 알았는데, 그게 아니어서 걱정이 살짝 되기도 했다. 그럼에도 카카오페이 과제에 집중하느라 제대로 준비하지 못했는데, 뭐 어찌 뙜건 얻은게 많다.
그 동안 면접에 대해 너무 안일하게 생각하고 있었던게 아닌가 하는 생각이 많이 들었다. 자기소개부터 시작해서 호눅스가 항상 말해주던 자신의 언어로 개념을 설명할 수 있어야 한다는 말을 왜 반복해서 해주셨는지 알 수 있었다. 거기에 준비도 안 되어 있는데, 개념까지 부족하니 나도 모르게 위축되고 그러다 보니 태도도 별로 좋아보이지 않았을 것이다. 그 외에 모르는 것을 함께 질문해가며 알아가는 것도 단박에 되기는 힘들다는걸 알게 됐다. 면접 리뷰나 가이드 같은걸 들을 때는 '아~ 저거 당연히 저렇게 해야지~' 이렇게 생각을 했는데, 막상 하니 쉽지가 않다. 무엇보다도 그런 식으로 어필할 수 있는 기회인지도 여유가 없으니 알기가 힘들었다.
앞서 얘기했지만, 매번 코테에서 떨어지다보니 기술 면접을 제대로 볼 기회가 없었는데, 너무 좋은 경험을 한 것 같다. 이번에 안 해봤으면 코테 붙고도 뭘 해야될지 몰라서 많이 헤멨을 것 같다. 문제는 이제 뭘 해야될지 아니 부담이 커지는건데, 열심히 해야지~ ㅎㅎㅎ..
어제 필요한 부분은 다 완성했고, 오늘은 인수테스트를 짜볼지 혹은 mysql로 마이그레이션을 할지 선택을 해야했다. 이래저래 생각해보다가 지금까지 단위테스트 해놓은게 아까워 인수테스트를 하기로 했다. 금방 끝날 줄 알았는데 고난의 시작이었다.
코쿼 프로젝트를 하며 삽질을 꽤 해봤기 때문에 틀 잡고 테스트 짜는 것 자체는 크게 어렵지 않았다. 하지만 문제는 테스트가 제대로 돌아가지 않았다. 단위 테스트에만 의존하다보니 프로그램 자체가 제대로 돌아가지 않는 것을 놓쳤던 것이다.
가장 먼저 찾아낸 것은 nano second 표현 방법과 관련된 것이었다. 나는 "2021-07-06T04:56:00.055" 와 같은 식으로 입력을 했다고 생각했는데, 결과가 그렇지 않았다. DB에 들어갈 때 부터 문제가 있었는데, 알고보니 내가 모르고 써서 문제였던 것이다. 다른 날짜 프레임워크나 언어도 마찬가지겠지만, LocalDateTime.of(year, month, date, hour, min, sec, nano sec)
과 같이 입력을 한다. 여기서 nano sec은 000, 000, 000
과 같이 구성되어 입력도 똑같이 000000000
의 형태로 해줘야 하는데, 이 부분을 놓치고 055
로만 입력을 해주고 있었다. 왜 그런지는 구현을 뜯어봐야 알겠지만(사실 이해가 안 된다), 어찌됐건 55000000
처럼 입력해야 내가 의도한 값이 나온다. 이외에도 앞에 0은 빼줘야 한다. 예를들어 055000000
는 다른 결과가 나온다.
둘 째로 문제가 발생했었던 LinkedHashSet의 순서가 내가 생각한 것과 다르게 나오는 것이었다. 분명 DB에 잘 들어갔고, 쿼리도 제대로 됐는데 결과가 맞지 않았다. @OrderBY
를 붙여주는 것으로 해결했는데, 그럼에도 인스턴스는 PersistSet이었다. 이 것도 구현을 좀 살펴봐야 더 어려운 문제가 발생했을 때 대응이 가능할 것 같다.
셋 째로 설계상 오류가 있었는데, 우선 관계 테이블의 제약에 제대로 걸리지 않았다. 복합 유니크 및 NotNull 제약을 걸어주고 나니, 애초에 서비스 로직의 흐름 자체가 잘못됐다는 것을 꺠달았다. 너무 기본적인 것인데, 목업 테스트로 처리하니 제대로 캐치 하지 못했던 부분이었다. 한 번에 문제를 처리할까 하다가 인수테스트와 단위테스트의 이러한 차이점을 좀 더 느껴보려고 단위테스트를 통과할 정도로만 로직을 짜놓고 인수테스트로 넘어갔다. 결국 정확한 로직은 인수테스트를 거쳐야 완성이 됐는데, 이렇게 되니 단위 테스트에 대해 생각을 다시 해보게 됐다.
마지막으로 테스트 데이터에 대한 문제가 있었다. 통합테스트 케이스 시나리오를 짜다보면 DB에 종속적이게 되는 경우가 생긴다. 단순 조회야 상관없겠지만, 삽입 수정 삭제가 들어가는 테스트를 통합테스트로 진행하게되면 DB에 있는 값이 변한다는 것이기 떄문에 각 테스트에서 사용하는 값이 매번 달라질 수 있다. 하지만 해당 테스트의 세팅은 해당 테스트에 맞도록 되어있는 것이 훨씬 편하다. 가장 큰 문제는 그렇게 하지 않으면 테스트 간의 종속성이 생겨버린다. 예를 들어 조회를 테스트 해보고 싶으면 삽입 테스트의 다음 번에 위치해야 한다는 점이다.
나의 경우도 마찬가지였는데, 전체 조회 테스트가 입력 테스트 이후에 이루어지다보니 내가 알 수 없는 결과로 이어졌다. 그러다보니 DB를 초기화 해줄 방법을 찾게 됐는데, 처음에 트렌젝션 어노테이션을 붙여봤지만 제대로 동작하지 않았다. 내가 제대로 이해하지 않고 그냥 뭔지만 아는 정도로 사용을 하다보니 문제가 됐던 것 같다. 모의 면접때도 질문 받았던 것이긴 하지만 얼른 공부를 해봐야 할 것 같다. 결국 DB에 값을 직접 넣어주는 방법을 선택했다. 이 것도 처음에는 쉽지 않았는데, JPA에서 업데이트 된 값을 제대로 찾을 수 없다는 문제가 계속해서 발생했기 떄문이다. 영속성 컨텍스트의 성질과 관계가 있는 문제인 것 같은데, 이 부분도 따로 공부를 해봐야 할 것 같다. 그리고
단위 테스트에 대해 생각을 다시 해봤다고 했는데, 단위테스트가 필요 없는 것은 아니다. 이번에도 리팩토링이나 로직 수정을 할 때 많은 도움을 받았다. 그런데 항상 단위테스트를 하면서 느끼는 점이 있는데, 가끔 단위테스트 내부에 로직이 들어가버리는 경우가 생긴다. 처음에는 테스트 단위가 너무 크니 좀 더 세부적인 테스트로 각각의 로직을 검증할 수 있도록 수정을 해야 한다고 생각했다. 틀린 것은 아닌 것 같고, 효과도 있었다. 그렇게 되면 해당 레이어에서는 진짜 그 레이어의 역할을 제대로 수행하는지만 테스트 할 수 있다. 어제 느꼈던 컨트롤러 단위 테스트의 역할과 비슷한 느낌인 것 같다.
그리고 JPA테스트를 하면서 느꼈던 부분도 마찬가지일 것이다. 어디선가는 로직에 대한 검증이 필요한데, 단위테스트는 해당 단위만을 테스트해야 하기 때문에 여러 단위들이 모이는 부분에 대한 테스트는 힘들다. 물론 합쳐지는 포인트마다 테스트를 짤 수 있겠지만 사실상 그러다보면 통합테스트와 차이가 없어지는 것 같다. 차이점이 있다면 엔드포인트 정도? 엔드포인트가 다르기 때문에 클래스의 래핑이나 표현이 조금 달라지긴 하지만 어쨌든 테스트 해야하는 알맹이는 같다. 이런 점 때문에 ATDD가 생겨난게 아닌가 하는 생각이 들었다. 조만간 ATDD도 공부를 해봐야겠다. 테스트가 고되지만 중요하다고 생각하는데, 어렵지만 알아갈 수록 재밌는 것 같다. 예전에 엑셀로 관리하던 테스트 문서의 트라우마가 남아서 그런 것일 수도 있겠다...
휴식
카카오페이 과제에 레디스를 붙여보기로 했다. 과제 막바지에 생각해봤던 레디스를 활용해서 캐싱하는 것인데, 쓰기 쉽게 나와있어 구현 자체는 어려울 것 같지 않다.
-p
명령어는 publish를 뜻하는 것이다. host에 노출시킬 포트를 뜻한다. 그렇게 되면 호스트(도커가 깔린 컴퓨터)에 해당 포트가 활성화 된 것을 확인할 수 있다. 즉 로컬호스트로 직접 연결이 가능해진다. 이는 도커 프록시가 연결을 감지해주기 때문이라고 한다.RedisTemplate과 RedisRepository를 제공해준다. 인스턴스로 Lettuce와 Jedis를 사용할 수 있는데, Lettuce가 기본으로 내장돼있다고 한다.
RedisTemplate은 수동으로 키를 지정해주는 것이고, RedisRepository는 Spring Data에서 제공하는 Repository인터페이스처럼 엔티티 타입과 ID타입을 지정할 수 있다.
MockMvc 분석
잭슨 리퀘스트 바디 파싱 분석
알고리즘
OS
AWS 강의듣기
s3 이용
블로그
면접
오라클이나 postgresql
Powered with by Gatsby 2.0