CHAAANY ARCHIVE

전체 글

508개의 기록을 주제별로 둘러보세요.

데이터베이스는 같은 SQL에서도 왜 읽는 순서를 고를까? 쿼리 실행 계획

SQL은 원하는 결과를 말한다. status = 'ready'인 행을 달라고 할 뿐, 테이블을 처음부터 읽을지 인덱스로 찾을지, 두 테이블 중 어디부터 읽을지는 지정하지 않는 경우가 많다. 데이터베이스는 가능한 경로의 비용을 예상하고 실제 실행 순서를 고른다. 이것이 쿼리 실행 계획이다.실행 계획을 이해하면 “인덱스가 있는데 왜 느릴까”라는 질문을 더 정확하게 바꿀 수 있다. 데이터베이스가 몇 행을 찾을 것으로 예상했고, 실제로는 얼마나 읽었으며, 어느 단계에서 작업량이 크게 늘었는지를 확인하게 된다.같은 결과를 만드는 읽기 방법은 여러 개다백만 행에서 status = 'ready'를 찾는다고 하자. 데이터베이스에는 적어도 두 경로가 있다.경로 A: 테이블 전체를 차례로 읽고 status를 확인경로 B:..

《기획이란 무엇인가》 2부 독서노트: 문제해결형 기획은 근거에서 실행까지 이어진다

도서관에서 빌린 길영로의 《기획이란 무엇인가》를 읽고 책을 반납했다. 이 글은 그중 2부 ‘문제해결형 기획의 프로세스와 방법론’을 읽으며 남긴 독서노트다. 앞서 정리한 1부가 용어·목적·팩트의 기준을 세우는 내용이었다면, 2부는 그 기준으로 문제를 어떻게 좁히고 실행 가능한 기획으로 연결하는지를 다룬다.2부를 읽으며 가장 분명해진 것은 문제해결형 기획이 아이디어에서 시작하지 않는다는 점이다. 먼저 기획이 왜 태어났는지 확인하고 목적과 제목을 정하고 팩트로 현상과 배경을 분석한다. 그 과정을 거쳐야 비로소 컨셉과 해결책, 실행계획을 말할 수 있다.2부에서 먼저 확인하게 된 것2부를 읽으며 먼저 떠올린 질문은 다음과 같다.이 기획은 어떤 변화에서 시작됐는가?이 일은 왜 존재해야 하며, 목적과 제목으로 설명할..

동시에 바꾸는 작업은 어떻게 서로를 방해하지 않을까? 잠금과 격리

트랜잭션이 여러 변경을 하나의 완료 단위로 묶어도, 두 트랜잭션이 동시에 같은 데이터를 바꾸는 문제까지 자동으로 사라지지는 않는다. 각각은 정상적으로 시작하고 커밋했는데, 함께 실행했을 때만 잘못된 결과가 나올 수 있다.동시성 제어는 단순히 한 작업을 멈춰 세우는 기능이 아니다. 어떤 중간 상태를 다른 작업이 볼 수 있는지, 같은 데이터를 바꾸려 하면 누가 기다리는지, 충돌한 작업을 실패시킬지 다시 시도할지를 정하는 규칙이다.재고 1개를 두 주문이 동시에 읽으면 어떻게 될까재고가 1개 남아 있고 주문 A와 B가 거의 동시에 들어왔다고 하자. 두 작업이 값을 읽고 애플리케이션에서 1을 뺀 뒤 다시 쓴다면 다음 순서가 가능하다.초기 재고 = 1A: 재고 1을 읽음B: 재고 1을 읽음A: 주문 가능하다고 판단..

트랜잭션은 여러 변경을 어떻게 하나의 작업으로 만들까? 커밋과 롤백

두 값을 함께 바꾸는 작업은 코드에서는 여러 줄이지만, 데이터에는 하나의 결과로 남아야 할 때가 있다. 잔액 A에서 10을 빼고 B에 10을 더하는 이체가 그 예다. A만 바뀐 채 프로그램이 멈추면, 시스템은 이미 틀린 상태다.트랜잭션은 여러 변경을 전부 완료로 만들거나 전부 미완료로 남기는 경계를 만든다. 핵심은 변경을 빨리 쓰는 데 있지 않다. 장애 뒤 다시 시작해도 이 작업이 완료됐는지 아닌지를 하나의 규칙으로 판단하게 하는 데 있다.이체는 왜 두 번의 쓰기만으로 끝나지 않을까가장 단순하게 A와 B를 차례로 바꾼다고 하자.1. A = A - 102. B = B + 101번 뒤에 전원이 꺼지면 A만 줄어든 상태가 남는다. 2번까지 실행했더라도, 저장장치에 어느 변경이 실제로 남았는지와 재시작 뒤 무엇..

육아휴직 4주차를 돌아보며, 첫 8km 러닝까지

육아휴직 4주차를 돌아보며, 첫 8km 러닝까지육아휴직 4주차.이번 주에도 이것저것 할 일이 많았다. 민방위 교육도 다녀오고, 차 문제도 알아보고, 아기 물건도 정리했다. 그 와중에 러닝과 실내 사이클도 꾸준히 했다. 저녁을 먹고 6km를 뛴 날은 엄청 뿌듯했고, 피곤한 날에는 무리하지 않고 실내 자전거를 탔다.수유하다가 웃는 아기이번 주에 제일 귀여웠던 건 수유하던 아기였다. 먹다가 갑자기 웃는데, 그냥 웃는 게 아니라 먹는 척을 하면서 웃었다. 종종 그러더니 이번에는 자꾸 먹는 척을 하며 웃는데 엄청 귀여웠다 ㅎㅎ흰색 옷을 입은 날에는 진짜 천사 같았다. 잘 웃고, 옹알이도 하고, 눈도 잘 마주쳤다. 터미타임도 전보다 오래 해냈다. 아기가 쑥쑥 무럭무럭 건강하게 자라는 걸 보면 정말 행복하다. 오전 ..

B-트리는 왜 디스크 인덱스에 어울릴까? 노드와 범위 조회

데이터베이스 인덱스가 찾는 것은 메모리 안의 값 하나가 아니라 저장장치에 있는 많은 페이지다. 이때 한 번 읽을 때마다 다음 위치를 하나만 알 수 있는 트리보다, 한 페이지 안에서 여러 갈림길을 판단할 수 있는 구조가 유리하다. B-트리는 이 조건에 맞춰 한 노드에 여러 키와 자식을 담는 정렬 트리다.해시 테이블이 “이 키와 같은 값은 어디 있나”에 강하다면, B-트리는 “이 값보다 작은 것과 큰 것은 어디 있나”, “이 구간의 값은 무엇인가”를 빠르게 찾기 위해 만든다.노드 하나는 저장장치 페이지 하나처럼 읽힌다작은 B-트리 노드가 10과 30을 가진다고 하자. 26을 찾을 때는 10보다 크고 30보다 작으므로 가운데 자식으로 내려간다. [10 | 30] / | \ ..

객체는 어디에 놓이고 언제 사라질까? 메모리 할당과 가비지 컬렉션

프로그램이 값을 다룰 때 모든 값이 같은 방식으로 메모리에 놓이지는 않는다. 함수가 잠깐 쓰는 지역값은 호출이 끝나면 함께 사라질 수 있지만, 함수 밖으로 전달되거나 크기가 달라지는 객체는 더 긴 수명을 가져야 한다. 이 객체들이 머무는 공간을 보통 힙이라고 부른다.힙에서 중요한 질문은 “언제 만들까”보다 “언제 다시 써도 될까”다. 아직 사용하는 객체를 너무 일찍 없애면 프로그램의 의미가 깨지고, 필요 없는 객체를 계속 남기면 메모리가 바닥난다. 가비지 컬렉션은 이 둘 사이에서 프로그램이 여전히 도달할 수 있는 객체를 찾아 보존하는 규칙이다.스택과 힙은 객체의 수명을 다르게 다룬다함수가 호출되면 지역 변수와 반환 위치 같은 짧은 수명의 정보가 스택에 쌓인다. 함수가 끝나면 그 호출의 스택 공간은 한꺼번..

가상 메모리는 왜 프로그램마다 자기 공간이 있는 것처럼 보일까? 페이지와 페이지 폴트

프로그램은 0x1000 같은 주소를 자기만 쓰는 서랍 번호처럼 사용한다. 실제 RAM의 위치를 직접 쓰지 않는다. CPU와 운영체제는 지금 실행 중인 프로세스의 페이지 테이블을 이용해, 그 가상 주소를 실제 물리 메모리의 페이지로 바꾼다.핵심은 주소를 큰 숫자로 바꾸는 데 있지 않다. 프로세스마다 다른 변환표를 가지게 해 서로의 메모리를 보호하고, 필요한 순간에만 실제 메모리를 준비하게 하는 데 있다.같은 주소가 다른 데이터를 가리키는 이유프로세스 A와 B가 모두 0x1000을 읽어도 CPU는 같은 곳을 읽지 않는다.프로세스 A의 페이지 테이블: 0x1000 → 물리 페이지 7프로세스 B의 페이지 테이블: 0x1000 → 물리 페이지 21A가 0x1000에 쓴 값은 7번 페이지를 바꾸고, B가 보는 21..

프로세스는 운영체제에 어떻게 일을 요청할까? 시스템 콜과 파일 디스크립터

프로그램이 파일을 열고 한 줄을 기록하는 일은 코드 안의 함수 호출만으로 끝나지 않는다. 파일과 저장장치, 네트워크, 실행 권한은 운영체제가 관리한다. 프로그램은 운영체제에 요청을 보내고, 운영체제는 그 요청을 허용하거나 거절한 뒤 결과를 돌려준다.이 경계를 이해하면 파일을 쓴 뒤 왜 반환값을 확인해야 하는지, 열린 파일을 왜 닫아야 하는지, 프로그램이 끝났을 때 무엇이 사라지는지를 한 흐름으로 볼 수 있다. open → write → close를 따라가면 파일 이름, 열린 대상, 실제 쓰기, 자원 반납이 서로 다른 상태라는 점이 보인다.프로세스는 실행 중인 프로그램의 상태다디스크에 있는 실행 파일은 아직 파일일 뿐이다. 운영체제가 실행을 시작하면 코드, 메모리 공간, 현재 실행 위치, 열린 파일 목록 ..

육아휴직 3주차, 아기의 회복을 지키고 백일을 준비한 기록

육아휴직 3주차는 아기의 예방접종과 설소대 시술이 있었던 주다. 많이 울던 시간과 그 뒤 이틀 동안 컨디션을 살피던 시간이 길게 남았다. 아기가 다시 편안해 보이기 시작하니 평소 같았던 하루가 더 반가웠다.8월 17일 대체공휴일 저녁에는 아내와 간식, 스파클링 맥주를 곁들이며 육퇴 시간을 보냈다. 잠든 아기 곁에서 조용히 한 잔을 나누는 것만으로도 그날은 충분히 쉬는 기분이었다.예방접종과 시술 뒤, 곁에서 지킨 이틀8월 18일에는 아기의 예방접종과 설소대 시술이 있었다. 아기가 많이 울고 상처가 쉽게 멎지 않는 것처럼 보여 아내는 내내 마음을 졸였다. 그러다 아기가 다시 웃자 아내도 눈물을 보였다. 짠하면서도, 아이를 바라보는 모습이 참 예쁘고 귀여웠다.진료를 기다리는 동안에는 내가 더 신경 썼어야 할 ..

작은 컴파일러는 문장을 어떻게 실행할 형식으로 번역할까? AST·바이트코드 원리

컴파일러는 사람이 쓴 문장을 다른 실행 형식으로 번역한다. 여기서 다룰 작은 컴파일러는 실제 CPU의 모든 기계어를 만드는 도구가 아니라, 앞에서 만든 AST를 바이트코드로 바꾸는 번역기다.핵심은 문장의 뜻을 새로 결정하는 데 있지 않다. 파서가 만든 구조가 가진 의미를 잃지 않고, VM이 실행할 수 있는 명령어 목록으로 옮기는 데 있다.AST는 어떻게 바이트코드가 될까1 + 2 * 3은 토크나이저와 파서를 거쳐 AST가 된다. AST에는 곱셈이 덧셈보다 먼저 계산돼야 한다는 구조가 이미 담겨 있다. (+) PUSH 1 / \ PUSH 2 1 (*) → PUSH 3 / \ ..

작은 바이트코드 VM은 왜 AST 대신 명령어를 실행할까? 스택과 명령어 포인터 원리

인터프리터는 사람이 쓴 문장을 AST로 만든 뒤 그 구조를 따라가며 값을 계산한다. 구조가 분명하다는 장점이 있지만, 같은 식을 여러 번 실행하면 노드 종류를 확인하고 자식 노드를 따라가는 일을 매번 반복한다.바이트코드 VM은 AST를 한 번 더 단순한 명령어 목록으로 바꾼다. 목표는 복잡한 문법을 실행할 때마다 다시 해석하지 않고, 정해진 명령어와 실행 규칙을 반복하는 것이다.AST는 어떻게 명령어 목록이 될까1 + 2 * 3은 AST에서 덧셈의 오른쪽에 곱셈이 있는 구조다. 이 구조를 실행 순서로 풀면 다음과 같은 바이트코드가 된다.PUSH 1PUSH 2PUSH 3MULADDPUSH는 숫자를 스택에 올린다. MUL은 스택 위의 두 값을 꺼내 곱하고, ADD는 그 결과와 1을 더한다.처음 ..

728x90