두 세계의 좋은 점만 가져가는 패턴
이 track 전체가 향해 온 한 수: custom layer 를 subclass 한 다음, Functional API 로 엮어. layer 는 안쪽에 필요한 Python 로직을 다 품고 있지만, 바깥에서 보면 tensor 받아 tensor 돌려주는 callable 일 뿐이야 — Dense 나 Conv2D 랑 구분이 안 돼. 그래서 Functional graph 안에서 built-in 처럼 그냥 불러 쓰면 돼 (Code block 참고).
seam 이 왜 매끄럽고, 왜 공짜인가
이게 깔끔하게 합쳐지는 이유는 layer 계약이야. 모든 Keras layer 는 built-in 이든 custom 이든 같은 인터페이스를 노출해: layer(tensor) -> tensor. Functional API 는 layer *안에서* 무슨 일이 일어나는지 신경 안 써 — 나온 tensor 를 다음 call 로 배선할 뿐이야. 그래서 skip connection 과 Python 로직을 가진 ResidualBlock 이 graph 에 끼워져도 주변 Functional 구조는 여전히 introspect 가능해: model.summary() 가 뼈대를 그려주고, custom block 의 내부만 불투명해져. lesson 1 에서 본 introspection 비용을 *그럴 만한 block 에만* 정확히 가두는 거야.
반대 방향도 돼: subclass Model 의 __init__() 에서 Functional sub-model 을 만들어 call() 에서 부를 수 있어. 실전에서 흔한 모양은 pretrained Functional backbone (ResNet, vision transformer) 을 custom routing / loss 처리하는 얇은 subclass head 가 감싸는 형태야.