NAT was not designed as a security boundary. Sure, it may block some kinds of incoming traffic accidentally and as a side-effect disrupt some attacks.
But why would you rather have an always-broken network that might block attackers instead of a deliberate "deny incoming" rule that does exactly what you want -- and that you can punch holes in if desired?
Instead we have apps circumventing this accidental barrier with STUN, uPNP, etc with little/no oversight and we also regularly encounter brokenness.