Für TeX hat jedes Zeichen einen „Kategorie-Code“ oder „category code“ zugeordnet, der seine Funktion festlegt. Insgesamt gibt es 16 Kategorie-Codes. Zum Beispiel hat \ üblicherweise Kategorie-Code 0 (= escape character, leitet eine Befehlssequenz ein), { hat 1 (= Beginn einer Gruppe), } hat 2 (Ende einer Gruppe) usw. Die „normalen“ Zeichen, d.h., die kleinen und großen Buchstaben haben Kategorie-Code 11 (= letter/Buchstabe), Ziffern, Satzzeichen und andere Symbole 12 (= other/anderes Zeichen). Das Zeichen @ hat ebenfalls Kategorie-Code 12. Wieso ist das wichtig? Nun, Befehlssequenzen können entweder nur aus Zeichen mit Kategorie-Code 11 oder aus einem Zeichen mit anderem Kategorie-Code bestehen.
dann kann \@name nicht direkt verwendet werden, solange @ Kategorie-Code 12 hat. Man würde stattdessen das Makro \@ gefolgt von den Buchstaben n, a, m und e aufrufen. Damit können interne Makros nicht aus Versehen aufgerufen oder überschrieben werden.
In Klassen- und Paket-Dateien sind \makeatletter und \makeatother nicht nötig, da dort @ schon von vornherein Kategorie-Code 11 hat, also als Buchstabe behandelt wird. Obwohl es heutzutage meistens wohl keinen Schaden anrichtet, sollten die Befehle darum in Klassen- und Paketdateien auch nicht verwendet werden.
Manchmal ist es jedoch nötig, im Dokument auf interne Befehle zuzugreifen. Hier kommen dann \makeatletter und \makeatother zum Einsatz. Wann immer man ein Makro, das ein @ im Namen hat definieren oder umdefinieren möchte, rahmt man die Modifikationen mit den beiden ein:
Übrigens: die LaTeX3-Programmiersprache expl3 verwendet nicht @ für interne Makros, sondern _ und :, die normalerweise Kategorie-Code 7 bzw. 12 haben. Ihre Verwendung ist allerdings wesentlich systematischer als beim @ in LaTeX 2e. Für expl3 Code verwendet man (nachdem man das Paket expl3 geladen hat) \ExplSyntaxOn und \ExplSyntaxOff. Ihre Funktion ist noch umfangreicher als alleine das Setzen Kategorie-Codes von _ und :, aber das ist vielleicht Thema für eine andere Frage.