Why and what wrapper should I use for my module's JavaScript file? I am defining a d3.js script for my module like this:

test:
  js:
    js/test.js: {}
  dependencies:
    - mymodule/d3
    - core/drupalSettings
d3:
  remote: https://d3js.org
  version: "4.x"
  license:
    name: BSD
    url: https://opensource.org/licenses/BSD-3-Clause
    gpl-compatible: true
  js:
    https://d3js.org/d3.v4.min.js: { type: external, minified: true }


In my controller, I am sending my data (in $data) to the script, like this:

$page[] = array(
  '#markup' =&gt; 'foo',
  '#attached' =&gt; array(
    'library' =&gt;  array(
      'mymodule/test',
    ),
    'drupalSettings' =&gt; array(
      'mymodule' =&gt; array(
        'test' =&gt; array(
          'data' =&gt; $data,
        ),
      ),
    ),
  )
);


It's working fine, but I've noticed that most js files in core have a wrapper - there is some information here.

Should I be using a wrapper for my script? and if so, what should the wrapper be? and why?

There is no jQuery in my script:

(function (Drupal, drupalSettings, d3) {
  Drupal.behaviors.mymoduleTest = {
    attach: function (context, settings) {

      const data = JSON.parse(drupalSettings.mymodule.test.data);

      ...

      console.log(data);

    }
  };
})(Drupal, drupalSettings, d3);


I'm wrapping my code, with these three lines top an bottom, but I don't understand if I need any of it?
There are a couple of different things at play here.

This:

(function (Drupal, drupalSettings, d3) {

})(Drupal, drupalSettings, d3));


is an Immediately Invoked Function Expression (IIFE). Quoting gion_13 from the canonical SO post on the subject:


  This pattern is often used when trying to avoid polluting the global namespace, because all the variables used inside the IIFE (like in any other normal function) are not visible outside its scope.


That's why you'll see it so often in Drupal's (and pretty much any other framework or library's) JS code; it's generally considered good practice.

Ben Alman's blog post is a must read if you're not familiar with this pattern. Yes, it's a good idea to use it in your own code.

This:

Drupal.behaviors.mymoduleTest = {
    attach: function() {

    }
};


is a Drupal "behavior". Quoting the docs:


  Any object defined as a property of Drupal.behaviors will get its attach() method called when the DOM has loaded both initially and after any AJAX calls. 


This allows your code to re-run on elements that may have been replaced as a result of an AJAX or other JS event, so you don't need to keep track of that. 

Say you had a d3 chart bound to an element in the content area, and an AJAX operation on the page replaces the content area with new HTML; the d3 bindings will be lost, and the chart will no longer show. Assuming the AJAX op was invoked by Drupal's API in some way, your attach method will be invoked automatically, and the chart will be re-bound to the new element in the content area.

It's a good idea to conform to this pattern when writing JS code for a Drupal site, it has the potential to save time and headaches later on. 

As always it'll pay to use common sense with stuff like this; if you find yourself using these patterns, then immediately trying to get around them for a couple of specific requirements, those situations may be exceptions where it's best not to use them.