See also answers on these questions:
1. Why not kernel itself should include the necessary drivers inside it
Firstly, know that kernel memory is not demand-paged. That would be a circular dependency. If you page out your disk driver to the disk when you're low on memory, you can't load it back later.
(And inside the Linux kernel, we don't try to define some higher layer which isn't involved in the storage path and can safely be paged out. Allegedly this is possible: Windows did it. I don't know what this higher layer is supposed to be though. Maybe it is defined dynamically. Or maybe Windows has the luxury of not supporting strange ideas like swap-over-NFS).
Instead, we support loading modules. If we don't need NFS on this particular computer, we don't have to load it.
In a modern distribution this saves on the order of a hundred megabytes of RAM overall. (Look at the space taken by
/lib/modules/$VERSION/. Note that in modern distributions, the modules are compressed e.g.
2. and why it depends on initrd
While kernel modules are the more obvious reason for the initrd, there is a second aspect.
It lets userspace build arbitrarily complex storage stacks to access the root filesystem. E.g. getting an IP address using DHCP, to support NFS, or prompting for a disk encryption passphrase.
Again, the kernel tries not to bloat too much e.g. with user interface code.
Memory usage is only one reason. The kernel/userspace division is overloaded with a number of purposes. E.g. the kernel can be one project and work specifically on kernel things. Userspace can be anything; it could be a "normal" Linux distribution, or it could be an entirely independent project like the Android OS.
This is different from other OS's, e.g. the BSDs maintain kernel + core userspace together. This is illustrated by BSDs being able to handle the 2038 problem with a single flag day conversion of both kernel and userspace.