테스트를 작성하는 것과, 테스트의 대상이 될 로직을 작성하는 것은 마치 서로 다른 사람이 하는 것처럼 구성해야 한다고 느꼈다. 내 입장에서 TDD의 원칙이 도움이 되었던 건, 테스트를 먼저 공격적으로 작성해두고 나서 그 요구사항을 충족시키기 위해 로직을 방어적으로 개발하게 되었던 부분이다. 로직을 먼저 작성하고 이걸 바탕으로 테스트를 만들면, fail이 나지 않게 하고 싶어서 괜히 테스트를 더 보수적으로 작성하곤 했으니 말이다.
테스트 커버리지가 100%인 코드도 버그가 생길 수 있다. 커버리지라는 게 솔직히 그냥 '코드가 이만큼 실행됐다'는 거지 '모든 시나리오로 테스트되었다'가 아니기 때문이다. 커버리지가 100%라고 해서 마냥 안심할 게 아니라, 어떻게 하면 내가 만든 코드가 에러를 뿜게 할 수 있을지 별 짓을 다 해보는 게 중요하다.
'테스트는 얼마나 작성해야 하나?'라고 했을 때, 테스트 덕분에 신규 작업자가 특별한 배경지식 없이도 코드를 마음껏 리팩토링할 수 있으면 충분한 것이라고 생각한다. 쉽지 않은 일이고, 내가 내년에 정말 많이 노력해야 할 부분이다.
외부 의존성이 없어야 하는 게 unit test의 조건이다. 나는 API와 관련된 부분을 많이 작업하는데, 보통 다 DB와 연계되어 있어서 unit test를 제대로 작성하려면 mock, stub 등의 방법론을 통해 고립을 보장해야 한다. 그러고 나서는 DB와 연결해 로직을 테스트하는 integration test도 작성해야 한다. 그러나 한정된 시간 내에서 작업하는 와중에 unit test에 욕심 부리기는 힘들다고 느꼈다. 테스트의 효용성과 테스트 퀄리티 간의 트레이드오프라고 정리하면 될 것 같은데, 애초에 커버리지도 낮은 와중에 빠르게 변화하는 프로덕트에 발맞춰서 이상적인 테스트 코드를 작성하긴 어려웠다. Integration test라도 빡세게 만들자.
integration test는 보통 사이드이펙트를 만든다. 테스트 A는 어느 테이블에 몇 번의 insert/update를 가하며 api 호출을 하고, 테스트 B는 테스트가 종료될 때 그 테이블을 truncate한다고 치자. 싱글 프로세스로 테스트가 돌아갈 땐 문제가 발생하지 않겠지만, 여러 프로세스가 테스트를 실행하는 상황을 가정해 보겠다.
프로세스 1이 테스트 A를 실행하는 와중에 프로세스 2가 테스트 B를 실행하면 테이블의 내용이 중간에 truncate되어 테스트가 실패할 가능성이 생긴다. 테스트 각각은 독립적이어야 하며, 순서에 의존하지 않아야 한다. 프로세스 20개가 동시에 무작위로 돌려도 문제 없는 테스트를 만들어야 한다.
나는 정해진 시간 내에 만들어낼 수 있는 output의 수준이 높으면 'capacity가 높다'고 이야기한다. 나보다 capacity가 높은 사람이 대충 만든 결과물이 내가 공들여서 만든 결과물보다 나을 수 있다. 업무 과중의 기준은 상대적이다. 어쩔 수 없이 나쁜 코드를 작성할 수는 있지만, '어쩔 수 없이'의 빈도를 낮출 수는 있겠다고 느꼈다. 그 방법이 뭐던 간에 capacity를 올려야겠다.
내가 사람을 평가한다면 '함께 일하고 싶은 사람인지'를 따져볼 것 같다. 내가 그런 사람이 되려고 노력하면 자기계발에 긍정적일 것 같았다. 물론 내 자신의 실력 수준에 아직 자신감이 많진 않다. 그만큼 올해에 성장을 크게 하지 못 하기도 했고. 레벨업을 좀 하긴 했는데 스탯이 여기저기에 분배된 느낌.
얼마 전에 이게 꼰대들이 하는 이야기라는 걸 봤다. 그래서 앞으로 남들한테 이 말을 하진 않겠지만(..), 누가 나한테 이 이야기를 한다면 정말 많이 동의할 것 같다.
소프트웨어라는 게 참 여기저기에 많이 얽혀있다. 운영체제나 설치된 패키지 버전, 프로세서의 비트 수, 서버에 설정된 네트워크 규칙 등 production에서는 신경써야 할 게 꽤 많다.
알고리즘은 어떤 입력 값에 대해서도 대응할 수 있는 일반적인 방법이어야 한다. 꼼수는 어떻게든 무너지게 되어 있다. '되게 만들기'와 '잘 되게 만들기'는 수준 차이가 큰 것 같다.
소프트웨어 전체로 따졌을 때, 나는 아직 많이 아는 상태가 아니다. 적어도 아는 것보다 모르는 게 더 많다. 뭐 좀 더 안다고 까불고 다닐 게 아니라 내년이면 5~6년째 일하고 있는 사수 따라잡는다 생각하고 공부해야 하는 게 맞다.
정리되지 않은 질문은 보통 환영받기 어렵다. 질문을 얼버무리기 시작하면 팀플레이에 큰 손해를 준다. 올해에 내가 그런 적이 많기도 했고, 외부에서 정리되지 않은 질문을 받아보기도 하니 경험적으로 확실히 느꼈다.
어차피 내 주변 사람들은 '도와주면 잘할 놈들'이다. 동료를 돕는 데에 시간을 내면, 그 시간동안 단순히 내 작업을 하는 것보다 더 많은 output이 잠재적으로 보장되는 경우가 꽤 많았다.
일이 잘 되게 하는 요소가 있다면 건의하고, 일이 안 되게 하는 원인이 있다면 '이래서 못했다'는 핑계를 댈 게 아니라 주변에 도움을 요청하면서라도 해결해나가야 한다. 그러라고 돈 받으면서 일하는 거니까.
퍼포먼스에 기복이 생기는 경우가 많았다. '적어도 무조건 이 만큼은 할 것'이라고 보고 일을 맡길테니, 내년엔 확실히 보장된 capacity를 확보해야 한다.
야심차게 진행했던 '백엔드가 이 정도는 해줘야 함'이 계획해 두었던 내용의 20% 남짓만 공개되고 연재가 멈춰졌다. 파이썬이나 Flask 관련 시리즈도 한두 챕터만 작성하고 말았다. 차라리 남는 시간이 있었더라면 내년 초부터라도 다시 진행해봤을텐데, 책 집필에 시간을 쏟게 되어 적어도 내년 4월까지는 연재가 멈춰진 채 두어야 한다는 게 너무 아쉽다.
레포만 만들어 놓고 손대지 않은 프로젝트가 꽤 많다. tf-idf 구현체, 마인크래프트 모드, 간단한 http 프레임워크, 앱 프로젝트 등등.. 레포 만들자 마자 바로 코딩해야 뭐라도 나오는데 그냥 미뤄버려서 보류된 채 가만히 두게 됐다.
개발에 대한 통찰이 공감이 가는내용이 많고, 고민을 많이한 흔적이 느껴지네요
정리도 잘하시는 것 같습니다!
잘 읽고갑니다.
기회가 닿는다면 언젠가 함께 일해보고싶은분이네요 ㅎㅎ