This can be done with @future as long as the receiver can handle a JSON object as a list and not just a single post.
If the receiving service cannot handle a JSON Object as a list then you will have to look at NON real time (batch, etc) or implement a transaction control object to process the records in "near real time" one at a time
The problem with any "near real time" option is the decision to send every change or just the current state at the time the data is sent.
Not really an option UNLESS you build a custom rest service to receive the SOAP payload and then pass it on to the service. May be an option as this will work on the individual records. You will have to worry about API call limits, etc
Custom Button on Opp
May be a great choice as by design this will be a one for one call and can be implemented by simply redirecting to a visual force page that does the work then takes the user back to the opp. Or simply a web service method that does the callout without much control with regards to displaying a progress, status that something is happening, etc. Since it requires a user to click on a button you will not have multiple records in the same transaction and the data is only sent when processes dictate. Cons - Users forgetting to send the information. you can make up for this by implementing a batch process to "sweep" the system for records that were modified and not sent, gather them up, and send one at a time. It all depends on how critical it is to have them sent real time and the impact the possibility of the user forgetting would be
Not really possible as an external service cannot "Listen" to SF for events (AFAIK) Someone please correct me if I am wrong..