Routehints are nothing complex. If you take a look at the code used to generate them routehints are pretty simple. The code simply grabs the first 20 (arbitrary limit) or so nodes with whom it has channels that fit certain parameters (healthy, active, otherwise usable and public).
They're just a method for private nodes (we can define a node as private when they have only private channels, as this directly results in none of their peers broadcasting their existence) to avoid broadcasting their existence but still reliably receive payments (so long as their peers are also accessible).
To rephrase, routehints bridge the gap left by the gossip layer by manually extending a payer's graph of known nodes/channels by embedding info in an invoice.
Radar puts it well:
Routing hints provide information to find non-advertised, or private, channels. This allows routing of payments to nodes that are not publicly visible on the network. A routing hint provides a partial route between the receiver's private node and a public node. This routing hint is then included in the invoice generated by the receiver and provided to the payer.
Lastly, because route hints are just depth 0 channels/nodes from the receiving node's perspective, it's possible for routehints to fail in their purpose if the receiving node is only able to supply nodes which are also considered private, since the payer isn't going to be able to route to them and in turn the receiving node.