본문으로 바로가기
반응형

웹 애플리케이션을 설계하고 개발하는 과정에서 Bean의 생명주기를 이해하고 무상태 설계를 적용하는 것은 중요한 부분입니다. 이 포스트에서는 왜 이러한 원칙들이 필요한지, 그리고 어떻게 적용할 수 있는지에 대해 살펴보겠습니다.

1. Bean의 생명주기
1.1. 싱글턴 스코프
스프링 프레임워크에서 Bean은 기본적으로 싱글턴 스코프로 생성됩니다. 이는 애플리케이션 내에서 하나의 인스턴스만 존재하게 됨을 의미합니다.

1.2. 프로토타입 스코프
필요에 따라 프로토타입 스코프를 사용하여 요청마다 새로운 인스턴스를 생성할 수도 있습니다. 그러나 상태를 공유하지 않는 무상태 설계를 통해 동일한 인스턴스를 안전하게 재사용할 수 있습니다.

2. 무상태 설계
무상태 설계는 여러 쓰레드가 동시에 동일한 인스턴스에 접근해도 상호 작용이 없도록 설계하는 패턴입니다. 즉, 인스턴스 변수를 사용하지 않거나 변경되지 않는 상수만을 포함하게 됩니다.

예시

@Service
public class StatelessService {

    public int add(int a, int b) {
        int result = a + b;
        return result;
    }
}

 

이 예제는 무상태 서비스로, 여러 쓰레드가 동시에 add 메서드를 호출하더라도 서로 영향을 미치지 않습니다.

3. 충돌 방지
상태를 공유하는 서비스 빈에서는 여러 쓰레드가 동일한 데이터를 동시에 변경하려고 할 때 데이터 일관성이 깨질 수 있습니다. 이로 인한 충돌을 방지하기 위해 무상태 설계를 적용하거나 동시성 제어 기법을 사용해야 합니다.

3.1. 데이터 무결성 손상
데이터의 일관성이 깨짐으로 인해 예측 불가능한 동작이 발생할 수 있으므로, 복잡한 동시성 제어 없이도 안전한 상호 작용을 보장하기 위한 무상태 설계가 중요합니다.

 

"충돌"이 발생하는 상황은 여러 쓰레드가 동일한 객체의 상태를 동시에 변경하려고 할 때 일어날 수 있습니다. 이로 인해 데이터 일관성이 깨질 수 있으며, 예기치 않은 결과를 초래할 수 있습니다.

3.2.상태 있는 서비스의 예
아래의 서비스 클래스는 계산 결과를 result라는 인스턴스 변수에 저장하는 상태가 있는 서비스입니다.

@Service
public class StatefulService {
    
    private int result;

    public void add(int a, int b) {
        result = a + b;
    }

    public int getResult() {
        return result;
    }
}

이 서비스 빈은 기본적으로 싱글턴 스코프로 생성되므로 애플리케이션 전체에서 하나의 인스턴스만 존재합니다.

충돌 상황
쓰레드 A: statefulService.add(10, 20);를 호출하여 result에 30을 저장합니다.
쓰레드 B: 거의 동시에 statefulService.add(5, 5);를 호출하여 result에 10을 저장합니다.
이 상황에서 쓰레드 A가 result 값을 읽으려고 하면 30이 아닌 10을 읽을 수 있습니다. 쓰레드 B가 쓰레드 A의 연산 후에 result 값을 변경했기 때문입니다.

문제점
이러한 충돌로 인해 다음과 같은 문제가 발생할 수 있습니다.

데이터 무결성 손상: 여러 쓰레드가 동일한 데이터를 동시에 변경하면 데이터의 일관성이 깨질 수 있습니다.
예측 불가능한 동작: 어떤 쓰레드의 연산이 먼저 완료될지, 어떤 연산이 다른 연산의 결과를 덮어쓸지 예측하기 어렵습니다. 따라서 애플리케이션의 동작이 예측 불가능해질 수 있습니다.
해결 방법
이러한 충돌을 피하려면 상태를 공유하지 않는 무상태 설계를 사용하거나 동시성 제어 기법 (예: 동기화)을 적용해야 합니다.

웹 애플리케이션에서는 동시에 많은 요청을 처리해야 할 수 있으므로, 여러 쓰레드가 동시에 동일한 서비스 빈 인스턴스에 접근할 가능성이 있습니다. 이런 경우에는 무상태(stateless) 설계를 추천하는 것이 일반적입니다.

무상태 설계는 다음과 같은 특징을 가집니다:

인스턴스 변수를 사용하지 않거나, 인스턴스 변수가 변경되지 않는 상수만을 포함합니다.
메서드의 동작이 입력값만에 의존하며, 외부의 상태에 의존하지 않습니다.
여러 쓰레드가 동시에 동일한 인스턴스에 접근하더라도 상호 작용이 없으므로 안전합니다.

 


결론
Bean의 생명주기를 이해하고 무상태 설계를 적용하는 것은 웹 애플리케이션의 성능과 안정성을 향상시키는 중요한 원칙입니다. 무상태 서비스는 다양한 요청에서 동시에 접근될 가능성이 있는 컴포넌트에 특히 유용합니다. 이 원칙을 적용함으로써 복잡한 동시성 제어를 회피하고 코드의 유지 보수성을 향상시킬 수 있습니다.

 

 

반응형