It’s a mess that originates from the notion that terminals must be able to control and interrupt processes started from a shell. Events from the terminal are translated to SIGxxxx and acted upon by well-behaving programs. Had there been no terminals from the beginning, we would probably have a different abstraction for interrupting processes.
There's also the signals that can originate from "within", like SIGILL, the SIGPIPE for interrupting otherwise blocking IO, and SIGCHILD for subprocess management.