Even combining codepoints are a thing that predates Unicode and simplifies a number of things, so they were a very useful thing to have in Unicode.

First off, diacritical marks have generally been just that: marks that get added to other characters. Notionally that is a great deal like combining codepoints. For example, typewriter fonts, and later ASCII, were designed to have useful overstrike combinations. So you could type á as a<BS>', both in typewriters and in ASCII! Yes, ASCII was a variable-length, multi-byte internationalized encoding for Latin scripts. For example, this is why Spanish used to drop diacritical marks when up-casing: because there was no room in those typewriter fonts for accents on upper-case letters, though nowadays we have much more luxurious fonts, and so you see marks kept on up-cased Spanish a lot more than one used to.

Second, diacritical marks as combining marks adds a great deal of flexibility and a fair degree of future-proofing to the system. This is a restatement of the first point, I know. Read on before telling me that flexibility is nice but expensive.

Third, it is much simpler to close canonical composition to new compositions by having canonical decomposition than it is to keep adding pre-compositions for every sensible and new character. Part of this is that we have a fairly limited codepoint codespace while pre-compositions are essentially a cartesian explosion, and cartesian explosion means consuming codepoint codespace very quickly. Cartesian explosions complicate software as well (more on this below). This really gets back to the point about flexibility.

Fourth, scripts and languages tend to have decomposition strongly built into their rules. It would complicate things to only let them have pre-composed characters! For example, Hangul is really a phonetic script, but is arranged to look syllabic. Now, clearly Hangul is a lot more like Latin in terms of semantics than like Hiragana, say, so you should want to process Hangul text as phonetic (letters) rather than syllabic, but the syllabic aspect of it can't be ignored completely. So Hangul gets precompositions (lots, thanks to cartesian explosion) but even in NFC Hangul is decomposed because that is much more useful for handling in software.

Emoji are mostly like ideographic CJK gluphs, except with color. The color aspect is what truly makes emojis a new thing in human scripts, but even color can be a combining mark. Emoji clearly illustrates the fact that our scripts are still evolving. This is a critical thing to understand: our languages and scripts are not set in stone! You could say that there was no need to add emoji all you want, but they were getting added in much software, and users were using them -- eventually the UC was going to have to acknowledge their existence.

Aside from emoji, which are truly an innovation (though, again, not the UC's), conceptual decomposition of characters had long been a part of scripts. It was there because it was useful. It's entirely natural, and a very good thing too, that it's there in Unicode as well. Decomposition, and therefore combining codepoints, was probably unavoidable.

Regarding digraphs and ligatures, these too are part of our scripts, and we can't very well ignore them completely.

This is not to say that the UC didn't make mistakes. Han unification was a mistake that resulted from not inventing UTF-8 sooner. Indeed, the UC did not even invent UTF-8. Some mistakes are going to be unavoidable, but decomposition and combining codepoints are absolutely not a mistake.

Finally, we're not likely to ever replace Unicode -- not within the next few decades anyways. However much you might think Unicode is broken, however widespread, right, or wrong that perception might be, Unicode is an unavoidble fact of developers' lives. One might as well accept it as it is, understand it as it is, and move on.