This question may sound like a beginner's question, because it is lol. When I started studying Rust, I thought that cloning was "wrong", that it was a performance detriment, that you could do it without cloning, using a reference, or deserializing an object and reusing it. However, recently, I started reading more code on GIT and I see that people are not "afraid" of cloning, I see a lot of structs with clone derivation and I wonder if this is "NORMAL?" Is it the only way to go or is it something easier and would not affect the application in the way I'm thinking
Generally there's an "if you can implement Clone you should" sentiment and probably a lot of people just derive it by default. That doesn't mean they clone it all the time when using it. (But depending on the use case, they might.)
If you want to implement Copy, you have to implement Clone.
Shared ownership (Rc<_>, Arc<_>) is also built upon (cheap) cloning.
References are more for short-term borrows rather than long-lived structs, and sometimes that means you clone or otherwise make data owned when building your data structures.
Whether cloning is perfectly fine or ideally avoided is use-case specific.
Cost of cloning is relative. Adding a .clone() call of a million-character String to your inner-most loop that's running a billion times in 10 seconds? That will make things a lot slower. Adding a few .clone() calls to your CliArgs struct at the beginning of the program? You will not be able to tell the difference even if you do statistics on it. But libraries merely slapping #[derive(Clone)] on structs so long as their semantics don't specifically rely on uniqueness is a courtesy that 1. might help people 2. would be cumbersome for users to do themselves if the library author didn't 3. adds no runtime cost unless it's actually taken advantage of.
I see far more beginners tying themself up in lifetime knots trying to avoid clones than I do them causing serious problems by over-cloning.
.clone() makes it visible, so keep an eye out for places where it's easily avoidable, especially in your tight loops. But most of the time it's not a problem, and you can wait until your profiler says otherwise before worrying about it heavily.
The question whether references are better than cloning is a bit like whether adding numbers is better than dividing them. Yes, addition is faster than division, but that doesn't matter – you need to use the right thing in the right place.
Ownership in Rust is incredibly important. You need to have an idea where every bit of data is owned, and when it can be borrowed.
References in Rust are primarily a temporary loan of data without permission to keep or move it anywhere, and the data must already have been stored somewhere.
It is sometimes necessary to clone, e.g. where you need to have more than one owner of the same data, or return data living for as long as necessary, rather than being borrowed temporarily within a single scope.
Knowing how to structure the ownership is the hard part of learning Rust, because in most other languages this is either abstracted away (GC) or presented from a different perspective (malloc and free).
Newcomers usually wrongly see it as merely a kind of performance optimization, rather than the primary way Rust controls how data is stored and destroyed. You may think you're telling Rust to be "faster" or avoid copying, but Rust hears "don't allow anyone to keep this data, and let all other copies be immediately destroyed", and you get the dreaded "does not live long enough error".
So when you're not sure if some data should be borrowed (reference) or owned (clone), it's easier to err on the side of cloning. If you overuse references, your program will not compile and you'll get frustrating errors. If you overuse cloning, it'll be mostly fine, and you can improve that later.
Cloning should generally be avoided if there is a simple, idiomatic, more efficient alternative. And often, there is. And sometimes, there isn't, and then, cloning is a perfectly fine thing to do.
If it weren't, then cloning wouldn't even be in the standard library. It's not like undefined behavior where you must, always, 100% avoid UB. Cloning is nothing like that.
When I was starting out with Rust, I fought the borrow-checker a lot. Someone, it may even been on these forums, suggested that beginners should stop trying to avoid clone(), because there are other things one should be learning about Rust as well, and there's no need to take on all battles at once.
In retrospect, there was definitely a lot of truth to that -- but I don't think I quite understood how much that tip helped me at the time.