사전 부트로더
개념

부트로더

gabury1고친 사람 github-actions[bot]

부트로더는 컴퓨터를 켤 때 운영체제를 불러와 실행을 넘겨줍니다. 막 켜진 컴퓨터는 디스크에 있는 운영체제를 스스로 읽지 못합니다. 그 사이를 잇는 작은 프로그램이 부트로더입니다. 운영체제가 돌기 시작하면 부트로더는 할 일을 마치고 물러납니다.

쉽고 빠른 이해

부트로더는 컴퓨터가 켜질 때 운영체제를 메모리에 올리고 실행을 넘겨줍니다. 정확히는 운영체제의 핵심 부분인 커널을 올립니다. 서버를 켜면 로그인 화면이 뜨기 전에 커널 목록이 잠깐 보일 때가 있습니다. 그 목록을 띄우는 프로그램이 부트로더입니다.

이런 프로그램이 따로 필요한 까닭은 켜진 직후의 메모리가 비어 있기 때문입니다. 운영체제는 디스크에 있습니다. 디스크에서 운영체제를 꺼내 올 프로그램도 아직 메모리에 없습니다.

어떻게 도나:

  1. 메인보드의 칩에 든 펌웨어가 먼저 돌아 부트로더를 찾아 올립니다
  2. 부트로더가 디스크에서 커널을 찾아 메모리에 올립니다
  3. 커널이 알아야 할 설정을 함께 넘기고 커널에 실행을 넘깁니다

대가는 켜는 과정에 단계가 하나 더 붙는다는 것입니다. 부트로더가 망가지면 운영체제가 멀쩡해도 컴퓨터가 켜지지 않습니다.

컨테이너처럼 이미 돌고 있는 커널 위에서 시작하는 것에는 부트로더가 없습니다. 새로 올릴 커널이 없기 때문입니다.

상세

큰 장작에 불을 붙일 때 성냥을 바로 장작에 대지 않습니다. 성냥으로 불쏘시개에 먼저 불을 붙입니다. 불쏘시개가 타오르면 그 불이 장작으로 옮겨 갑니다.

부트로더는 이 불쏘시개에 해당합니다. 컴퓨터가 켜진 직후에 돌아 운영체제를 메모리에 올립니다. 올리기가 끝나면 운영체제에 제어를 넘기고 물러납니다.

제어를 넘긴다는 것은 다음에 실행할 명령어를 상대 쪽 코드로 옮긴다는 뜻입니다. 넘긴 쪽은 그 뒤로 다시 돌지 않습니다. 함수를 부른 뒤 돌아오기를 기다리는 호출과 다릅니다. 돌아올 곳을 남기지 않고 넘깁니다.

컴퓨터를 켜서 운영체제를 쓸 수 있게 되기까지의 과정을 부팅이라고 부릅니다. 부트로더는 부팅의 가운데 단계를 맡습니다. 그 앞에는 메인보드의 칩에 미리 든 프로그램이 돕니다. 그 뒤에는 운영체제가 돌기 시작합니다.

부트로더가 필요한 까닭

메모리는 전원이 꺼지면 내용이 지워집니다. 그래서 막 켜진 컴퓨터의 메모리에는 실행할 프로그램이 하나도 없습니다. 운영체제는 전원이 꺼져도 내용이 남는 디스크에 들어 있습니다.

CPU(Central Processing Unit, 중앙 처리 장치)는 디스크에서 명령어를 바로 꺼내 실행하지 못합니다. 명령어는 주소로 곧장 읽을 수 있는 곳에 있어야 합니다. 디스크의 운영체제를 쓰려면 누군가 먼저 그것을 메모리로 옮겨야 합니다.

그런데 옮기는 일도 프로그램이 해야 합니다. 그 프로그램은 누가 옮겨 줄까요. 닭과 달걀 같은 문제입니다.

이 문제는 작은 프로그램에서 큰 프로그램으로 차례차례 넘어가며 풉니다. 처음에는 전원이 꺼져도 지워지지 않는 칩에 미리 들어 있는 프로그램이 돕니다. 그 프로그램이 조금 더 큰 부트로더를 올립니다. 부트로더가 가장 큰 운영체제를 올립니다.

펌웨어에서 커널까지

전원을 넣으면 CPU 는 미리 정해진 주소 하나에서 명령어를 읽기 시작합니다. 이 주소를 리셋 벡터라고 부릅니다. 리셋 벡터에는 메인보드의 칩에 든 프로그램이 놓여 있습니다.

그 프로그램이 펌웨어입니다. 펌웨어는 하드웨어에 붙박이로 실려 나오는 소프트웨어입니다. 부팅 때 펌웨어는 메모리와 장치를 쓸 수 있게 깨웁니다. 그다음 디스크에서 부트로더를 찾아 메모리에 올립니다.

부트로더는 디스크에서 커널 파일을 찾아 메모리에 올립니다. 커널은 운영체제의 핵심 부분으로, 하드웨어를 관리하고 프로그램을 돌립니다. 앞에서 부트로더가 운영체제를 올린다고 한 것은 정확히는 이 커널을 올린다는 뜻입니다. 운영체제의 나머지는 커널이 뜬 뒤에 커널이 읽어 들입니다.

부트로더는 커널이 알아야 할 설정도 함께 챙깁니다. 준비가 끝나면 커널에 제어를 넘깁니다.

커널은 장치를 마저 준비하고 첫 프로세스를 띄웁니다. 프로세스는 메모리에 올라 돌고 있는 프로그램 하나입니다. 그 뒤로 서비스와 로그인 화면이 차례로 뜹니다.

세 단계가 각각 어디서 시작하는지 그려 보면 이렇습니다.

flowchart TD
    P0["전원을 넣는다"] --> F
    subgraph 칩["메인보드의 칩 · 전원이 꺼져도 남는다"]
        F["펌웨어"]
    end
    subgraph 메모리["메모리 · 켤 때마다 비어 있다"]
        B["부트로더"]
        K["커널"]
    end
    F -->|"디스크에서 읽어 올린다"| B
    B -->|"디스크에서 읽어 올린다"| K
    K --> P["첫 프로세스"]

펌웨어만 칩에서 곧장 돌기 시작합니다. 부트로더와 커널은 앞 단계가 디스크에서 읽어 메모리에 올려 줍니다. 앞 단계가 다음 단계를 올리는 모양이 두 번 되풀이됩니다.

펌웨어가 커널을 바로 올리지 않는 까닭

펌웨어는 어느 운영체제가 깔릴지 모르는 채로 만들어집니다. 그래서 운영체제마다 다른 것을 몰라도 되도록 일을 좁게 잡습니다. 정해진 방식으로 부트로더 하나를 찾아 올리는 데까지만 합니다.

커널을 어디서 찾을지는 운영체제마다 다릅니다. 커널 파일은 대개 파일 시스템 안에 들어 있습니다. 파일 시스템은 디스크에 파일을 이름으로 저장하고 찾는 방식입니다. 이 방식도 운영체제마다 여럿입니다.

커널에 무엇을 넘겨야 하는지도 운영체제마다 다릅니다. 이 차이를 부트로더가 떠안습니다. 부트로더는 운영체제와 함께 깔리고 함께 바뀝니다.

덕분에 새 커널을 깔 때 펌웨어는 손대지 않아도 됩니다. 부트로더의 설정만 새 커널을 가리키도록 고치면 됩니다. 그 대가로 켜는 과정에 단계가 하나 더 붙습니다. 망가질 수 있는 곳도 하나 늡니다.

펌웨어가 부트로더를 찾는 두 방식

개인용 컴퓨터와 서버의 펌웨어는 크게 두 방식으로 나뉩니다. 둘은 부트로더를 찾는 방법이 다릅니다.

BIOS(Basic Input/Output System, 기본 입출력 시스템)는 오래된 방식입니다. 디스크 맨 앞의 작은 구역을 읽어 거기 담긴 코드를 실행합니다. BIOS 는 파일 시스템을 모릅니다. 디스크의 정해진 위치만 읽습니다.

UEFI(Unified Extensible Firmware Interface, 통합 확장 펌웨어 인터페이스)는 BIOS 를 대신하려고 나온 방식입니다. UEFI 는 파일 시스템 하나를 읽을 줄 압니다. 그래서 부트로더를 파일로 두고 이름으로 찾아 실행합니다.

그 파일은 부트로더를 두려고 따로 떼어 둔 파티션에 들어 있습니다. 파티션은 디스크 하나를 나눈 구획입니다. 운영체제의 나머지 파일은 다른 파티션에 둡니다.

방식 부트로더를 찾는 곳 파일 시스템을 아나
BIOS 디스크 맨 앞의 작은 구역 ✗
UEFI 부트로더용 파티션에 든 파일 ✓

BIOS 가 읽어 주는 구역이 너무 작아서 생기는 문제가 하나 있습니다.

부트로더를 여러 단계로 나누는 까닭

BIOS 방식에서 펌웨어가 읽어 주는 디스크 맨 앞 구역은 아주 작습니다. 파일 시스템을 읽는 코드와 메뉴 화면까지 담기에는 모자랍니다. 그래서 부트로더를 둘로 나눕니다.

첫 단계는 그 작은 구역에 들어갑니다. 하는 일은 하나뿐입니다. 디스크의 정해진 위치에 있는 둘째 단계를 찾아 메모리에 올립니다.

둘째 단계가 부트로더의 본체입니다. 파일 시스템을 읽어 커널 파일을 찾습니다. 메뉴를 띄워 올릴 커널을 고르게 합니다. 그리고 커널을 올립니다.

디스크의 앞에서 뒤로 무엇이 놓이는지 쌓아 보면 이렇습니다.

block-beta
columns 1
  a["디스크 맨 앞의 작은 구역 · 부트로더 첫 단계"]
  b["첫 단계가 읽는 위치 · 부트로더 둘째 단계"]
  c["파일 시스템 · 커널 파일 · 부트로더 설정 파일 · 운영체제의 나머지 파일"]

맨 위 두 칸은 파일 시스템 밖에 있습니다. 그래서 파일 이름 없이 위치로만 찾습니다. 마지막 칸의 파일은 둘째 단계가 파일 이름으로 찾습니다.

UEFI 방식에서는 펌웨어가 부트로더 파일을 곧장 읽어 줍니다. 그래서 첫 단계를 따로 둘 필요가 줄어듭니다.

커널에 넘겨주는 것

부트로더는 커널만 올리고 끝내지 않습니다. 커널이 막 깨어난 순간에 스스로 알아낼 수 없는 것을 챙겨 함께 넘깁니다. 커널과 함께 넘기는 것은 다음 셋입니다.

넘기는 것 무엇인가 왜 필요한가
초기 램디스크 메모리에 통으로 올려 쓰는 작은 파일 모음 진짜 디스크를 읽는 데 필요한 드라이버가 이 안에 있다
커널 명령줄 커널에 주는 설정 문자열 어느 디스크를 쓸지, 로그를 어디로 낼지 같은 것을 정한다
하드웨어 정보 메모리가 어디에 얼마나 있는지, 어떤 장치가 붙었는지 커널이 장치를 쓰기 전에 알아야 한다

초기 램디스크는 또 하나의 닭과 달걀 문제를 풉니다. 커널이 디스크를 읽으려면 그 디스크용 드라이버가 필요합니다. 그 드라이버 파일이 하필 그 디스크 안에 있을 수 있습니다.

그래서 부트로더가 드라이버를 담은 초기 램디스크를 커널과 함께 메모리에 올려 둡니다. 커널은 이것부터 읽어 드라이버를 챙깁니다. 진짜 디스크는 그다음에 읽습니다.

커널 명령줄은 부트로더 설정 파일에 적어 두면 켤 때마다 커널에 전해집니다. 커널을 다시 빌드하지 않고도 커널의 동작을 바꾸는 통로입니다.

부팅 메뉴

부트로더는 올릴 커널을 고르게 해 줍니다. 디스크에 커널이 여럿 있으면 켤 때 목록을 띄웁니다. 아무것도 안 고르면 정해 둔 커널로 넘어갑니다.

이 목록은 새 커널이 망가졌을 때 쓸모가 있습니다. 새 커널로 켜지지 않으면 목록에서 옛 커널을 골라 켤 수 있습니다. 옛 커널을 지우지 않고 남겨 두는 까닭이 이것입니다.

한 디스크에 운영체제 둘을 깔아 번갈아 쓰는 것도 이 목록 덕분입니다. 이것을 듀얼 부팅이라고 부릅니다.

프로그램 로더와 다른 점

로더는 운영체제 안에서 프로그램 파일을 메모리에 올리는 구성요소입니다. 하는 일은 부트로더와 닮았습니다. 둘 다 파일을 메모리에 올리고 그 코드에 제어를 넘깁니다.

차이는 도와줄 운영체제가 있느냐입니다. 로더는 커널이 제공하는 파일 읽기와 메모리 관리를 빌려 씁니다. 부트로더가 돌 때는 커널이 아직 없습니다. 디스크를 읽는 코드와 파일 시스템을 해석하는 코드를 부트로더가 몸에 지니고 있어야 합니다.

로더 부트로더
도는 때 운영체제가 돌고 있을 때 운영체제가 올라오기 전
올리는 것 프로그램 운영체제의 커널
디스크 읽기 커널에 맡긴다 스스로 한다
라이브러리 실행할 때 이어 붙인다 빌드할 때 미리 다 넣어 둔다

표의 「라이브러리」 줄이 정적 링크와 이어집니다. 정적 링크는 필요한 라이브러리 코드를 빌드할 때 실행 파일 안에 모두 넣는 방식입니다. 부트로더는 이 방식으로 빌드합니다.

로더는 프로그램을 올린 뒤 라이브러리를 찾아 이어 붙이는 일을 동적 링커에게 맡깁니다. 동적 링커도 운영체제 위에서 도는 프로그램입니다. 부트로더가 돌 때는 동적 링커도 없습니다. 그래서 부트로더는 필요한 코드를 모두 품은 한 덩어리여야 합니다.

임베디드 장치의 부트로더

임베디드 장치는 공유기나 가전처럼 정해진 일만 하도록 기계 안에 들어간 컴퓨터입니다. 이런 장치도 부트로더를 씁니다. 모양은 개인용 컴퓨터와 조금 다릅니다.

임베디드 장치의 두뇌는 대개 SoC(System on Chip, 시스템 온 칩)입니다. SoC 는 CPU 와 주변 장치를 칩 하나에 모은 부품입니다.

SoC 안에는 공장에서 새겨 넣은 작은 부팅 코드가 들어 있습니다. 이 코드가 개인용 컴퓨터의 펌웨어 몫을 합니다. 부팅 코드는 플래시 메모리나 메모리 카드에서 부트로더를 찾아 올립니다.

플래시 메모리는 전원이 꺼져도 내용이 남는 저장 칩입니다. 임베디드 장치에서는 이 칩이 디스크 몫을 합니다.

임베디드 보드는 어떤 장치가 어디에 붙었는지를 커널에 스스로 알려 주지 못할 때가 많습니다. 그래서 그 목록을 적은 파일을 부트로더가 커널에 넘깁니다. 이 파일을 디바이스 트리라고 부릅니다. 「커널에 넘겨주는 것」 소절 표의 「하드웨어 정보」 줄이 이것입니다.

프로그램을 바꿔 끼우는 부트로더

마이크로컨트롤러는 SoC 보다 더 작은 칩입니다. 여기서는 운영체제 없이 프로그램 하나만 돕니다. 이런 장치의 부트로더는 올릴 커널이 없습니다.

이 장치에서는 부트로더가 올리는 그 프로그램을 흔히 펌웨어라고 부릅니다. 앞에서 본 펌웨어는 부트로더보다 먼저 도는 칩 속 프로그램이었습니다. 여기서는 부트로더 뒤에 도는 쪽을 그렇게 부릅니다.

대신 새 프로그램을 받아 플래시 메모리에 쓰는 일을 맡습니다. 장치를 공장에 되돌려 보내지 않고도 프로그램을 바꿀 수 있게 됩니다. 부트로더는 켤 때마다 두 가지를 봅니다.

flowchart TD
    A["전원을 넣는다 · 부트로더가 돈다"] --> B{"새 프로그램을 받으라는 신호가 왔나"}
    B -->|왔다| C["새 프로그램을 받아 플래시에 쓴다"]
    B -->|안 왔다| D{"플래시에 든 프로그램이 온전한가"}
    C --> D
    D -->|온전하다| E["그 프로그램에 제어를 넘긴다"]
    D -->|깨졌다| F["부트로더에 머물며 새 프로그램을 기다린다"]

첫째는 새 프로그램을 받으라는 신호입니다. 연결된 컴퓨터가 신호를 보내기도 합니다. 켤 때 누른 버튼이 신호가 되기도 합니다.

둘째는 플래시에 든 프로그램이 온전한지입니다. 쓰는 도중에 전원이 끊기면 프로그램이 반쯤만 쓰여 깨질 수 있습니다.

그림의 「깨졌다」 갈래가 부트로더의 쓸모를 보여 줍니다. 프로그램이 깨져도 부트로더는 제어를 넘기지 않고 버팁니다. 부트로더만 살아 있으면 새 프로그램을 다시 받아 장치를 되살릴 수 있습니다. 부트로더 자체는 좀처럼 고쳐 쓰지 않는 까닭이 이것입니다.

다음 단계를 검사하고 넘기기

부트로더는 커널을 올리기 전에 그 커널을 믿어도 되는지 검사할 수 있습니다. 공격자가 디스크의 커널을 바꿔치기하면 운영체제 전체가 넘어갑니다. 운영체제가 뜬 뒤에 하는 검사로는 이것을 못 막습니다. 검사하는 쪽이 이미 바꿔치기된 커널 위에서 돌기 때문입니다.

검사에는 전자 서명을 씁니다. 전자 서명은 파일을 만든 쪽이 자기만 가진 비밀 키로 만들어 붙이는 값입니다. 받는 쪽은 널리 공개된 짝 키로 확인합니다. 파일이 한 글자라도 바뀌었으면 확인이 실패합니다.

각 단계는 다음 단계의 서명을 확인한 뒤에만 제어를 넘깁니다. 펌웨어가 부트로더를 확인합니다. 부트로더가 커널을 확인합니다. 이렇게 이어지는 확인을 신뢰 사슬이라고 부릅니다.

신뢰 사슬로 켜는 방식을 보안 부팅이라고 부릅니다. 사슬의 첫 고리는 펌웨어입니다. 펌웨어는 칩에 들어 있어 디스크를 바꿔치기해도 함께 바뀌지 않습니다.

백엔드 개발자가 부트로더를 만나는 때

서버에 커널 업데이트를 깔고 재부팅하면 부트로더가 새 커널을 올립니다. 새 커널로 켜지지 않으면 서버에 원격으로 접속할 수 없습니다. 네트워크를 여는 것이 운영체제이기 때문입니다.

이때는 서버의 화면과 키보드를 원격으로 넘겨받는 콘솔로 들어갑니다. 부팅 메뉴에서 옛 커널을 골라 켠 뒤 원인을 찾습니다. 부트로더 설정 자체가 망가졌으면 메뉴조차 안 뜹니다. 그때는 다른 저장 장치로 켜서 부트로더를 다시 깔아야 합니다.

가상 머신도 부팅을 거칩니다. 가상 머신은 한 컴퓨터 위에 소프트웨어로 흉내 낸 컴퓨터입니다. 흉내 낸 펌웨어가 먼저 돕니다. 그다음 디스크 이미지 안의 부트로더가 커널을 올립니다.

컨테이너는 이 과정을 건너뜁니다. 컨테이너는 이미 돌고 있는 호스트의 커널 위에서 프로세스로 시작합니다. 올릴 커널이 없으니 부트로더도 없습니다. 컨테이너가 가상 머신보다 빨리 뜨는 까닭 가운데 하나입니다.

이름의 유래

부트로더의 「부트」는 부트스트랩(bootstrap)을 줄인 말입니다. 부트스트랩은 장화 뒤축에 달린 손잡이 끈입니다. 영어에는 「장화 끈을 잡아당겨 제 몸을 들어 올린다」는 표현이 있습니다. 남의 도움 없이 불가능해 보이는 일을 해낸다는 뜻입니다.

빈 메모리에서 운영체제가 제 힘으로 일어서는 모습이 이 표현과 닮았습니다. 그래서 켜는 과정을 부트스트랩이라 불렀습니다. 이 말이 줄어 부트가 됐습니다. 컴퓨터를 켜는 일을 부팅이라고 부르는 것도 이 이름에서 왔습니다.

관련 항목

부팅에서 부트로더 앞뒤에 서는 단계

부팅 · 리셋 벡터 · 펌웨어 · BIOS · UEFI · 커널 · init · 운영체제

부트로더가 읽고 커널에 넘기는 데이터

커널 이미지 · 초기 램디스크 · 커널 명령줄 · 디바이스 트리 · 파일 시스템 · 파티션 · MBR · GPT · EFI 시스템 파티션

부트로더를 구현한 프로그램

GRUB · systemd-boot · U-Boot · LILO

부트로더가 닮은 다른 로더

로더 · 동적 링커 · 클래스 로더 · 동적 로딩

부트로더를 빌드하는 방식

정적 링크 · 크로스 컴파일 · 실행 파일 · 진입점 · 링커 스크립트

부트로더가 도는 임베디드 기계

임베디드 · SoC · 마이크로컨트롤러 · RISC-V

부트로더가 맡는 펌웨어 교체

펌웨어 업데이트 · OTA 업데이트 · 체크섬 · 플래시 메모리

부트로더를 지키는 검증 수단

보안 부팅 · 신뢰 사슬 · 전자 서명 · 공개 키 · TPM

부팅 방식이 다른 실행 환경

가상 머신 · 하이퍼바이저 · 컨테이너 · 베어 메탈

다른 이름: bootloader · boot loader · 부트 로더 · 부트스트랩 로더