← 에세이 /Post · 02 of 22 · Embedded Dev

LLM PCB 라우팅: 사람이 고친 것을 규칙으로

자동 라우팅으로 96%까지 간 PCB를 외주에 넘겼다. 사람은 남은 4%만 연결하지 않았고, 그 차이를 다음 에이전트가 쓸 규칙 16개로 만들었다.

· updated ·13 min read · · · #pcb#kicad#ai-agents#hardware#spoton
LLM PCB 라우팅: 사람이 고친 것을 규칙으로
On this page

지름 21mm짜리 작은 PCB를 LLM과 코드로 설계하고 있다.

부품 배치와 자동 라우팅까지 진행했더니 전체 연결의 약 96%까지는 만들 수 있었다. 문제는 마지막 4%였다. 몇 개의 Net은 끝까지 연결되지 않았고 DRC 위반도 남았다. 그래서 PCB 엔지니어에게 20만원을 주고 마무리를 맡겼다.

돌아온 보드를 비교해보니 예상과 조금 달랐다. 사람은 남아 있던 4%만 연결하지 않았다. 자동 라우터가 이미 끝났다고 판단한 배선도 지우고 다시 그었고, layer를 바꾸고 via를 추가하면서 전체 topology를 다시 정리했다.

그래서 두 PCB를 Net 단위로 비교해봤다. 사람이 무엇을 다르게 했는지 찾아내고, 그 차이를 다음 PCB에서 에이전트가 다시 사용할 수 있는 routing 규칙으로 만들었다. 현재 그렇게 정리된 기법이 16개다. 다만 그중 7개는 아직 자동으로 실행할 수 없다.

이 글은 LLM이 PCB를 잘 그렸다는 이야기가 아니다. 어디까지 자동화할 수 있었고, 어디에서 사람의 판단이 필요했는지를 기록한 이야기다.

라우팅 판단에는 Claude Fable 5를 사용했다.

어떤 보드인가

대상은 지름 21mm의 4층 원형 PCB다. CR1632 코인셀 위에 올라가는 보드라 배선할 수 있는 공간이 매우 작다. 한 개의 내층은 GND plane으로 사용하고, 수정 전후를 비교하기 위해 주요 Net 15개를 추적했다.

PCB에 익숙하지 않은 SW 엔지니어를 위해 이 글에서 자주 나오는 용어 세 개만 먼저 설명한다.

  • Net은 전기적으로 서로 연결되어야 하는 한 묶음이다. 예를 들어 SPI_SCK라는 Net에는 MCU의 SCK 핀, 센서의 SCK 핀, 그 사이의 trace와 via가 모두 포함된다.
  • Via는 한 copper layer에서 다른 layer로 배선을 넘기기 위해 사용하는 도금 구멍이다.
  • DRC(Design Rule Check)는 PCB가 설정된 설계 규칙을 지키고 있는지 검사한다. 소프트웨어의 linter와 비슷하다.

DRC에는 중요한 차이가 하나 있다. 등록된 규칙만 검사한다. 설계 의도까지 판단하지는 않는다. 이 차이가 뒤에서 계속 문제가 된다.

이 PCB는 KiCad에서 처음부터 마우스로 그리지 않는다. Python 코드가 부품 배치와 routing 데이터를 만들고 자동 라우터가 배선을 생성한다. 당시 주요 routing rule은 다음과 같았다.

TRACK_MIN_MM = 0.127
CLEARANCE_MM = 0.1
VIA_DRILL_MM = 0.3
VIA_DIA_MM   = 0.5

특히 CLEARANCE_MM = 0.1은 21mm 안에서 조금이라도 routing 공간을 확보하기 위해 의도적으로 좁힌 값이었다. 나중에 문제를 추적해보니 여러 trade-off가 이 결정과 연결되어 있었다.

자동 라우팅은 어디까지 갔나

첫 자동 라우팅 결과에는 DRC 위반이 143건 있었다. 숫자만 보면 완전히 실패한 것처럼 보였지만, 상당수는 같은 원인이 반복해서 잡힌 것이었다.

가장 큰 원인은 via template이었다. 자동 라우터가 만든 via의 annular ring이 0.075mm였는데 보드 규칙에서는 최소 0.10mm를 요구하고 있었다. 같은 문제가 여러 via에서 반복되면서 이 항목만 90건의 DRC 위반을 만들었다. 원인은 단순했다. 자동 라우터가 사용하는 via 규격과 KiCad의 보드 규칙이 서로 달랐다.

via 규격을 보드 규칙에 맞추자 이 90건은 사라졌다. 이후 다른 규칙도 함께 정리하면서 전체 DRC 위반은 64건까지 줄었다. 여기까지만 보면 개선이다.

그런데 via가 커지자 다른 문제가 생겼다. 21mm 안에서 via가 차지하는 공간이 늘면서 routing density가 더 높아졌고, 끝까지 연결하지 못한 Net은 6개에서 13개로 늘었다.

보드의 상태가 그만큼 좋아졌다고 말하기는 어려웠다. DRC 숫자는 줄었는데 연결하지 못한 Net은 오히려 늘었기 때문이다. 내부에서는 이 상태를 DENSITY_LIMITED로 분류했다.

규칙 값을 조금씩 조정하는 방식으로는 더 이상 해결하기 어려운 지점에 도달했다는 의미다. 이게 자동 라우팅의 첫 번째 경계였다.

DRC 숫자가 좋아져도 보드는 나빠질 수 있었다

외주를 맡기기 전에 한 가지 설정도 시험했다. 전역 clearance를 0.1mm에서 0.16mm로 늘려 자동 라우팅을 다시 실행했다. 그러자 당시 남아 있던 경계 관련 DRC 위반 11건을 0으로 만들 수 있었다. 대신 연결하지 못한 Net이 6개에서 15개로 늘었다.

DRC 숫자가 좋아진 이유는 설계가 좋아졌기 때문이 아니었다. 배선을 더 많이 포기했기 때문이었다. DRC만 KPI로 봤다면 11건에서 0건은 명백한 개선처럼 보였을 것이다. 그래서 이 설정은 사용하지 않았다.

이 비교의 일부 숫자는 이전 revision에서 측정한 값이라 절대값보다는 trade-off의 방향을 보는 것이 맞다. 중요한 것은 분명했다. DRC 숫자 하나만으로 routing 품질을 평가할 수는 없었다.

DRC에 아예 잡히지 않는 문제도 있었다

더 중요한 문제 하나는 DRC에 나타나지 않았다. 외주를 넘기기 전 PCB에서 다음 세 Net의 trace width가 모두 0.2mm였다.

  • VBAT
  • GND
  • SPI_SCK

배터리 전원, 접지, SPI clock이 모두 같은 routing policy를 사용하고 있었다. 0.2mm라는 숫자 자체가 반드시 전기적으로 잘못됐다는 뜻은 아니다. 실제 적정 폭은 전류, trace 길이, copper thickness, 허용 voltage drop 같은 조건에 따라 달라진다. 문제는 자동 라우터가 Net의 역할을 구분하지 않았다는 점이었다.

외주 엔지니어가 수정한 보드에서는 VBAT가 구간에 따라 0.25에서 1.0mm로 넓어졌고 GND도 0.3에서 0.7mm를 사용했다.

기존 0.2mm 배선은 DRC 규칙을 위반하지 않았기 때문에 아무 경고도 나오지 않았다. DRC는 규칙 위반은 찾지만, 이 Net이 전원인지 clock인지까지 판단하지 않는다. 이게 두 번째 경계였다.

반대로 코드는 잘하는 일이 분명했다

모든 부분에서 사람이 더 잘한 것은 아니다. 부품 방향을 탐색하는 작업은 코드가 훨씬 잘했다.

14개 부품에 각각 두 가지 회전 방향이 있다고 하면 조합은 2^14 = 16,384가지다. Python 코드로 이 조합을 전부 계산해 전체 예상 Net 길이가 가장 짧은 배치를 찾았다. 그 결과 예상 배선 길이가 128.62mm에서 124.38mm로 약 3.3% 줄었다.

사람이 16,384개의 조합을 직접 비교하는 것은 현실적이지 않다. 이런 탐색은 코드가 압도적으로 유리하다.

하지만 전체 Net 길이가 가장 짧은 배치가 곧 가장 좋은 PCB라는 뜻은 아니다. power routing이 적절한지, 제조가 가능한지, 이미 연결된 Net을 뜯어내고 다른 layer로 보내는 편이 나은지 같은 판단은 별개의 문제다. 이번 작업을 하면서 역할이 조금 명확해졌다. 탐색은 코드가 잘했고, topology를 바꾸는 판단은 사람이 더 잘했다.

자동 라우팅 96%에서 사람에게 넘겼다

부품 배치는 이미 확정되어 있었고 자동 라우팅도 약 96%까지 끝난 상태였다. 남아 있는 Net 5개와 DRC 위반 11건을 마무리하고, 내가 놓친 설계 문제가 있으면 같이 지적해달라고 PCB 엔지니어에게 맡겼다. 비용은 20만원이었다.

엔지니어에게는 내가 만든 PCB를 그대로 제공했다. 따라서 이것은 blind test나 사람과 AI의 성능 비교 실험이 아니다. 그냥 실제 PCB를 완성하기 위한 외주 작업이었다. 그런데 돌아온 결과를 보니 비교해볼 가치가 있었다.

사람은 남은 4%만 연결하지 않았다

두 PCB 파일을 파싱해서 Net별 trace 길이, via 수, 사용 layer를 비교했다. 차이가 큰 Net 몇 개를 보면 다음과 같다.

Net외주 전외주 후Trace 길이 변화
IMU interrupt 226.8mm, via 29.8mm, via 063% 감소
IMU interrupt 125.5mm11.8mm54% 감소
Module reset39.4mm14.4mm63% 감소
SWDIO21.3mm14.6mm31% 감소

여기서 중요한 점이 있다. 이 네 Net은 외주를 넘기기 전에도 이미 연결이 끝나 있었다. 자동 라우터 입장에서는 완료된 Net이었다. 사람은 그렇게 보지 않았다. 기존 trace를 지우고 다시 그었고, 이 행동을 이후 routing 기법에서 rip-up & reroute로 분류했다.

LLM이 배선을 끝낸 기판의 3D 뷰. 지름 21mm 원형 초록 기판에 긴 선들이 가장자리를 크게 돌아간다
외주 전, 자동 라우팅 결과
외주 엔지니어가 다시 그린 기판의 3D 뷰. 같은 기판인데 선이 짧게 끊겨 있고 실크스크린도 정리됐다
외주 후, 엔지니어 수정본

외주 엔지니어가 한 일은 남은 4%를 마무리하는 것이 아니었다. 이미 완료됐다고 생각한 96% 중 일부까지 다시 검토한 것이다.

layer 사용 방식도 달랐다

차이는 PCB 앞면만 봐서는 잘 보이지 않았다. 라우팅에 사용하는 내층을 비교하면 더 분명했다.

LLM이 배선한 기판의 안쪽 2층. 긴 직선 여섯 가닥이 판을 가로지른다
외주 전, 내층
외주 엔지니어가 다시 그린 기판의 안쪽 2층. 짧은 선이 훨씬 빽빽하게 들어차 있다
외주 후, 내층

외주 전에는 이 layer를 사용하는 Net이 6개였고 trace segment는 12개였다. 외주 후에는 기존 6개 Net 중 3개가 빠지고 새로운 5개가 들어와 총 8개가 이 layer를 사용했다. segment는 12개에서 79개로 늘었다.

PCB 전체로 보면 via도 37개에서 58개로 늘었고, trace segment도 151개에서 282개로 증가했다. 언뜻 보면 더 복잡해진 것이다. 그런데 앞서 본 주요 Net의 실제 경로는 오히려 훨씬 짧아졌다.

즉 사람은 via 수나 segment 수를 최소화하려고 한 것이 아니었다. 필요한 곳에서는 via와 segment를 더 사용하면서 어떤 Net을 어떤 layer로 보낼지 전체 topology를 다시 구성했다. 자동 라우터와 사람이 최적화하고 있던 대상이 달랐다.

hole clearance 11건은 어떻게 없어졌나

외주 전에 남아 있던 DRC 위반 11건은 모두 hole_clearance 관련이었다. 실제로 문제를 만든 via는 5개였고, 같은 via가 주변의 여러 copper와 충돌하면서 총 11건으로 집계됐다. 요구한 hole clearance는 0.25mm였고 실제 측정값은 약 0.2017에서 0.2423mm였다.

외주 수정본에서는 이 위반이 모두 사라졌다. 동시에 via 규격도 바뀌었다. drill은 Ø0.3mm 그대로였지만 pad가 Ø0.5에서 Ø0.6mm로 커졌다.

처음에는 나도 이 관계를 잘못 해석했다. hole_clearance는 drill hole과 다른 copper 사이의 거리이므로 drill이 그대로라면 pad만 키워서 기존 위반이 없어질 수는 없다. 그 부분은 맞았다.

하지만 pad 크기는 이후 자동 라우팅에서 같은 위반이 다시 생길 가능성에는 영향을 준다. 기존 via는 다음과 같았다.

pad Ø0.5
drill Ø0.3

annular ring = (0.5 - 0.3) / 2 = 0.10mm

자동 라우터가 copper-to-copper clearance 0.1mm만 확보한다고 하면 drill edge부터 다른 copper까지의 거리는 이렇게 된다.

0.10mm annular ring + 0.10mm copper clearance = 0.20mm

KiCad에서 요구한 0.25mm보다 0.05mm 부족하다. pad를 Ø0.6mm로 키우면 annular ring은 (0.6 - 0.3) / 2 = 0.15mm가 된다. 여기에 0.1mm clearance를 더하면 정확히 0.25mm다.

따라서 via pad를 키우는 것은 새로 배선할 때 같은 종류의 violation을 만들지 않게 하는 방법으로는 의미가 있다. 하지만 이미 0.20mm 거리에 놓여 있는 copper가 pad를 키운다고 저절로 움직이지는 않는다. 기존 11건을 없애려면 해당 구간의 copper도 다시 배치되어야 한다.

실제 PCB 파일을 비교해보니 문제를 만들었던 다섯 위치의 routing geometry가 바뀌어 있었다. 다만 결과 파일만으로는 엔지니어가 해당 부분을 직접 지우고 다시 그은 것인지, 새 via 규칙을 적용하고 rerouting하는 과정에서 바뀐 것인지까지는 구분할 수 없었다. 여기까지가 데이터로 확인할 수 있는 범위다.

의뢰 조건에도 문제가 있었다

외주 과정에서 엔지니어가 처음 보고한 DRC 문제 13건 중 10건은 PCB 자체보다 우리가 전달한 요구조건에서 시작됐다. 배터리 pad 자체가 특정 금지 영역 안에 있는데 우리는 해당 영역에 copper를 넣지 말라고 적어두었다. via-in-pad를 예외로 허용한다는 조건을 명시하지 않았기 때문에 문자 그대로는 만족시킬 수 없는 요구사항이었다. 나머지 3건은 작업 환경에 우리와 동일한 component/footprint 파일이 없어서 발생했다.

사람이 발견한 문제 중 일부는 설계의 결함이 아니라 specification과 환경의 결함이었다. 이 역시 자동화할 때 구분해야 할 문제였다.

사람의 수정 방법을 다음 규칙으로 만들었다

PCB 자체는 외주 결과로 완성됐다. 이제 관심사는 다른 곳으로 옮겨갔다. 다음 PCB에서 같은 문제를 다시 만났을 때 에이전트가 무엇을 할 것인가.

그래서 외주 수정본을 단순히 정답으로 저장하지 않았다. 외주 전후 PCB를 파싱해서 Net별로 다음 차이를 추출했다.

  • trace 길이
  • via 수
  • 사용 layer
  • routing topology 변화

이 차이에서 재사용할 수 있는 routing 기법을 만들었다. 처음에는 12개였고 이후 작업을 거치면서 현재 16개가 됐다. 예를 들어 두 가지가 중요하다.

  • T1: via-size-normalization. 자동 라우터가 사용하는 via 규격을 KiCad와 제조 규칙에 맞춘다.
  • T2: rip-up-and-reroute. 이미 연결된 Net이라도 topology가 좋지 않으면 기존 배선을 지우고 다시 라우팅한다. 앞에서 길이가 크게 줄어든 네 Net이 모두 T2에 해당한다.

문제는 T2를 현재 에이전트가 직접 실행하지 못한다는 것이다. 기법 등록부에는 각 작업을 어떤 함수가 실행할지 기록한다. 실행할 함수가 아직 없는 작업에는 gui_card라는 값을 넣어 사람에게 넘긴다. 현재 등록된 16개 기법 중 7개가 이 상태다.

그리고 이번 외주에서 가장 효과가 컸던 rip-up-and-reroute도 그 일곱 개 중 하나다. 즉 지금 자동화 수준을 꽤 솔직하게 표현하면 이렇다. 배울 수는 있었지만, 아직 실행하지 못하는 기법이 절반 가까이 된다.

또 하나 추가한 원칙도 있다. 에이전트의 판단 confidence가 기준보다 낮으면 억지로 routing 기법을 선택하지 않는다. 추측해서 PCB를 수정하는 대신 사람에게 넘긴다. 하드웨어에서는 틀린 자동화보다 어디에서 자동화를 멈춰야 하는지를 아는 것이 더 중요할 때가 있다.

배운 규칙을 다시 사용할 수 있는지 시험했다

다음 질문은 이것이었다. 외주 결과에서 뽑은 규칙이 한 번의 설명으로 끝나는가, 아니면 에이전트가 다시 사용할 수 있는가.

이를 보기 위해 외주 엔지니어의 최종 수정본을 보여주지 않은 상태에서 같은 종류의 문제 세 가지를 다시 처리하게 했다. 평가할 조건은 미리 정했다.

항목기준결과
clock trace가 pad 사이에 지나치게 가까이 들어가는가edge clearance 0.15mm 이상0.105 / 0.115mm, 사람에게 넘김
SWD/UART 주변 via가 지나치게 밀집되는가중심 간 1.0mm 이상성공, 최소 1.031mm
clock/data가 다른 via clearance 영역을 침범하는가via 중심 기준 0.58mm 이상성공, 위반 0

사전에 정한 기준만 보면 세 항목 중 두 개를 통과했다. 하지만 그대로 2/3 성공이라고 부르기는 어렵다.

두 번째 항목은 1.031mm로 사전 기준 1.0mm를 넘겼지만, 이후 geometry를 다시 계산해보니 두 clearance 영역이 실제로 겹치지 않으려면 약 1.25mm가 필요했다. 즉 테스트에는 통과했지만 테스트 기준 자체가 충분하지 않았다.

첫 번째 항목은 에이전트가 직접 고치지 않고 사람에게 넘겼다. 이것도 완전한 성공이라고 볼 수는 없다.

다만 이전과 달라진 점은 있다. 처음 자동 라우팅에서는 DRC report 안에 문제가 그대로 남아 있었는데도 내가 그 의미를 뒤늦게 발견했다. 이번에는 에이전트가 해결하지 못하는 조건이 수동 작업으로 명시적으로 드러났다. 그 차이는 의미가 있었다.

하지만 여기에도 한계가 있다. 일부 기법과 분류 규칙이 테스트 이전부터 존재했다는 것을 git history만으로 완전히 재현할 수 없는 구간이 있었다. 따라서 그 부분은 학습 효과의 증거로 세지 않았다.

아직 사람이 더 잘하는 부분이 있다

외주 엔지니어는 SWD 관련 trace를 다시 그으면서 via를 없애고 내층 사용도 줄였다. 내 재현본은 그 수준까지 가지 못했다.

더 중요한 한계도 있다. 대조군이 없다. 같은 에이전트를 새로 만든 routing 기법 없이 다시 실행한 결과가 없기 때문에, 개선이 정말 새 기법 때문이라고 인과적으로 증명할 수 없다.

그리고 기법을 추출한 PCB와 재현 시험을 한 PCB도 같은 제품 계열이다. 따라서 지금 확인한 것은 같은 PCB 계열에서 일부 판단이 재현된다 정도다. 다른 PCB에서도 같은 기법이 작동하는지는 아직 모른다. 진짜 transfer test는 다음 시제품에서 해야 한다.

자동화 자체도 여러 번 틀렸다

PCB routing 문제만 있었던 것도 아니다. 중간에는 routing script 자체가 제대로 실행되지 않는 문제도 있었다. commit log에는 이런 기록이 남아 있다.

route.py did not run at all — SWIG ownership trap, plus two clobber hazards

SWIG 객체 소유권 문제 때문에 route.py가 실행되지 않았는데, 나는 한동안 이전 실행에서 남은 결과를 현재 결과라고 생각하고 분석하고 있었다. stale artifact를 분석한 셈이다. 또 에이전트가 “Ø21mm 안에는 더 이상 공간이 없다”고 판단했던 조건도 실제 geometry를 다시 측정하니 틀렸다.

결국 PCB 자동화만 필요한 것이 아니었다. 자동화가 실제로 실행됐는지, 그리고 판단의 근거가 실제 geometry와 맞는지를 검증하는 계측 코드도 같이 필요했다.

이런 실패도 routing 기법과 체크리스트에 남겼다. 성공한 방법만 기록하면 같은 실패를 다시 막을 수 없기 때문이다.

아직 보드가 동작한다는 증거는 없다

현재 PCB 5장을 발주한 상태다. 사양은 4-layer FR-4, 0.8mm, Ø21mm, ENIG다. 아직 실제 보드는 도착하지 않았다.

첫 발주에서는 조립성 검토도 놓쳤다. 직접 조립할 생각이면서 0.5mm pitch 14-pad LGA 패키지를 선택했다. PCB routing과 별개로 내 작업 환경에서 다루기 어려운 부품이었다.

더 중요한 사실도 있다. 현재 발주한 PCB는 지금의 routing 기법 등록부가 완성되기 전에 만들어진 보드다. 즉 이 workflow가 처음부터 끝까지 새로운 PCB를 만든 사례는 아직 없다.

지금까지 확인한 것은 routing 과정이다. 전원을 넣었을 때 실제로 부팅하는지, 센서가 정상적으로 동작하는지, RF와 전원에 문제가 없는지는 아직 알 수 없다. 그 결과는 보드가 도착한 뒤 벤치에서 확인해야 한다.

결국 어디에서 사람을 불러야 하나

이번 작업에서 DRC 숫자보다 더 유용했던 신호가 몇 가지 있었다.

  • DRC가 줄어드는데 unrouted Net이 늘어나는 경우. clearance를 늘려 DRC 11건을 없앴지만 미배선 Net은 6개에서 15개로 늘었다. 숫자는 좋아졌지만 routing은 더 나빠졌다.
  • DRC에는 문제가 없지만 Net의 역할이 반영되지 않은 경우. VBAT, GND, SPI clock이 모두 같은 0.2mm 정책으로 라우팅되어 있었던 것이 그 예다.
  • 에이전트가 어떤 기법을 써야 할지 충분한 confidence를 갖지 못하는 경우. 이 경우에는 추측해서 수정하지 않고 사람에게 넘긴다.

그래서 지금은 DRC를 최종 판정으로 사용하지 않는다. DRC 통과는 필요조건이지만 충분조건은 아니다. fabrication 전에 별도의 제조 가능성 체크도 함께 확인한다.

그리고 외주를 사용한다면 완성된 PCB 파일만 받는 것보다 수정 전후를 비교할 수 있는 형태로 남기는 것이 훨씬 값어치가 있었다. 이번에 만든 routing 기법도 결국 그 차이에서 나왔다.

현재 16개 기법 중 7개는 아직 사람의 GUI 작업이 필요하다. 다음 PCB에서 내가 가장 보고 싶은 숫자는 DRC 0이 아니다. 이 7개가 몇 개까지 줄어드는가. 그게 이번에 만든 자동화가 실제로 나아지고 있는지를 보여줄 숫자다.

ecro
글쓴이 ecro

LLM 펌웨어 벤치마크를 만들었습니다. EmbedEval →

프로젝트에 맞는 Claude Code / Cursor / Codex 하네스를 생성하는 도구를 만듭니다. harness-maker →

Datasheet을 읽는 터미널을 만들고 있습니다. NeuroTerm →

댓글

댓글 불러오는 중...