'스타트업'에 해당하는 글 1건

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

동료들과 대화를 하다보면 오버엔지니어링이라는 단어가 종종 나온다. 주로 안 좋은 문맥에서 이 단어를 사용하게 된다. 전임자가 어떤 코드부분을 오버엔지니어링 해놓아서 이해하기가 어려웠다고도 하고, 더 나아가서는 시스템 자체가 오버엔지니어링 되어 있어 유지보수에 큰 어려움을 겪는다고 얘기하기도 한다. 오버엔지니어링이 미치는 부정적인 영향아 많아 보인다. 그런데, 여러 관점에서 생각해보니 오버엔지니어링은 단순히 부정적으로 보기에는 아깝고, 여러모로 생각할만한 꺼리가 있다고 생각한다. 그래서 이번 글에서 오버엔지니어링에 대한 생각을 정리해보려고 한다. 


1. 오버엔지니어링? 엔지니어링?


오버엔지니어링에 대한 여러 얘기를 나누기 전에 오버엔지니어링에 대한 간단한 정리가 필요할 것 같다. 위키피디아 등의 정의와 더불어 개발자들이 보통 인식하는 오버엔지니어링은 다음과 같다.


현재 필요한 것 보다 더 과하게 제품을 디자인 하는 것이다. 즉, 제품을 더 견고하게 만들거나, 더 복잡하게 만드는 것이다. 핵심개념만을 담아 최대한 단순하게 만들자는 최소주의와는 대비되는 개념이다. 예를 들어 실제로는 만 명의 사용자가 쓰는 시스템이 내부적으로는 1억의 사용자에 맞춰 설계 개발되어 있고, 이로인해 100만의 사용자 규모에는 필요없는 구성요소들이 들어가 있을 때 오버엔지니어링 되어 있다고 얘기한다. 보통 오버엔지니어링 되어 있으면 이후 제품을 운영 할 때 어려움을 줄 때도 많다. 단순한 구조에서는 간단히 할 수 있는 일을 더 복잡하게 해야 하는 등이 일이 발생하기 때문이다.


추가로 앞으로의 글에서 자주 사용할 '엔지니어링'이라는 표현에 대해서도 정리를 해보고 싶다. 나는 기능구현을 위해 꼭 필요한 것은 아니지만 안정성이나 확장성을 위해 부가적으로 하는 일을 '엔지니어링 한다'고 표현한다. 예를 들어 안정성을 위해 입력값을 검사하는 코드를 넣는 것이나 향후 확장성을 위해 디자인 패턴을 적용하는 것 등이 있다. 이러한 활동이 과다해지는 것을 사람들이 대게 '오버엔지니어링 한다'라고 표현하는 것을 볼 때 뜻이 적절하다고 본다. 하지만, 다른 사람이 동일하게 표현하는 것을 한번도 못 보아서 확신은 없다. 


2. 오버엔지니어링이 시작되는 이유


오버엔지니어링의 정의만 보면 이상할 수도 있다. 왜 필요보다 과하게 만드는 걸까? 내 생각에 개발자가 오버엔지니어링을 하게 되는 계기는 이렇다. 보통 초보 개발자 시절에는 오버엔지니어링을 하지 않는다. 아니 못한다. 아무래도 개발 실력이 부족할 때는 다른 것에 신경 쓸 여력이 없기 때문이다. 따라서 일단은 단순히 잘 동작하는 제품을 만드는 데 집중하고 집중한다. 얼마 후 본인이 만든 잘 동작하는 제품을 릴리즈한다. 릴리즈 후 정신없이 고객문의가 들어온다. 다양한 고객문의를 보며 안정성, 예외처리 등 고려하지 못한 부분이 많다는 것을 깨닫는다. 이런 문제를 해결해가며 잘 동작하는 기능 말고도 중요한 게 있다는 것을 깨닫는다.


다음 제품부터는 적절히 엔지니어링을 하기 시작한다. 예전과는 달리 입력 값이 잘못 들어왔을 때를 대비한 처리를 해놓기도 하고, 소스 구조도 단순히 동작하는 것을 넘어 나중에 고치기 쉽게 만들기도 한다. 이런 과정에서 초보 시절 단순히 기능구현만을 신경썼을 때 보다 소스량이 다소 늘어나게 된다. 보통 이정도 수준까지는 오버엔지니어링이라고 부르지 않는다. 오히려 코드 리뷰 등을 할 때 이런 부분에 신경 쓴 것에 긍정적인 평가를 받을 때가 잦다. 이렇게 긍정적인 평가를 받다보면 아무래도 이런 부분을 지속적으로 신경쓰게 된다. 더 고려해야 할 것이 없는지 비판적인 시각으로 제품을 살펴본다. 


경험이 많아짐에 따라 단순히 입력 값이 잘못 들어왔을 때를 대비해 몇줄의 소스 코드를 넣던 수준에서, 시스템 구조 수준에 대비를 하기에 이른다. 예로 왠지 미래에 생길 것 같은 다양한 보안 요구사항을 고려하여 복잡하지만 유연한 보안 관련 프레임웍을 미리 도입하기도 하고, 당장은 불편하지만 차후 확장성이 좋은 방향으로 저장소 구조를 설계하기도 한다. 이렇게 하는 이유는 잘못된 입력 값을 처리하던 이유와 같다. 미래에 있을법한 일에 미리 대비하여 제품의 안정성 등을 확보하자는 것이다. 이정도 수준에 이르면 종종 주변 동료에게 오버엔지니어링이 아니냐는 도전을 받기도 한다.


3. 엔지니어링은 성공해야 하는 투자


그렇자면 오버엔지니어링이 나쁜 것인가? 예로 저장소 구조에 대한 가상사례를 가지고 생각해본다. 단순히 개발해도 약 500만명의 사용자까지는 문제 없는데, 1억명 까지 사용자가 늘어나는 상황을 고려해 구조를 설계 및 구현해놓았다. 제품을 릴리즈 하고 서비스를 한다. 그런데, 초기 사용자는 10만을 넘지 않는다. 1년이 지난다. 서비스 사용자는 여전히 100만 정도이다. 당분간 더 늘 것 같지도 않다. 이 때 저장소 구조에 대해 이미 해둔 엔지니어링을 어떻게 평가해야 할까? 나는 부정적으로 본다. 왜냐하면, 1억명의 사용자를 고려하여 설계 및 구현하는 비용을 사용했는데 실제로는 사용자가 1억명이 되지 않았기 때문이다. 이렇게 될꺼라면 굳이 엔지니어링을 하지 않아도 됐다.


정반대의 상황도 생각해본다. 제품을 릴리즈 했다. 그런데, 사용자가 폭팔적으로 늘어난다. 릴리즈 한 달 만에 사용자가 1,000만명이 넘었다. 다행히 미리 해둔 엔지니어링 덕분에 사용자의 제품 사용에 큰 문제가 없다. 만약 미리 엔지니어링을 해두지 않았다면 어땠을까? 개발자는 급하게 구조를 변경해야했을 것이고, 작업기간 동안 사용자는 접속불안이나, 응답속도저하 등의 문제를 겪었을테다. 게다가 생각해보니 초기에 2주 정도를 투자해서 준비했기 망정이지, 이미 릴리즈해서 서비스 중인 제품으로 엔지니어링 했더라면 훨씬 많은 시간이 필요했음이 분명하다. 어쩌면 4주 이상이 걸렸을 지도 모르겠다. 작업 과정에서 장애도 많이 났을테고 말이다.


이런 맥락에서 볼 때 엔지니어링은 투자라고 생각한다. 마치 유망주에 투자를 하듯이 미래에 생길 것 같은 일에 투자를 하는 것이다. 위 가상의 예에서 볼 수 있듯이 실패하면 엔지니어링에 대한 투자는 아무것도 아니게 된다. 반면 성공하면 매우 긍정적인 결과가 있다. 문제는 경험 상 이런 투자가 성공으로 이어지는 때가 적다는 것이다. 정확히 측정 해보지 않았지만, 내가 봐온 많은 투자가 실패했다. 게다가 흥미로운 점은 엔지니어링의 규모가 크면 클수록 실패할 확률이 더 높다는 것이다. 특히 저장소 확장성 설계 같은 규모가 큰 엔지니어링은 이후에 보면 사용자가 적어 필요없을 때가 잦았고, 개발 뿐 아니라 운영에도 부담을 주곤 했다.


4. 적정엔지니어링


이런 이유로 가급적 성공할만한 투자만 하자는 것은 이견이 없을 것 같다. 그리고 이를 잘 판단할 수 있는 것은 개발자이다. 그런데, 현실에서 개발자는 의외로 성공하기 어려운 투자를 자주 감행한다. 이는 여러 원인이 있다고 본다. 첫째는 책임 문제이다. 예로 사용자가 폭팔적으로 증가했을 때 기술적 준비가 안 되어 있다면 개발자는 타격을 받는다. 둘째는 개발자의 욕심이다. 개발자는 대게 기술에 대한 욕심이 있는데, 엔지니어링은 이런 욕심을 충족시키는 좋은 방법 중 하나다. 셋째는 개발자가 엔지니어링을 당연하게 생각하기 때문이다. 어떤 개발자는 엔지니어링은 투자이고 선택할 수 있는 영역이라고 판단한다. 그런데, 어떤 개발자는 엔지니어링은 무조건 해야 하는 것으로 인식한다.


위 세 가지 중 개발자 책임 문제는 까다로운 문제 같다. 개발자들끼리의 회의에서 엔지니어링을 가지고 논쟁이 벌어지다 가끔 나오는 말이 있다. "그럼 나중에 장애나면 누가 책임질껀데?" 이런 말이 나오면, 그냥 모두 맘 편하게 오버엔지니어링을 하기도 한다. 합리적으로 판단해 엔지니어링을 하지 않았는데 이후 사용자가 폭팔적으로 증가해 제품의 서비스가 멈추기라도 할 때 개발자에게 책임을 묻는 사태가 일어날까 걱정하는 것이다. 또한, 이럴 때 기술적 이해가 부족한 외부부서는 개발자를 무능하게 볼 수 있고 이는 힘을 빠지게 한다. 나중에 급히 준비하는 과정도 개발자에겐 너무 힘들다. 당장 서비스에 문제가 생기면, 퇴근하기도 힘들어지기 때문이다.


두 번째 개발자의 욕심 또한 생각해볼만한 문제다. 경험상 실력이 좋은 개발자일수록 엔지니어링에 욕심이 있는 것 같다. 기술적 지식이 많다보니 제품을 설계할 때 많은 고민을 한다. 고민을 통해 인지하게 된 제품의 기술적 약점을 보완하고 싶은 마음이 자연스레 생긴다. 약점이 뻔히 보이는 데 아무것도 안 하고 넘어가는 것은 개발자에게는 힘든 문제일수도 있다. 한편 신기술을 극단적으로 선호하는 개발자도 있다. 이런 개발자는 나름의 근거를 가지고 새로나온 프레임웍 등의 신기술을 도입한다. 하지만, 가만히 살펴보면 도입근거가 미약할 때가 많고, 외부 시선으로 보기에는 오버엔지니어링으로 판단하게 될 때도 있다.


그래서 나는 개발자가 현재 비즈니스 상황에 따라 적절한 엔지니어링 수준을 결정하는 능력이 중요하다고 생각한다. 이를 위해서는 세 가지 정도 꼭 필요한 능력이 있다고 생각하는데 첫째가 용기다. 용기가 필요한 이유는 엔지니어링 결정으로 인해 최악의 경우 다소 억울한 비난을 받을수도 있기 때문이다. 이런 부분을 감안하고도 옳은 판단을 내릴 수 있어야 한다고 본다. 둘째는 비지니스에 대한 이해이다. 예로 확장성에 대한 엔지니어링 결정을 하려면, 어떤 데이터가 많이 증가할지 예측이 가능해야 한다. 이런 부분은 기술력보다는 비즈니스 이해가 판단에 더 많은 영향을 미친다고 생각한다. 마지막으로 당연히 기술력이 필요하다.


그런데, 초반 제품을 개발할 때 위에서 얘기한 적정엔지니어링 관점으로 준비를 했다고 가정하면, 이후 제품 운영이 더 어려울 수도 있다. 왜냐하면, 경험상 미리 준비하는 것보다 운영 중에 준비하는 것이 훨씬 어렵기 때문이다. 따라서, 적정엔지니어링을 적용해 제품을 개발했다면 비즈니스 상황 및 시스템 모니터링을 통해 필요한 엔지니어링을 지속적으로 확보해가는 능력이 필요하다고 본다. 또한, 이 때도 적정엔지니어링을 유지하는 것이 좋다고 본다. 운영 중 확장성 문제가 생겼을 때 한번에 투자하기 보다는, 조금씩 투자하며 현재 상황에 맞게 전진할 수 있다고 보기 때문이다. 아래는 이런 노력을 하며 실제 있었던 경험담이다. 다만, 많은 것이 생략 된 대략적인 내용이다.


최초 상황


- MySQL Master 1대 /Slave 1대

- Master는 Insert/Update/Delete 쓰기 요청을 받음, Slave는 Select 요청을 받음

- Master의 데이터는 Slave로 실시간 복제 됨

- 릴리즈 한지 약 2년 정도 된 제품


첫 번째 엔지니어링


- Slave에 복잡한 쿼리가 많아 Slow Query가 늘어나며 부담이 생김

- 추가 Slave를 투입하여 Slave를 2대로 만듬

- Round Robin 방식으로 Slave#1, Slave#2가 번갈아 가며 요청을 처리하게 함

- 결과로 Slow Query가 줄고 부담이 경감 됨

- 위 작업에 2일 정도 소모


두 번째 엔지니어링(준비했었으나 실제 제휴가 진행되지 않아 계획만 세움)


- 제휴로 인해 약 10배 사용자가 예상 됨, 곧바로 샤딩을 할수도 있지만 비용을 고려하여 다시 한번 조금만 엔지니어링 하기로 함

- Master는 N개로 늘릴 수 없기 때문에 Scale-Up(하드웨어 업그레이드) 방식으로 확장

- Slave는 필요한 만큼 확장하고 마찬가지로 Round Robin 방식으로 서비스, 단 복제지연을 고려해야 함

- 이후 모니터링 중 복제지연이 생기면 필요한 튜닝을 진행

- 만약 사용자가 10배 그 이상이 될 소지가 보이면 비즈니스/기술 부서에서 최소한 1달 전에 인지하여 준비


설명


위 경험담을 보면 보통 사용하는 샤딩이 안 되어 있는 상황이다. 아마 초기에 이로 인한 여러 이득이 있었을 것으로 판단한다. 그 후 성능 문제가 발생했지만, 아무래도 큰 작업인 샤딩을 진행하지는 않는다. 다만, 가까운 미래에 필요할 정도로만 엔지니어링을 한다. 이후 10배 사용자가 필요한 상황이 되었지만, 이때도 어떻게든 구조를 많이 변경하지 않고 엔지니어링을 해본다. 10배 이상이 되면 구조적인 한계가 있기 때문에 샤딩을 진행한다. 다만, 샤딩은 시간이 필요하기 때문에 모니터링 및 판단을 잘 해서 최소한 1달 전에 알 수 있도록 준비한다.


5. 적정엔지니어링이 개발자에게 미치는 영향

적정엔지니어링은 비즈니스 관점에서 긍정적으로 볼 수 있을 것 같다. 미리 기술에 투자하지 않고 필요할 때마다 조금씩 점진적으로 해나가기 때문에 빠르게 제품을 릴리즈 하는데 도움이 되기 때문이다. 특히 스타트업처럼 시간적 여유가 부족하다면 더욱 빛을 발할 것 같다. 게다가, 데이터베이스 샤딩을 하지 않는 사례를 보면 제품 개발 시점 뿐 아니라 운영 시점에 긍정적 영향을 주기도 한다. 그런데, 개발자에게는 어떨까? 부정적인 점이 있다고 본다. 적정엔지니어링의 필요성을 느낀 후 반년 넘게 실천을 해보았다. 처음에는 내가 성숙한 개발자가 된 것 같아 기분이 좋았다. 그런데, 시간이 갈수록 뭔가 문제가 있다는 생각이 들었다.


자연스레 예전 모습을 기억해보았다. 예전에는 프로젝트 중 10~20%정도는 기술적으로 도전하곤 했었다. 도전이라는 것은 어떤 면에서는 적정엔지니어링을 하지 않았다는 뜻이다. 투자 관점의 합리적인 엔지니어링보다는 단순히 기술적 도전을 위한 엔지니어링을 시도했다. 이런 도전을 통해 재미를 느꼈고 새로운 것을 배웠다. 그런데, 적정엔지니어링에 몰입하고 난 후에는 항상 비즈니스를 고려한 최적의 결정만을 하려 노력했다. 자연스레 예전 습관이었던 10~20% 기술적 도전은 사라졌다. 이로인해 단기간에 내가 할 수 있는 최선의 결과를 냈는지는 모르겠지만, 장기적으로는 재미를 잃어가고 한편으로 지쳐갔다.


나는 적정엔지니어링은 성숙한 개발자라면 꼭 해야한다고 생각해 실천했었고, 지금도 이 생각은 변함없다. 그럼에도 한편에서 개발자는 항상 도전하는 게 반드시 필요하다고 생각한다. 특히 개인적 시간에 따로 도전하는 것도 좋지만, 업무 영역에서 많이 도전해야 한다고 생각한다. 경험상 업무적 도전이 훨씬 현실적이고 배우는 게 많기 때문이다. 따라서 적정엔지니어링과 오버엔지니어링 모두 조화롭게 추구하는 게 좋다고 생각한다. 적정엔지니어링을 너무 심하게 하는 것도, 오버엔지니어링을 너무 심하게 하는 것도 금물이라 본다. 프로젝트 위험도나 본인의 상황에 따라 틀리겠지만 적절한 비율은 8:2 혹은 9:1 정도가 아닐까 싶다. 물론 많은 편이 적정엔지니어링이다.[1]


6. 요약


사람들은 누군가 불필요한 엔지니어링을 한다고 판단할 때 오버엔지니어링이라 부르며 부정적으로 생각한다. 엔지니어링은 어떤 면에서 미래를 위한 투자로 볼 수 있다. 이런 투자가 과열될 때 오버엔지니어링이 되기 쉬운 것 같다. 그래서 개발자는 오버엔지니어링을 하기보다는 적절한 수준의 엔지니어링을 뜻하는 적정엔지니어링을 추구할 필요가 있다고 본다. 하지만, 적정엔지니어링만 추구하다보면 개발의 재미가 없어지고 발전도 더뎌지는 것 같다. 따라서 장기적인 관점에서 개발자는 어느정도의 오버엔지니어링을 통해 본인의 재미와 발전을 추구하는 것이 좋다고 생각한다.


[1] 단순히 프로젝트를 하는 것만으로도 많이 배우는 상황에 있는 개발자에게는 해당하지 않는 내용이다.


* 이어지는 글 '최소엔지니어링에 대한 생각' : http://wave.ivorypen.com/minslovey/5



WRITTEN BY
차민창
르세상스 엔지니어가 사회를 이끌어나가는 상상을 하며!

,