소프트웨어 최적화 작업을 위해 검토할 5가지 문제

소프트웨어 최적화 작업은 어렵습니다. 시간이 소요되고 실수가 나오기도 합니다. 그래서 많은 개발자가 이 주제를 무시하거나, 시간이 지나서야 배우게 됩니다. 하지만 겁먹지 않아도 됩니다. 소프트웨어 최적화가 필요한 상황을 연습하다 보면 보다 효과적이고 실용적으로 효율성을 높이는 방법을 이해할 수 있습니다. 이번에는 소프트웨어 최적화 작업을 위해 검토해 볼 만한 근본적인 문제들을 살펴보겠습니다.


1. 프로그램에서 성능 문제를 일으키는 부분을 예측하기 어렵다

프로그램의 어느 부분이 자원을 가장 많이 사용하는지 그리고 얼마나 사용하는지, 개발자들은 잘 예측하지 못합니다. 하지만 방법은 있죠. 일반적으로 파레토 법칙Pareto Principle 1이 적용되기 때문이죠. 최적화 작업은 시간이 많이 소요되기 때문에, 노이즈가 아닌 중요한 작업 20%에 집중해야 합니다.

    

2. 개발자들은 정확한 자원 사용을 추정하는 데 소질이 없다

앞서 언급한 내용과 비슷하게, 특정한 최적화가 도움이 되는지에 관해서도 개발자들은 추측을 잘하지 못합니다. 경험을 통해 나아질 수 있지만 본인의 판단을 온전히 신뢰하지 않는 것이 최선이라고 할 수 있죠. 이때는 의도적 최적화 후에 모든 수치를 측정하고 확인하는 작업이 중요합니다. 소프트웨어 실행에 여러 레이어와 알 수 없는 변수가 존재하기 때문입니다.

    

3. 시간이 흐를수록 효율성을 유지하는 일은 어렵다

복잡한 소프트웨어의 실행 레이어(예: 새로운 운영체제, 하드웨어, 펌웨어 등)들은 지속적으로 바뀌고, 프로그램 자체도 발전하며, 심지어 코드를 수정하는 사람이 바뀌기도 합니다. 특정 부분을 최적화하는 데 몇 주를 소요했다 하더라도, 회귀에 대해 대비하지 않는다면 해당 작업은 무의미할 수 있습니다. 주변 환경은 매일 변화하기 때문에 프로그램의 효율성을 위해 자동화하거나 적어도 벤치마킹과 검증 절차를 구성하는 방법들을 사용하기를 권합니다.

    

4. 성능에 대한 신뢰할 만한 검증을 수행하기는 매우 어렵다

효율성을 벤치마킹하고, 측정하고, 검증하는 것이 이 문제의 해결책입니다. 그러나 이는 수행하기 어렵고 에러를 발생시키기 쉽습니다. 여기에는 다양한 이유가 있는데, 그 중 하나가 실행 환경을 비슷하게 구현하기 어렵기 때문입니다. 서로 다른 프로세스가 동시에 아래와 같은 이유가 될 수 있죠.

  • 같은 자원을 두고 경쟁하는 시끄러운 이웃noisy neighbor
  • 프로그램 실행 준비 단계warm-up phase의 부족
  • 잘못된 데이터 세트
  • 마이크로벤치마크의 우연한 컴파일러 최적화

    

5. 최적화는 다른 소프트웨어 품질에 쉽게 영향을 끼칠 수 있다

견고한 소프트웨어는 기능성, 호환성, 사용성, 안정성, 보안성, 유지보수성, 이식성, 효율성이 뛰어납니다. 해당 특성을 하나하나 제대로 살펴보기는 쉽지 않기에, 개발 과정에서 약간의 비용이 발생하죠. 각각의 중요도는 사용 사례에 따라 다를 수 있습니다. 그러나 프로그램을 유용한 상태로 유지하기 위해서는 최소한의 소프트웨어 품질 기준을 충족시켜야 합니다. 더 많은 기능과 최적화를 추가하면 이를 충족시키기가 더 어려워지게 됩니다.

    

+ 특히 Go에서는 메모리 관리에 대한 엄격한 통제를 지원하지 않는다

Go는 가비지 컬렉션을 지원하는 언어입니다. 이는 코드의 단순함, 메모리 안정성 및 개발 속도를 향상시키지만, 메모리를 효율적으로 사용하고 싶을 때는 단점이 될 수 있죠. Go 코드가 메모리를 더 적게 사용하기 위해서 사용할 수 있는 방법은 다양하지만, 메모리 할당 해제가 즉시 이뤄지지는 않기 때문에 어려울 수도 있습니다. (메모리 관리 연습이 필요할 땐, 책 『Go 성능 최적화 가이드』 5.2절을 참고하면 좋습니다.)

    


그렇다면, 프로그램이 ‘충분히’ 효율적인 시점은 언제일까?

어떠한 노력 없이 최적화를 달성할 수는 없습니다. 개발자들은 최적화를 위해 크고 작은 노력을 하게 되죠. 합리적이고 의도적인 최적화 모두 선행 지식과 시스템 구현, 실험, 테스팅 그리고 벤치마킹하는 시간이 필요합니다. 그리고 노력에 상응하는 정당성을 부여해야 합니다. 그렇지 않으면 이 소중한 시간이 다른 곳에 쓰일 수 있기 때문이에요. 특정 낭비를 최적화시켜야 할까요? X 자원 사용을 Y 자원 사용과 맞교환해야 할까요? 그렇다면 이 교환은 유용할까요? 답은 “아니오”일 가능성이 높습니다. 그러나 “예”라는 답변이 나올 경우 효율성을 얼마만큼 개선해야 충분할까요?

바로 이 지점에서 목표를 확실히 정해야 합니다. 개발하는 동안 어떤 자원, 품질 등에 신경을 쓰고 있는지는 설계하기에 따라 다를 수 있습니다.


1 80%의 결과가 20%의 원인에서 나온다는 경제학 용어로 소프트웨어에 대입하면 ‘프로그램에서 사용한 시간이나 자원의 80%는 프로그램이 수행한 작업의 20%에서 나온다’로 적용해 생각해 볼 수 있습니다.


이 글은 Go 성능 최적화 가이드 도서 내용을 발췌한 글입니다. Go 언어를 통해 소프트웨어의 효율성 및 성능 개선을 진행하는 더 다양하고 자세한 내용은 아래 도서에서 확인하실 수 있습니다.

Go 성능 최적화 가이드

Comments are closed