본문 바로가기
책/크로스플랫폼 핵심 모듈 설계의 기술

2장. 개발기법 (#2)

by 정선한 2023. 6. 17.
728x90
반응형

이전 내용과 이어지는 글 입니다.
 

1장 크로스 플랫폼으로 개발하라.

C++ 언어가 어려운 이유, 개발자에게 여러 운영체제 자원들(CPU, 메모리, 디스크)을 자유롭게 이용할 수 있는 C언어를 탑재하고 있기 때문이다. C언어는 어셈블리를 내장한 극단적인 최적화도 가능

time-for-us-to-shine.tistory.com


모듈 트리
"규모가 큰 모듈의 종속성 문제"
크로스 플랫폼 핵심 모듈을 개발하다 보면 생각보다 코드의 규모가 커지는 것을 알 수 있다. 그 이유는 일반적인 경우에는 구현하지 않는 기저 함수들 부터 각 플랫폼에 맞는 함수들까지 모두 개발되어야 하기 때문이다.
이렇게 되면 각 파일들의 종속 관계도 복잡해지는 일이 빈번하게 발생한다. 이런 코드들은 기존 코드를 수정, 삭제 해야할 일이 있을 때 문제가 발생할 수 있고 연관된 종속 파일 들 대문에 코드 전체를 고쳐야 하는 최악의 상황을 마주하게 될 수 있다.

이럴때 개발자들은 종속성을 낮추는 방법으로 모듈을 더 작은 모듈들로 분리하는 작업을 한다.
모듈 내부에 존재하는 소스 파일 자체가 적어지면 당연히 파일 간의 종속성은 줄어들 것이며, 각 모듈의 대표 헤더 파일을 생성하여 외부에 노출할 헤더 파일들을 한꺼번에 참조하도록 할 수 있다.
그 후 외부의 파일은 해당 모듈을 참조하기 위해 대표 헤더 파일만을 참조하게 된다.

모듈을 분리할 때에는 기준을 잘 잡아야 한다. 
각 기준에 따라 적절히 새로운 모듈을 생성하거나, 기존의 모듈을 분리할 수 있어야 하며 구현하려는 기능을 더 단순화 시켜 이미 나누어진 모듈의 컨셉을 해치지 않도록 해야 한다.
이 과정에서 때로는 상호 참조가 되는 현상이 발생할 수 있는데 이 경우에는 애초에 모듈의 설계가 잘못되었을 수 있기에 모듈의 설계까지도 고려할 수 있어야 한다.

"모듈의 순환 참조 구조"
그러나 이러한 과정 중에서 순환 참조 구조를 조심해야 한다. 상호 참조는 두 모듈 간의 관계이므로 비교적 쉽게 눈에 보이나 순환 참조는 셋 이상의 관계에서 나타나는 것이므로 뒤늦게 발견될 가능성이 높다.

트리구조 이미지 (출처 : 나무위키)

우리가 흔히 아는 위의 트리 구조와 같이 모듈들에 대하여 참조 관계에 따라 모듈을 상하로 배치하여 트리 구조로 표현을 해볼 수 있는데 그 결과의 형태모듈 트리라고 부른다.
이러한 모듈 트리는 참조 레벨에 다라 구분할 수 있으며 가장 많이 참조되는 모듈을 최상단에 두고 가장 많이 참조하는 모듈은 최하단에 둔다. 그런 둘 사이에 순차적으로 참조되는 경우가 많은 모듈을 상단에 차례대로 배치하여 구분하면 각 모듈들의 참조 레벨이 결정된다.

이때 결정되는 참조 레벨은 되도록이면 설계를 해치지 않는 선에서 유지하여야 하며 이 참조 레벨이 역전되거나 역참조 하는 경우가 발생하면 참조 레벨을 재조정 해야 한다. 이렇게 관리되는 모듈 트리는 모듈 단위 설계의 가이드 라인이 된다.

"핵심 모듈의 형태"
모듈의 형태는 결국 동적, 정적 라이브러리, 실행 파일 중 하나가 된다.

정적 라이브러리 : 컴파일 타임 함수 호출
- 빌드된 바이너리와 컴파일/ 링크 타임 결합
동적 라이브러리 : 런타임 함수 호출
- 빌드된 바이너리와 런타임 결합
실행파일 (상주 프로세스 | 데몬, 서비스) : 파이프, 소켓, 시그널 등의 IPC
- 임시 프로세스와 IPC통신
실행파일 (임시 프로세스) : 커맨드라인 인터페이스
- 빌드된 바이너리와 커맨드 라인 호출 및 실행 결과 수집

이 중 C++의 핵심 모듈이 되기에 적합한 형태는 정적 라이브러리 이다. 그 이유는 동적 라이브러리 처럼 복잡하게 구현할 필요도 없고 컴파일러와 링커가 존재하기 때문에 런타임에서 발생할 수 있는 문제들을 최소화하여 배포할 수 있다.

모듈이 업데이트 되는 과정에서 기존의 달라진 기능이나 인터페이스로 인해 명확한 커뮤니케이션 없이 고치지 않으면 런타임 에러가 발생할 수 있다. 따라서 정적 라이브러리 이외의 모듈은 코드 작성에 제약이 존재한다.
하지만 정적 라이브러리는 새롭게 업데이트된 모듈이 기존에 사용하던 방식을 지원하지 않으면 컴파일이나 링크 에러를 발생 시키기 대문에 개발자 입장에서는 강력한 안전 장치를 가진다고 볼 수 있다.

공통 헤더 파일(stdafx.h)과 대표 헤더 파일의 활용
대표 헤더 파일은 라이브러리 이름으로 헤더 이름을 정하고, 그 안에 속한 헤더 파일들을 모두 적어 놓는 방식으로 작성한다. (노출할 필요 없는 헤더는 제외) 이렇게 정의된 대표 헤더 파일이 존재하면 다른 라이브러리에서 이 라이브러리를 사용할 대, 간단히 대표 헤더만 포함하면 된다.
공통 헤더 파일은 STL과 같은 공통 모듈 헤더가 이에 해당된다. 더불어 상위 참조 모듈의 대표 헤더 파일도 공통 헤더 파일에 선언할 수 있다.

이렇게 두 헤더 파일은 각 모듈 사이의 접점으로서의 역할을 수행하며 두 파일을 잘 이용하면 소스 파일들 간의 연관 관계를 한결 갈끔하게 정리할 수 있다.

테스트 기법
핵심 모듈은 안정성이 핵심이기에 버그를 최소화 해야 한다. 기본적으로 버그가 적은 코드를 작성하기 위해서는 개발자의 능력이 가장 중요하지만 그 개발자의 능력 중엔 코드를 검증할 수 있는 능력도 겸비해야 한다.
코드는 얼마나 많은 예외를 미리 에상하고 그에 따른 적절한 기능을 수행할 수 있느냐가 관건이기 때문에 그렇다.

단위테스트(Unit Test) -> 통합테스트(Integration Test) -> 환경테스트(System Test) -> 인수테스트(Acceptance Test)
- 인수테스트 : 일반적인 QA 검증단계
- 단위테스트 : 프로그램의 가장 작은 단위인 함수 호출 수준에서 코드를 검증

 "가장 간단한 테스트 코드"
단위 테스트의 기법.
테스트 주도 개발 : 애자일 기법으로써 테스트 코드를 먼저 작성하고 모듈을 나중에 개발하는 방식이다.

"테스트 모듈의 일반화"
gtest : 단위테스트 플랫폼 

"테스트 조건 구성"
Fixture : 파일이나 네트워크 등의 특정 상황 아래에서 테스트 하는 코드를 작성할 때 사용. 즉, 테스트 함수를 호출하기 전에 공통적으로 필요한 파일이나 기타 커널 객체를 생성해 두고, 테스트 후에는 자동으로 해당 객체들을 정리하게 도와준다.

728x90
반응형