본문

테크
초보 개발자를 위한 설계 비법

작성일 2023년 07월 03일
main

들어가며

소프트웨어 개발은 복잡한 과정이며, 이 과정에서 설계 능력은 아키텍트와 같은 특정인이 아닌 모든 개발자에게 필요한 핵심 능력입니다. 설계는 프로그램의 전체 구조를 결정하고, 각 기능이 어떻게 상호작용 할지를 정의하는 중요한 단계입니다.

그러나, 특히 초보 개발자들이 주로 접하게 되는 간단한 이슈에 대한 개발에서는 설계의 중요성이 종종 과소평가되는 경향이 있습니다. 이는 각자의 관점이나 역할에 따라 다르게 느껴질 수 있지만, 설계는 결국 모든 개발자에게 중요한 업무입니다.

하지만, 초보 개발자들이 처음 개발 임무를 부여받았을 때, 어디서부터 시작해야 할지 막막함을 느끼는 경우가 많습니다. 기술적 이해도가 아직 충분하지 않고, 다양한 경험이 부족하기 때문에 해결책이 즉시 떠오르지 않는 것이 당연합니다.

이런 상황에서는 첫 단계부터 차근차근 계획된 절차를 따라 진행하는 것이 도움이 됩니다. 무엇보다도, 개발을 시작하는 데 필요한 기본적인 이해와 준비가 필요합니다. 이는 문제를 이해하고, 해결 방법을 계획하는 데 도움이 됩니다.

이번 글에서는 이렇게 개발을 시작할 때 무엇부터 해야 할지 막연하게 느껴지는 분들을 위해 몇 가지 간단한 팁을 제공하고자 합니다. 이 팁들은 개발 과정을 조금 더 명확하게 이해하고, 효과적으로 시작하는 데 도움이 될 것입니다.


가장 근본이 되는 기능 설계

소프트웨어 개발을 시작할 때, 기능 목록을 작성하는 것은 간단하지만 확실한 효과를 가져옵니다. 이 기능 목록을 통해, 처음에는 막연하게 느껴졌던 개발 목표가 좀 더 구체적이고 명확하게 그려지게 됩니다.

예를 들어, '회원 관리'라는 업무를 개발해야 한다고 가정해봅시다. 추가적인 정보가 거의 없다면, 이는 상당히 추상적이고 막연한 미션으로 느껴질 수 있습니다. 이런 상황에서는, 트리를 만드는 것처럼 작은 단위로 과제를 조각내 보는 것이 도움이 됩니다. 이렇게 하면, 어떤 문제들을 해결해야 하는지, 어떤 기능들이 필요한지가 점점 더 명확해질 것입니다.

이렇게 과제를 조각 내는 과정은 복잡한 문제를 작은 문제들로 분해하여, 각각을 개별적으로 이해하고 해결하는 데 도움을 줍니다. 이는 설계의 핵심 원칙 중 하나인 분할과 정복을 실제로 적용하는 것입니다. 이 방법을 통해, 초보 개발자라도 복잡한 문제를 효과적으로 관리하고 해결할 수 있게 됩니다.

blog_1.jpg

무엇보다도 기능 설계는 개발 범위를 가늠하는데 도움이 되고 일정 예측의 근거 자료가 됩니다.

blog_2.jpg


이런 상황에서는, 주어진 미션을 여러 개의 작은 기능으로 분해하고, 각각의 작은 기능에 대한 예상 시간을 작성하는 방법을 사용할 수 있습니다. 이렇게 하면 전체 작업을 한 번에 예측하는 것보다 훨씬 정확한 예측이 가능해집니다.

그러나 완벽한 일정 예측은 어렵기 때문에, 어느 정도의 여유 시간을 설정해야 합니다. 이런 여유 시간은 일정 예측의 '버퍼' 역할을 합니다. 그리고 이런 예측과 피드백을 반복하면서, 일정을 이 버퍼 내에서 관리할 수 있는 수준에 도달하게 됩니다.

실제로, 작은 단위로 개발 업무를 쪼개고 마일스톤을 세우는 방식은 프로젝트의 전반적인 관리와 효율성을 크게 향상시킵니다. 이렇게 하면 각 단계에서 진행 상황을 명확하게 파악할 수 있고, 문제가 발생했을 때 즉시 대응할 수 있습니다. 또한, 이 방식은 개발 팀이 전체 프로젝트에 대한 명확한 이해를 가지고 일정을 관리하도록 돕습니다.


일정을 예측하는 방법은 다양하며, 상황에 따라 적절한 방법을 선택해야 합니다. 저는 특히 다음 두 가지 방식을 주로 사용합니다.

첫 번째는 각 기능마다 난이도와 확실성의 단계를 측정하여 시간을 예측하는 방법입니다.

난이도는 다음과 같이 구별합니다.

  • 상: 외부 도움이 필요하거나 상당히 노력이 필요하다
  • 중: 스스로 해결 가능하다
  • 하: 단순 업무다

확실성은 다음과 같이 구별합니다.

  • 상: 요구 사항 및 구현 방향이 확실하다
  • 중: 구현 방법이 아직 뚜렷하지는 않다
  • 하: 요구 사항이 추상적이거나 구현 방법이 막연하다 (개발을 시작하면 안되는 Task, 추가 분석 요망)

예상 시간은 기능을 구현하는 순수한 시간만 고려하여 적습니다. 테스트나 기타 업무를 함께 고려하는 것이 이상적일 수 있지만, 실무에서는 어떤 변화가 발생할지 예측할 수 없으므로 이 방법이 크게 도움이 되지 않습니다.

최종적으로 예측 시간은 다음과 같이 계산됩니다.


예측 시간: f(난이도) * g(확실성) * 예상 시간

여기서 난이도 함수 f와 확실성 함수 g는 팀원들의 기량에 맞춰서 계수 값을 조정하며 적절한 값을 정합니다. 릴리즈를 반복하면서 예상과 다른 부분들을 수정해 나가며 정확도를 향상시킵니다. 이렇게 하면 개발 일정 예측의 정확성을 점차 높일 수 있습니다.


function estimateTime(difficulty, accuracy, time) {
c = 1.4;
if (difficulty === "상") d = 3.0;
if (accuracy === "중") c = 2.0;
return d * c * time; }

blog_3.jpg

위에서 설명한 시트의 원본은 아래 링크를 참고하시기 바랍니다.

두 번째 방법은 각 기능에 대해 최적의 상황, 일반적인 상황, 그리고 비관적인 상황을 고려하여 시간을 각각 예측하는 것입니다. 이렇게 각 상황에 대한 예상 시간을 합산하여 전체 예측 시간을 계산합니다. 이 계산은 아래와 같은 방식으로 이루어집니다.


blog_4.jpg

'O'는 최적(optimistic) 시간을 나타냅니다. 이는 모든 것이 완벽하게 흘러갔을 때 필요한 시간을 의미합니다. 'M'은 가장 가능성 높은(most likely) 시간을 나타냅니다. 이는 가장 가능성이 높은 시나리오에 대한 시간을 의미합니다. 'P'는 비관적(pessimistic) 시간을 나타냅니다. 이는 최악의 경우에 대한 시간을 의미합니다.
PERT(Program Evaluation and Review Technique)라는 프로젝트 관리 기법에서 사용하는 일정 예측 공식입니다. PERT는 미국 해군에서 개발되었으며, 불확실성이 높은 프로젝트의 일정을 관리하는 데 사용됩니다.

단순하지 않은 문제를 다룰 때 도움이 되는 동적 설계

복잡한 문제를 해결해야 할 경우, 동적 설계를 사용하는 것이 큰 도움이 됩니다. 저는 다음의 이미지와 같은 다이어그램을 사용하는데요. 이 다이어그램은 시스템을 여러 개의 객체로 분리하고, 이 객체들이 서로 어떤 메시지를 주고받아야 하는지를 표시하는 목적으로 사용됩니다.

이 과정에서 중요한 것은 플로우 자체보다는 객체 간의 의존 관계를 찾아내는 것입니다. 동적 설계를 통해 얻을 수 있는 가장 큰 이점은 코드를 작성하기 전에 매우 작은 비용으로 요구 사항과 아이디어를 검증할 수 있다는 것입니다.

동적 흐름을 살펴보는 과정에서 기능 목록에서는 드러나지 않는 문제점들이 시뮬레이션 효과를 통해 명확해집니다. 이를 통해 개발 전에 문제점을 미리 발견하고, 해결 방안을 모색할 수 있습니다. 마치 건물을 짓기 전 미니어처를 먼저 만들어 보는 것과 같은 원리입니다.


blog_5.jpg동적 설계의 예시

특히, 이러한 방법은 개발자가 아닌 고객과의 커뮤니케이션에서도 매우 유용하게 사용됩니다. 비 개발자와의 커뮤니케이션에서는 기술적인 세부 사항보다는 전체적인 흐름을 이해하는 것이 중요하기 때문에, 모든 요소를 네모 박스로 표현하여 간단하게 표현하는 것이 효과적입니다.

이때, 다이어그램에 등장하는 객체들은 반드시 시스템 모듈이어야 하는 것은 아닙니다. 관리자, 택배 회사와 같은 현실 세계의 객체도 포함하여 시스템의 전체적인 흐름과 각 요소가 시스템에 어떤 영향을 미치는지 분석할 수 있습니다. 이렇게 현실 세계의 객체를 포함하여 분석하면, 시스템이 실제 운영 환경에서 어떻게 작동할지에 대한 보다 정확한 이해를 얻을 수 있습니다.


blog_6.jpg비개발자와 요구 사항 점검하는 과정의 예시

위에 나오는 다이어그램의 실전 예제는 아래 링크를 참고하시기 바랍니다.

동적 설계 과정에서는 제가 사용하는 방식 외에도 다른 다양한 방법들이 있습니다. 널리 알려진 UML(Unified Modeling Language)을 활용하는 것을 고려해보시기 바랍니다. UML은 시스템의 동작을 시각적으로 표현하는 데 유용한 도구입니다.

동적 설계에 관해서는 UML 중에서도 액티비티 다이어그램, 시퀀스 다이어그램, 커뮤니케이션 다이어그램, 스테이트 다이어그램 등을 참고하시면 됩니다.

  • 액티비티 다이어그램: 시스템의 동작을 순차적으로 표현합니다.
  • 시퀀스 다이어그램: 객체 간의 상호작용을 시간 순서에 따라 나타냅니다.
  • 커뮤니케이션 다이어그램: 시퀀스 다이어그램과 유사하지만, 객체 간의 관계에 더 초점을 맞춥니다.
  • 스테이트 다이어그램: 객체의 상태 변화를 표현합니다.

문제가 보다 복잡해지면 구조 설계를

구조 설계는 클래스 다이어그램과 컴포넌트 다이어그램 등을 활용하여 시스템의 전반적인 구조를 정의하게 됩니다. 이러한 다이어그램들은 시스템의 구성 요소와 그들 간의 관계를 명확하게 표현하므로, 개발자들이 시스템의 전체적인 구성을 이해하는 데 큰 도움이 됩니다.

시스템이 복잡해질수록, 논리적으로 모든 기능을 구현한 것만으로는 충분하지 않습니다. 복잡성이 증가함에 따라 이를 효과적으로 관리하는 방법이 필요해집니다. 이 때 구조 설계의 중요성이 더욱 부각됩니다.

구조 설계는 복잡한 시스템을 여러 개의 관리 가능한 부분으로 분할하는 데 도움이 됩니다. 이를 통해 각 부분을 독립적으로 개발하고 테스트할 수 있으며, 이는 전체 시스템의 품질 향상에 기여합니다. 따라서, 복잡한 시스템을 효과적으로 구축하려면 구조 설계가 필수적인 단계가 됩니다.


마치며

지금까지 설계의 기본이 되는 기능 설계, 동적 설계, 그리고 구조 설계에 대해 간략하게 살펴보았습니다. 설계에 대한 유익한 자료들이 많이 있으므로, 이를 참고하시는 것도 좋습니다. 그러나 설계에는 '정답'이 없습니다. 상황에 따라 적용 범위와 방법이 크게 달라질 수 있기 때문입니다.

따라서, 편견 없이 다양한 이론을 공부하고, 실전에 적용해보는 것이 중요합니다. 이 과정을 통해 문제 해결 능력이 점차 향상되는 것을 느낄 수 있을 것입니다. 설계 능력을 키우는 것은 단순히 좋은 코드를 작성하는 것 이상의 가치가 있습니다. 설계 능력은 복잡한 문제를 이해하고, 효과적으로 해결하는 데 필요한 핵심 능력이기 때문입니다.

감사합니다.

류종택[email protected]
Development TeamAPM Agent Developer

지금 바로
와탭을 경험해 보세요.