The servo library uses the following defaults for servo range:
#define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo
#define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo
And, the .write() function, which sends commands in degrees, maps degrees to microseconds as follows:
value = map(value, 0, 180, SERVO_MIN(), SERVO_MAX());
(If the defaults aren't changed, SERVO_MIN() and SERVO_MAX() evaluate to MIN_ and MAX_PULSE_WIDTH)
With this logic, commanding a servo to 90 degrees (it's center position) will be translated to 1472 microseconds. But, the correct center position for a servo, in microseconds, is 1500. Roughly a 3 degree error.
Now, this can be overcome by initializing the servo range, via .attach(), to 600 - 2400 - the nominal range for most servos.
But, why is the default min value "wrong"? Is there some historic or legacy reason for this?
Well the whole servo concept that all servos can move 0-180 degrees and that it always corresponds to a 600 to 2400 pulse width range is a pretty caviar and somewhat reckless assumption in my opinion. There are servos that will slam hard up against their mechanical stops trying to use those 600 and 2400 ending values, drawing excessive current at those values and possibly damaging the gear train. All servos are designed to operate within the R/C servo standard range of 1000 to 2000 usec pulses and there is no standard of how many degrees that corrosponds as it to is servo specific, and while most all servos do have pulse widths ranges in excess of the standard 1-2 msec, they do not all have the same excess range values.
So yes it's a legacy thing that just started out that way and they don't want to mess with it I guess. But the prudent person would 'charactrize' their specific servos to find out what the mechanical travel limits are and what pulse widths they are at and then if they still want to work in degrees of travel commands make their own specific map command to use. So because the servo library allows one to state their specific pulse width values they at least give us the means to correctly use the servo library with our specific servos via the servo.writeMicroseconds() command.