- AI와 빅데이터로 건설업계의 디지털 혁신을 이끄는 (주)산군의 Jun Kang입니다. 대규모 데이터 처리, DB 최적화, 확장 가능한 시스템 구축에 관심이 많으며, 개발팀의 건강하고 지속 가능한 성장 문화를 문화를 만들어가고 있습니다.
- 주요 관심사: Backend Development, Cloud Computing, DevOps, Database, AI, 개발 문화 형성
로그가 0줄인 것은 아무 일도 없었다는 뜻이 아니다
두 달 동안 관찰 모드로 돌려둔 기능이 있었다. 실제 차단은 하지 않고 “차단했을 것"만 로그로 남기는 방식이었다. 전환 시점이 되어 로그를 확인했더니 관련 로그가 한 줄도 없었다. 처음 든 생각은 “오탐이 0이구나, 안전하게 켜도 되겠다"였다. 다행히 켜기 전에 한 번 더 봤는데, 실제로는 오탐이 0이 아니라 관찰 결과가 한 시간 이상 남지 않는 상태였다. 로그를 매시간 비우는 크론이 따로 돌고 있었던 것이다. 두 달치 관찰을 했다고 믿었지만 실제로 본 것은 직전 몇십 분이었다. 그 뒤로 비슷한 유형을 몇 번 더 밟았고, 공통점이 있어서 정리해둔다. 전부 관찰 결과가 관찰 대상보다 먼저 사라지는 문제다. ...
console.log는 로깅이 아니다 — 운영에서 살아남는 로그 설계
배포 전에 지우는 로그 console.log를 잔뜩 박아두고 배포 직전에 전부 지워본 적이 있다면, 그건 로깅이 아니라 디버깅이다. 둘은 목적이 다른 별개의 활동이다. 디버깅 로깅 수명 일시적 영구적 시점 개발 중 운영 중에 더 중요 독자 사람 사람 + 기계 형식 자유 구조화 배포 시 삭제 남는다 운영에서의 로깅은 이런 요구를 만족시켜야 한다. 6개월 뒤에 누군가가 어제 새벽 2시에 무슨 일이 있었는지 검색할 수 있게 만드는 것. 그러려면 형식이 있어야 하고, 검색 가능해야 하고, 보관돼야 한다. 이 세 조건을 하나씩 짚어보려 한다. ...
[PostgreSQL] 트랜잭션 ID는 42억 개인데 왜 20억마다 freeze가 도는가
시작은 사소한 의문이었다 PostgreSQL의 트랜잭션 ID(XID)는 32비트다. 그러면 2^32, 약 42억 9천만 개를 쓸 수 있다. 그런데 운영 문서를 읽다 보면 기준선이 자꾸 20억 근처에서 잡힌다. autovacuum_freeze_max_age의 상한도 20억이고, wraparound 경고도 20억 언저리에서 나온다. 공간은 42억인데 왜 절반만 쓰는 걸까. “안전 마진이겠지” 하고 넘어갔다가, 마진치고는 너무 정확히 절반이라는 게 계속 걸렸다. 그래서 물어봤고, 답을 듣고 나니 이건 마진이 아니라 구조적으로 그 이상 쓸 수 없는 값이었다. 순환 카운터에는 “절대적인 전후"가 없다 핵심은 XID가 단조 증가하는 값이 아니라 순환 카운터(circular counter) 라는 데 있다. 42억까지 올라가면 다시 0부터 시작한다. ...
PostgreSQL POSITION 함수로 문자열 내 위치 찾기
PostgreSQL에서 문자열 처리 작업을 하다 보면, 특정 단어가 문자열 안에 포함되어 있는지 또는 어느 위치에 있는지를 알아야 할 때가 있습니다. 이럴 때 유용하게 쓸 수 있는 함수가 바로 POSITION() 입니다. 1. POSITION 함수란? POSITION() 함수는 문자열 안에서 부분 문자열(substring)의 첫 번째 위치를 반환합니다. MySQL의 LOCATE(), Oracle의 INSTR()와 비슷한 역할을 합니다. `POSITION(substring IN string)` 리턴값: 부분 문자열이 시작하는 위치 (1부터 시작) 찾지 못하면: 0 반환 2. 기본 예제 SELECT POSITION('abc' IN '123abc456'); -- 4 SELECT POSITION('zzz' IN '123abc456'); -- 0 'abc'는 네 번째 문자에서 시작하므로 4를 반환합니다. 'zzz'는 존재하지 않기 때문에 0이 나옵니다. ...
[Spring] 스프링부트와 HikariCP를 활용한 Connection Pool 설정 및 최적화
몇 년 전 운영 프로젝트 설정 시 자세하게 봤던 내용이지만, 트래픽이 대폭 증가하고, DBMS에 연결된 프로젝트와 모듈이 늘어남에 따라 재설정을 위해 개념을 다시 정리하게 되었다. 1. 기본적인 데이터베이스 연결과정 DB Connection 열기- 데이터베이스 드라이버를 사용하여 데이터베이스 서버와의 연결 TCP 소켓 열기 - 데이터베이스 전송을 위해 TCP 소켓을 생성하고 데이터베이스 서버와 통신채널을 설정 데이터 통신 수행 - 생성된 소켓을 통해 SQL 쿼리를 전송하고 데이터를 Read / Write DB연결 닫기 - 데이터 통신이 완료되면 데이터베이스와의 연결을 종료 TCP 소켓 닫기 - 사용한 TCP 소켓을 닫아 통신 채널 해제 웹 어플리케이션은 클라이언트의 HTTP 요청이 들어오면 스레드를 생성한다. 각 요청 시 DB서버로부터 데이터를 얻기 위해서 DB에 지속적으로 접근하는 작업이 필요하다. 스프링부트를 예로 들면, DB에 직접 연결하는 경우, JDBC 드라이버는 애플리케이션 시작 시 한번 로드되고, 사용자 요청 시마다 새로운 connection 객체 생성하여 데이터베이스에 연결한 후 종료되어야 한다. 이렇게 사용자 요청 시 매번 connection 객체를 생성/연결/종료해야 한다면 굉장히 비효율적이다. ...