Closed byunyourim closed 6 days ago
스택의 가장 큰 특징은 LIFO 후입 선출구조로 가장 최근(마지막)에 들어간 값이 제일 먼저 나온다.
Stack은 상위 클래스로 Vector를 상속받는다.
Vector는 ArrayList와 같이 List 인터페이스를 구현한 컬렉션 프레임워크로 thread-safe하다.
Vector는 데이터를 저장하는 방식이나 동적 크기 조정, 삽입 및 삭제 기능에서 ArrayList와 비슷하지만, thread-safe하다는 부분에서 차이가 있다.
Vector는 요소를 임의로 접근하거나 수정할 수 있는 get(), set() 메서드, insertElementAt()와 같은 메서드를 제공하는데, 이로인해 인덱스를 사용해 중간 값에 접근하거나 조작할 수 있다. 이러한 메서드는 스택의 특성과 맞지 않는다.
이러한 Vector의 추가적인 메서드는 스택의 목적에 맞지 않고, 복잡성을 초래하여, 스택의 동작에 혼란을 줄 수 있다.
Vector는 동적 배열을 사용하여 요소를 저장한다. 요소를 추가할 때마다 배열의 크기를 자동으로 늘리지만, 이 과정에서 불필요하게 많은 메모리를 할당할 수 있다. 예를 들어, Vector는 배열의 크기가 꽉 차면 배열을 두 배로 늘리는 방식으로 크기를 확장하는데, 이로인해 메모리 낭비를 초래할 수 있다. 스택 자료 구조의 특성상, 이렇게 불필요한 메모리 할당을 최소화하고, 더 효율적인 메모리 관리 방식이 필요하다.
Vector의 메모리 관리 방식은 스택의 요구에 적합하지 않으며, 장기적으로 메모리 누수를 일으킬 수 있다.
Vector는 모든 메서드에 synchronized를 사용한다.
Vector는 모든 메서드에 synchronized 키워드를 사용하여 동기화를 처리하는데, 이 방식은 멀티스레드 환경에서 효율적이지 않으며, 단일 스레드 환경에서는 불필요한 동기화로 인해 성능 저하를 야기한다.
멀티스레드 환경에서는 보통 특정 작업 단위로 동기화를 묶어서 처리해야 하지만, Vector는 메서드 단위로 동기화되어 있어, 온전한 동기화 처리를 제공하지 못한다.
결과적으로, Vector는 성능과 안정성 면에서 모두 비효율적이기 때문에, 이를 사용해야 할 이유가 없다. 멀티스레드 환경에서는 Vector 대신 ConcurrentHashMap, CopyOnWriteArrayList 등 더 효율적이고 안전한 대안이 존재한다.
동기화 단위가 비효율적이기 때문이다.
Vector는 메서드 단위로 동기화를 적용하는데, 멀티스레드 환경에서는 일반적으로 작업 단위를 묶어서 동기화하는 것이 더 효율적이다.
예를 들어, 여러 메서드 호출(add와 get)을 하나의 작업으로 묶어야 안전하게 동작하는 경우가 많다. 하지만 Vector는 메서드 단위로만 동기화를 제공하기 때문에, 이런 복합 작업을 수행할 때 여전히 경쟁 상태(Race Condition)가 발생할 수 있다.
위의 문서에서 보듯이 자바에서는 Stack을 대신 Deque 관련 컬렉션을 사용할 것을 추천한다. Deque(Double-Ended Queue) 인터페이스는 양방향 큐를 지원하며, 스택(LIFO)과 큐의 기능(FIFO)을 모두 지원하며, 구현제로 ArrayDeque나 LinkedList가 있다.
Deque는 더 나은 성능을 제공하며, 멀티스레딩 환경에서 Stack보다 더 효율적이다.
만약 멀티스레드 상황에서 사용해야 한다면 ConcurrentLinkedDeque를 사용하자~!
Stack이 Vector를 상속한 이유는 자바의 초기 설계 방식에 있다. 자바가 처음 설계될 때, 스택을 배열 기반으로 구현하려 했고, 그 시점에서 Vector는 동적 배열을 지원하는 대표적인 자료 구조 였다.
Vector는 동적 크기 확장 기능을 제공해 배열의 고정 크기 한계를 극복하였고, 스택의 LIFO 동작을 구현하기에도 적합했다.
또한, Vector는 List 인터페이스를 구현하여, 요소 관리에 필요한 기본적인 기능을 제공할 수 있다. 이러한 이유로 자바 초기 설계에서 Stack이 Vector를 상속하는 방식으로 구현되었다.
자바의 컬렉션 프레임워크가 발전하면서 Stack을 대신할 Deque와 같은 더 나은 대체제가 등장하였다. Deque는 스택과 큐의 기능을 모두 제공하면서 성능과 효율성 면에서 Stack보다 더 좋다.
Stack은 SOLID 원칙 중 리스코프 치환 원칙에 위배하는 사례이다.
이슈:
Stack
사용을 왜 지양해야 할까?배경:
Stack
을 지양해야 한다는 말을 들었으나, 그 이유를 정확히 몰라서 학습하고자 이 이슈를 등록하게 되었습니다.등록일: 2024.11.18
참고:
Stack
공식 문서Stack
대체 방법에 대한 블로그 글문제점:
Stack
사용을 지양해야 하는 이유:Vector
상속:Stack
은Vector
를 상속받는데,Vector
에서 제공하는 불필요한 메서드들이Stack
의 기본 목적에 맞지 않는다.Vector
는 동적 크기 조정을 사용하는데, 이로 인해 특정 상황에서 메모리 효율이 저하될 수 있다.Vector
의 내장 동기화 기능.ArrayDeque, LinkedList
와 같은 더 효율적이고 성능 좋은 대체 자료 구조들의 등장.해결 방안:
Stack
대신 사용하기 좋은 자료 구조:ArrayDeque
:스택 연산에 최적화된 더 효율적인 대체 자료 구조
LinkedList
:Stack
처럼 사용할 수 있지만, 성능 면에서는ArrayDeque
가 더 낫다.추가 정보:
Deque
인터페이스 문서:문서화 결과
추진 일정: