리버스 프록시와 동시성 제어 기법

웹 애플리케이션 개발에서 리버스 프록시의 역할과 다양한 동시성 제어 기법의 특징, 적용 시나리오 및 분산 환경에서의 구현 전략을 종합적으로 설명하는 실무 중심 가이드입니다.



리버스 프록시와 동시성 제어 기법 with Proxy?

프록시(Proxy)란 ‘대리’ 를 의미

POINT: 동일한 요청을 매번 처리하는 것은 곧 리소스 낭비 와 서버의 부하 -> 본 서버에 도달하기 전에 새로운 서버(proxy server)를 미리 배치하여 중복 요청에 대해 (연산이 필요없는) 동일한 응답을 할 수 있다면, 클라이언트에겐 빠른 속도의 서비스를, 서버에게는 불필요한 부하를 줄이는 효과

Forward Proxy, Reverse Proxy 그림

image

프록시 서버 위치

  • Forward Proxy 서버는 클라이언트 앞에 놓여져 있는 반면,
  • Reverse Proxy 서버는 웹서버/WAS 앞에 놓여 있다는 차이점이 있다.

프록시 서버 통신 대상

  • Forward Proxy는 내부망에서 클라이언트와 Proxy 서버가 통신하여 인터넷을 통해 외부에서 데이터를 가져온다.
  • Reverse Proxy는 내부망에서 Proxy 서버와 내부망서버가 통신하여 인터넷을 통해 요청이 들어오면 Proxy 서버가 받아 응답해준다.

감춰지는 대상

  • Forward Proxy는 내부망에서 인터넷 상에 있는 서버에 요청할때 먼저 포워드 프록시 서버를 호출하고 프록시가 서버에게 요청을 보내게 되는데, 이로서 서버에게 클라이언트가 누구인지 감출수 있다. 즉, 서버 입장에서 응답받은 IP는 포워드 Forward Proxy의 IP이기 때문에 클라이언트가 누군지 알 수 없다.
  • Forward Proxy는 직접 서버 url로 요청을 보내지만, Reverse Proxy는 프록시 서버 url로만 접근이 가능하다.이로서 Reverse Proxy는 본서버의 IP 정보를 숨길수 있는 효과를 얻게 된다.

예시

  • 우리가 naver.com 을 요청하면 포워드 프록시 서버가 naver.com 리소스를 대신 구해와 클라이언트에게 내밀어준다(forward)고 생각하면 된다.
  • 우리가 구성하는 일반적인 WEB(Apache, nginx) - WAS(Tomcat) 분리 형태를 Reverse 프록시라고 보면 된다.여기서 WEB(Apache, nginx)가 reverse proxy가 된다.물론 아파치 톰캣 같이 물리적인 한서버에 web, was가 존재한다면 reverse proxy라고 볼 수 없다.

참고 문헌


1. 리버스 프록시 (Reverse Proxy)

리버스 프록시는 클라이언트의 요청을 여러 백엔드 서버로 분배하거나, 로드 밸런싱, 캐싱, 보안 강화 등의 목적으로 서버와 클라이언트 간의 중개 역할을 수행하는 프록시 서버이다. 클라이언트는 리버스 프록시 서버를 통해 백엔드 서버와 통신하며, 이를 통해 서버 부하 분산 및 보안을 강화할 수 있다.

  • 주요 목적: 로드 밸런싱, 보안 강화, 백엔드 서버 보호
  • 예시: Nginx와 Apache HTTP Server는 웹 서버이자 리버스 프록시 서버로 사용할 수 있다.
  • 포지션: 리버스 프록시는 웹서버/WAS 앞에 놓여 서버 요청을 처리하고, 클라이언트에게는 프록시 서버의 IP만 노출되게 하여 보안을 강화한다.


2. 주로 사용하는 동시성 제어 기법

DB 행에 Lock을 거는 것은 애플리케이션 단이든 데이터베이스(ex:Oracle) 단이든 같음!
-> 다만, 저장된 데이터의 안정성(DB) / 비즈니스 로직 레벨에서의 동시성 문제 해결(앱) 이 목적

동시성 문제를 해결하기 위한 주요 방법들로는 비관적 잠금, 낙관적 잠금, 메시지 큐, 트랜잭션과 인덱스 등이 있다. 이들은 각각 데이터베이스 레벨과 애플리케이션 레벨에서 동시성을 관리하는 데 사용된다.

  1. 비관적 잠금 (Pessimistic Locking)
    • 사용 방법: @Lock(LockModeType.PESSIMISTIC_WRITE) (쿼리에 적용)
    • 특징: 데이터 충돌 가능성이 높을 때 사용. 트랜잭션을 유지하면서 데이터에 락을 걸어 다른 트랜잭션의 접근을 막음
  2. 낙관적 잠금 (Optimistic Locking)
    • 사용 방법: @Version (엔티티 클래스의 필드에 적용)
    • 특징: 충돌 가능성이 낮을 때 사용. 버전 번호를 통해 데이터 변경 여부를 검증하여 동시성을 관리
  3. 메시지 큐 (Message Queue)
    • 예시: RabbitMQ, Kafka 등 사용
    • 특징: 동시성 문제를 해결하기 어려운 경우 큐를 사용해 처리 요청을 순차적으로 처리. 단일 소비자가 요청을 순차적으로 처리하여 동시성을 해결
  4. 트랜잭션과 인덱스
    • 트랜잭션: 여러 인스턴스에서 데이터를 변경할 때 ACID 속성을 보장하는 트랜잭션을 사용하여 데이터의 일관성을 유지
    • 인덱스: 특정 컬럼에 유니크 인덱스를 설정하여 동시에 접근할 때 충돌을 방지. 유니크 인덱스는 데이터베이스가 자동으로 락을 지원


3. (중요) Synchronized와 DB Lock 언제?

개념확립 하기 좋은 문서

결론: 실무에선 DB Lock을 좀 더 사용.
Synchronized(스레드에 락 검)는 하나의 프로세스에서만 동시성 제어하므로 여러 서버에서 하나의 DB에 접속하는건 동시성 제어가 불가함.
따라서 DB 단에서 해결할 수 있는 DB Lock을 활용! (Spring에서 애노테이션으로 간편히 제공 중)



댓글남기기