CertNote/ 출퇴근 학습 노트
로드맵
KOEN
리눅스마스터 2급 · 2급리눅스마스터 2급
리눅스마스터 1급 · 1급리눅스마스터 1급
  • Week 1
    • 1.운영체제와 리눅스: 커널이 하는 일
    • 2.자유 소프트웨어와 배포판: 라이선스가 만든 생태계
    • 3.설치와 부팅: 전원을 켜는 순간부터
    • 4.파일시스템 구조와 파일의 종류: 모든 것은 파일이다
    • 5.Week 1 종합 복습: 개념을 꿰뚫는 시간
  • Week 2
  • Week 3
  • Week 4
  • Week 5
  • Week 6
  • Week 7
    • 1.패키지 관리: RPM·YUM/DNF와 DEB·APT 두 계열을 한 손에
    • 2.소스 컴파일과 라이브러리: tar→configure→make→make install의 의미
    • 3.커널과 모듈: 시스템의 심장과 그 확장 부품 다루기
    • 4.장치 관리와 프린터: /dev·udev로 하드웨어 다루고 CUPS로 인쇄하기
    • 5.Week 7 종합 복습: 백업과 시스템 관리의 큰 그림
    • 6.가상화 관리: 하이퍼바이저·KVM·컨테이너로 한 서버를 여럿처럼 쓰기
  • Week 8
  • Week 9
  • Week 10
  • Week 11
  • Week 12
  • Week 13
  • Week 14
합격 후기

© CertNote · 주간랩스

  • 소개
  • 수정 기록
  • 문의
  • 이용약관
  • 개인정보처리방침
← 리눅스마스터 1급/Week 7/Day 2

기준: 리눅스마스터 1급 출제 기준·오류 제보

리눅스마스터 1급· AssociateWeek 7 · Day 2읽기 약 11분
핵심 정리
  • 소스 설치 4단계는 역할이 또렷하다 — tar(풀기) → ./configure(시스템 정찰 + Makefile 생성) → make(컴파일·링크) → make install(시스템 경로 복사).
  • --prefix가 설치 최상위 경로를 정한다(기본 /usr/local). 패키지와 충돌을 피하려면 /usr/local이나 /opt.
  • 소스 설치는 rpm/dpkg 데이터베이스에 기록되지 않는다. yum remove로 못 지우고 make uninstall 또는 수동 삭제뿐 — 소스 설치 최대 단점.
  • 라이브러리는 정적(.a, 컴파일 시 실행 파일에 포함)과 동적(.so, 실행 시 로드·공유)으로 갈린다.
  • ldd로 의존성을 보고, 새 .so 경로는 /etc/ld.so.conf(.d) 등록 + ldconfig로 알려준다. "cannot open shared object file" 오류의 표준 해법이다.

Day 2 - 소스 컴파일과 라이브러리: tar→configure→make→make install의 의미

압축 해제 — tar로 소스 꾸러미 풀기

  • 소스 코드는 보통 이름-버전.tar.gz(또는 .tar.bz2, .tar.xz) 형태의 압축 아카이브로 배포된다.
  • 소스 컴파일을 하는 이유: 저장소에 없는 최신 버전이 필요하거나, 빌드 옵션을 직접 고르고 싶거나, 내 CPU에 최적화된 바이너리를 얻고 싶을 때.
tar -zxvf nginx-1.24.0.tar.gz    # gzip 압축 풀기(z) + 추출(x) + 상세(v) + 파일(f)
tar -jxvf nginx-1.24.0.tar.bz2   # bzip2 압축(j)
tar -Jxvf nginx-1.24.0.tar.xz    # xz 압축(대문자 J)
cd nginx-1.24.0                   # 풀린 디렉터리로 진입
옵션의미
ccreate(묶기)
xextract(풀기)
tlist(목록 보기)
zgzip(.gz)
jbzip2(.bz2)
Jxz(.xz)
vverbose(과정 표시)
ffile(아카이브 파일 지정, 항상 마지막)

tar의 f 옵션은 반드시 마지막에 와야 한다. 바로 뒤의 인자를 "아카이브 파일 이름"으로 읽기 때문이다. tar -zxvf file.tar.gz에서 f 다음의 file.tar.gz가 대상이다. -zxfv처럼 순서를 바꾸면 v를 파일명으로 오해해 오류가 난다. 압축 종류(z/j/J)는 풀 때 생략해도 최신 tar는 자동 감지하지만, 시험에서는 명시한 보기를 답으로 본다.

풀린 디렉터리에는 거의 항상 README, INSTALL, configure 스크립트, Makefile.in 등이 있다. 설치 전 INSTALL 파일을 읽는 것이 정석이다 — 필요한 빌드 도구나 라이브러리, 특이한 옵션이 거기 적혀 있다. tar -tzvf file.tar.gz로 풀기 전에 내용 목록만 미리 확인할 수도 있다(t = list).

./configure — 시스템 정찰과 Makefile 생성

  • ./configure는 소스 디렉터리에 포함된 셸 스크립트로, 내 시스템 환경을 조사한다.
  • 점검 항목: 어떤 컴파일러가 있는지, 필요한 라이브러리와 헤더가 설치돼 있는지, CPU 아키텍처가 무엇인지.
  • 그 결과를 바탕으로 이 시스템에 맞는 Makefile을 만들어 낸다.
./configure                              # 기본 설정으로 점검 + Makefile 생성
./configure --prefix=/usr/local/nginx    # 설치 위치 지정
./configure --with-http_ssl_module       # SSL 모듈 포함(기능 켜기)
./configure --without-http_rewrite_module  # 특정 기능 빼기
./configure --help                       # 사용 가능한 옵션 전체 보기

--prefix는 나중에 make install이 파일을 복사할 최상위 경로를 정한다. 기본값은 보통 /usr/local이다. --prefix=/opt/myapp로 주면 실행 파일은 /opt/myapp/bin, 라이브러리는 /opt/myapp/lib에 들어간다. 소스 설치를 한 디렉터리에 격리하고 싶을 때 핵심이 되는 옵션이다. 패키지 관리자와 충돌하지 않도록 보통 /usr/local이나 /opt를 쓴다.

⚠️ 함정: ./configure가 "필요한 라이브러리가 없다(configure: error: ... not found)"며 멈추는 일이 매우 흔하다. 이는 개발용 헤더 패키지(-devel 또는 -dev 접미사)가 없어서다. 예컨대 SSL 기능을 빌드하려면 openssl-devel(RHEL) 또는 libssl-dev(Debian)가 필요하다. 컴파일 오류의 대부분이 이 단계에서, 의존 개발 패키지 누락으로 발생한다.

모든 소스에 configure가 있는 것은 아니다. 이 스크립트는 GNU Autotools(autoconf/automake)가 생성한 것으로, 그 자체로는 소스에 포함돼 배포된다. CMake를 쓰는 프로젝트는 cmake .로, Python은 setup.py로 대신한다. 하지만 리눅스마스터가 묻는 전통적 흐름은 Autotools 기반 ./configure다.

make — 컴파일과 링크

  • make는 configure가 만든 Makefile의 지시대로 소스 파일을 컴파일한다.
  • 이어 생성된 오브젝트 파일들을 라이브러리와 링크해 실행 파일을 만든다.
  • 실제로 "번역"이 일어나는 단계가 여기다.
make            # Makefile에 따라 컴파일 + 링크
make -j4        # CPU 4코어로 병렬 컴파일(속도↑)
make clean      # 컴파일 산출물 제거(다시 빌드 전)

컴파일은 사실 두 하위 단계다. (1) 컴파일: 각 .c 소스를 .o(오브젝트, 기계어 조각)로 번역. (2) 링크: 여러 .o와 라이브러리(.so/.a)를 묶어 하나의 실행 파일을 완성. make 출력에서 gcc -c ...(컴파일)와 마지막의 gcc -o 실행파일 ...(링크)을 구분해 보면 이 흐름이 보인다. "undefined reference" 오류는 거의 항상 링크 단계에서 라이브러리를 못 찾을 때 난다.

make는 파일의 수정 시각을 비교해 바뀐 부분만 다시 컴파일한다. 그래서 큰 프로젝트에서 코드 한 줄만 고친 뒤 make를 다시 돌리면 전체가 아니라 해당 파일과 그에 의존하는 부분만 빌드돼 빠르다. 처음부터 깨끗이 다시 빌드하려면 make clean 후 make를 한다. make는 인자 없이 실행하면 Makefile의 첫 번째 타깃(보통 all)을 수행한다.

make install — 시스템 경로에 복사

  • 마지막 make install은 완성된 실행 파일·라이브러리·문서를 --prefix로 지정한 시스템 경로에 복사한다.
  • 이 단계만 보통 root 권한이 필요하다(/usr/local 등 시스템 영역에 쓰기 때문).
sudo make install    # 빌드 산출물을 시스템 경로로 복사(설치)
단계명령하는 일산출물/결과
1tar -zxvf압축 해제소스 디렉터리
2./configure시스템 점검Makefile 생성
3make컴파일 + 링크실행 파일(빌드 디렉터리 안)
4make install시스템 경로 복사/usr/local/...에 설치 완료

⚠️ 함정: 소스 컴파일로 설치한 프로그램은 패키지 데이터베이스(rpm/dpkg)에 기록되지 않는다. 따라서 rpm -qa나 dpkg -l에 나타나지 않고, yum remove로 지울 수도 없다. 삭제하려면 make uninstall(Makefile이 지원할 때)을 쓰거나 설치된 파일을 수동으로 지워야 한다. 이 "관리 사각지대"가 소스 설치의 가장 큰 단점이다.

# 직접 쳐보기 — 전형적 소스 설치 흐름 (개발 도구 설치되어 있다고 가정)
tar -zxvf hello-2.12.tar.gz
cd hello-2.12
./configure --prefix=/usr/local/hello
make
sudo make install
/usr/local/hello/bin/hello       # 설치한 프로그램 실행

정적 라이브러리 vs 동적 라이브러리

  • 여러 프로그램이 공통으로 쓰는 코드(예: 수학 함수, 암호화)는 라이브러리로 묶여 재사용된다.
  • 링크 방식에 따라 두 종류로 갈린다.
구분정적(static)동적(shared)
확장자.a.so
연결 시점컴파일 시 실행 파일에 포함실행 시 로드
실행 파일 크기큼(코드 복사됨)작음
메모리프로그램마다 별도 사본여러 프로그램이 공유
라이브러리 교체재컴파일 필요.so 교체만으로 반영
배포독립 실행(의존성 없음).so 함께 있어야 동작

정적 라이브러리(.a)는 컴파일할 때 그 코드가 실행 파일 안으로 복사된다. 그래서 실행 파일이 크지만 혼자서도 돈다. 동적 라이브러리(.so, shared object)는 실행 파일에 "이 라이브러리가 필요하다"는 참조만 남기고, 실행되는 순간 동적 링커가 메모리로 로드한다. 그래서 실행 파일이 작고, 같은 .so를 여러 프로그램이 메모리에서 공유한다. 보안 패치가 나오면 .so 하나만 교체해 모든 프로그램에 반영되는 것도 동적의 장점이다.

동적 라이브러리는 보통 libNAME.so.X.Y.Z 형태의 실제 파일과, 그것을 가리키는 심볼릭 링크 libNAME.so.X(soname), libNAME.so(개발용)로 구성된다. 버전 번호 체계 덕분에 호환되는 범위 안에서 라이브러리를 교체할 수 있다. 실행 파일은 soname(libssl.so.1.1 등)으로 의존성을 기록한다.

ldd · ldconfig · /etc/ld.so.conf — 동적 링커 다루기

  • 동적 라이브러리는 "실행 시 로드"되므로 관리 도구가 두 가지 질문에 답해야 한다.
    • 실행 파일이 어떤 .so를 필요로 하는가 → ldd
    • 그 .so를 어디서 찾을 것인가 → /etc/ld.so.conf + ldconfig
ldd /usr/bin/nginx        # 이 실행 파일이 의존하는 동적 라이브러리 목록
ldconfig                   # 라이브러리 캐시(/etc/ld.so.cache) 재생성
ldconfig -p                # 현재 캐시에 등록된 라이브러리 목록
# 새 라이브러리 경로를 동적 링커에 등록하기
echo "/usr/local/mylib/lib" > /etc/ld.so.conf.d/mylib.conf
ldconfig                   # 캐시 갱신 → 이제 그 경로의 .so를 찾을 수 있음

ldd(list dynamic dependencies)는 실행 파일이 의존하는 동적 라이브러리와 그것이 실제로 어디에 연결되는지를 보여준다. not found가 뜨면 그 라이브러리를 시스템이 못 찾는 것이고, 프로그램 실행이 실패한다. 이때 라이브러리 경로를 /etc/ld.so.conf(또는 /etc/ld.so.conf.d/*.conf)에 추가하고 ldconfig로 캐시를 갱신해야 한다.

동적 링커는 매번 디렉터리를 뒤지는 대신 /etc/ld.so.cache라는 바이너리 캐시를 참조해 빠르게 라이브러리를 찾는다. ldconfig는 /lib, /usr/lib, 그리고 /etc/ld.so.conf에 적힌 경로들을 스캔해 이 캐시를 다시 만든다. 그래서 새 .so를 시스템 경로 밖에 설치했다면 ldconfig를 반드시 실행해야 인식된다. 임시로는 환경변수 LD_LIBRARY_PATH로 경로를 더할 수도 있지만, 영구 등록은 ld.so.conf + ldconfig가 정석이다.

소스 설치한 프로그램이 "error while loading shared libraries: libxxx.so.1: cannot open shared object file"로 실행 실패하는 일이 잦다. 원인은 그 .so가 /usr/local/lib 같은 비표준 경로에 있는데 동적 링커가 모르기 때문이다. 해결: 그 경로를 ld.so.conf.d에 추가하고 ldconfig. 이 시나리오가 시험과 실무 모두에서 겪는 상황이다.

초기 유닉스는 정적 링크만 썼다. 메모리가 귀하던 시절, 같은 라이브러리 코드가 모든 실행 파일에 중복 복사되는 건 큰 낭비였다. 1980년대 후반 동적 공유 라이브러리(.so)가 도입되면서 디스크와 메모리를 극적으로 아꼈고, 보안 패치를 라이브러리 하나만 교체해 전 시스템에 적용하는 길이 열렸다. 2014년 Heartbleed(OpenSSL 취약점) 대응이 빨랐던 것도, libssl.so 하나만 갈아 끼우면 그것에 동적 링크된 모든 프로그램이 즉시 패치됐기 때문이다. 동적 링크의 가치를 보여주는 대표 사례다.

📖 용어

  • 소스 컴파일 : 사람이 쓴 C/C++ 코드를 내 시스템에서 직접 기계어로 번역해 설치하는 것. 미리 만든 꾸러미를 받는 패키지 설치와 반대다.
  • ./configure : 시스템을 정찰해 컴파일러·라이브러리·아키텍처를 확인하고 그 환경에 맞는 Makefile을 만드는 스크립트.
  • Makefile : 무엇을 어떤 순서로 컴파일하고 링크할지 적어 둔 빌드 지시서. make가 이걸 읽는다.
  • --prefix : make install이 파일을 복사할 최상위 경로. 기본값은 보통 /usr/local.
  • -devel / -dev 패키지 : 컴파일에 필요한 헤더 파일 모음. 이게 없어서 configure가 멈추는 경우가 가장 흔하다.
  • 컴파일 vs 링크 : .c를 .o 기계어 조각으로 번역하는 단계 / 그 조각들과 라이브러리를 묶어 실행 파일을 완성하는 단계.
  • undefined reference : 링크 단계에서 필요한 라이브러리·함수를 못 찾았을 때 나는 오류.
  • 정적 라이브러리(.a) : 컴파일할 때 코드가 실행 파일 안으로 복사되는 방식. 파일은 커지지만 혼자 돈다.
  • 동적 라이브러리(.so) : 실행되는 순간 로드되어 여러 프로그램이 메모리에서 공유하는 방식. 교체만으로 전체에 패치가 반영된다.
  • soname : libssl.so.1.1처럼 호환 버전을 나타내는 라이브러리 이름. 실행 파일은 이 이름으로 의존성을 기록한다.
  • ldd : 실행 파일이 어떤 동적 라이브러리에 의존하는지, 실제로 어디에 연결되는지 보여주는 명령.
  • ldconfig / /etc/ld.so.cache : 라이브러리 경로를 스캔해 캐시를 다시 만드는 명령 / 동적 링커가 참조하는 바이너리 캐시.

📝 연습 문제

선택지를 클릭하면 정답·해설이 펼쳐집니다.

문제 1

nginx-1.24.0.tar.bz2 파일을 풀고 과정을 화면에 표시하려 한다. 가장 올바른 명령은?

문제 2

소스 설치 과정에서 ./configure가 수행하는 핵심 역할은?

문제 3

소스 설치 시 프로그램이 설치될 최상위 경로를 지정하는 ./configure 옵션은?

문제 4

정적 라이브러리(.a)와 동적 라이브러리(.so)의 차이로 옳은 것은?

문제 5

실행 파일이 의존하는 동적 라이브러리 목록과 실제 연결 상태를 확인하는 명령은?

문제 6

/usr/local/lib에 새로 설치한 동적 라이브러리를 시스템이 인식하도록 영구 등록하는 올바른 절차는?

문제 7

소스 컴파일로 설치한 프로그램의 특징으로 옳은 것은?

이전패키지 관리: RPM·YUM/DNF와 DEB·APT 두 계열을 한 손에Week 7 · Day 1다음 커널과 모듈: 시스템의 심장과 그 확장 부품 다루기Week 7 · Day 3

참고 공식 자료

  • 리눅스마스터 1급 공식 출제 기준(새 탭에서 열림)

이 페이지

  • 압축 해제 — tar로 소스 꾸러미 풀기
  • configure — 시스템 정찰과 Makefile 생성
  • make — 컴파일과 링크
  • make install — 시스템 경로에 복사
  • 정적 라이브러리 vs 동적 라이브러리
  • ldd · ldconfig · /etc/ld.so.conf — 동적 링커 다루기
  • 용어
  • 연습 문제