카테고리 없음

[유레카 / 백엔드] TIL - 6 (MySQL)

coding-quokka101 2025. 10. 16. 18:16

데이터베이스 정규화와 트랜잭션

안녕하세요! 멀티캠퍼스에서 데이터베이스를 배우고 있는 수강생입니다. 이번 주는 긴 연휴 끝에 정말 따라가기 힘든 한 주였던 것 같습니다.  정규화부터 트랜잭션, 락, 데드락, 격리 수준까지... 솔직히 오랜만에 배워서 헷갈렷는데 하루 종일 실습하고 나니 뭔가 정리가 되는 느낌이 들어서 재밌기도하더라고요. 복습도 할 겸 블로그에 정리해봅니다!

MySQL로 배우는 데이터베이스 개론과 실습-2판 - 영풍문고


🌟성취

오늘 제일 뿌듯했던 건 데드락을 직접 발생시켜보고 MySQL이 어떻게 처리하는지 확인한 것이었어요. 강사님이 "두 개의 터미널 띄워서 동시에 실행해보세요"라고 하셨을 때는 솔직히 무슨 말인지 몰랐거든요. 근데 직접 해보니까 "아, 이래서 데드락이 생기는구나!" 하고 확 와닿더라고요. 그리고 실습 중 세이브 포인트를 실무에서는 여러 개 사용하는건가?, 롤백 돌리고 다시 롤백 돌리기 전으로 돌리고 싶으면 어떻게 처리하지? 등등 궁금했는데 정말 신기하게도 강사님이 바로 다음 세션에서 간략하게 알려주셔서 1분만에 궁금증을 해결했었어요! 

 


 

1. 데이터베이스 정규화 - 데이터 정리의 기술

정규화는 쉽게 말하면 **"데이터베이스를 깔끔하게 정리하는 방법"**이에요. 중복을 없애고, 데이터를 논리적으로 분리해서 관리하기 쉽게 만드는 거죠.

정규화 개념 및 특징

이상현상

데이터 조작 중 테이블의 일관성을 훼손하여 데이터의 무결성을 깨뜨리는 현상

  • 삽입 이상 → NULL 값 문제 발생
  • 삭제 이상 → 연쇄 삭제 문제 발생
  • 수정 이상 → 일관성 없음 문제 발생

⇒ 졍규화는 이상현상을 해소하기 위하여 진행한다.

종류 설명 예시

삽입 이상 (Insertion Anomaly) 필요한 데이터를 삽입하기 위해 불필요한 데이터까지 강제로 삽입해야 하는 문제. 수강 과목이 없는 학생 정보를 추가하려고 할 때, 기본 키를 만족시키기 위해 '과목 정보'에 임의의 값을 넣어야 하는 경우.
갱신 이상 (Update Anomaly) 중복된 데이터 중 일부만 수정되어 데이터 간에 **모순(불일치)**이 발생하는 문제. 한 학생의 전화번호가 여러 행에 중복 저장되어 있을 때, 그 중 일부 행만 수정하고 나머지는 놓친 경우.
삭제 이상 (Deletion Anomaly) 어떤 데이터를 삭제할 때, 보존해야 할 다른 데이터까지 연쇄적으로 삭제되는 문제. 특정 과목을 수강하는 마지막 학생의 정보를 삭제했을 때, 그 과목에 대한 정보(예: 과목명, 교수명)까지 함께 사라지는 경우.

 


함수종속성(Functional Dependency)

개념:

  • 속성 간의 관계를 나타냄
  • X → Y: X가 Y를 결정한다 (X가 결정자, Y가 종속자)
  • 예: 학생번호 → 학생이름 (학생번호가 결정되면 학생이름이 유일하게 결정됨)

함수 종속성 다이어그램:

  • 화살표로 종속 관계를 표현
  • 결정자와 종속자의 관계를 시각적으로 나타냄

함수 종속성 규칙

  1. 부분집합 규칙 : X가 Y를 포함하면, X가 Y를 결정한다.
  2. 증가 규칙 : X→Y가 성립하면 XZ → YZ
  3. 이행 규칙 : X → Y, Y → Z 이면 X → Z
  4. 결합 규칙 : X → Y, X→ Z 가 성립하면 X → YZ
  5. 분해 규칙 : X → YZ 가 성립하면 X → Y, X→ Z
  6. 유사이행 규칙 : X → Y, WY → Z 이면 WX → Z



1차 정규화 (1NF) - 반복 그룹 제거

제일 기본이에요. 한 칸에 하나의 값만 들어가야 한다는 규칙이죠.

예를 들어 회원 테이블에 전화번호를 여러 개 저장하고 싶다면?

회원번호 | 회원명 | 전화번호
C001    | 홍길동 | 010-1111-1111, 010-2222-2222  ❌ 이렇게 하면 안돼요!

이걸 1차 정규화하면 전화번호를 별도 테이블로 분리해야 해요.

제 1차 정규화

2차 정규화 (2NF) - 부분 함수 종속성 제거

이게 좀 헷갈렸는데, 강사님이 예를 들어주셔서 이해했어요.

주문 테이블에 (제품번호 + 주문번호)가 복합키인데, 제품명이나 제품 재고는 제품번호에만 의존하잖아요? 이런 걸 부분 종속이라고 하는데, 2차 정규화는 이걸 분리하는 거예요.

결과적으로 제품 정보는 제품 테이블로, 주문 정보는 주문 테이블로 깔끔하게 나뉘었어요!

제 2차 정규화

 

3차 정규화 (3NF) - 이행적 종속성 제거

3차는 "간접적인 의존관계"를 없애는 거예요.

주문 테이블에 회원번호가 있고, 회원번호로 회원명과 주소를 가져올 수 있다면? 회원명과 주소는 사실 주문번호에 직접 의존하는 게 아니라 회원번호를 거쳐서 의존하는 거잖아요. 이런 이행적 종속을 제거하는 게 3차 정규화예요.

제 3차 정규화

정규화의 핵심은 "중복 제거 + 논리적 분리"인 것 같아요!


2. 트랜잭션 - 데이터베이스의 안전장치

트랜잭션은 오늘 배운 것 중에 제일 중요한 개념이었어요. 쉽게 말하면 **"여러 개의 SQL을 하나로 묶어서 처리하는 것"**이에요.

ACID 속성

강사님이 "트랜잭션은 ACID를 만족해야 한다"고 하셨는데, 처음엔 무슨 말인지 몰랐어요. 근데 예제로 계좌 이체를 생각해보니까 이해가 됐어요!

[데이터베이스] 트랜잭션의 ACID 성질 - 하나몬

  • 원자성(Atomicity): 전부 성공 or 전부 실패
    • A계좌에서 출금 성공했는데 B계좌 입금 실패하면? 전체 취소! (rollback)
  • 일관성(Consistency): 데이터가 항상 일관된 상태
    • 계좌 이체 전후 총 금액은 같아야 해요
  • 고립성(Isolation): 트랜잭션끼리 간섭 안 함
    • 내가 돈 이체하는 중에 다른 사람이 내 잔액을 못 바꿔야죠
  • 지속성(Durability): 커밋되면 영구 저장
    • 서버가 꺼져도 데이터는 남아있어야 해요

실제 사용법

start transaction;  -- 트랜잭션 시작

insert into customer values (1, '홍길동');
insert into customer values (2, '이길동');

savepoint s1;  -- 중간 저장점

insert into customer values (3, '삼길동');

rollback to s1;  -- s1으로 되돌리기 (3번만 취소)

commit;  -- 최종 확정

savepoint가 진짜 유용한 게, 전체를 롤백하지 않고 중간 지점으로만 돌아갈 수 있다는 거예요!


3. 락(Lock) - 동시 접근 제어

이 부분이 좀 어려웠는데, 실습하면서 이해했어요.

락의 종류

  • 공유 락(S-Lock): 읽기 작업용
    • 여러 트랜잭션이 동시에 읽기 가능
    • 쓰기는 차단
  • 배타 락(X-Lock): 쓰기 작업용
    • 읽기/쓰기 모두 차단
    • 독점 사용

락 호환성 규칙

현재 락 공유 락 요청 배타 락 요청

제일 기억에 남는 건, MySQL은 ROW 단위로 락을 건다는 거예요. 컬럼 단위가 아니라요! 그래서 한 행을 수정 중이면 그 행의 다른 컬럼도 수정할 수 없어요.


4. 데드락 - 교착 상태

-- 터미널 1
start transaction;
update book set price = 8000 where bookid = 1;  -- 1번 락
update book set price = 8000 where bookid = 2;  -- 2번 대기...

-- 터미널 2
start transaction;
update book set price = 8000 where bookid = 2;  -- 2번 락
update book set price = 8000 where bookid = 1;  -- 1번 대기...

-- 결과: 서로 대기하다가 데드락!

🔒Mysql의 잠금(Lock)과 데드락(DeadLock) 발생


5. 격리 수준 - 동시성과 일관성의 균형

이 부분이 오늘 배운 것 중에 제일 헷갈렸어요. 하지만 각 레벨을 실습해보니까 차이가 명확하더라고요.

READ UNCOMMITTED (레벨 0)

set transaction isolation level read uncommitted;
start transaction;

select * from users where id = 1;  -- 30
-- 다른 트랜잭션이 20으로 update (커밋 안함)
select * from users where id = 1;  -- 20 (커밋 안됐는데 보임!)
-- 다른 트랜잭션이 rollback
select * from users where id = 1;  -- 30 (다시 원래 값)

Dirty Read 발생! 커밋 안 된 데이터를 읽어버려요. 

READ COMMITTED (레벨 1)

커밋된 데이터만 읽어요. Oracle 기본값이라고 하시더라고요. 하지만 Non-Repeatable Read 문제가 있어요. 같은 쿼리를 두 번 실행했는데 결과가 다를 수 있다는 거죠.

REPEATABLE READ (레벨 2) - MySQL 기본값

MySQL의 기본 격리 수준이에요! 트랜잭션 시작 시점의 스냅샷을 유지해서, 같은 쿼리는 항상 같은 결과를 반환해요.

start transaction;
select * from users where id = 1;  -- 30
-- 다른 트랜잭션이 20으로 update & commit
select * from users where id = 1;  -- 여전히 30!
commit;
select * from users where id = 1;  -- 이제 20

SERIALIZABLE (레벨 3)

완벽한 격리지만 너무 느려서 거의 안 쓴다고 하셨어요.

 


 

💡팁 & 복습 방법

1. 두 개의 터미널로 실습하기

트랜잭션이랑 락은 혼자서는 테스트하기 어려워요. 터미널 2개 띄워놓고 동시에 실행해보면서 락이 어떻게 걸리는지, 데드락은 언제 발생하는지 직접 확인하는 게 최고예요!

2. 노션에 표로 정리하기

특히 격리 수준이나 락 호환성 같은 건 표로 정리해두니까 한눈에 들어오더라고요. 저는 노션에 정리해뒀는데, 나중에 면접 준비할 때도 유용할 것 같아요.

3. 실제 서비스 상황으로 연결하기

"만약 쇼핑몰에서 마지막 1개 남은 상품을 여러 명이 동시에 구매하려고 하면?" 이런 식으로 실제 상황을 상상해보니까 왜 트랜잭션과 락이 필요한지 확실히 이해됐어요.

 



😊 좋았던 점

  1. 실습 위주 수업: 직접 코딩하면서 배우니까 이해 빠름
  2. 실무 경험 공유: "READ UNCOMMITTED는 절대 쓰지 마라" 같은 팁들이 좋았어요
  3. 체계적인 순서: 정규화 → 트랜잭션 → 락 → 격리수준 순서가 논리적이었어요

😅 아쉬웠던 점

  1. 시간 부족: 격리 수준 각각을 더 깊이 실습하고 싶었어요
  2. 예제 다양성: 회원-제품-주문만 계속 써서 아쉬웠어요
  3. 이론-실습 간격: 이론 듣고 바로 실습하면 더 좋을 것 같아요

🤔 어려웠던 점과 해결

문제 1: 2차 vs 3차 정규화 구분

"부분 종속성"이랑 "이행적 종속성" 뭔 소린지 모르겠더라고요.

해결: 테이블 그려서 화살표로 의존 관계 표시해봤어요. 시각화하니까 이해됨!

 

문제 2: 격리 수준 차이

READ COMMITTED랑 REPEATABLE READ가 뭐가 다른지 헷갈렸어요.

해결: 터미널 2개로 각각 실행해봤어요. 결과를 표로 정리하니까 명확해짐.

 

문제 3: 데드락 이해

"서로 대기한다"는 게 추상적이었어요.

해결: 업데이트 순서 바꿔가면서 여러 번 실습. 순서가 중요하다는 걸 깨달음!


📚 향후 과제

  1. 역정규화 개념 예습: 오늘 정규화를 배웠으니, 내일 배울 역정규화도 미리 찾아봐야겠어요.
  2. 트랜잭션 예제 더 만들어보기: 계좌 이체 말고 다른 예제(예: 좌석 예약, 재고 관리)도 직접 코드로 작성해보려고요.
  3. 격리 수준 실습 반복: 오늘 시간이 부족해서 못 한 부분을 집에서 더 연습해볼 거예요.
  4. 정규화 문제 풀어보기: 인터넷에서 정규화 연습 문제 찾아서 풀어보면서 확실히 다지려고요!

🎯 마무리하며

이번 주 정말 빡셌지만, 그만큼 배운 게 많은 하루였어요. 특히 "실무에서 어떤식으로 사용해야 하는가?"에 대한 답을 실습을 통해 직접 찾아가는 과정이 정말 재미있었어요.

데이터베이스가 단순 CRUD인 줄 알았는데, 동시 접근 제어나 일관성 유지가 이렇게 복잡한 줄 몰랐네요. 

같이 공부하시는 분들 화이팅! 💪