연결 리스트를 구현하면서 append() 메서드를 만들 때, 혼란을 겪는 지점이 있었다. 바로 tail을 수정했는데 왜 head.next가 바뀌는가?에 대한 부분이다.

문제의 코드 (LinkedList.js)

class LinkedList {
    constructor(value) {
        this.head = { value: value, next: null };
        this.tail = this.head; // 초기 상태: head와 tail이 같은 객체를 참조
        this.length = 1;
    }
    
    append(value) {
        const newNode = new Node(value);
        this.tail.next = newNode; // [질문 포인트] 왜 head.next도 newNode가 될까?
        this.tail = newNode;      // tail을 새 노드로 교체
        this.length++;
    }
}

의문점: head.next는 계속 null 아닌가?

리스트에 데이터가 하나(length: 1)일 때 append(2)를 하면, head.next는 생성자에서 정한 대로 계속 null이어야 할 거로 생각했다. 하지만 실제로는 head.next에 자동으로 2번 노드가 연결됬다.

원인: 자바스크립트의 ‘객체 참조(Reference)’

그 이유는 this.tail = this.head가 복사가 아닌 참조이기 때문이였다.

초기 상태: this.head와 this.tail은 메모리상의 동일한 노드 객체(A)를 가리키는 이정표가된다.

this.tail.next = newNode: tail이 가리키는 객체(A)의 next를 수정한다. 그런데 head도 객체(A)를 보고 있으므로, head.next 역시 자연스럽게 newNode를 가리키게 된다!

여기서 this.tail은 이제 객체(A)를 버리고 새 노드 객체(B)를 가리키게 된다.

하지만 this.head는 여전히 객체(A)를 잡고 있다.

결과적으로 head(A) -> B(tail) 라는 연결 구조가 완성된다.

즉, this.length = 1 일 때 append를하게되면 this.head.next와 this.tail을 동시에 수정하게되는 셈인거다.