서버 구조를 공부하다 보면 어느 순간부터는 “메모리도 거리 개념이 있다”는 이야기를 듣게 된다. 나도 처음에는 RAM은 그냥 어디서 접근하든 속도가 비슷한 줄 알았다. 실제로 일반 데스크톱 PC에서는 CPU 하나와 메모리 구조가 단순하기 때문에 그런 차이를 체감하기 어렵다. 그런데 데이터센터나 AI 서버처럼 CPU가 여러 개 들어가는 멀티소켓(Multi-Socket) 서버 환경에서는 이야기가 완전히 달라진다고 한다. 특히 최신 서버들은 CPU 코어 수가 엄청 많아지고 메모리 용량도 수백 GB~수 TB 수준까지 올라가면서, 단순히 “메모리가 많다”보다 CPU가 어느 메모리를 접근하느냐가 성능에 굉장히 큰 영향을 주기 시작했다고 한다. 그리고 이런 구조를 설명할 때 반드시 등장하는 개념이 바로 NUMA(Non-Uniform Memory Access)다. 처음 이름만 들었을 때는 굉장히 어려운 서버 하드웨어 용어처럼 느껴졌는데, 구조를 이해하고 나니까 왜 데이터베이스 서버와 AI 서버, 가상화 환경에서 NUMA 최적화를 그렇게 중요하게 보는지 조금 감이 오기 시작했다. 특히 인상 깊었던 건 현대 서버에서는 CPU 계산 속도보다 “메모리까지 얼마나 멀리 이동해야 하는가”조차 성능 병목이 될 수 있다는 점이었다. 나도 처음에는 메모리 접근 속도가 CPU 위치에 따라 달라질 수 있다는 사실 자체가 꽤 충격적으로 느껴졌다.

멀티소켓 서버에서는 CPU마다 가까운 메모리가 따로 존재한다
예전 컴퓨터 구조에서는 CPU 하나가 전체 메모리를 관리하는 방식이 일반적이었다. 그런데 서버 성능이 계속 발전하면서 CPU 코어 수를 늘리는 것만으로는 한계가 생기기 시작했고, 결국 여러 개 CPU(Socket)를 하나의 서버 안에 넣는 멀티소켓 구조가 등장하게 되었다. 문제는 CPU가 많아질수록 모든 CPU가 하나의 메모리 컨트롤러를 공유하는 방식에서는 병목이 심해질 수 있다는 점이었다. 그래서 현대 멀티소켓 서버는 보통 CPU마다 자신과 직접 연결된 로컬 메모리(Local Memory)를 가지는 구조를 사용한다. 즉 CPU A 가까이에 연결된 RAM과 CPU B 가까이에 연결된 RAM이 따로 존재하는 것이다. 처음에는 나도 “어차피 같은 RAM 아닌가?”라고 생각했는데, 실제로는 CPU가 자기 근처 메모리를 접근할 때와 다른 CPU 쪽 메모리를 접근할 때 속도 차이가 꽤 발생할 수 있다고 한다. 예를 들어 CPU A가 자기 로컬 메모리를 읽는 경우는 굉장히 빠르지만, CPU B에 연결된 메모리를 읽으려면 CPU 간 인터커넥트(Interconnect)를 거쳐야 하기 때문에 추가 지연(latency)이 발생하게 된다. 그리고 이런 구조를 바로 NUMA라고 부른다. 즉 메모리 접근 속도가 균일하지 않다(Non-Uniform)는 의미다. 나도 처음에는 RAM 속도는 전부 비슷할 줄 알았는데, 최신 서버에서는 CPU와 메모리 사이 “물리적 거리” 자체가 성능 문제로 이어질 수 있다는 걸 알고 꽤 신기했다. 결국 현대 서버는 단순 CPU 성능 경쟁이 아니라, CPU와 메모리를 얼마나 가까이 붙여 효율적으로 사용할 수 있는가의 경쟁으로까지 발전하고 있었던 것이다.
NUMA 환경에서는 메모리 locality가 성능에 엄청 중요해진다
NUMA 구조에서 가장 중요한 개념 중 하나는 locality(지역성)다. 쉽게 말하면 CPU가 최대한 자기 근처 메모리를 사용하도록 만드는 것이다. 예를 들어 CPU A 위에서 실행되는 프로세스가 CPU A 로컬 메모리를 사용하면 굉장히 효율적이지만, 계속 CPU B 메모리를 접근하게 되면 원격 메모리(Remote Memory Access)가 반복되면서 성능이 떨어질 수 있다고 한다. 처음에는 나도 “메모리 접근 조금 멀어진다고 그렇게 차이 나나?” 싶었는데, 최신 서버 환경에서는 CPU 속도가 워낙 빠르다 보니까 메모리 지연 자체가 굉장히 큰 병목으로 느껴질 수 있다고 한다. 특히 데이터베이스 서버나 AI 서버처럼 엄청난 양의 메모리를 계속 읽고 쓰는 환경에서는 NUMA locality가 성능에 매우 큰 영향을 줄 수 있다고 한다. 예를 들어 어떤 프로세스가 특정 CPU에서 실행되는데 메모리는 다른 소켓에 계속 할당된다면 CPU는 데이터를 가져오기 위해 계속 원격 접근을 반복하게 된다. 결국 캐시 효율도 떨어지고 메모리 지연도 증가하면서 전체 처리량이 감소할 수 있는 것이다. 그래서 Linux는 NUMA Balancing이라는 기능을 통해 프로세스와 메모리를 최대한 가까운 위치로 자동 이동시키려고 하기도 한다고 한다. 나도 Huge Page를 공부하면서 CPU가 주소 변환 때문에도 바빠질 수 있다는 걸 느꼈는데, NUMA까지 보니까 현대 서버는 메모리 “용량”보다 메모리 “위치”까지 최적화해야 하는 시대라는 게 꽤 인상 깊었다. 결국 최신 서버는 데이터를 얼마나 빨리 계산하느냐뿐만 아니라, 데이터를 얼마나 가까운 곳에서 가져올 수 있는가가 훨씬 중요해지고 있었던 것이다.
그래서 AI 서버와 데이터센터는 NUMA 최적화를 굉장히 중요하게 본다
지금까지 공부했던 Huge Page, RDMA, DPDK, XDP 같은 기술들을 보면 전부 공통된 방향이 있었다. 바로 CPU가 불필요하게 기다리거나 멀리 이동하지 않도록 만드는 것이다. NUMA 역시 완전히 같은 흐름 위에 있다. 다만 이번에는 네트워크나 시스템 콜이 아니라 메모리 위치 자체를 최적화하는 방향인 것이다. 특히 최신 AI 서버는 GPU 여러 개와 CPU 여러 개가 동시에 연결되어 있고, 메모리 사용량도 엄청나기 때문에 NUMA 구조 영향이 훨씬 커질 수 있다고 한다. 예를 들어 AI 학습 프로세스가 잘못된 NUMA 노드 메모리를 계속 사용하면 GPU와 CPU 사이 데이터 이동 효율이 크게 떨어질 수도 있다고 한다. 나도 처음에는 데이터센터 최적화라는 게 그냥 CPU와 GPU 스펙 경쟁인 줄 알았는데, 실제로는 메모리 위치와 locality까지 전부 성능에 영향을 준다는 게 꽤 흥미로웠다. 특히 클라우드 환경에서는 VM과 컨테이너까지 NUMA 구조 영향을 받을 수 있기 때문에, 운영체제 스케줄러와 메모리 할당 정책이 굉장히 중요해지고 있다고 한다. 결국 현대 서버는 단순히 “빠른 CPU와 많은 RAM”만으로 설명되는 시대를 넘어서, CPU·메모리·네트워크 위치 관계까지 전부 최적화해야 하는 방향으로 계속 발전하고 있었던 것이다. 이걸 공부하면서 가장 인상 깊었던 건 현대 컴퓨터 구조는 단순 계산 속도 경쟁이 아니라, 데이터를 얼마나 가까운 위치에서 효율적으로 처리할 수 있는가의 경쟁으로 바뀌고 있다는 점이었다.
한 줄로 정리하면 NUMA는 멀티소켓 서버에서 CPU마다 가까운 메모리 영역이 따로 존재하는 구조이며, 원격 메모리 접근 비용을 줄이고 locality를 높이는 것이 데이터베이스·AI·가상화 서버 성능 최적화에 매우 중요하다.