개념
웹 테스트와 무엇이 다른가
웹 서비스를 테스트할 때 우리는 운영체제·브라우저·네트워크가 대부분의 일을 알아서 해 준다고 가정한다. 메모리가 부족하면 운영체제가 관리하고, 시간은 충분하며, 오류가 나면 로그가 남는다. 임베디드 시스템에서는 이 가정이 하나씩 깨진다.
| 웹 서비스 | 임베디드 시스템 |
|---|---|
| 메모리는 기가바이트, 운영체제가 관리 | 수십~수백 킬로바이트, 개발자가 직접 배치 |
| 응답이 늦으면 사용자가 기다린다 | 응답이 늦으면 모터가 멈추지 않는다(실시간 요구) |
| 오류는 로그와 화면에 남는다 | 화면이 없을 수 있고, 로그 저장 공간도 제한적 |
| 입력은 키보드·마우스·API | 입력은 센서 전압·통신 신호·버튼·타이머 |
| 재시작은 쉽다 | 재시작 자체가 위험할 수 있다(동작 중인 장치) |
| 업데이트는 배포 한 번 | 현장의 장치 수만 대에 펌웨어를 보내야 한다 |
이 차이 때문에 임베디드 테스터는 시스템이 어떻게 생겼는지 를 웹 테스터보다 훨씬 깊이 알아야 한다. 모듈 9의 "코드 읽기"가 여기서는 "구조 읽기"까지 확장된다.
층으로 보는 임베디드 시스템
┌─────────────────────────────────────┐
│ 응용 계층 제어 로직, 상태 머신, 통신 프로토콜 처리 │
├─────────────────────────────────────┤
│ 미들웨어 RTOS, 통신 스택, 파일 시스템 │
├─────────────────────────────────────┤
│ 드라이버 UART·SPI·I2C·CAN·ADC·PWM·GPIO 제어 │
├─────────────────────────────────────┤
│ 부트로더 시작, 무결성 확인, 펌웨어 업데이트 │
├─────────────────────────────────────┤
│ 하드웨어 MCU 코어, 주변장치, 클럭, 전원, 센서 │
└─────────────────────────────────────┘위 그림의 드라이버 칸에 낯선 약어가 몰려 있다. 이 모듈 전체에서 계속 나오므로 여기서 한 번 정리한다. 지금 외울 필요는 없고, 읽다가 막히면 이 표로 돌아오면 된다.
| 약어 | 무엇인가 |
|---|---|
| UART | 선 두 가닥으로 글자를 한 줄씩 주고받는 가장 단순한 통신 |
| SPI | 한 주인이 여러 부품을 선으로 골라 가며 빠르게 주고받는 방식 |
| I2C | 선 두 가닥을 여러 부품이 나눠 쓰고, 주소로 상대를 고르는 방식 |
| CAN | 자동차 안에서 여러 장치가 같은 선으로 신호를 주고받는 방식 |
| ADC | 센서의 전압처럼 끊김 없이 변하는 값을 숫자로 바꾸는 장치 |
| PWM | 켜고 끄는 비율을 바꿔 밝기나 모터 속도를 조절하는 방법 |
| GPIO | 켜짐·꺼짐만 읽고 쓰는 범용 핀 |
메모리도 세 가지가 나온다. 플래시 는 전원이 꺼져도 내용이 남는 저장 공간(펌웨어가 여기 구워진다), RAM 은 전원이 꺼지면 사라지는 작업용 공간, EEPROM 은 설정값처럼 자주 바뀌는 작은 데이터를 전원과 무관하게 담아 두는 공간이다. 쓸 수 있는 횟수에 한계가 있어 몇 번까지 쓰느냐가 시험 항목이 된다.
뒤 레슨에서 FW(펌웨어의 줄임말)와 HAL 도 나온다. HAL 은 칩마다 다른 부분을 한 겹으로 감싸 윗층 코드가 칩을 몰라도 되게 만든 층이다 — 그 덕에 실제 칩 없이도 윗층만 따로 시험할 수 있다(레슨 8).
MCU(마이크로컨트롤러) 는 CPU 코어·메모리(플래시·RAM)·주변장치(타이머·ADC·통신 컨트롤러)를 한 칩에 넣은 것이다. 주변장치는 레지스터라는 특수한 메모리 주소를 통해 제어된다. 드라이버는 이 레지스터를 읽고 쓰는 코드다.
펌웨어 는 이 모든 층의 소프트웨어를 합쳐 플래시에 굽는 하나의 이미지다. 웹처럼 "서버만 재배포"하는 개념이 없다. 드라이버 한 줄을 고쳐도 전체 이미지를 다시 만들고 다시 굽는다.
층마다 생기는 전형적 결함
| 층 | 전형적 결함 | 드러내는 시험 |
|---|---|---|
| 하드웨어 | 전원 잡음, 클럭 오차, 풀업 저항 누락 | 계측(레슨 4), 전원 장애 주입(레슨 6) |
| 부트로더 | 업데이트 중 전원 차단 시 벽돌(brick), 무결성 검사 누락 | 업데이트 중단 시험(레슨 7) |
| 드라이버 | 레지스터 설정 오류, 통신 속도 불일치, 버퍼 오버런 | 통신 경계 시험(레슨 2·3) |
| 미들웨어·RTOS | 태스크 우선순위 오류, 교착, 스택 오버플로 | 부하·타이밍 시험, 스택 여유 측정 |
| 응용 | 상태 머신 누락 전이, 센서 값 경계 처리 | 상태 전이·경계값(모듈 3), SIL(레슨 5) |
베어메탈과 RTOS
작은 시스템은 운영체제 없이 슈퍼루프 로 동작한다.
int main(void) {
init_hardware();
while (1) { // 영원히 반복
read_sensors();
update_control();
send_status();
}
}단순하지만, 한 함수가 오래 걸리면 나머지가 모두 늦어진다. send_status() 가 통신 대기로 50ms 걸리면 센서는 50ms 동안 읽히지 않는다. 테스터는 최악의 루프 한 바퀴 시간 을 재야 한다.
복잡한 시스템은 RTOS(실시간 운영체제 — FreeRTOS, Zephyr, AUTOSAR OS 등)를 쓴다. 기능을 여러 태스크로 나누고 우선순위에 따라 스케줄링한다. 이때 새로운 결함 유형이 생긴다.
| RTOS 결함 | 설명 | 시험 관점 |
|---|---|---|
| 우선순위 역전 | 낮은 우선순위 태스크가 자원을 잡고 있어 높은 우선순위 태스크가 기다림 | 자원 공유 태스크를 동시에 부하 |
| 교착(deadlock) | 두 태스크가 서로의 자원을 기다림 | 잠금 순서가 다른 경로를 동시에 실행 |
| 스택 오버플로 | 태스크에 할당된 스택보다 깊은 호출 | 최악 호출 경로 실행 후 스택 여유(high-water mark) 측정 |
| 기아(starvation) | 낮은 우선순위 태스크가 전혀 실행되지 않음 | 고부하에서 모든 태스크의 실행 주기 기록 |
우선순위 역전은 1997년 화성 탐사선 Mars Pathfinder의 반복 리셋 원인으로 유명하다. 지상 시험에서 드물게 재현되던 현상을 무시했다가 화성에서 문제가 됐다. "드물게 재현되는" 은 임베디드에서 가장 위험한 말이다.
인터럽트 — 언제든 끼어드는 코드
인터럽트는 하드웨어 사건(타이머 만료, 데이터 수신, 버튼 눌림)이 생기면 현재 코드를 멈추고 인터럽트 서비스 루틴(ISR) 을 실행하는 구조다. 임베디드의 비결정적 결함 대부분이 여기서 나온다.
- 공유 변수 경쟁 — 메인 루프가 변수를 읽는 도중 ISR이 그 변수를 바꾼다. 16비트 MCU에서 32비트 값을 두 번에 나눠 읽는 사이에 ISR이 끼어들면 반쪽만 바뀐 값 이 읽힌다
- ISR이 너무 길다 — 다른 인터럽트가 밀리고, 통신 데이터를 놓친다
- 인터럽트 폭주 — 버튼 채터링(접점 떨림)이나 잡음으로 인터럽트가 수천 번 발생
시험 관점은 타이밍을 흔드는 것 이다. 통신 수신 속도를 최대로 올리면서 타이머 인터럽트를 겹치고, 버튼을 빠르게 연타하고, 잡음을 주입한다.
메모리 — 어디에 무엇이 있나
| 영역 | 내용 | 결함 |
|---|---|---|
| 플래시 | 프로그램 코드, 상수 | 쓰기 횟수 제한(수만~수십만 회), 쓰기 중 전원 차단 |
| RAM — 스택 | 지역 변수, 함수 호출 | 오버플로 → 다른 메모리 덮어쓰기, 불규칙한 동작 |
| RAM — 힙 | 동적 할당 | 단편화 → 장시간 운영 후 할당 실패 |
| EEPROM·데이터 플래시 | 설정값, 보정값, 로그 | 수명(쓰기 횟수), 쓰기 중 전원 차단 시 데이터 손상 |
많은 임베디드 코딩 규칙(MISRA C 등, 모듈 35 레슨 4)이 동적 할당을 금지하거나 제한하는 이유가 힙 단편화다. 몇 시간 테스트로는 드러나지 않고, 현장에서 몇 주 운영한 뒤에 나타난다. 그래서 장시간 연속 시험(soak test) 이 임베디드에서 특히 중요하다.
EEPROM에 1초마다 상태를 기록하는 설계를 보면 즉시 계산한다. 수명 10만 회라면 약 28시간이면 수명이 끝난다. 이것은 코드 리뷰나 설계 리뷰 단계에서 테스터가 잡을 수 있는 결함이다.
실무에서 왜 필요한가
임베디드 결함은 발견이 늦을수록 비싸다. 현장에 설치된 장치의 결함은 회수·방문 수리·리콜로 이어지고, 안전과 관련되면 사고가 된다. 구조를 이해한 테스터는 "기능이 동작하는가"를 넘어 "어떤 조건에서 동작하지 않을 수 있는가" 를 물을 수 있다. 우선순위 역전, 스택 오버플로, EEPROM 수명 같은 결함은 기능 테스트로는 거의 잡히지 않고, 구조에서 출발한 시험으로만 잡힌다.
채용시장에서의 위치
임베디드 검증 면접은 "RTOS 태스크 간 동기화 문제를 어떻게 시험하나", "스택 오버플로를 어떻게 찾나", "인터럽트와 메인 루프가 공유하는 변수의 문제는" 같은 구조 질문으로 시작하는 경우가 많다. C 코드를 직접 짜지 않더라도 이 질문에 구조와 시험 방법으로 답할 수 있으면 웹 QA 출신이라도 진지하게 검토된다.