본문 바로가기
CS

개발자를 위한 최소한의 실무 지식

by Diligejy 2024. 2. 9.

 

 

p.24

트랜잭션(transaction)은 컴퓨터로 처리하는 작업의 단위를 말합니다. 트랜잭션에 속한 모든 작업이 성공적으로 완료되어야 트랜잭션의 실행도 완료되기 때문에 트랜잭션은 '작업과 운명을 함께한다'라고 표현할 수 있습니다.

 

p.25

트랜잭션에는 커밋(commit)과 롤백(rollback)이라는 명령어를 사용합니다. 커밋은 '약속하다'라는 뜻으로 여러 개의 쿼리를 묶어 하나의 트랜잭션으로 처리하겠다고 약속하는 명령어입니다. 그리고 롤백은 쿼리 실행 도중 오류가 발생하면 상태를 되돌리기 위해 사용하는 명령어입니다.

 

컴퓨터의 모든 작업이 메모리에서 실행되지만, 작업한 결과는 반드시 디스크에 기록되어야 합니다. 메모리가 가진 휘발성이라는 특징 때문인데요. 전원 연결이 끊어지면 메모리의 데이터가 연기처럼 사라지기 때문에 데이터를 꼭 디스크에 기록해야 한답니다. 이러한 까닭에 커밋 명령어를 사용해 쿼리문 실행 결과를 디스크에 기록합니다. 반면, 롤백 명령어를 사용하면 트랜잭션이 실행되기 전 상태로 되돌리기 때문에 쿼리문 실행 결과가 디스크에 기록되지 않습니다.

 

p.26~27

오토커밋은 쿼리문을 실행할 때마다 자동으로 커밋이 실행되는 DBMS 기능입니다. 쿼리문마다 커밋 명령이 실행되기 때문에 쿼리문 하나가 곧 트랜잭션의 구간이 됩니다. 앞에서 언급한 계좌이체에 빗대어보면 인출 작업 완료 후 커밋 실행, 입금 작업 완료 후 커밋 실행 순으로 동작합니다.

 

DBMS에서 테이블을 만들면 오토커밋이 기본으로 설정되지만, 코딩을 하려면 이 설정을 해제해야 합니다. 왜 그럴까요? 그 이유는 다음과 같습니다. 

 

[그림 1-2]와 같이 인출 후 입금하는 도중 에러가 났다고 가정하겠습니다. 오토커밋을 설정하지 않았다면 두 작업은 하나의 트랜잭션으로 묶이기 때문에 에러 발생 이전 상태로 되돌릴 수 있습니다. 하지만 [그림1-3]과 같이 오토커밋을 설정했다면 인출 후 바로 커밋이 실행되기 때문에 쿼리 실행 결과가 디스크에 기록되고 에러 발생 이전 상태로 되돌릴 수 없습니다. 즉, 돈이 인출은 됐는데 입금은 되지 않는 문제가 생기죠. 이런 이유로 여러 개의 작업을 논리적으로 묶어야 하는 경우에는 오토커밋을 사용하지 않는 편이 좋습니다.

 

p.31

쿼리문을 빠르게 실행하기 위해서는 인덱스를 잘 활용해야 한다는 사실을 놓치는 개발자들이 있습니다. 이런 안타까운 상황을 면하려면 인덱스가 무엇이고 어느 경우에 만들어야 하는지 이해해야 합니다. 

 

DBMS의 인덱스는 인덱스 키(key)와 행 주소(row address)에 대한 정보를 담고 있습니다. 인덱스 키는 우리가 찾고자 하는 키워드를 말하고, 행 주소는 책의 인덱스에 있는 페이지 번호처럼 위치를 나타내는 정보입니다. 인덱스의 페이지 번호를 따라가면 본문에서 해당 키워드를 바로 찾듯이, 인덱스의 데이터 위치를 따라가면 테이블에서 원하는 데이터를 쉽게 찾게 됩니다.

 

p.40

다음의 실행 계획을 확인해보니 key 열 값이 'NULL"입니다. WHERE 절을 사용했는데 왜 인덱스 스캔이 아니라 풀 데이터 스캔으로 검색했을까요?

EXPLAIN SELECT * FROM 학생 WHERE 학과 = '컴퓨터공학과';

 

 

id select_type table type possible_keys key key_len ref rows extra
1 SIMPLE 학생 ALL NULL NULL NULL NULL 8 Using where

 

 

p.42~43

데이터 무결성을 배워도 이를 제대로 알고 사용하는 경우는 많지 않습니다. 데이터 무결성이 중요한 만큼 데이터를 체계적으로 관리해야 하는 DBMS에서 세 가지 무결성을 지원한다는 사실조차 모르고 코드를 작성하기도 하지요.

 

'데이터 무결성을 확보하기 위해 코드만 잘 작성하면 되지 않나요?' 라고 생각하는 분도 있을 것 같습니다. 하지만 코드만으로는 데이터 무결성을 보장하기 어렵기 때문에 DBMS에서 제공하는 기능을 잘 활용해야 합니다.

 

예를 들어 설명하겠습니다. 회원가입 기능을 구현할 때 다음과 같이 아이디 중복을 체크하는 코드를 추가할 수 있습니다. 사용자 테이블에 아이디가 존재하면 '이미 등록된 아이디입니다'라고 알려주고, 존재하지 않으면 '사용 가능한 아이디입니다'라고 알려주는 의사코드(psudocode)이지요. 의사코드란 프로그램의 실행 흐름을 쉽게 이해할 수 있도록 자연어로 작성된 코드를 말합니다.

 

/* 아이디 중복 체크 의사코드 */

입력한 아이디가 사용자 테이블에 존재하는지 확인하기 위한 조회 쿼리문 실행

만약, 사용자 테이블에 아이디가 존재한다면,
    사용자에게 안내 메시지("이미 등록된 아이디입니다.")를 출력
    
만약, 사용자 테이블에 아이디가 존재하지 않는다면,
    사용자에게 안내 메시지("사용 가능한 아이디입니다.")를 출력

 

중요한 사실은 이 코드만으로는 데이터 무결성을 보장할 수 없다는 점입니다. 왜일까요? 동시성이 발생하는 상황에서 무결성 보장을 고려하지 않았기 때문입니다. 

 

두 명의 사용자가 동시에 회원가입을 하는 상황을 생각해봅시다. 두 사용자가 동시에 동일한 아이디로 회원가입을 하면 해당 코드도 동시에 실행됩니다. 두 사람이 입력한 사용자 아이디가 아직 DBMS의 사용자 테이블에 존재하지 않으므로 동일한 아이디를 사용했음에도 두 사람은 모두 '사용 가능한 아이디입니다'라는 결과를 얻게 되겠지요. 결국 테이블에 동일한 아이디가 입력되는 문제가 생긴답니다.

 

이렇듯 코드 작성만으로 데이터 무결성을 보장하기는 매우 어렵습니다. 우리가 DBMS에서 제공하는 세 가지 무결성을 제대로 이해하고 활용해야 하는 이유가 바로 이것입니다. 

댓글