Search

무분별한 배치 프로세싱과 캐싱이 위험한 이유

웹 서비스를 운영하다보면 다양한 기술적 문제를 마주하게 된다.
사실 대부분의 문제는 데이터를 어떻게 다룰 것인지로 귀결된다.
IT 산업에서 가장 중요한건 결국 데이터다.
하지만 문제를 해결하는 방법은 개발자마다 각양각색이다.
여기서 개발자의 실력이 판명나는 부분이다.
실력이라고 하려면 명확한 평가 기준이 필요하기 때문에 취향이라고 표현하는게 맞을지도 모르겠다.
대표적인 문제 해결 방법 중 배치 프로세싱과 캐싱에 대해 이야기 해보겠다.

배치 프로세싱(Batch Processing)

배치 프로세싱(이하 배치)은 컴퓨터가 주기적으로 대량의 반복적인 데이터 작업을 완료하는 데 사용하는 방법이다.
계산 집약적인 태스크를 일정한 시각에 몰아서 처리하는 것이다.
주로 크론잡의 형태로 많이 실행된다.
은행 시스템이 매일 자정에 15분씩 멈춰있는 이유다.
계산 작업을 일정한 시각에 몰아서 하는 이유는 간단하다.
효율적이기 때문이다.
엔지니어링에서 ‘왜 그렇게 할까’에 대한 답은 거의 ‘효율적이라서’다.

캐싱(Caching)

캐싱은 데이터를 빠르게 접근할 수 있도록 메모리와 같은 저장장치에 임시로 저장하는 기술이다.
캐싱은 왜 필요할까? 당연히 효율적이기 때문이다.
캐싱의 주요 목적은 더 느린 스토리지에 액세스해야 하는 필요를 줄임으로써 데이터 탐색 성능을 높이는 것이다.
이 때 사용되는 저장소를 캐시라고 부른다.
캐시 없는 컴퓨터는 상상할 수 없다.
CPU, DNS, CDN, 웹 서비스, 데이터베이스 등 캐싱이 쓰이지 않는 곳이 없다.

배치와 캐싱의 문제점

배치와 캐싱은 매우 중요한 기술이다.
규모 있는 서비스를 운영해본 개발자라면 대부분 배치와 캐싱을 개발해본 적이 있을 것이다.
두 기술은 안정적으로 시스템을 운영하는데 많은 도움이 된다.
배치가 없다면 개별 트랜잭션에서 불필요한 계산이 너무 많이 발생한다.
이 때 발생하는 동시성 문제나 성능 문제도 매우 골치 아프다.
캐싱은 내가 가장 사랑하는 테크닉 중 하나다.
캐싱을 잘 이해하고 있지 않으면 절대로 멋지고 안정적인 시스템을 만들 수 없다.
그럼에도 불구하고 배치와 캐싱을 적용할 때 매우 망설인다.
왜냐하면 배치와 캐싱은 잠시 달콤한 미봉책일 때가 많기 때문이다.
문제를 해결할 때 쉽게 배치와 캐싱이 떠오르더라도 정말 필요한 것일지 여러번 고민한다.
현대의 컴퓨팅 관련 문제들은 시간 복잡도 해결이 가장 중요하다.
1초는 인간의 입장에서는 찰나지만 컴퓨터의 입장에서는 너무 긴 시간이다.
특히 배치와 캐싱을 이용하면 이런 시간 복잡도 문제를 많이 해결할 수 있다.
하지만 배치와 캐싱이 문제가 되는 이유는 웹 어플리케이션과 별도의 프로세스이기 때문이다.
웹 어플리케이션의 입장에서 배치와 캐시는 외부의 독립적인 프로세스다.
외부의 독립적인 프로세스는 예측이 불가능하다.
말 그대로 시스템 외부에서 시스템과 독립적으로 동작한다.
서로 데이터 소스를 공유하고 있다면, 데이터가 예측 불가능한 상태가 된다.
데이터의 정합성이 매우 중요한 서비스라면 이건 매우 중요한 문제다.
그래서 은행은 어쩔수 없이 15분 간 시스템을 멈춘다.
하지만 요즘 이런식의 운영이 가능한 웹 서비스가 얼마나 될까?
데이터를 잘 다루기 위해 적용한 기술이 데이터를 다루기 힘들게 만드는 모순이 발생한다.
그나마 시스템을 이해하고 있는 개발자에 의해 예측이 가능하다고 하자.
그럼에도 불구하고 외부 프로세스를 통제하는건 여전히 어렵다.
데이터가 변경되는 수많은 경우의 수와 동시성 이슈를 계속 고려해야 한다.
물론 실제로 캐시를 운영해보면 웹 어플리케이션과 캐시가 완전히 독립적이지 않다.
보통 웹 서버에서 캐시를 관리하는 구조로 구성되어 있다.
대신 캐시를 관리하기 위해 메인 시스템이 복잡해지는 것을 감수해야 한다.
또 그에 따라 파생되는 다양한 고민과 노력이 필요하다. 그리고 그 노력은 생각보다 까다롭다.
오죽하면 컴퓨터 공학에는 아래와 같은 격언까지 존재한다.
There are only two hard things in Computer Science: cache invalidation and naming things. 컴퓨터 공학에는 오직 두 개의 어려운 것이 있다: 캐시 무효화와 이름 짓기
미봉책이라고 표현한 이유는 당장 문제를 해결하기 좋아보이지만 결국 시스템을 복잡하게 만들기 때문이다.
각 프로세스에서 변환시키는 데이터 상태 cardinality 곱이 최종적인 시스템의 복잡도가 된다.

은탄환은 없다(No Silver Bullet)

배치와 캐싱은 절대 쓰면 안 된다는 말은 아니다.
다만 모든 문제를 해결하기 위한 은탄환(silver bullet)처럼 사용해서는 안 된다는 것이다.
시간 복잡도를 줄이려는 노력은 컴퓨터의 탄생과 함께 시작된 고민이다.
따라서 위의 두 가지 방법이 아니더라도 시간 복잡도를 해결하기 위한 다양한 대안이 있다.
웹 서비스에서 시간 복잡도를 해결할 수 있는 대표적인 방법은 다음과 같다:
적합한 알고리즘과 자료구조 선택
HashTable을 이용한 Memoization
Database Query/Index Tuning
반복문 순회 횟수 줄이기
비동기 I/O

참고