본문 바로가기
JS

JS 배열(Collection) 캡슐화

by 쪼꼬에몽 2026. 3. 8.

1. 배열을 직접 노출하지 않기

class UserService {
  #users = [];
  
  getUsers() {
    return this.#users;
  }
}

 

보통 이렇게 만들 때가 많다.

이렇게 만들 때, 발생할 수 있는 문제.

const users = service.getUsers();
users.push(new User('a', 10));

 

을 하면 서비스 내부 배열이 바뀌게 된다.

즉, 외부 코드로 내부 배열을 수정할 수 있게 된다.

캡슐화가 깨진다.

2 배열을 Collection 객체로 감싸기

이를 해결하기 위해 Collection으로 감싸야 한다.

class UserCollection {
  #users = [];
  
  add(user) {
    if (user instancdof User) {
      this.#users.push(user);
    }
  }
  
  getUsers() {
    return [...this.#users];
  }
}

 

외부에서는 배열을 직접 만질 수 없게 한다.

3. private 필드 #users

#users = [];

 

내부에서만 접근 가능하게 private 설정을 한다.

4. add() 메서드 - 배열 수정 통제

add(user) {
  if (user instanceof User) {
    this.#users.push(user);
  }
}

 

배열 수정은 반드시 메서드를 통해서만 이루어지게 한다.

list.add(new User("영희", 40));

 

이렇게 하면 내부에서만 push가 발생한다.

if (user instancdof User)

 

instanceof를 이용해 해당 user 배열이 User 객체에 포함되어 있는지도 확인한다.

타입 검증을 한다.

이렇게 User 객체만 저장되게 한다.

5. getUsers() - 얕은 복사 반환

getUsers() {
  return [...this.#users];
}

 

... (spread)

새로운 배열 생성

#users = [A, B, C]

 

spread를 사용하면 새로운 배열 [A, B, C]를 생성한다.

외부 코드가

const users = list.getUsers();
users.push(new Users('철수', 20));

 

을 해도

users 배열만 배경된다.

내부 배열은 그대로 유지된다.

#users = [A, B, C]

 

6. 실제 사용 흐름

const list = new UserCollection();

list.add(new User('a', 30));
list.add(new User('b', 20));

 

내부 상태

#users = [
  User('a', 30),
  User('b', 20)
]

 

조회

console.log(
  list.getUsers().map(u => u.getDetails())
);
getUsers() -> 복사된 배열 반환 -> map 실행 -> User.getDetails()

// ["a (30세)", "b (20세)"]

 

7. Collection 객체를 따로 만드는 이유

  • 배열 직접 수정 차단
  • 규칙을 넣기 쉬움
add(user) {
  if (this.#users.length >= 10) {
    throw new Error("최대 10명");
  }
  
  this.#users.push(user);
}
  • 관련 로직을 모을 수 있음
getAdults() {
  return this.#users.filter(u => u.age >= 20);
}

'JS' 카테고리의 다른 글

타입스크립트 - 탄생  (0) 2026.03.25
JS 클래스 형태  (1) 2026.03.08