
Makefile은 프로그램을 빌드(컴파일, 링크, 테스트, 배포 등)하는 과정을 자동화하기 위한 설정 파일입니다. 원래는 Unix의 make 도구가 읽어서 실행하도록 만들어졌지만, 지금도 C/C++ 프로젝트뿐 아니라 다양한 개발 작업 자동화에 사용됩니다.
왜 사용하는가?
예를 들어 C 프로젝트에 파일이 여러 개 있다고 가정해 보겠습니다.
main.c
math.c
math.h
컴파일하려면 매번 이런 명령을 입력해야 합니다.
gcc -c main.c
gcc -c math.c
gcc main.o math.o -o app
파일이 수십 개가 되면 매우 번거롭습니다.
Makefile을 작성해 두면:
make
한 줄만 실행해도 필요한 컴파일과 링크가 자동으로 수행됩니다.
기본 구조
간단한 예시:
app: main.o math.o
gcc main.o math.o -o app
main.o: main.c math.h
gcc -c main.c
math.o: math.c math.h
gcc -c math.c
clean:
rm -f *.o app
구조는 다음과 같습니다.
대상(target): 의존성(dependencies)
실행할 명령(command)
예:
main.o: main.c math.h
gcc -c main.c
의미:
main.o를 만들기 위해main.c,math.h가 필요하며필요 시
gcc -c main.c를 실행
장점
1. 빌드 자동화
make
한 번에 전체 빌드
2. 변경된 파일만 다시 컴파일
예를 들어 math.c만 수정했다면:
make
는 math.c 관련 부분만 다시 컴파일합니다.
전체 재빌드보다 훨씬 빠릅니다.
3. 반복 작업 자동화
컴파일 외에도:
test:
pytest
run:
python main.py
deploy:
./deploy.sh
처럼 사용할 수 있습니다.
실행:
make test
make run
make deploy
자주 보는 예제
Python 프로젝트:
install:
pip install -r requirements.txt
test:
pytest
lint:
flake8 .
run:
python app.py
사용:
make install
make test
make run
특수 변수
Makefile에는 자주 쓰는 변수들이 있습니다.
app: main.o math.o
gcc $^ -o $@
main.o: main.c
gcc -c $< -o $@
의미:
$@: 현재 타겟$<: 첫 번째 의존성$^: 모든 의존성
예를 들어:
main.o: main.c
gcc -c $< -o $@
는 실제로:
gcc -c main.c -o main.o
와 같습니다.
현대 개발에서는?
최근에는 언어별 빌드 도구가 많이 사용됩니다.
C/C++ → CMake, Meson
Rust → Cargo
Java → Maven, Gradle
JavaScript → npm, pnpm
하지만 Makefile은 여전히:
간단한 프로젝트
서버 운영 스크립트
Docker 명령 모음
CI/CD 작업
등에서 매우 널리 사용됩니다.
예를 들어:
build:
docker build -t myapp .
start:
docker compose up
stop:
docker compose down
이렇게 작성해 두면:
make build
make start
make stop
으로 긴 명령어를 외울 필요가 없습니다.
한마디로 Makefile은 "명령어를 이름(타겟)으로 묶어 두고, 필요한 작업을 자동으로 실행하는 빌드 및 작업 자동화 스크립트"라고 생각하면 됩니다.
