PieterP:
I really don't recommend AT commands for anything other than really simple stuff (and even then programming it directly is easier).
If you need more advanced functions like MQTT, programming it directly is the way to go.
The AT vs direct programming matter has been discussed many times on this forum.
AT commands and complex networking protocols
AT commands are a convoluted way to communicate with the ESP, and all code executes on the Arduino. AT commands only really support raw TCP and UDP, if you want to use protocols on top of that (e.g. HTTP, MQTT, OSC ...), all that code executes on your Arduino, using a lot of resources. Especially if you need to parse text-based requests requiring large or dynamic buffers.
It's also much, much harder to debug or to check for errors. If you program the ESP directly, you have high-level functions and classes for these protocols, that provide a simple interface and you can easily check if a function completed successfully by checking if it returned true or false. This makes error handling much simpler.
These libraries do not exist for AT commands, and even if they do exist, they are much less mature. Their documentation is often very poor, and the online resources are limited, because pretty much nobody uses them.
If you have to do multiple protocols at once (e.g. a HTTP web server and an OSC client), you can just about forget about it if you try to use AT commands.
Pretty much all code is blocking, because it uses the same Serial connection, and you can really only do one thing at once.
If you program the ESP directly, you can have many services running "in parallel". (e.g. a HTTP web server, an OSC client, a DNS server, mDNS server, OTA service ... all at once.)
Resource management
The Arduino has limited resources (32KiB flash, 2KiB or RAM and an 8-bit 16MHz CPU in case of the UNO) while the ESP is much faster and has many times more memory (4MiB flash, 64 KiB of instruction RAM, 96 KiB of data RAM, 32-bit CPU up to 160MHz).
So if you've got the choice, it makes sense to run all heavy networking code and text processing/parsing on the ESP, and save the resources of the Arduino for your actual microcontroller sketch.
Abstraction and code quality
My preferred approach is to have one piece of code on the ESP that connects to WiFi, sets up mDNS services, OTA update services, web servers, UDP listeners, MQTT clients ... whatever you need.
All code that receives and parses network requests runs on the ESP as well. If the ESP receives a command (e.g. "Turn on the lights"), it sends a command over serial to the Arduino (e.g. "Pin 16, HIGH").
On the other hand, if the Arduino wants to send something over the internet (e.g. to post the temperature to a database), it just sends it over serial to the ESP (e.g. "Temperature=21.3°C"), and the ESP takes this data, establishes a connection to the server, constructs a request, adds the right data, sends the request, checks the response, etc.
This greatly improves the readability and abstraction of both pieces of code. Having to mix networking stuff and microcontroller logic in one sketch is just really cumbersome.
For communication between the two MCUs, take a look at Robin2's Serial Input Basics.
Debugging
Another advantage is that you can test the microcontroller code without the ESP, by just using the Serial Monitor. The Arduino doesn't care if it's talking to an ESP8266 or to a human with a serial console.
You can also use UART1 on the ESP for printing debug information from the ESP, and UART0 on the Arduino for printing debug information from the Arduino.
If you use AT commands, debugging becomes a whole lot harder, especially if you use an UNO, where the only UART that is used for debugging over USB is also used for AT communication. This means that you can't read the responses from the AT firmware, only the commands sent by the Arduino.
Please don't take my word for it, try it yourself, and pick the approach you like the most.
I used AT commands when I got my first ESP8266, but ever since I discovered the ESP8266 Arduino Core for programming it directly, I've never touched AT commands again.
Whichever approach you pick, I'd recommend to get a dev board that supports both approaches.
At $3.50, there's really no valid argument against a WeMos D1 mini (clone).
Even if you decide to use AT commands, it will still be easier because you have a decent power supply on-board, and you can use the USB interface to update the AT firmware really easily.