Executable compression (AKA executable packing) is the idea that an PE, ELF and MACHO file formats were not fully designed to be compact for obvious reasons.
In the past, when memory was scarce, making executable files smaller in size was often a goal either mandatory of preferable.
For that reason, tools were created to keep an executable functional while making it smaller in size. For that, different compression algorithms were employed on code and data parts of executables, and a small decompression code stub was added to reverse the process during the executable's runtime.
The basic idea is that you take a given executable and compress it's entire code and data sections (which are often most of the file). You would then include the compressed output as part of a new executable and include in that new executable a subroutine that does the opposite - decompresses the compressed data back into it's original (bigger) form, and then execute the original uncompressed entry point as if the code was never compressed.
As the need for compact executables faded when storage memory became cheaper an interesting property of compressed executables was discovered: a compressed executable's code is harder to read without prior decompression.
Developers and coders started using compression to hide code they wanted to hide from third parties. Packing became a way to avoid or complicate reverse engineering processes and packers shifted focus from compression to obfuscation, encryption and anti-reverse-enginerring tools.