Developer Roadmap/C++

C++ 코드 구조화 제대로 이해하기 - 네임스페이스부터 헤더/소스 분리까지

gigyesik 2025. 6. 19. 17:07
반응형

썸네일

C++ 코드 구조화 제대로 이해하기

유지보수성, 가독성, 빌드 속도까지 개선하는 C++ 프로젝트 설계법


C++로 프로젝트를 진행하다 보면 점점 파일이 많아지고, 클래스 간 의존성도 복잡해진다.
이럴수록 코드를 체계적으로 나누고 정리하는 구조화 전략이 중요해진다.

이번 글에서는 실무에서 자주 사용되는 C++ 코드 구조화 방법을 예제와 함께 정리해보았다.


네임스페이스로 이름 충돌 방지하기

C++에서 여러 라이브러리나 클래스가 같은 이름의 함수나 변수를 가지면 충돌이 발생할 수 있다.
이를 방지하기 위해 namespace를 사용하면 코드의 모듈화도 동시에 이룰 수 있다.

namespace MyApp {
    int add(int a, int b) {
        return a + b;
    }
}

int result = MyApp::add(3, 4);

네임스페이스는 중첩도 가능하고, using 키워드로 일부 또는 전체를 가져올 수도 있다.


인클루드 가드로 헤더 중복 막기

같은 헤더 파일이 여러 소스에서 참조될 경우, 중복 정의 오류가 날 수 있다.
이를 방지하기 위한 방법이 include guard다.

#ifndef MY_HEADER_H
#define MY_HEADER_H

// 클래스나 함수 선언

#endif

#pragma once를 사용하는 것도 가능하지만, 호환성과 명확성을 위해 전통적인 include guard도 여전히 널리 사용된다.

헤더(.h) 파일과 소스(.cpp) 파일 분리하기

C++에서는 선언과 구현을 분리하는 것이 일반적인 패턴이다.

  • .h 파일: 클래스와 함수의 선언
  • .cpp 파일: 실제 구현

이렇게 구조를 나누면 컴파일 시간도 줄고, 유지보수 시에도 한눈에 파악하기 쉬워진다.

// Example.h
class Example {
public:
    void print();
};

// Example.cpp
#include "Example.h"
#include <iostream>

void Example::print() {
    std::cout << "Hello, world!" << std::endl;
}

전방 선언으로 의존성 최소화

클래스나 함수가 다른 파일에서 참조될 때, 정의 없이 먼저 선언해두는 것이 전방 선언이다.
이는 컴파일 속도 향상과 순환 참조 방지에 큰 도움이 된다.

class MyClass; // 정의 없이 선언만

void doSomething(MyClass* ptr); // 포인터 또는 참조로만 사용 가능

함수도 마찬가지로 먼저 선언하고 나중에 정의하는 방식이 가능하다.

int add(int, int); // 선언

int main() {
    return add(2, 3);
}

int add(int a, int b) {
    return a + b;
}

코드 분할과 개별 컴파일

코드를 기능 단위로 분할하고 각 소스 파일을 독립적으로 컴파일하면 효율적인 빌드가 가능하다.
예를 들어, 클래스마다 .cpp 파일을 만들고 별도로 오브젝트 파일을 생성한 후 링크하면 된다.

g++ -c main.cpp -o main.o
g++ -c utils.cpp -o utils.o
g++ main.o utils.o -o my_program

빌드 속도 개선과 함께 유지보수 시에도 수정 범위가 줄어든다.


스코프를 명확히 구분하자

변수나 함수가 어디에서 유효한지를 결정하는 범위를 스코프(scope)라고 한다.
C++에서는 다음과 같은 스코프가 존재한다.

  • 전역 스코프: 파일 전체에서 접근 가능
  • 지역 스코프: 함수나 블록 내에서만 유효
  • 클래스 스코프: 클래스 내부 멤버 전용
  • 네임스페이스 스코프: 특정 네임스페이스 내에서만 사용
int globalValue = 10;

void func() {
    int localValue = 5;
    std::cout << globalValue + localValue;
}

스코프를 정확히 구분하면 변수 충돌과 메모리 관리에서 불필요한 혼란을 줄일 수 있다.


마무리

프로젝트가 커질수록 코드의 구조는 곧 유지보수성과 직결된다.
네임스페이스, include guard, 전방 선언, 헤더/소스 분리, 코드 분할 등의 전략은 C++ 실무 개발의 필수 요소다.

이제부터는 기능을 구현하는 것뿐 아니라, 구조를 어떻게 잡을지도 함께 고민하며 코드를 작성해보자.

반응형