2023년 3월 진행된 우아한테크세미나 테크 리더 3인이 말하는 “개발자 원칙” 중 이동욱님 세션을 듣고나서 정리한 내용.

일정은 지키지만 버그가 많은 것 vs 일정은 못 지키지만 버그가 없는 것

일정은 곧잘 지켜내지만 버그를 많이 만들어내는 개발자와 일정은 못 지키지만 버그가 없는 완벽한 프로그램을 만드는 개발자 중 어떤 개발자가 더 좋은 개발자일까?

사실 이 질문에 대한 답변은 이미 2020년 4월 5일에 이동욱님 블로그에 올라온 일정 vs 퀄리티 (오늘의 질문 2020.04.04) 에 나와있다. 프로그래머에게 요구되는 것은 100점이 아닌, 80~90점 짜리 프로그램을 기한 내에 완성하는 일이다. 가장 중요한 것은 고객이 원하는 기능을 ‘고객이 원하는 시점’에 전달하는 것. 개발자 뿐만 아니라 모든 직군에 있어서, 돈을 받으며 일을 하는 프로로서 당연히 지켜야 할 원칙이라고도 볼 수 있겠다.

오해해서 안되는 것은, 일정을 지키기 위해 20~30점 짜리 프로그램을 만들어도 된다는 것은 아니다. 아무리 급해도 항상 80~90점 짜리 소프트웨어를 일정 내에 개발할 수 있는 방법을 연구하고, 연마해야 한다. 그것이 경력이고, 짬밥이고, 생산성이다.

그렇다면 항상 일정을 잘 지키면서도 퀄리티 높은 코드를 만드는 개발자들의 특징은 무엇일까?

대부분의 개발자는 자신이 최근에 접한 이야기나 읽은 책, 인상 깊었던 이야기에 따라서 매번 다르게 설계를 고민한다. 그러나 그렇게 단기간에 만들어진 원칙들은 디테일한 부분까지 답을 내려주지 못하고, 설계에 대한 확신을 갖지 못해 많은 시간을 허비하게 만든다.

그러나 실력이 뛰어난 개발자들은 본인만의 원칙을 기준으로 빠르게 의사결정을 진행한다. 그동안 경험을 통해 여러가지 확고한 원칙을 세웠기 때문에 대부분의 경우 빠르게 결정을 내릴 수 있고, 정말 설계가 필요한 부분에서만 깊은 고민을 진행할 수 있기 때문이다. 이렇게 되면 일정은 일정대로 지켜지고, 퀄리티가 정말 중요한 부분에서도 퀄리티를 챙길 수 있게 된다.

정리해보면 둘의 차이는 “매 순간마다 자신의 선택을 고민하느냐, 원칙에 따라 빠르게 결정 후 중요한 것만 고민하느냐.” 가 된다.


제어할 수 없는 것에 의존하지 않기

현실 세계의 변화와 설계 사이의 결합도를 줄여야 한다.
사용자의 휴대전화번호를 식별자로 사용하는가?
자신의 힘으로 제어할 수 없는 속성에는 의존하지 말라.

‘실용주의 프로그래머’ 중

“한국 사람의 주민등록번호는 절대 변하지 않는 고유 식별자니까, 주민등록번호를 PK 로 사용하자.” 라는 의사 결정으로 주민등록번호를 PK 로 회원정보를 저장했다가, 사용자의 주민등록번호를 함부러 수집하지 못하도록 개인정보보호법 개정되어 큰 낭패를 본 사례는 이미 너무나도 유명하다.

외부에서 전달 받은 데이터를 절대 주요한 결정 키로 사용해선 안된다. 내가 직접 만들고 관리할 수 있는 값이 아니라면, 주요한 의사결정 키로 선택하지 말자. 그래야 외부의 변화로부터 안전할 수 있고, 큰 변화가 발생하더라도 제어할 수 있다.

백엔드 입장에서는 조금 더 적나라한 이야기를 해보자. SQL 보다는 애플리케이션 레벨에서 값을 직접 다루자. 단순하게 생각했을 땐 백엔드 개발자 입장에서 SQL 보다는 애플리케이션 코드를 더 자주 보게 되므로 관리하기가 쉽고, 엣지 케이스를 생각해봐도 데이터베이스보다 애플리케이션 실행 코드를 튜닝하는 것이 훨씬 쉽다.

만약 데이터베이스에서 password(), encrypt() 와 같은 함수를 사용해서 비즈니스 로직을 구현한 경우 분산 환경, 멀티 마스터, 데이터베이스 교체와 같은 상황에서 곧바로 영향을 받게 된다. 제어할 수 없는 것에 크게, 많이 의존할 수록 변화에 쉽게, 자주 흔들리는 소프트웨어가 만들어진다.

class Car {
    var distance: Int = 0
        private set
    
    fun move() {
        val randomNumber = Random.nextInt(0, 9)
        if (randomNumber > 4) {
            distance += 1
        }
    }
}

위와 같은 Car 클래스의 move() 메서드에 대해 테스트를 작성해보자.

"자동차는 숫자 4 이상이면 이동한다." {
    val car = Car()
    car.move()
    car.distance shouldBe 1
}

move() 내부에서 Random 에 의존하고 난수를 생성하고 있기 때문에 테스트 작성이 거의 불가능하다. 확률적으로 테스트는 통과하거나 실패할 것이고, 아마도 reflection 이나 mock 프레임워크를 이용해야 테스트가 가능할 것이다. 하나의 테스트를 위해 mock 프레임워크가 추가되어야 하며, 만약 mock 프레임워크를 제거할 경우 테스트는 바로 실패하게 될 것이다. 불필요한 의존으로 인해 변화에 쉽게 흔들리는 소프트웨어가 된 상태다.

class Car {
    var distance: Int = 0
        private set
    
    fun move(number: Int) {
        if (number > 4) {
            distance += 1
        }
    }
}
"자동차는 숫자 3 이하면 이동하지 않는다." {
    val car = Car()
    car.move(3)
    car.distance shouldBe 0
}

"자동차는 숫자 4 이상이면 이동한다." {
    val car = Car()
    car.move(4)
    car.distance shouldBe 1
}

하지만 Random에 대해 의존하지 않고, Random을 통해 생성된 값을 외부로부터 주입 받는다면 내가 만들어낸 Car 클래스에 대해 자유롭고 편리한 테스트 작성이 가능해진다. 내가 제어할 수 있는 것과 제어할 수 없는 것들을 분류하면, 제어할 수 있는 것들에 대한 단위 테스트가 쉬워진다. 제어할 수 없는 내용들을 모두 mock 처리하는 것도 테스트가 쉬워진다.

내가 제어할 수 있는, 제어하기 쉬운 것들은 내가 만들어낸 비즈니스 로직들. 내가 제어할 수 없는, 제어하기 어려운 것들은 외부로부터 전달되는 UI, Data, 서버 통신들.

그렇다면 우리가 해야할 일은 무엇일까?

정말 단순하게도 제어가 쉽게 가능한 코드들을 생산해서 domain 계층을 최대한 두텁게 만들고, 제어가 어려운 코드들은 ui, persistence 계층으로 최대한 밀어넣어 격리 시키는 것. 그렇게 해서 유지보수 할 일이 생기면 domain 계층에서 최대한 일을 해결하는 것.


리더로서 제어할 수 있는 것들

리더로서 회사 생활 내에서도 내가 제어할 수 있는 것과 제어할 수 없는 것들이 나뉘어 있다. 우리 회사의 매출이나 투자 상황, 개발자의 연봉이나 업계 전반적인 분위기는 내가 제어할 수 없다. 그렇지만 우리 팀원들의 성장과 성장을 위한 환경 조성에는 기여할 수 있는 부분이 상당히 많다.

팀원들의 성장을 위해선 주변에 좋은 개발자가 많아야한다. 그러나 좋은 개발자를 쉽게 제어할 순(데려올 순) 없다. 그래서 우리 팀원들이 좋은 시니어들의 노하우를 흡수 할 수 있는 환경에 계속 노출 시킨다. (운이 좋다면 좋은 개발자가 발표 도중 우리 팀을 마음에 들어할 수도 있다!) 정기적인 외부 시니어 강연을 진행한다면 팀원들이 먼저 필요한 노하우에 대해 이야기 하기 시작한다. “YY 컨퍼런스에서 발표하신 BB 님께 여쭤보고 싶은게 있어요.”, “XX 회사의 리드로 계신 AA 님을 만나뵙고 싶어요.”

그 외에도 잦은 빈도로 피드백을 줄 수 있는 환경을 조성해야한다. 인격적인 피드백 뿐만 아니라 코드에 대해서도. sonarqube 를 이용한 정적 분석이나 테스트 코드 작성, Lint, 코드 포맷팅도 빠질 수 없는 요소다.


결론은?

제어할 수 없는 것에는 거리를 두고, 제어할 수 있는 것에만 집중하기.
할 수 있는 것에만 집중하고 긍정적으로 상황 해석할 줄 알아야 한다. 제어할 수 없는 것에 매달리고 비관적으로 생각해봤자 달라지는 것은 아무 것도 없다.

수년간 160km 이상 떨어진 다른 학교에서 연습 경기를 해야 하는 팀의 감독이라면?

“장소를 옮겨 가면서 홈경기를 치르면 원정경기에 강해질 것이다. 다른 곳에서 시합할 때의 산만함과 혼란스러움에 익숙할 테니까.” - 88연승의 비밀 중

되는 일만 하면 성공할 수 없다. 안되는 일을 되게 한다라는 믿음, 뽕이 있어야 한다. 안되는 일을 하는 곳이 스타트업이다. 그런 뽕맛이 있어야 한다.

“트래픽이 큰 회사에 가서 여러가지 장애 상황을 겪어봐야지 성장할 수 있는게 아닐까?”

물론 그런 상황을 자주 겪을수록 빠르게 성장할 수 있겠지만, 트래픽이 작다 뿐이지 우리회사에서 진행 중인 개발문화나 프로세스가 틀리지 않았다는 것을 꼭 인지해야한다. 어떻게 하면 보다 더 큰 경험을 할 수 있을지. 만약 좋지 않은 환경에 놓여 있다면 그 환경 속에서도 배울 부분을 찾아내고, 긍정적으로 생각하는 방법을 연습하자.

image


부록 - 유연하게 성장할 수 있는 개발 습관

“제가 틀렸네요.” 라고 말하고 인정할 수 있는 것. 주니어 땐 너무나 꺼내기 쉬운 말이지만 시니어가 될수록 말하기 어렵다. 연차가 쌓이기 전부터 미리미리 자신이 틀렸음을 이해하고 인정하고 이야기할 수 있는 습관을 만들어두자. 훗날 큰 도움이 되어 줄 것이다.

항상 긍정적으로 생각하고, 겸손하자.


태그:

업데이트:

댓글남기기