특수화와 범용성

Posted by 엘키의 주절 주절 on January 6, 2019

처음 프로그래밍을 시작한 시점부터 얼마나 많은 코드를 작성해왔는지, 그 코드들 중 얼마나 많은 코드가 아직도 실행되고 있는지를 알 순 없지만, 내가 짠 꽤나 많은 코드가 아직 현역일 것이다.

그 과정에서 자주 고민하게 되는 이슈 중 하나는 바로, 특수화와 범용성이다.

혹자는 특수화 자체를 나쁘다고 규정 짓곤 하지만, 투입되는 코스트가 작아지고 예외가 적어질 수 있다는 점에서 특수화는 분명히 큰 장점이 있다.

서두에 왜 내가 짠 코드가 아직도 현역일 것이란 얘기를 했냐하면, 범용성이란 내가 작성한 코드가 현역인지 여부보다는 내가 작성한 코드가 얼마나 더 수정되거나, 재사용 될 것인가에 의미가 있기 때문이다.

심지어는 수정이 되는 과정에서나, 수정이 되기 위해 검토되는 과정에서 마저 특수화가 더 중요한 가치일 때가 많다.

범용성을 위해 모호한 네이밍, 모호한 사용법, 열려있는 기능이 코드 분석을 어렵게 할 수 있는 요인이 되기 때문이다.

물론 범용성 자체가 나쁘단 얘긴 절대 아니다. 범용성 자체는 중요한 가치중 하나다. 작은 수정에도, 기존 코드에 큰 수정을 가해야해 리스크를 크게 가져가야 하는 상황은 분명히 잘못됐다. 하지만, 이미 오래 전에 open-close 원칙으로 확장에 유연하고, 기존 동작에 리스크 없게끔 범용성을 갖추는 방법이 고안되어있으며, 20-80 법칙등을 근거로 자주 사용될 때는 범용성을, 자주 호출되서 실행시간의 80%이상에 포함되는 코드는 특수화를 통한 성능 향상과 오류율 감소를 얻어내야 한다.

작성하는 코드가 해야 할 역할에 따라서 다르다는 점은 매우 중요하다. 재사용되지 않을 기능, 특수한 상황만을 위한 어쩔 수 없는 비지니스 특화 코드 등에 범용성을 위한 코스트를 들이는 것은 낭비라고 볼 수 있다.

심지어는 어설픈 범용성으로 인해, 기능을 재사용하기 위해 많은 수정이 다시 필요한 경우도 존재한다는 점도 무시할 수 없다. 모든 시나리오를 위한 범용성을 갖췄을리 없기 때문에, 새로운 요구사항 혹은 새로운 사용법이 필요해졌을 때가 대비되어 있지 않을 가능성이 높기 때문이다.

다시 고칠일이 없는 코드에 범용성을 위해 몇일을 소모하는, 휴먼 리소스 낭비마저 합리화 될 순 없다. 모두에게 시간은 평등하고, 가치 있기 때문에, 오버 엔지니어링 하지 않고 효율성도 고려하는 것이 좋은 엔지니어이기 때문이다.

대부분의 경우에는, 나쁘지 않은 구현으로 기능을 개발 한 뒤, 자주 사용되거나, 요구 사항이 확정 되거나, 피드백을 반영해서 완성하는 것이 합리적일 때가 많다.

내 경험상으로는 범용성을 위해서 들이는 코스트도, 특수화를 위한 결단과 판단력도 모두 빠른 프로토타이핑 혹은 방향성을 확인하기 위한 예광탄으로 검증 된 뒤 고도화 하는 것이 합리적인 경우가 많았다.

대부분의 요구 사항은 결과물을 보기전까지 모호함과 결함을 내재하고 있기 때문이다. 이 것이 애자일에서 주로 언급하는 빠른 이터레이션이다. 그 과정을 좀 더 명확해진 설계로 이어지고, 곧 좀 더 특수화, 범용화 하기 쉬워진다.

재작업을 비효율이라 여기는게 개발자들의 공통적인 생각인데, 범용화를 위해 쓰이는 시간이 낭비가 될 수 있다면, 이 역시 비효율로 여겨져야 한다고 생각한다.

범용화를 위해 확장성도 있고, 안정성도 잡는 룰을 갖추고, 그 룰의 시행착오를 갖추고 적용하기 위해선 아주 아주 많은 코스트가 들지만, 그만큼 가치있다.

그럼에도 거기에 들어가는 시간이 과다하다면, 엔지니어도, 엔지니어와 협업하는 다른 사람들도 납득시키기 어렵다.

난 코드 작성시의 범용성을 최우선 가치로 여기는 것은 옳지 않다고 생각한다. 범용성이 필요한 상황은 분명히 존재하나, 항상, 매번 중요한 가치로 여겨지기엔 들어가는 코스트가 너무 크고, 그 코스트가 효율성을 얻기 어려운 상황을 나는 매우 자주 접했기 때문이다.

빠른 구현을 통해 방향성과 타당성을 검증하고, 그 이후에 범용성을 선택할지, 특수화를 선택할지 상황과 해야 될 일에 맡게 판단하는 것이 합리적인, 실용적인 프로그래머가 아닐까?