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 |