To expand a bit:
1. dlopen has interactions with static linking that you should understand if you use both at the same time. Different libcs expose different symbols for libc functions, so building your dynamic library against one libc may make it incompatible with another. And two libcs in the same program (one from the dylib, one from the binary) is a recipe for a very bad time - imagine freeing a pointer allocated with a different malloc implementation, or a different layout of libc structs
2. the complexity with glibc is it invokes dlopen as part of NSS, a feature that gets used as part of looking up users, among other things (it does this to allow integration with LDAP etc). You can actually see warnings at link time if you statically link glibc but pull in symbols that use NSS. You can disable NSS if you like at build time of glibc itself [0] (i.e. not your binary)
3. musl doesn't have the complexities of NSS and can be statically linked happily by default (I suspect that's probably what musl is most used for)
[0] https://sourceware.org/glibc/wiki/FAQ#Even_statically_linked...