Before NAT every device connected to the internet had its own IP address. That was how the internet was designed. This gives you great flexibility and visibility. If you have a firewall then it can filter traffic for each address, protocol, port etc individually if you want. Because the source address and port (if applicable, not all protocols have ports) and destination address and port do not change between the sender and the receiver it is much much easier to debug. And if you want to let a device look after its own security that is possible too: just tell the firewall not to filter anything on that address, or not use a firewall device at all. Your choice :)
Let's look at the simplest case of NAT: When you ISP only gives you one address you can only connect one device to the internet. This is not what most people want: they need to connect multiple devices. So that single device performs a masquerading trick so that to the outside world it looks like that single device is doing all the internet communication, while behind that device there can be multiple devices that think they have a normal connection to the internet while not really having one. The trick that that single device with a real internet address uses is NAT.
NAT can only do its 'multiplexing' for protocols that use port numbers. For protocols without port numbers a connection is defined by the addresses. As you only have one 'real' address you can only have one connection. For protocols with port numbers like UDP and TCP a connection is usually defined by both addresses and ports. So
18.104.22.168:12345 <-> 22.214.171.124:80 can be one connection and
126.96.36.199:23456 <-> 188.8.131.52:80 another.
184.108.40.206 was a NAT device (it's not, it is my own PC's address, I don't use NAT here) it could have an internal state table that remembers that
220.127.116.11:12345 corresponds to internal address
192.168.0.11:32431. Outgoing packets get their original source address and port (
192.168.0.11:32431) replaced with the NAT device's own (
18.104.22.168:12345), and the reverse is done for incoming packets.
What often causes some confusion with NAT and (stateful) firewalling is that both of those functions need to remember state: who is talking to whom?
A stateful firewall also has to keep track of who is talking to whom. So both a NAT device and a firewall need to remember that there is a session
22.214.171.124:12345 <-> 126.96.36.199:80. A NAT device also has to remember that
188.8.131.52:12345 is really
192.168.0.11:32431. A firewall does some extra filtering and inspections to the traffic.
A NAT device without a firewall function will let unwanted traffic through if it happens to match something in its state table. A firewall will apply inspections to prevent that. But a firewall can also do that if the addresses of incoming and outgoing packets aren't changed: it doesn't need NAT to be able to perform its function.
NAT is considered a hack because it makes the internet more complex. Addresses and ports are being changed, a NAT device has to remember what the original addresses and ports were, it has to actually understand all transport protocols it is applying NAT to so it prevents new transport protocols from being deployed (nobody will use new transport protocols because no NAT device will support them, and NAT devices won't support them because nobody uses them) etc.