Hey there. Both Three.js and Babylon.js are suitable for the job. If optimized, rendering 50k triangles in WebGL is not an problem for desktop computer.
As you have found out, problem is draw calls. It's not WebGL, Three or Babylon related, it is same across all rendering engines. Everytime rendering engine needs to change shader, it generates new draw call (there are few more cases when new draw call is generated)
Order of rendered elements is crucial.
Let's say in your scene you have: wall, decoration, window, wall, decoration, wall; all types using different material (shader). If you draw them on screen in such order, material has changed 6 times -> hence 6 draw calls.
But if you draw them in wall, wall, wall, decoration, decoration, window order -> you get 3 draw calls. You have successfully reduced draw calls by merging same type of geometries inside of one cube. But you have X cubes in your scene.
So, next thought would be to merge all walls in scene into single mesh, all decorations in scene into another mesh, etc. In ideal world you will end up with one big mesh for walls, one big mesh for decorations, ...
Avoid doing that for very large scene as you will loose culling capability. Divide it in reasonable large groups - you have to play with it and tune it up directly for your scene.
As mentioned, you can reduce geometry/materials by using single texture applied to wall. If all your walls don't look same, merge couple of wall textures into one texture atlas and use 3D modelling app (Max, Maya, Blender) to shift UVs around it.
You can still use normal map on top of it to make your decorations look like they are offsetted from wall. And you can also experiment with using LODs, instances.
Hope that helped a bit, one last advice: fake everything you can