본문 바로가기

분류 전체보기

(59)
[OS] 유저 모드와 커널 모드, 시스템 콜 유저 모드 프로세스는 파일 읽기, 메모리 받기, 네트워크 전송, 프로세스 생성 등 자기 주소 공간 밖의 모든 일을 시스템 콜이라는 단 하나의 통제된 통로로만 커널에 요청할 수 있다. 이 경계가 리눅스 보호 모델 전체의 출발점이다. 우리가 파일 입출력, 메모리 확장, 네트워크 통신, 새 프로세스 생성 등 프로그램이 한다고 여기는 거의 모든 일은 프로그램이 커널에게 부탁한 일이다. 왜 프로그램이 하드웨어를 직접 못 만지게 막아두었을까 그리고 그 '부탁'은 어떻게 커널에 전달될까이 두 질문의 답이 운영체제에서 가장 근본적인 경계인 유저 모드와 커널 모드의 분리, 그리고 두 모드를 잇는 단 하나의 통로인 system call(시스템 콜)이다. 이 경계는 리눅스의 거의 모든 것을 떠받친다. 프로세스 보호, 메모리..
[PostgreSQL] MVCC 완전 정복 설계 배경 — 읽기와 쓰기가 서로를 막지 않아야 한다전통적인 동시성 제어 방식인 2PL(Two-Phase Locking)은 명쾌하다. 읽기는 공유 락을, 쓰기는 배타 락을 잡는다. 충돌하는 연산은 서로를 기다리게 만들어 실행 순서를 강제로 직렬화한다. 그러나 실제 운영 환경에서는 치명적인 문제가 드러난다. 읽기가 쓰기를 막고, 쓰기가 읽기를 막으면서 트래픽이 조금만 몰려도 대기 체인이 폭발적으로 늘어난다. 오래 걸리는 리포트 쿼리 하나가 OLTP(Online Transaction Processing, 짧고 빈번한 쓰기·읽기가 뒤섞인 실시간 거래 처리) 쓰기 전체를 멈추게 하는 장애가 반복됐다. PostgreSQL의 전신인 Berkeley POSTGRES는 1980년대 후반 이 문제에 근본적으로 다른 해답..
[PostgreSQL] PostgreSQL이 메모리를 관리하는 법 - Shared Buffer Cache & Clock Sweep 한 줄 요약: PostgreSQL은 OS의 page cache를 믿지 않고, shared_buffers로 지정한 메모리에 자체 버퍼 풀을 운영한다. 어떤 페이지를 내보낼지는 LRU가 아닌 Clock Sweep이 결정한다.설계 배경 — OS page cache가 있는데 왜 또 버퍼가 필요한가파일 I/O를 하면 운영체제는 자동으로 읽은 블록을 page cache에 보관한다. 같은 블록을 다시 읽으면 디스크에 가지 않고 메모리에서 돌려준다. 그렇다면 PostgreSQL이 shared_buffers라는 별도 버퍼 풀을 유지하는 이유는 무엇인가?첫째, OS page cache는 WAL 선행 원칙을 알지 못한다. PostgreSQL은 dirty page를 디스크에 쓰기 전에 반드시 해당 페이지 변경을 기술한 WAL..
[PostgreSQL] 스토리지 레이어: 페이지 레이아웃 & TOAST 왜 페이지가 8KB인가PostgreSQL의 모든 테이블 데이터는 8KB 고정 크기 블록(페이지) 단위로 관리된다. 행이 1바이트짜리 값 하나를 담든, 수백 컬럼을 담든 관계없이 디스크 I/O의 최소 단위는 항상 8KB다. 이 결정은 PostgreSQL 초창기에 내려졌고, 오늘날까지 기본값으로 이어진다. 왜 8KB인가? 답은 세 가지 트레이드오프에 있다.행 크기와 페이지 크기의 균형이다.4KB 페이지를 쓰면 텍스트 컬럼 몇 개만 있어도 행 하나가 페이지를 꽉 채워 버리고, 페이지당 행이 하나뿐인 극단적인 상황이 생긴다. 반면 32KB처럼 너무 크면 단 한 행을 읽으려 해도 불필요하게 많은 데이터를 메모리에 올려야 한다.8KB는 "웬만한 행은 한 페이지 안에 담기고, 메모리 낭비도 크지 않다"는 실용적 타협..
[Zero Trust - Continuous Verification] SIEM 아키텍처: 이벤트의 바다에서 위협 패턴을 찾는 방법 보안 팀이 사후 분석 보고서를 작성하고 있다. 공격자가 처음 침투한 것은 6개월 전이었다. 초기 침투는 스피어 피싱 이메일을 통한 인증 정보 탈취였고, 그 계정으로 VPN에 처음 접속한 시각은 새벽 2시 14분이었다. 이후 공격자는 3개월 동안 내부를 조용히 탐색했다. LDAP 쿼리로 서비스 계정 목록을 수집했고, 관리자 권한이 있는 계정들을 차례로 장악했다. 5개월 차부터는 소량의 데이터를 외부로 반출하기 시작했다. 분석가가 로그를 열어보자 모든 흔적이 있었다. 비정상적인 시간대의 VPN 접속, 평소와 다른 서브넷 스캔, LDAP 열거 패턴, 외부 IP로의 비정기 HTTPS 연결. 개별 이벤트로 보면 하나하나는 이상해 보이지 않았다. 조합해보면 누군가 시스템 안에서 움직이고 있었다는 것이 분명했다. 단..
[PostgreSQL] 프로세스 아키텍처 & 공유 메모리 PostgreSQL은 프로세스인가많은 현대 데이터베이스는 멀티스레드 모델을 채택한다. MySQL의 InnoDB, MongoDB, SQL Server 모두 하나의 프로세스 안에서 여러 스레드가 클라이언트 요청을 처리한다. 그런데 PostgreSQL은 정반대다. 클라이언트가 접속할 때마다 OS 수준의 새로운 프로세스가 fork()되어 그 연결을 전담한다. 이 설계는 1986년 UC Berkeley에서 시작된 POSTGRES 프로젝트의 유산이다. 당시는 POSIX 스레드 표준이 정립되기 전이었고, UNIX 계열 시스템 간에 스레드 API가 통일되어 있지 않았다. 가장 이식성 높은 동시성 단위는 fork() 한 번으로 복제되는 프로세스뿐이었다. 하지만 30년이 지난 지금까지 PostgreSQL이 프로세스 모델을..
[Zero Trust - Policy Engine] Connector와 Gateway: 정책 결정이 실제 트래픽으로 집행되는 방법 보안 감사 중에 이런 질문이 나올 때가 있다."VPN 없이 내부 개발 서버에 접근한다면, 그 연결은 어떻게 만들어지나요? 내부 서버의 포트가 외부에 열려 있는 건가요?" 이 질문이 불편하게 느껴지는 데는 이유가 있다. VPN을 걷어냈다고 선언했다면, 그 자리를 대체하는 것이 무엇인지를 구체적으로 설명할 수 있어야 한다. "Zero Trust를 도입했습니다"라는 말만으로는 충분하지 않다. Vol.11에서 PDP(Policy Decision Point)가 접근 요청에 허용/거부를 결정한다고 설명했다. 앞선 포스팅에서는 OPA와 Cedar가 그 결정을 어떤 언어로 표현하는지를 다뤘다. 그런데 OPA가 allow = true를 반환했다고 해서 사용자의 노트북과 내부 앱 서버 사이에 연결이 저절로 생기지는 않는다..
[Zero Trust - Policy Engine] OPA와 Cedar: 두 정책 언어가 같은 문제를 다르게 정의한 이유 외부 감사가 시작됐다. 감사팀은 간단한 질문을 던졌다."현재 프로덕션 데이터베이스에 접근 가능한 사람 전체 목록을 주세요." 담당 엔지니어는 그 질문에 즉시 답할 수 없었다. 프로덕션 DB 접근 권한은 세 가지 경로로 나뉘어 있었다.첫째는 사용자 서비스의 JWT 클레임에서 db_admin 역할을 확인하는 로직둘째는 내부 배포 도구가 LDAP 그룹 멤버십을 직접 조회하는 방식셋째는 데이터 분석 플랫폼이 자체 권한 테이블을 관리하는 구조세 군데를 각각 쿼리하고, 중복을 걸러내고, 이미 퇴사한 계정이 혹시 남아있지는 않은지 수동으로 확인하는 데 이틀이 걸렸다.문제는 감사팀이 다음 질문을 이어서 던진다는 것이다."이 중에서 지난 90일간 실제로 접근한 사람은 몇 명이고, 접근 권한이 있지만 한 번도 쓰지 않은 ..