It is better to use the rpc module, because if you do not: you will need to manage the monitoring of the remote node, provide a unique call identifier, processing timeouts, and you will also have to provide a wrapper for feedback feedback from the function result.
But all these manipulations are common and implemented in the rpc module.
By the way, there are various options for remote calls that are implemented in rpc : synchronous and asynchronous calls , cast (send a message that does not require an answer), even the parallel card function ( pmap ).
PS
Compare - just using rpc: call against an implementation from scratch (also this is a simple implementation that does not handle some important cases):
-module(myrpc). -compile(export_all). server() -> receive {{CallerPid, Ref}, {Module, Func, Args}} -> Result = apply(Module, Func, Args), CallerPid ! {Ref, Result} end. call(Node, Module, Func, Args) -> monitor_node(Node, true), RemotePid = spawn(Node, ?MODULE, server, []), Ref = make_ref(), RemotePid ! {{self(), Ref}, {Module, Func, Args}}, receive {Ref, Result} -> monitor_node(Node, false), Result; {nodedown, Node} -> error end.