본문 바로가기

전체 글

(40)
[DB] 데이터베이스와 색인(hash, LSM tree) 데이터베이스와 색인 데이터베이스의 기본은 특정 데이터를 write & read 하는 데 있다. 값을 특정 저장소에 넣어두고 필요할 때 꺼내쓰는 것이다. 일반적으로 하나의 파일 끝에 write만 하는 작업은 매우 효율적이기 때문에 많은 데이터베이스가 내부적으로 추가 전용(append-only) 데이터 파일인 로그(log)를 사용한다. 하지만 원하는 데이터 값을 읽어오려면 전체 파일을 스캔해서 찾아와 읽어야 한다. 검색 비용이 O(n)이다. read를 효율적으로 수행하기 위해서 색인(index)라는 데이터 구조가 필요하다. 하지만 별도의 index를 관리해야 하기 때문에 특히 write 할 때 오버헤드가 발생한다. 이러한 작업은 단순히 파일 끝에 write 하는 것보다 쓰기 속도를 느리게 한다. 데이터를 ..
Spring boot 도커 hub에 올리고 로컬 DB(MySQL)와 연동하기(feat. github actions) Spring Boot(2.7.11)와 MySQL(8.0.32) 기반으로 애플리케이션을 만들기로 했다. 이 때 github actions를 활용해 CI/CD(CD까진 아니고 deploy를 하기 위한 환경을 준비했다고 해두자) 이 때 다음과 같은 요구사항을 만족하고자 했다. 전제 조건: github에 올린 소스를 clone 받아서 로컬 MySQL 서버와 연동하는 것이 아니라 docker hub에 업로드 한 app image를 pull 받아서 로컬에 이미 설치해 둔 MySQL과 연동한다. 이는 배포한 docker image를 다른 개발자들이 pull 받아서 로컬 MySQL 서버와 연동해 테스트하기 위함이다. 1. spring app은 docker image로 만들어 docker hub에 push 한다. 2. ..
[DB] 트랜잭션(3) - 격리 수준과 동시성 문제, 그 해결 [DB] 트랜잭션(1) - ACID와 격리 수준(isolation level) [DB] 트랜잭션(2) - repeatable read 격리 수준에서의 phantom read 현상 [DB] 트랜잭션(3) - 격리 수준과 동시성 문제, 그 해결 이전 글에서 트랜잭션과 격리성을 살펴보았다. 트랜잭션은 작업의 완전성을 보장하기 위한 개념이다. 격리성은 각 트랜잭션이 다른 트랜잭션에 영향을 받지 않게 하려는(즉, 동시성 문제를 해결하려는) 개념이다. 가장 엄격한 격리성은 직렬로 모든 트랜잭션을 처리하는 것이다. 그런데 가장 엄격한 격리성은 동시성 문제를 해결하기 보다는 동시성 문제를 아예 회피하는 전략이다. 이는 동시성의 단점을 배제하고자 그 장점을 모두 버린 해결책이다. 이는 성능 문제를 야기했다. 격리 수..
[DB] 트랜잭션(2) - repeatable read 격리 수준에서의 phantom read 현상 [DB] 트랜잭션(1) - ACID와 격리 수준(isolation level) [DB] 트랜잭션(2) - repeatable read 격리 수준에서의 phantom read 현상 [DB] 트랜잭션(3) - 격리 수준과 동시성 문제, 그 해결 이전 글에서 repeatable read는 팬텀 리드 현상이 발생한다고 하였다. 조금 더 자세히 살펴보자. Phantom Read 현상 위 예제에서 B 트랜잭션이 emp_no >= 500000 을 select for update를 통해 명시적인 read/write lock을 걸었다. 하지만 A트랜잭션에서 emp_no이 500001인 데이터(B 트랜잭션 입장에서는 현재 존재하지 않는 데이터)를 insert 하고 있다. A 트랜잭션이 락을 거는 시점에 존재하지 않는 ..
[DB] 트랜잭션(1) - ACID와 격리 수준(isolation level) [DB] 트랜잭션(1) - ACID와 격리 수준(isolation level) [DB] 트랜잭션(2) - repeatable read 격리 수준에서의 phantom read 현상 [DB] 트랜잭션(3) - 격리 수준과 동시성 문제, 그 해결 트랜잭션과 격리 수준에 대해서는 여러 책과 블로그 등에서 상세히 다루고 있으므로 개념을 살펴보진 않으려 한다. 간단하게만 짚고 넘어가면 다음과 같다. 트랜잭션 - 작업의 완전성을 보장해준다. 즉, 논리적인 작업 셋이 모두 성공(commit)하거나 실패(abort, rollback)하도록 보장한다. - '데이터 중심 애플리케이션 설계' 책에서는 트랜잭션이 제공하는 안전성 보장을 흔히 ACID로 알려져 있다고 말하지만, 그 개념은 데이터베이스에 따라 제각각이고 개념 ..
HikariCP - max lifetime과 DB wait_timeout의 관계 이전 글에서 maximum pool size와 db max connections size의 관계를 살펴보면서, HikariCP의 maximum pool size를 어떻게 조정해야 좋은지 살펴보았다. pool size를 조정하는 것은 db와 connection을 맺은 connection을 얼마나 관리할 것인가에 관심이 있다면, 이제 살펴볼 max lifetime은 pool에서 관리할 connection의 생명주기를 어떻게 가져갈 것인가 하는 문제에 관심이 있다. max lifetime은 어떻게 설정해야 할까? 다음 블로그 글에서 max lifetime 설정에 대해서 자세히 설명하고 있다. 결론부터 말하자면 max lifetime의 값을 db wait_timeout 보다 최소 2~5초는 짧게 설정하는 것이 ..
HikariCP - maximum pool size와 DB max_connections의 관계 Maximum pool size는 어떻게 조정해야할까? HikariCP maximum pool size 설정 시 어떤 것을 고려해야 하나 찾아보던 차에 잘 정리된 블로그 글을 발견했다. connection pooling을 해주는 HikariCP가 사용자의 요청(thread)에 대해 어떻게 connection을 관리하는지 알 수 있었고, 할당된 thread 수에 따라 maximum pool size를 어떻게 조정하면 좋은지도 알 수 있었다. 위 글에서 설명된 maximum pool size 설정값은 HikariCP 공식 github의 wiki에 잘 정리되어 있다. 대강 정리하면 다음과 같다. - connection pool 사이즈를 CPU 코어에 맞게 조정하면 성능 향상을 볼 수 있다. (다른 변경 사항 ..
비밀번호는 왜 해시 함수를 이용해 암호화를 할까?(feat. 디피 헬만 키 교환) 개요 어떤 사이트에 접속해서 아이디와 패스워드를 입력해 가입을 한 뒤 로그인을 한다고 가정해보자. 아이디와 비밀번호라는 개인정보가 모두 공개되지 않으면 좋겠지만, 아이디는 비교적 공개되어도 되는 데이터에 가깝다. 하지만 비밀번호는 절대 공개되어선 안되는 데이터다. 심지어 웹사이트를 관리하는 관리자조차도 비밀번호를 함부로 알아선 안된다. 그렇지만 사용자가 로그인을 하기 위해선 회원가입 시에 입력한 비밀번호의 값을 서버 저장소에 보관한 뒤, 로그인 시에 입력하는 비밀번호가 저장된 비밀번호와 일치하는지 확인하는 작업이 필요하다. 보통 비밀번호는 평문 자체를 저장하지 않고 암호화한 임의의 값을 저장한다. 여기에서 핵심은 다음과 같다. 데이터를 한방향으로만 흐르게 해야 한다. 임의의 값으로 암호화하는 작업은..