LLM PCB 라우팅: 사람이 고친 자리에서 배운 것
자동 라우팅으로 96%까지 간 PCB를 외주에 넘겼다. 사람은 남은 4%만 잇지 않고 끝난 배선까지 다시 그었다. 그 차이를 다음 에이전트가 쓸 규칙 16개로 남겼다.
On this page
- 어떤 보드인가
- 자동 라우팅은 어디까지 갔나
- DRC 숫자가 좋아져도 보드는 나빠질 수 있었다
- DRC에 아예 잡히지 않는 문제도 있었다
- 반대로 코드는 잘하는 일이 분명했다
- 자동 라우팅 96%에서 사람에게 넘겼다
- 사람은 남은 4%만 연결하지 않았다
- layer 사용 방식도 달랐다
- hole clearance 11건은 어떻게 없어졌나
- 의뢰 조건에도 문제가 있었다
- 사람의 수정 방법을 다음 규칙으로 만들었다
- 배운 규칙을 다시 사용할 수 있는지 시험했다
- 아직 사람이 더 잘하는 부분이 있다
- 자동화 자체도 여러 번 틀렸다
- 아직 보드가 동작한다는 증거는 없다
- 결국 어디에서 사람을 불러야 하나
요즘 나는 지름 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마다 되풀이되면서 이 항목 하나가 DRC 위반 90건을 만들었다. 원인은 단순했다. 자동 라우터가 사용하는 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에서 VBAT, GND, SPI_SCK 세 Net의 trace width는 모두 0.2mm였다. 배터리 전원과 접지, 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 2 | 26.8mm, via 2 | 9.8mm, via 0 | 63% 감소 |
| IMU interrupt 1 | 25.5mm | 11.8mm | 54% 감소 |
| Module reset | 39.4mm | 14.4mm | 63% 감소 |
| SWDIO | 21.3mm | 14.6mm | 31% 감소 |
여기서 중요한 것은 따로 있다. 이 네 Net은 외주를 넘기기 전에 이미 연결이 끝나 있었다. 자동 라우터가 보기에는 완료된 Net이었다. 사람은 그렇게 보지 않았다. 기존 trace를 지우고 다시 그었고, 나는 나중에 이 행동을 routing 기법에서 rip-up & reroute로 분류했다.


그러니 외주 엔지니어가 한 일은 남은 4%를 마무리하는 데 그치지 않았다. 이미 완료됐다고 생각한 96% 중 일부까지 다시 검토한 것이다.
layer 사용 방식도 달랐다
이 차이는 PCB 앞면만 봐서는 잘 드러나지 않았다. 라우팅에 쓰는 내층을 나란히 놓으니 더 분명해졌다.
외주 전에는 이 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개가 몇 개까지 줄어드는가. 이번에 만든 자동화가 정말 나아지고 있는지는 그 숫자가 말해 줄 것이다.
댓글
댓글 불러오는 중...