
C++ 프로젝트를 만들다 보면 점점 코드가 복잡해지고 관리하기 어려워진다. 이럴 때 중요한 것이 바로 코드베이스 구조화이다. 코드의 구조를 잘 정리해두면 유지보수도 쉬워지고 협업도 훨씬 수월해진다. 이번 글에서는 C++에서 사용할 수 있는 대표적인 코드 구조화 기법들을 정리해본다.
네임스페이스는 변수나 함수, 클래스 이름 충돌을 방지해주는 유용한 도구다. 동일한 이름을 가진 요소가 여러 파일에 존재해도 각각 다른 네임스페이스에 속해 있다면 문제없이 사용할 수 있다.
namespace MyNamespace {
int myFunction() {
return 42;
}
}
int main() {
int value = MyNamespace::myFunction();
}
헤더 파일이 여러 번 포함되는 것을 방지하기 위해 인클루드 가드를 사용한다. 전처리기 지시문을 통해 한 번만 포함되도록 막아준다.
#ifndef MY_HEADER_H
#define MY_HEADER_H
// 헤더 파일 내용
#endif // MY_HEADER_H
C++에서는 .h 파일과 .cpp 파일을 분리하여 선언과 구현을 구분하는 것이 일반적이다. 이렇게 하면 재사용성과 가독성이 높아진다.
// MyClass.h
#ifndef MY_CLASS_H
#define MY_CLASS_H
class MyClass {
public:
MyClass();
int doSomething();
};
#endif
// MyClass.cpp
#include "MyClass.h"
MyClass::MyClass() {}
int MyClass::doSomething() {
return 10;
}
정해진 코드 스타일을 유지하는 것은 협업과 유지보수를 위해 매우 중요하다. 들여쓰기, 괄호 위치, 변수명 스타일 등을 팀에서 합의한 스타일 가이드에 따라 맞추자.
Google에서 제공하는 C++ Style Guide를 참고해도 좋다.
전방 선언은 클래스나 함수를 미리 알려주어 컴파일러가 타입 정보를 인식하게 해주는 기법이다. 의존성 줄이기, 컴파일 시간 단축에 유리하다.
class MyClass; // 클래스 전방 선언
void process(MyClass& obj); // 포인터 또는 참조만 가능
int sum(int a, int b); // 함수 전방 선언
int main() {
return sum(1, 2);
}
int sum(int a, int b) {
return a + b;
}
코드를 여러 파일로 나누면 유지보수가 쉬워지고, 각 파일을 독립적으로 컴파일할 수 있어 빌드 시간도 줄일 수 있다.
// example.h
#ifndef EXAMPLE_H
#define EXAMPLE_H
class Example {
public:
void print();
};
#endif
// example.cpp
#include "example.h"
#include <iostream>
void Example::print() {
std::cout << "Code splitting example\n";
}
# 컴파일
g++ -c main.cpp -o main.o
g++ -c example.cpp -o example.o
g++ main.o example.o -o my_program
변수나 함수가 어디까지 유효한지를 나타내는 것이 스코프다. 스코프를 잘 이해하면 변수 충돌이나 메모리 낭비를 줄일 수 있다.
int globalVar = 10; // 전역 변수
int main() {
int localVar = 5; // 지역 변수
std::cout << globalVar << localVar;
}
C++에서 코드베이스를 잘 구조화하면 프로젝트가 커져도 복잡함을 줄이고 유지보수도 쉬워진다.
지금까지 소개한 기법들을 실무 코드에 적용해보며 익히면 큰 도움이 될 것이다.