Altium PCB component placement — derive board size, decide rotation for main ICs and connectors, split zones, generate a 1:1 placement plan drawing, then inject real coordinates after approval, and check overlaps. Triggers: "PCB placement", "place the components", "how big should the board be", "board outline", "start the layout", "which way should this IC face", "socket orientation", "schematic is done, now PCB". Does NOT do routing or autorouting. 한국어: PCB 배치 — 보드 사이즈 산출, 주요 IC·커넥터 회전 결정, 존...
Scanned 9/5/2026
Install to Claude Code
npx -y skills add ScottJeong/altium-claude-skills --skill altium-pcb-placement --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Altium Pcb Placement?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/scottjeong-altium-pcb-placement)More formats (shields.io, HTML) on the badges page.
---
name: altium-pcb-placement
description: Altium PCB component placement — derive board size, decide rotation for main ICs and connectors, split zones, generate a 1:1 placement plan drawing, then inject real coordinates after approval, and check overlaps. Triggers: "PCB placement", "place the components", "how big should the board be", "board outline", "start the layout", "which way should this IC face", "socket orientation", "schematic is done, now PCB". Does NOT do routing or autorouting. 한국어: PCB 배치 — 보드 사이즈 산출, 주요 IC·커넥터 회전 결정, 존 분할, 배치 가안 도면, 승인 후 좌표 투입, 겹침 검사. "PCB 배치", "배치 가안", "부품 배치", "보드 사이즈", "레이아웃 시작", "이 IC 어느 방향으로 놓지", "소켓 방향", "PCB로 넘어가자" 같은 말이 나오면 쓴다. 라우팅·자동배선은 하지 않는다. 회로도 검토는 altium-schematic-review, 라이브러리 제작은 altium-library 스킬이다.
---
# Altium PCB 배치
배치는 두 종류가 섞여 있다. **섞어서 다루면 둘 다 망한다.**
| | 성격 | 처리 |
|---|---|---|
| **회전·사이즈** | 데이터에서 유도된다. 정답이 하나다 | **계산해서 근거와 함께 제시** |
| **어느 변에 뭘 둘까** | 사용자 취향·기구 제약. 정답이 없다 | **물어보고 그림으로 수렴** |
## 하나만 지킨다면 이것
> **가안은 반드시 그림에서 수렴시킨 다음 Altium 에 넣는다.
> 그림은 싸고 PcbDoc 은 비싸다.**
가안은 **2~4회 바뀐다고 보고 시작한다.** 한 번에 맞지 않는다.
주로 바뀌는 것은 이 넷이고, 전부 §0 에서 미리 물으면 줄일 수 있다.
- 큰 커넥터를 어느 변에 둘지
- 커넥터를 한 변에 몰지, 기능별로 흩을지
- 주요 IC 의 회전 기준을 무엇으로 잡을지
- 보드 크기 목표
**배치 하나하나에 이유를 댈 수 없으면 그건 아직 가안이 아니다.**
"왜 여기?" 에 "딱히" 라고 답할 부품이 있으면 그만큼 보드가 크다.
## 0. 사용자 제약을 먼저 캔다 — 여기서 회차가 갈린다
계산 전에 물어본다. 나중에 알면 전부 다시 그린다.
- **큰 커넥터는 어느 변인가.** 방향이 보드 종횡비를 통째로 결정한다
- **커넥터를 한 변에 몰 것인가**, 기능별로 흩을 것인가
- **결합 상대가 있는가** — 상대 보드가 위로 겹치는지 옆으로 나가는지.
라이트앵글이면 대개 평면 연장이라 높이 간섭이 없다. **앵글/스트레이트를 확인한다**
- 기구 제약 — 케이스, 고정 홀, 높이 제한
- 보드 크기 목표가 있는가
## 1. 제약 수집
```
python scripts/connectivity_matrix.py <SchDoc> --ref <기준부품>
```
- **부품쌍 넷 수** — 존 분할의 1차 근거. 16넷으로 묶인 두 부품은 붙여 놓는다
- **TP 소속** — 테스트포인트를 어느 부품 옆에 둘지
- **기준부품 핀별 상대** — §2 회전 결정의 입력값
파이썬은 **`altium_monkey` 가 설치된 3.12 venv 인터프리터**를 쓴다
(이 패키지가 Python `<3.13` 을 요구한다). 아래에서는 그걸 `python` 이라고 쓴다.
### 치수는 라이브러리에서 잰다. PCB 는 필요 없다
```
python scripts/measure_from_lib.py <SchDoc> --libs <라이브러리폴더>
```
회로도가 참조하는 풋프린트 이름을 뽑아 `.PcbLib` 에서 bbox 를 잰다.
**PcbDoc 도, Update PCB 도 필요 없다.** 외주 PCB 설계업체에 넘길 가안처럼
애초에 PCB 문서가 없는 경우가 오히려 흔하다.
| 출처 | 얻는 것 | 비고 |
|---|---|---|
| **라이브러리 `.PcbLib`** | **풋프린트 bbox·패드·홀 — 원본** | 기본 경로 |
| PcbDoc (있으면) | 같은 값 + 현재 배치·회전 | **복사본이다** (아래) |
| 벤더 도면 PDF | 몸체, 레버 스윙, 높이, 볼트홀 — 풋프린트에 없는 것 | altium-library `measure_drawing.py` |
**PcbDoc 은 풋프린트를 복사해 들고 있다.** 라이브러리를 고쳐도
`Tools ▸ Update From PCB Libraries` 전까지 PcbDoc 은 옛 모양 그대로다.
실측 17건 중 2건이 이것 때문에 0.2~0.5mm 어긋났다. **라이브러리가 원본이다.**
### 라이브러리가 없으면 데이터시트로 간다 — 추정으로 가지 않는다
**PCB 외주 설계업체를 쓸 때는 풋프린트 라이브러리를 아예 안 만드는 게 흔하다.**
그 경우가 배치 가안이 가장 필요한 경우이기도 하다. 라이브러리 없음은 정상 상황이지
포기 사유가 아니다.
부품마다 이 사다리를 위에서부터 내려간다. **맨 아래로 떨어지지 마라.**
| # | 출처 | 얻는 것 | 표시 |
|---|---|---|---|
| 1 | 라이브러리 `.PcbLib` | 실제 랜드+실크 | 실측 |
| 2 | 데이터시트 **권장 랜드패턴 / PCB layout 뷰** | 랜드 실치수 → 코트야드만 더함 | 실측 |
| 3 | 데이터시트 **몸체 치수표** (D/E/e/b/L) | 랜드를 유도 → 코트야드 | **유도값** |
| 4 | 패키지 이름만 (`QFN32 4x4`) | IPC-7351 표준 랜드 | **유도값** |
| 5 | 추정 | — | **금지** |
라이브러리 경로 찾는 순서: 프로젝트 폴더 → Altium 워크스페이스
(`%APPDATA%\Altium\Altium Designer {GUID}\LastWorkspace\*.DsnWrk` 안에 `.LibPkg`
절대경로가 그대로 있다) → **사용자에게 묻는다.** 전체 드라이브 `find` 는 타임아웃 난다.
### 몸체 치수를 그대로 쓰지 마라
데이터시트 치수표의 `D`/`E` 는 **몸체**다. 보드가 먹는 면적이 아니다.
랜드패턴이 몸체 밖으로 나오고, 그 위에 코트야드와 실크가 얹힌다.
실측 대조 — 몸체 대비 실제 풋프린트가 얼마나 커지는가:
| 부품 | 몸체 | 라이브러리 풋프린트 |
|---|---|---|
| QFN32 | 4.00 × 4.00 | **7.05 × 7.00** |
| SOT-223 | 6.50 × 3.50 | **8.83 × 7.25** |
| 0805 | 2.00 × 1.25 | **3.90 × 1.90** |
| 0603 | 1.60 × 0.80 | **2.30 × 1.10** |
**일정한 배수가 없다.** 라이브러리·업체마다 실크 여유가 달라서 단일 계수 환산은 틀린다.
그러니 3~4단계로 잡은 값은:
- 랜드패턴을 먼저 유도하고, 그 위에 코트야드를 더한다 (유도 규칙은 IPC-7351 확인)
- 가안 `label` 에 **「유도값」** 이라고 적는다
- **배치 여유를 더 준다.** 나중에 실물 풋프린트가 크면 다시 그려야 한다
공칭·기억으로 잡은 값이 실측과 얼마나 벌어지는지 (실측 대조):
| 부품 | 공칭으로 잡기 쉬운 값 | 실제 풋프린트 |
|---|---|---|
| QFN32 | 4 × 4 (몸체/다이 크기) | **7.05 × 7.00** — 43% 과소 |
| DC 잭 | 14 × 11 | **9.90 × 14.40** — 폭·깊이가 뒤집힌다 |
| DIP 스위치 4연 | 10 × 6 | **12.34 × 10.90** |
**크기보다 나쁜 건 방향이다.** 실측을 미루면 핀이 어느 쪽으로 나오는지까지
기억으로 추론하게 되고, 그건 재보면 반대인 경우가 있다. 30초짜리 측정이다.
벤더 도면 실측이 정확했다고 나머지도 괜찮을 거라 넘기지 마라 — 그게 이 사고의 경로였다.
몸체와 금지구역은 다르다. 테스트 소켓은 **레버가 도는 범위**가 몸체보다 크고,
그 밑에는 테스트포인트를 못 깐다(프로브가 안 들어간다). 실측 예: 몸체 36×36,
레버 포함 46.2, 높이 31.7 — 이 세 값이 전부 다른 제약이다.
## 2. 회전 결정 — 이 스킬의 핵심
**QFN/QFP 는 핀번호가 변을 결정하므로 회전이 순수 계산으로 나온다.**
```
python scripts/pin_side_map.py --pins-per-side 16 --start left --dir ccw \
--group "MII=1-12,61-68" --group "BUS=14-22,25,32,33" \
--want "MII=NE" --want "BUS=W"
```
`--start` / `--dir` 는 **본드 도면이나 패키지 도면으로 확인해서 넣는다.**
추정하면 결과가 통째로 뒤집힌다. 자세한 절차와 실증 예는 `references/rotation-decision.md`.
출력은 회전 0/90/180/270 각각에서 각 신호 무리가 어느 방향으로 나오는지다.
**코너(NE/NW/SE/SW)로 나온 무리는 그 대각에 상대 부품을 놓으면 교차가 0 이 된다.**
**커넥터는 이 방법으로 안 나온다.** 커넥터에 필요한 건 핀 매핑이 아니라
**개구부가 어디를 보는가** 다. 「패드 bbox 대비 실크가 더 튀어나온 쪽」이 개구부고,
그 방향이 보드 바깥을 향해야 한다.
```
python scripts/connector_facing.py <SchDoc> --libs <라이브러리폴더>
```
**bbox 는 180° 회전으로 안 변하므로 겹침·외곽 검사에 안 걸린다.**
배치를 끝낸 뒤 이 표와 실제 회전을 따로 대조한다. 안 하면 개구부가 보드 안쪽을
향한 채로 넘어간다.
이건 사용자에게 물어볼 일이 아니라 **계산 결과를 근거와 함께 제시할 일**이다.
비교표를 그대로 보여준다 — 왜 다른 3개가 아닌지가 같이 보여야 납득된다.
## 3. 보드 사이즈
**축별로 치수를 누적해서 역산한다.** 어림하지 않는다.
```
X: 커넥터 온보드 깊이 + 라우팅 채널 + 소켓존(금지구역+TP뱅크) + 주변IC + 여유
Y: (그 축을 지배하는 부품 하나) + 양끝 여유
```
한 축은 대개 **부품 하나가 강제**한다(긴 커넥터 등). 그 축은 못 줄인다.
다른 축이 자유롭다 — 거기서 낭비를 찾는다. 자세한 건 `references/board-sizing.md`.
**모든 배치에 이유를 대본다.** "왜 여기?" 에 답이 "없다" 인 부품이 하나라도 있으면
그만큼 보드가 크다. 커넥터 하나를 이유 없이 대각선에 두면 그 축이 30mm 커진다.
## 4. 가안 도면 — 반복하는 단계
```
python scripts/plan_svg.py plan.json -o <출력경로>
```
`plan.json` 스키마는 `references/plan-schema.md`,
**동작하는 예제는 `examples/plan.example.json`** — 거기서 시작하는 게 빠르다.
- **반드시 1:1 축척.** 눈대중은 "들어갈 것 같다" 를 만들고 그건 늘 틀린다
- 금지구역·테스트포인트 뱅크·주요 신호 흐름·NOTE 를 같이 그린다
- **NOTE 에 판단 근거를 적는다.** 나중에 "왜 이렇게 했지" 를 푸는 유일한 기록이다
- 생성 후 **PNG 를 직접 읽어서 겹침을 확인한다.** 라벨이 부품을 가리거나 부품이
홀과 겹치는 건 코드로 안 잡히고 그림을 봐야 보인다
사용자 피드백이 오면 JSON 만 고쳐 다시 렌더한다. **이 왕복이 이 스킬의 정상 동작이다.**
2~4회는 당연하다고 보고 진행한다.
### 테스트포인트 뱅크
- 피치를 먼저 정하고 span 을 계산한다. **뱅크 span 이 부품 몸체보다 크면 안 된다**
- 금지구역이 있는 변은 몸체가 아니라 **금지구역 바깥**에 붙인다
- 실제 패드 지름을 모르면 그렇게 적는다. 피치가 패드보다 작으면 다시 그려야 한다
## 5. 겹침 검사
배치를 넣은 뒤(또는 넣기 전 시뮬레이션으로) 물리 충돌을 본다.
```
python scripts/overlap_check.py <PcbDoc> --pads-only --gap 0.3
```
`--pads-only` 는 실크를 빼고 패드만으로 본다 (실크 겹침은 무해할 때가 많다).
`--gap` 은 요구 최소 간격 mm — 0 이면 실제 교차만 잡는다.
출력은 네 갈래이고 **심각도가 다르다.**
| 항목 | 뜻 |
|---|---|
| 같은 면 겹침 | 진짜 충돌. 고친다 |
| 반대면 관통홀 충돌 | THT 핀·기구홀이 반대면 부품을 뚫는다. 고친다 |
| 패드가 보드 밖 | 제조 불가. 고친다 |
| 실크·하우징만 보드 밖 | 엣지 커넥터면 정상. 눈으로만 확인 |
### 반대면끼리 XY 가 겹치는 것은 겹침이 아니다
디커플링은 **반대면에 놓는 게 정석**이다. 소켓·대형 IC 는 몸체가 주변을 덮어서
같은 면에서는 핀 가까이 못 간다. 실측 예 — 36mm 소켓에서 같은 면 최근접이
핀에서 15.5mm, 반대면으로 내리면 2.3mm 였다.
그래서 **레이어를 안 보는 겹침 검사는 이 배치에서 통째로 오탐이 된다.**
`overlap_check.py` 는 면을 갈라 판정한다.
단 관통홀은 예외다. 홀은 판을 뚫으므로 반대면 부품과 진짜로 부딪친다.
**관통홀은 하나씩 비교한다** — 네 모서리에 기구홀이 있는 소켓은 홀들을 합친
bbox 가 몸체 전체가 되어, 그 아래 반대면 부품을 전부 오탐으로 잡는다.
**이 검사는 커넥터 개구부 방향을 못 잡는다.** bbox 가 180° 회전으로 안 변하기
때문이다 — §2 의 `connector_facing.py` 로 따로 대조한다.
## 6. 좌표 투입 — 승인 후 1회
**사용자가 "이대로 확정" 이라고 말하기 전에는 하지 않는다.**
```
python scripts/plan_to_placements.py plan.json > placements.json
```
→ `altium-mcp` **`place_components`** 에 그대로 넣는다 (배치 전용 배치 API, 1 undo 단계).
**단위·기준이 다르다. 그대로 넣으면 어긋난다.**
| 가안 | Altium |
|---|---|
| mm | **mils** |
| bbox 좌하단 | **컴포넌트 원점** (풋프린트에 따라 pad1 이거나 몸체 중심) |
| — | rotation 은 **반시계(CCW) 도** |
그래서 **2패스**다. 1패스로 넣고, 실제 bbox 를 읽어 의도한 중심과의 차를 구해
`--offsets` 로 2패스를 돌린다. 함정은 `references/injection.md`.
`place_components` 는 반환값에 Altium 이 보고하는 최종 x/y/rotation 이 들어 있다.
**그걸 읽어서 대조한다.** 넣고 끝내면 어긋난 걸 모른다.
## 어디까지 자동으로 할 것인가 — 이게 이 스킬의 경계다
| | 자동 | 이유 |
|---|---|---|
| 보드 사이즈·외곽·고정홀 | **○** | 치수 누적. 정답이 하나 |
| 주요 IC 회전 | **○** | 핀→변 매핑에서 유도된다 |
| 큰 부품(커넥터·소켓·IC) 배치 | **○** | 변 제약·상대 거리로 풀린다 |
| 테스트포인트 뱅크 | **○** | 핀 순서대로 규칙 격자 |
| 겹침·외곽밖 검사 | **○** | 순수 기하 |
| **패시브 배치** | **✕ 사람이 한다** | 아래 |
| 라우팅·자동배선 | ✕ | MII·차동쌍은 손으로 |
| DRC 판정 / 넷클래스·룰 | ✕ | 별개 작업 |
### 패시브를 자동으로 놓지 마라
패시브 자리는 **라우팅 의도**가 정한다 — 디커플링 루프 면적, GND 리턴 경로,
트레이스가 IC 어느 변으로 빠지는지, 어느 패드가 비아로 내려가는지.
규칙이 아는 건 "누구와 넷을 공유하나" 와 "안 겹치나" 둘뿐이라 그 위 정보가 없다.
**결과: 겹치지 않는 배치는 만들어도 좋은 배치는 못 만든다.**
규칙을 네 번 고쳐 겹침 0 까지 만들어도 결론은 같다 —
**큰 부품은 쓸 만하고 패시브는 수동이 낫다.**
**그러니 패시브는 「주인 IC 근처 · 겹침 0」 까지만 만들고 넘긴다.**
그 상태가 손으로 다듬기 좋은 출발점이다. 규칙을 더 정교하게 만들려 하지 마라 —
그 방향으로는 답이 안 나온다.
## 참고 파일
| 파일 | 언제 |
|---|---|
| `references/rotation-decision.md` | §2 회전. 핀→변 매핑 확인법과 실증 예 |
| `references/board-sizing.md` | §3 사이즈. 축 누적법 |
| `references/plan-schema.md` | §4 plan.json 스키마 |
| `references/injection.md` | §6 투입 **전에**. 단위·원점 함정 |
| 스크립트 | 용도 |
|---|---|
| `scripts/apply_outline.py` | 보드 외곽(모서리 라운드) + 대칭 고정홀. **Altium 이 문서를 닫은 상태에서** |
| `scripts/measure_from_lib.py` | §1 회로도+라이브러리만으로 풋프린트 실측 |
| `scripts/connector_facing.py` | 커넥터 개구부 방향 → 변별 회전값. **배치 후 반드시 대조** |
| `scripts/connectivity_matrix.py` | §1 부품쌍 넷 수 · TP 소속 · 핀별 상대 |
| `scripts/pin_side_map.py` | §2 회전 4안 비교 |
| `scripts/plan_svg.py` | §4 가안 도면 |
| `scripts/plan_to_placements.py` | §6 mm/bbox → mils/원점 변환 |
관련: 회로도 검토 **`altium-schematic-review`** · 라이브러리 제작 **`altium-library`**.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!