Skip to main content
Summary

GPIO는 라즈베리 파이의 손끝이다

지난 장에서 파이썬은 화면에 글자를 출력하고, 값을 판단하고, 파일에 기록했다. 이번 장부터는 그 명령이 실제 세계로 나간다. LED가 켜지고, 버튼을 누르면 프로그램이 반응한다. 이때 라즈베리 파이가 바깥 전자부품과 만나는 지점이 GPIO다.

GPIO는 General Purpose Input/Output의 줄임말이다. 한국어로 풀면 "범용 입력·출력 핀"이다. 핀 하나를 출력으로 쓰면 LED를 켤 수 있고, 입력으로 쓰면 버튼이 눌렸는지 읽을 수 있다.

라즈베리 파이의 40핀 헤더에는 여러 종류의 핀이 섞여 있다.2

  • GPIO 핀: 신호를 입력하거나 출력하는 핀이다. 파이썬 코드로 제어한다.

  • 3.3V 핀: 3.3V 전원을 공급하는 핀이다.

  • 5V 핀: 5V 전원을 공급하는 핀이다.

  • GND 핀: 전기의 기준점이 되는 0V 핀이다. 회로의 돌아오는 길이다.

가장 중요한 규칙은 하나다.

주의: 라즈베리 파이 GPIO 핀에는 5V를 직접 넣으면 안 된다. GPIO 신호는 3.3V 기준이며, 5V 신호를 GPIO 입력에 연결하면 보드가 영구적으로 손상될 수 있다.

5V 핀은 USB 장치나 일부 모듈에 전원을 줄 때 쓰는 핀이지, GPIO 입력에 연결하는 핀이 아니다. 초보 실습에서는 5V 핀을 사용하지 않는다고 생각해도 좋다. 이번 장의 기본 LED와 버튼 실습은 GPIO와 GND를 중심으로 연결하고, 버튼 입력은 라즈베리 파이 내부의 3.3V 기준 풀업을 사용한다.

핀 번호도 헷갈리기 쉽다. 라즈베리 파이에는 두 가지 번호 체계가 있다.

  • 물리 핀 번호: 보드에 꽂힌 실제 핀의 순서다. 1번, 2번, 3번처럼 센다.

  • BCM GPIO 번호: 칩에서 쓰는 GPIO 번호다. 파이썬 gpiozero 라이브러리는 이 번호를 사용한다.

예를 들어 GPIO17은 물리 핀 11번에 해당한다. 코드에서는 LED(17)처럼 쓴다. 11이라고 쓰지 않는다. 이 장에서는 다음 핀만 사용한다.

용도BCM 번호물리 핀 번호
LED 출력GPIO1711
버튼 입력GPIO2713
GND-6 또는 14

작업 전에는 라즈베리 파이를 종료하고 전원을 뽑은 뒤 회로를 연결하자.

sudo shutdown -h now

초록 LED가 꺼지고 몇 초 지난 뒤 전원 케이블을 뽑는다. 회로를 바꿀 때마다 이 습관을 들이면 실수를 크게 줄일 수 있다.

GPIO와 전자회로 첫걸음AI 생성 이미지

전압, 전류, 저항을 LED로 이해하기

전기를 물의 흐름에 비유해 보자. 전압은 물을 밀어내는 압력이고, 전류는 실제로 흐르는 물의 양이다. 저항은 흐름을 적당히 막아 주는 좁은 관이다.

LED는 전류가 흐르면 빛을 내는 부품이다. 하지만 LED는 전류를 스스로 적당히 조절하지 못한다. 그래서 저항 없이 GPIO와 GND 사이에 바로 연결하면 너무 많은 전류가 흐를 수 있다.

주의: LED는 반드시 저항과 함께 연결한다. LED를 GPIO와 GND에 직접 연결하지 않는다.

이번 실습에서는 330Ω 저항을 사용한다. 220Ω, 330Ω, 470Ω 정도도 기본 LED 실습에 자주 쓰인다. 처음에는 330Ω 또는 470Ω을 고르면 안전하다.

간단히 계산해 보자. 빨간 LED는 대략 2V 정도를 사용한다고 생각할 수 있다. GPIO 출력은 3.3V다. 저항에 걸리는 전압은 대략 다음과 같다.

3.3V - 2.0V = 1.3V

전류를 약 5mA 정도로 낮게 잡으면 필요한 저항은 다음과 같다.

저항 = 전압 ÷ 전류
     = 1.3V ÷ 0.005A
     = 260Ω

실제로는 딱 260Ω 저항을 쓰지 않아도 된다. 가까운 표준값인 330Ω을 쓰면 전류가 조금 더 줄어 안전하다.

전류 = 1.3V ÷ 330Ω
     ≈ 0.004A
     ≈ 4mA

LED가 조금 어두워도 괜찮다. 라즈베리 파이 GPIO 실습에서는 밝기보다 안전이 먼저다.

브레드보드는 납땜 없는 연습장이다

브레드보드는 전자부품을 꽂아 회로를 만드는 판이다. 납땜하지 않고 점퍼선과 부품을 꽂았다 뺄 수 있어 실습에 좋다.

브레드보드 가운데에는 홈이 있다. 이 홈을 기준으로 왼쪽과 오른쪽이 나뉜다. 일반적인 브레드보드는 다음처럼 연결되어 있다.

  • 가운데 작업 영역은 가로로 5개 구멍씩 서로 연결되어 있다.

  • 가운데 홈을 사이에 둔 양쪽은 서로 연결되어 있지 않다.

  • 가장자리의 +, - 전원 레일은 길게 연결되어 있다.

  • 일부 브레드보드는 전원 레일이 중간에서 끊어져 있다.

처음에는 전원 레일을 복잡하게 쓰지 않아도 된다. GPIO 핀에서 나온 점퍼선을 브레드보드 한 줄에 꽂고, 저항과 LED를 이어서 GND로 돌아오게 만들면 된다.

이번 LED 회로는 다음 순서로 연결한다.

GPIO17 → 330Ω 저항 → LED 긴 다리 → LED 짧은 다리 → GND

LED에는 방향이 있다.

  • 긴 다리: + 쪽, 애노드라고도 부른다.

  • 짧은 다리: - 쪽, 캐소드라고도 부른다.

실제로 연결할 때는 이렇게 하자.

  1. 라즈베리 파이 전원을 끈다.

  2. 물리 핀 11번(GPIO17)에서 점퍼선을 브레드보드 한 줄로 연결한다.

  3. 같은 줄에 330Ω 저항 한쪽 다리를 꽂는다.

  4. 저항의 다른 쪽 다리를 다른 줄에 꽂는다.

  5. 그 줄에 LED 긴 다리를 꽂는다.

  6. LED 짧은 다리를 또 다른 줄에 꽂는다.

  7. LED 짧은 다리가 있는 줄을 GND 핀, 예를 들어 물리 핀 6번에 연결한다.

저항은 LED 앞에 있어도 되고 뒤에 있어도 된다. 같은 회로 안에서 전류를 제한하기만 하면 된다. 하지만 초보자는 "GPIO → 저항 → LED → GND" 순서로 외우면 실수가 적다.

파이썬으로 LED 켜기

회로를 연결했다면 전원을 다시 넣고 부팅한다. 터미널을 열고 실습 폴더를 만든다.

mkdir -p ~/pi-study/gpio
cd ~/pi-study/gpio

먼저 gpiozero가 설치되어 있는지 확인한다. Raspberry Pi OS에는 보통 기본으로 들어 있다. 파이썬에서 불러와 보자.

python3 -c "from gpiozero import LED; print('gpiozero OK')"

gpiozero OK가 보이면 준비가 끝났다. 만약 ModuleNotFoundError가 나오면 다음 명령으로 설치한다.

sudo apt update
sudo apt install python3-gpiozero

이제 LED를 2초 동안 켜는 파일을 만든다.

nano led_on.py

다음 코드를 입력한다.

from gpiozero import LED
from time import sleep

led = LED(17)

led.on()
sleep(2)
led.off()

저장한 뒤 실행한다.

python3 led_on.py

정상이라면 LED가 2초 동안 켜졌다가 꺼진다. 켜지지 않으면 다음 순서로 확인한다.

  1. LED 긴 다리와 짧은 다리가 바뀌지 않았는가?

  2. 저항이 빠지지 않았는가?

  3. GPIO17, 즉 물리 핀 11번에 연결했는가?

  4. GND가 물리 핀 6번 또는 14번에 연결되었는가?

  5. 코드에서 LED(17)이라고 썼는가?

이번에는 LED를 계속 깜박이게 해 보자.

nano led_blink.py
from gpiozero import LED
from signal import pause

led = LED(17)

led.blink(on_time=0.5, off_time=0.5)
pause()

실행한다.

python3 led_blink.py

LED가 0.5초마다 켜지고 꺼진다. 멈추려면 터미널에서 Ctrl + C를 누른다.

여기서 중요한 점은 파이썬 코드가 GPIO 핀의 상태를 바꾼다는 것이다. led.on()은 GPIO17을 켜는 명령이고, led.off()는 끄는 명령이다. 이제 화면 속 명령이 실제 부품의 변화로 이어졌다.

버튼 입력 읽기

LED는 출력 장치다. 라즈베리 파이가 바깥으로 신호를 보낸다. 버튼은 입력 장치다. 사람이 누른 상태를 라즈베리 파이가 읽는다.

버튼 실습에서는 GPIO27을 사용한다. 버튼은 한쪽을 GPIO27에, 다른 쪽을 GND에 연결한다. gpiozero의 Button은 기본적으로 내부 풀업을 사용하므로, 버튼을 GND에 연결하는 방식이 권장된다.1

연결 순서는 다음과 같다.

GPIO27 → 버튼 → GND

4다리 택트 스위치를 쓴다면 방향이 중요하다. 같은 쪽 두 다리는 내부에서 이미 연결되어 있는 경우가 많다. 버튼을 브레드보드 가운데 홈을 가로지르도록 꽂으면 실수할 가능성이 줄어든다.

연결 방법은 다음과 같다.

  1. 라즈베리 파이를 종료하고 전원을 뽑는다.

  2. 버튼을 브레드보드 가운데 홈을 가로질러 꽂는다.

  3. 버튼 한쪽을 GPIO27, 물리 핀 13번에 연결한다.

  4. 버튼 반대쪽을 GND, 예를 들어 물리 핀 14번에 연결한다.

  5. 다시 전원을 연결해 부팅한다.

이제 버튼 상태를 출력하는 코드를 작성한다.

cd ~/pi-study/gpio
nano button_read.py
from gpiozero import Button
from signal import pause

button = Button(27)

def pressed():
    print("버튼 눌림")

def released():
    print("버튼 떼어짐")

button.when_pressed = pressed
button.when_released = released

pause()

실행한다.

python3 button_read.py

버튼을 누르면 버튼 눌림, 떼면 버튼 떼어짐이 출력된다. 멈추려면 Ctrl + C를 누른다.

이번에는 버튼으로 LED를 직접 제어해 보자. LED 회로는 그대로 두고, 버튼 회로를 추가로 연결한다.

nano button_led.py
from gpiozero import LED, Button
from signal import pause

led = LED(17)
button = Button(27)

button.when_pressed = led.on
button.when_released = led.off

pause()

실행한다.

python3 button_led.py

버튼을 누르는 동안 LED가 켜지고, 손을 떼면 꺼진다. 이것이 가장 작은 형태의 입력·처리·출력 시스템이다.

버튼 입력 → 파이썬 판단 → LED 출력

앞으로 센서와 모터, 웹 대시보드를 다룰 때도 구조는 같다. 입력이 센서 값으로 바뀌고, 출력이 LED 대신 릴레이나 알림으로 바뀔 뿐이다.

풀업과 풀다운: 떠 있는 입력을 붙잡는 방법

버튼 회로에서 가장 이상한 현상은 "누르지 않았는데 눌린 것처럼 보이는" 문제다. 이유는 입력 핀이 아무 곳에도 확실히 연결되지 않았기 때문이다. 이런 상태를 플로팅 입력이라고 한다. 말 그대로 입력값이 공중에 떠 있어서 주변 전기 잡음에 따라 0과 1 사이를 흔들린다.

이를 막기 위해 풀업 또는 풀다운을 사용한다.

  • 풀업: 버튼을 누르지 않았을 때 입력을 1, 즉 HIGH 상태로 잡아 둔다.

  • 풀다운: 버튼을 누르지 않았을 때 입력을 0, 즉 LOW 상태로 잡아 둔다.

이번 실습의 버튼 연결은 내부 풀업 방식이다.

버튼을 누르지 않음: GPIO27은 내부적으로 HIGH
버튼을 누름: GPIO27이 GND와 연결되어 LOW

그런데 코드에서는 button.is_pressed가 눌림 여부를 알아서 True 또는 False로 보여 준다. 내부 전기 상태가 LOW가 되더라도, gpiozero가 "버튼이 눌렸다"는 의미로 바꿔 주기 때문이다.

반대로 버튼을 3.3V에 연결하고 싶다면 풀다운 방식을 쓸 수 있다.

button = Button(27, pull_up=False)

이때 회로는 다음처럼 바뀐다.

GPIO27 → 버튼 → 3.3V

하지만 초보 실습에서는 버튼을 GND에 연결하고 Button(27) 기본값을 사용하는 편이 안전하고 단순하다. 3.3V와 5V를 헷갈릴 위험도 줄어든다.

버튼이 한 번 눌렸는데 두세 번 눌린 것처럼 출력되는 경우도 있다. 버튼 내부 금속 접점이 아주 짧은 시간 동안 튀듯이 여러 번 붙었다 떨어지기 때문이다. 이것을 바운스라고 한다. 필요하면 bounce_time을 줄 수 있다.1

button = Button(27, bounce_time=0.05)

0.05는 0.05초, 즉 50밀리초다. 버튼이 흔들리며 만든 짧은 중복 신호를 무시하는 데 도움이 된다.

실습 후 정리와 안전 체크

오늘 만든 회로는 단순하지만, 앞으로 모든 GPIO 프로젝트의 기본이 된다.

  • GPIO 출력으로 LED를 켰다.

  • GPIO 입력으로 버튼 상태를 읽었다.

  • 저항으로 LED 전류를 제한했다.

  • GND가 회로의 돌아오는 길이라는 점을 확인했다.

  • 풀업으로 버튼 입력을 안정시켰다.

마지막으로 회로를 바꾸기 전에는 프로그램을 멈추고 전원을 끈다.

sudo shutdown -h now

다음 장에서는 이 구조를 센서와 액추에이터로 확장한다. LED 하나를 켜는 대신 온도나 거리 값을 읽고, 버튼 대신 센서 변화에 반응하게 만들 것이다. 하지만 출발점은 같다. GPIO 핀 하나를 안전하게 연결하고, 파이썬 코드로 읽고 쓰는 것이다.

참고

1gpiozero Button API

2Raspberry Pi GPIO pin reference and gpiozero guide

책 목록

라즈베리 파이 학습: 설치부터 GPIO, 웹 서버, IoT 프로젝트까지

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기