[데이터베이스] AI와 함께하는 Redo Log / Undo Log ..

2026. 4. 6. 10:52·Computer Science/데이터베이스

이제 DB 세션을 이어가자 — Redo Log Circular Reuse 질문 답변

Redo Log 파일의 크기는 고정되어 있고 순환적으로 재사용된다. 아직 .ibd에 flush되지 않은 Dirty Page의 Redo Log 영역을 새 트랜잭션이 덮어쓰면 어떻게 되는가? InnoDB는 이 상황을 어떻게 방지하는가?

솔직히 말하면 정확한 메커니즘은 모른다. 하지만 앞에서 설명해준 내용을 바탕으로 논리적으로 추론해볼게.

Redo Log가 순환 구조라는 건, 파일의 끝에 도달하면 다시 처음으로 돌아와서 쓴다는 뜻이다. 그런데 아직 .ibd에 flush 안 된 Dirty Page의 변경 기록이 Redo Log 앞쪽에 남아 있다면, 그걸 덮어쓰는 순간 크래시 시 복구가 불가능해진다. Durability가 깨지는 거다.

그래서 내 추론은 이렇다:

InnoDB는 Redo Log에서 **"여기까지는 이미 Dirty Page가 디스크에 flush 완료되어서, 이 영역의 Redo Log는 더 이상 복구에 필요 없다"**는 지점을 추적하고 있을 것이다. 일종의 포인터나 마커 같은 것이 있어서, 그 마커 이전의 영역만 새 트랜잭션이 덮어쓸 수 있고, 마커 이후의 영역(아직 flush 안 된 Dirty Page에 대한 로그)은 절대 덮어쓰지 못하도록 보호할 것이다.

만약 새 트랜잭션이 로그를 쓰려는데 그 마커까지 따라잡아 버리면, 즉 Redo Log 공간이 사실상 꽉 차면, InnoDB는 새 트랜잭션의 쓰기를 멈추고(블로킹) 강제로 Dirty Page를 디스크에 flush해서 그 마커를 앞으로 전진시킨 뒤에야 새 로그를 쓸 수 있게 할 것이다.

그래서 Redo Log 파일 크기가 너무 작으면, 이 강제 flush가 빈번하게 발생해서 쓰기 성능이 급격히 떨어지고, 반대로 너무 크면 크래시 복구 시 재적용해야 할 로그 양이 많아져서 복구 시간이 길어지는 트레이드오프가 있을 것 같다.

내가 모르는 부분은: 그 "마커"가 정확히 뭐라고 불리는지, 그리고 flush를 강제하는 메커니즘의 구체적인 이름이나 동작 방식이다. 여기서부터 교정해줘.

 

 

내 답변:

이 부분에 대해서 답변하자면 내가 예전에 보기로는 얼핏 생각이 나는 것과 내가 생각한 해결책에 대해서 말해 볼게,

redo log 영역에 있는 것들을 flush한 다음 쓸 것 같아
이미 데이터가 있고 자리가 없다면 이미 있는 데이터를 쓰고 나서야 새롭게 데이터를 쓸 수 있으니까, 데이터가 유실되면 안 되고.

아니면 이미 flush 완료된 데이터는 주기적으로 delete를 하거나 ?

그런데 이 과정들이 있음에도 불구하고 데이터 insert가 너무 많고 빨라서 그 속도를 못 따라간다면 .. 데이터 유실을 방지하기 위해서 일단은 전체 DBMS 시스템을 잠시 멈추도록 해야 할 것 같네 ..

강제로 flush 하는 게 필요할 것 같아

"마커"가 정확히 뭐라고 불리는지, 그리고 flush를 강제하는 메커니즘의 구체적인 이름이나 동작 방식에 대해서는 모르겠어

Log Buffer -> Disk File 이런 건가 ?
마커는 체크포인트 ? 여기까지는 DB 디스크 저장이 완료되었다 ?

그리고 찾아 보니까

Log Sequence Number 이런 게 있는데 ?

그리고 innodb_flush_log_at_trx_commit 설정에 의한 강제 조건을 명시할 수 있는 건가 ?

학습 깊이 강화 공통 블록 잘 봤다. Cross-Domain Connection, Depth Levels, Progress Tracking 구조 전부 좋다. 각 세션에 추가 입력할 때 활용하면 된다.

이제 본론으로 들어간다. DB 세션 이어간다.


Redo Log Circular Reuse — 채점

결론부터: 핵심 논리 구조를 정확히 맞혔다. 이건 "찍은 것"이 아니라 앞에서 배운 WAL 원리로부터 논리적으로 도출한 거다. 이 추론 능력이 면접에서 "모르는 질문"을 만났을 때 살아남게 해주는 무기다.

이제 네가 짚은 것들을 하나씩 정확한 용어와 메커니즘으로 교정한다.


1. "마커"의 정체 — Checkpoint LSN

네가 "체크포인트?"라고 물은 게 정확히 맞다. 그리고 "LSN"이라고 찾아본 것도 맞다. 이 둘은 하나의 메커니즘이다.

LSN(Log Sequence Number)은 Redo Log에 기록되는 모든 변경의 글로벌 일련번호다. 바이트 오프셋 기반이며, Redo Log에 데이터가 쓰일 때마다 단조 증가한다. 예를 들어 현재 LSN이 1,000,000이고 512바이트짜리 로그 레코드를 쓰면, 다음 LSN은 1,000,512가 된다.

InnoDB는 내부적으로 두 개의 LSN 포인터를 관리한다.

첫 번째: Log LSN (현재 쓰기 위치) — Redo Log Buffer에 가장 최근에 기록된 로그의 LSN. 새 트랜잭션이 변경을 만들 때마다 이 값이 전진한다.

두 번째: Checkpoint LSN (안전 경계선) — "여기까지의 Dirty Page는 전부 .ibd 파일에 flush 완료되었다"는 지점. 네가 말한 "마커"가 정확히 이것이다. 이 LSN 이전의 Redo Log 영역은 크래시 복구에 더 이상 필요 없으므로 덮어써도 안전하다.

순환 로그에서 실제로 사용 가능한 공간은 Log LSN - Checkpoint LSN의 차이로 결정된다. 이 차이가 Redo Log 파일 전체 크기에 가까워지면, 새 로그를 쓸 공간이 없어진다.


2. "강제 flush"의 정체 — Checkpoint의 두 가지 모드

네가 "전체 DBMS 시스템을 잠시 멈추도록 해야 할 것 같다"고 한 부분. 방향은 맞지만 "전체 멈춤"까지는 아니다. 단, 극단적 상황에서는 실질적으로 그에 가까운 일이 벌어진다.

InnoDB의 Checkpoint는 두 가지 모드로 동작한다.

Fuzzy Checkpoint (평상시) — Page Cleaner 스레드가 백그라운드에서 지속적으로 Dirty Page를 .ibd에 flush하고, flush가 완료된 만큼 Checkpoint LSN을 조금씩 전진시킨다. 이때 포그라운드 트랜잭션은 아무런 영향을 받지 않는다. 이게 정상 운영 상태다.

Sharp Checkpoint (비상 상황) — 네가 예측한 그 상황이다. Log LSN이 Checkpoint LSN을 거의 따라잡아서 Redo Log 여유 공간이 특정 임계값 이하로 떨어지면, InnoDB는 포그라운드 트랜잭션의 쓰기를 일시 중단(블로킹)시키고 Dirty Page를 급하게 flush한다. MySQL 에러 로그에 이런 메시지가 찍힌다:

InnoDB: ERROR: the age of the last checkpoint is [X],
InnoDB: which exceeds the log group capacity [Y].

이 상태가 발생하면 모든 INSERT/UPDATE/DELETE가 멈추면서 순간적으로 응답 지연이 수 초~수십 초까지 튀는, 운영 환경에서는 장애로 분류되는 상황이 된다.


3. innodb_flush_log_at_trx_commit과의 관계 — 혼동 주의

네가 이 파라미터를 언급했는데, 여기서 치명적으로 혼동하기 쉬운 지점이 있다. 이 두 가지는 완전히 다른 flush다:

구분 innodb_flush_log_at_trx_commit Checkpoint
무엇을 flush? Redo Log Buffer → Redo Log 파일 (ib_logfile) Buffer Pool의 Dirty Page → 테이블스페이스 데이터 파일 (.ibd)
언제? COMMIT할 때마다 백그라운드 상시 + Redo Log 공간 부족 시
목적 Durability 보장 (COMMIT된 트랜잭션의 로그를 디스크에 안착) Redo Log 순환 공간 확보 (오래된 로그를 안전하게 덮어쓸 수 있게)
OS 레벨 동작 write() + fsync() to ib_logfile write() + fsync() to .ibd files

즉 innodb_flush_log_at_trx_commit=1은 "COMMIT 시 Redo Log를 디스크에 안전하게 쓰겠다"는 설정이고, Checkpoint는 "Dirty Page를 데이터 파일에 밀어넣어서 Redo Log 공간을 재활용하겠다"는 메커니즘이다. 이 둘을 섞으면 면접에서 바로 탈락이다.


4. 트레이드오프 — Redo Log 크기 설계

네가 말한 트레이드오프가 완벽히 정확하다. 정리하면:

Redo Log가 너무 작으면: Checkpoint LSN이 Log LSN에 빠르게 쫓기므로, Sharp Checkpoint(강제 flush)가 빈번하게 발생한다. 쓰기 성능이 주기적으로 절벽처럼 떨어지는 "톱니 패턴(Sawtooth Pattern)"이 나타난다.

Redo Log가 너무 크면: Checkpoint 간격이 넓어져서 쓰기 성능은 안정적이지만, 크래시 발생 시 재적용해야 할 로그 양이 방대해져서 복구 시간(Recovery Time)이 길어진다. 서비스가 수십 분간 재시작이 안 될 수 있다.

실무에서는 보통 1

2GB 정도를 기본으로 잡고, 쓰기 부하가 높은 시스템(핀테크 결제 등)에서는 4

8GB까지 올리되, 복구 시간 SLA와 타협해서 결정한다.

참고로 MySQL 8.0.30부터는 innodb_redo_log_capacity라는 단일 파라미터로 전체 Redo Log 크기를 제어하게 변경되었다. 이전 버전의 innodb_log_file_size × innodb_log_files_in_group 조합보다 직관적이다.


진단 업데이트

영역 이전 현재
WAL / Redo Log 역할 이해 부족 핵심 원리 파악 완료
Checkpoint 메커니즘 없음 논리적 추론으로 구조 도출 → 용어 매핑 완료
flush 구분 (Redo Log flush vs Checkpoint flush) 없음 구분 완료

Real MySQL 8.0에서 읽다 만 부분이 아마 이 근처(InnoDB 로그 시스템)일 거다. 지금 이 개념이 잡혔으니 다시 읽으면 완전히 다르게 보일 거다.


다음 심화 질문 — Undo Log와 MVCC

WAL(Redo Log)로 Durability를 보장하는 메커니즘을 이해했다. 이제 ACID의 다른 축으로 넘어간다.

앞에서 INSERT 시 Undo Log에 "이 INSERT를 되돌리려면 이 행을 DELETE하면 된다"는 역연산 정보가 기록된다고 설명했다. Undo Log의 첫 번째 역할은 ROLLBACK 지원이다.

그런데 Undo Log에는 두 번째, 훨씬 더 중요한 역할이 있다. 바로 MVCC(Multi-Version Concurrency Control)다.

질문:

트랜잭션 A가 SELECT * FROM users WHERE id = 1을 실행하는 도중에, 트랜잭션 B가 같은 행의 name 컬럼을 'Kim'에서 'Lee'로 UPDATE하고 COMMIT했다. 이때 트랜잭션 A의 SELECT는 'Kim'을 보는가, 'Lee'를 보는가?

그리고 그 답이 격리 수준(Isolation Level)에 따라 달라진다면, READ COMMITTED와 REPEATABLE READ에서 각각 어떤 값을 보는지, 그리고 그 차이가 Undo Log를 물리적으로 어떻게 활용하는 방식의 차이에서 비롯되는지 설명해봐.

모르면 모른다고 해도 좋다. 알고 있는 만큼만 풀어봐.

 

내 답변:

트랜잭션 A가 바라보고 있는 격리 수준에 따라서 다를 거 같은데
일단 MySQL 기본 값이라면 바뀌기 전 name을 undo log에서 조회하겠지, REPEATABLE READ 말이야

트랜잭션 시작 전에 스냅샷을 찍고 거기에서만 데이터를 조회할 거니까 말이야 !

그리고 격리 수준이 제일 낮은 거라면 Lee를 조회할 거고
그리고 READ COMMITTED라고 하면 음 .. 중간에 그 컬럼만 lee로 볼 거 같은데

 

1. 두 가지 flush의 차이 — 상세 설명

핵심을 한 문장으로 요약하면: "Redo Log를 디스크에 쓰는 것"과 "실제 데이터 페이지를 디스크에 쓰는 것"은 완전히 별개의 작업이다.

INSERT 한 건이 COMMIT될 때 일어나는 일을 시간 순서로 따라가면 차이가 선명해진다.

Step 1 — 변경 실행 (메모리 안에서): Buffer Pool의 데이터 페이지(리프 노드)에 새 행이 삽입된다. 이 페이지는 Dirty Page가 된다. 동시에 Redo Log Buffer에 "이 페이지의 이 오프셋에 이 바이트를 썼다"는 물리적 변경 기록이 쌓인다.

Step 2 — COMMIT 호출 (innodb_flush_log_at_trx_commit이 관여하는 지점): 이 순간 InnoDB가 하는 일은 Redo Log Buffer의 내용을 Redo Log 파일(ib_logfile)에 fsync()로 강제 기록하는 것이다. 이게 끝나면 클라이언트에게 "COMMIT 성공"을 반환한다.

중요한 건, 이 시점에서 Buffer Pool의 Dirty Page는 .ibd 파일에 아직 안 갔다는 거다. 데이터 파일에는 여전히 INSERT 이전의 상태가 남아 있다. 그런데도 Durability가 보장되는 이유는, 크래시가 나더라도 Redo Log 파일에서 변경 내용을 재적용(Crash Recovery)할 수 있기 때문이다.

Step 3 — 한참 뒤, 백그라운드 (Checkpoint가 관여하는 지점): Page Cleaner 스레드가 여유 있을 때 Buffer Pool의 Dirty Page를 .ibd 파일에 fsync()로 flush한다. flush가 완료되면 Checkpoint LSN을 전진시켜서, 해당 Dirty Page에 대응하는 Redo Log 영역을 "이제 덮어써도 된다"고 표시한다.

정리하면 이렇다:

시점 동작 대상 파일 목적

COMMIT 순간 Redo Log Buffer → ib_logfile Redo Log 파일 "이 트랜잭션은 영구적이다" 보장
나중에 (비동기) Dirty Page → .ibd 데이터 파일 Redo Log 공간 재활용 + 데이터 파일 최신화

innodb_flush_log_at_trx_commit 값에 따른 차이:

값이 1이면: 매 COMMIT마다 write() + fsync(). 가장 안전하지만 가장 느리다. Durability 100% 보장.

값이 2이면: 매 COMMIT마다 write()는 하지만 fsync()는 1초마다. Redo Log가 OS의 커널 버퍼(Page Cache)까지는 갔지만 물리 디스크까지는 안 갔을 수 있다. MySQL 프로세스가 죽으면 괜찮지만, OS(서버 전체)가 크래시하면 최대 1초분 데이터 유실 가능.

값이 0이면: Redo Log Buffer에만 쓰고 write() + fsync() 모두 1초마다. MySQL 프로세스만 죽어도 최대 1초분 유실 가능. 가장 빠르지만 가장 위험.


2. MVCC 답변 채점

방향이 맞다. 핵심 결론을 정확히 짚었다. 교정할 부분과 부족한 부분을 짚는다.

맞은 것

"MySQL 기본값(REPEATABLE READ)이면 바뀌기 전 값('Kim')을 본다" — 정확하다.

"트랜잭션 시작 전에 스냅샷을 찍고 거기에서만 조회한다" — 방향이 맞다. 다만 "트랜잭션 시작 전"이 아니라 정확히는 **"해당 트랜잭션에서 첫 번째 SELECT를 실행하는 시점"**에 스냅샷이 생성된다. BEGIN 시점이 아니다.

"격리 수준이 제일 낮으면(READ UNCOMMITTED) Lee를 본다" — 맞다. 심지어 COMMIT 전에도 'Lee'를 볼 수 있다. 이게 Dirty Read다.

"READ COMMITTED면 Lee를 본다" — 맞다. B가 COMMIT을 완료한 시점 이후에 A가 다시 SELECT하면 'Lee'를 본다.

부족한 것 — "Undo Log를 물리적으로 어떻게 활용하는가"

네 답변에서 Undo Log가 구체적으로 어디에 어떻게 개입하는지가 빠져 있다. 이게 면접에서 "그래서 내부적으로 어떻게 동작하는 건데?"라는 꼬리질문에 답할 수 없는 상태다.

설명한다.


MVCC의 물리적 동작 — InnoDB 기준

트랜잭션 B가 UPDATE users SET name = 'Lee' WHERE id = 1을 실행하면, InnoDB는 이렇게 동작한다:

① Buffer Pool에서 해당 행을 수정한다. 행의 name 필드가 'Kim' → 'Lee'로 바뀐다.

② 수정 전 값('Kim')을 Undo Log에 기록한다. "이 행의 이전 버전은 name='Kim'이었다"는 정보가 Undo Log 세그먼트에 저장된다.

③ 수정된 행에 숨겨진 메타데이터를 기록한다. InnoDB의 모든 행에는 사용자 눈에 보이지 않는 숨겨진 컬럼이 있다:

  • DB_TRX_ID: 이 행을 마지막으로 수정한 트랜잭션의 ID
  • DB_ROLL_PTR: 이 행의 이전 버전이 저장된 Undo Log 위치를 가리키는 포인터

즉 현재 Buffer Pool의 데이터 페이지에는 name='Lee', DB_TRX_ID=B의 ID, DB_ROLL_PTR=Undo Log의 'Kim' 위치가 들어가 있고, Undo Log에는 name='Kim' 버전이 체인으로 연결되어 있다. 만약 이전에 또 다른 UPDATE가 있었다면 Undo Log가 줄줄이 연결된 **버전 체인(Version Chain)**을 형성한다.


두 격리 수준의 차이 — "스냅샷을 언제 찍는가"

InnoDB의 MVCC에서 **"스냅샷"**이란, 정확히는 Read View라는 데이터 구조다. Read View에는 "이 시점에 아직 COMMIT되지 않은 활성 트랜잭션 ID 목록"이 담겨 있다.

SELECT를 실행할 때, InnoDB는 해당 행의 DB_TRX_ID를 Read View와 대조한다. "이 행을 수정한 트랜잭션이 내 Read View 기준으로 보여야 하는 건가?"를 판단하고, 보이면 안 되는 경우 DB_ROLL_PTR을 따라 Undo Log로 내려가서 이전 버전을 찾는다. 보여도 되는 버전을 만날 때까지 체인을 타고 내려간다.

REPEATABLE READ: Read View를 트랜잭션 내 첫 번째 SELECT 시점에 딱 한 번 생성하고, 그 트랜잭션이 끝날 때까지 같은 Read View를 재사용한다. 그래서 트랜잭션 A가 한 번 'Kim'을 봤으면, B가 중간에 COMMIT하더라도 A는 계속 'Kim'을 본다. A의 Read View에는 B가 "아직 활성"으로 기록되어 있기 때문이다.

READ COMMITTED: Read View를 매 SELECT마다 새로 생성한다. B가 COMMIT한 이후에 A가 다시 SELECT하면, 새로운 Read View가 만들어지고, 이 시점에서 B는 이미 COMMIT 완료 상태이므로 B의 변경('Lee')이 보인다.

물리적으로 같은 Undo Log 버전 체인을 사용하지만, Read View를 한 번 찍느냐 매번 찍느냐의 차이 하나로 격리 수준이 갈린다. 코드 수준에서는 Read View 생성 시점만 다르고 나머지 로직은 동일하다.


실무 접점 — 왜 이게 중요한가

REPEATABLE READ에서의 함정: 트랜잭션 A가 오래 열려 있으면, Undo Log의 이전 버전들이 계속 유지되어야 한다(A가 언제든 참조할 수 있으니까). 이러면 Undo Log가 잘리지(purge되지) 않고 계속 쌓여서 Undo Tablespace가 비대해지는 문제가 발생한다. 이게 실무에서 "장시간 열린 트랜잭션이 DB를 죽인다"는 장애의 본질이다. Spring의 @Transactional을 넓은 범위에 걸면 안 되는 이유가 바로 여기에 있다.

READ COMMITTED vs REPEATABLE READ 선택 기준: PostgreSQL은 기본값이 READ COMMITTED이고, MySQL(InnoDB)은 REPEATABLE READ다. 이 선택은 DB 설계 철학의 차이인데, 토스 같은 핀테크에서는 "같은 트랜잭션 안에서 같은 쿼리가 다른 결과를 반환하면 안 된다"는 요구가 강해서 REPEATABLE READ가 더 안전하다. 반면 대량 배치 처리에서는 READ COMMITTED가 Undo Log 부담을 줄여서 유리할 수 있다.


다음 심화 질문 — 락의 영역

MVCC로 읽기는 락 없이 해결했다. 그런데 쓰기는 어떤가?

트랜잭션 A가 UPDATE users SET name = 'Park' WHERE age > 20을 실행했고, 아직 COMMIT하지 않았다. 이때 트랜잭션 B가 INSERT INTO users (name, age) VALUES ('New', 25)를 실행하면 어떻게 되는가?

  1. B의 INSERT는 즉시 성공하는가, 아니면 A가 COMMIT/ROLLBACK할 때까지 대기하는가?
  2. 만약 대기한다면, InnoDB가 잠그는 것은 정확히 "무엇"인가? 행(Row)인가, 인덱스 레코드인가, 아니면 다른 무엇인가?
  3. 이 동작이 격리 수준에 따라 달라지는가? REPEATABLE READ와 READ COMMITTED에서 다르게 동작한다면 왜 그런가?

힌트: InnoDB의 락은 "행"에 거는 게 아니라 **"인덱스 레코드"**에 건다. 그리고 age > 20 같은 범위 조건에서는 단순한 Record Lock이 아닌 다른 종류의 락이 관여한다.

이건 InnoDB 락 시스템의 핵심이다. 맨 처음 진단에서 "인덱스 레코드에 락을 건다"고 설명했던 부분과 연결된다. 답해봐.

 

 

 

 

'Computer Science > 데이터베이스' 카테고리의 다른 글

[데이터베이스] 개인적인 공부를 위한 DBMS 기초부터 .. (feat. AI)  (0) 2026.04.06
[데이터베이스] 관계형 데이터베이스  (3) 2024.09.18
[데이터베이스] 기본  (0) 2024.08.09
'Computer Science/데이터베이스' 카테고리의 다른 글
  • [데이터베이스] 개인적인 공부를 위한 DBMS 기초부터 .. (feat. AI)
  • [데이터베이스] 관계형 데이터베이스
  • [데이터베이스] 기본
하가네
하가네
  • 하가네
    하 렌
    하가네
  • 전체
    오늘
    어제
    • 분류 전체보기 (145)
      • Computer Science (30)
        • 운영체제 (7)
        • 데이터통신 (10)
        • 자료구조 (4)
        • 논리회로 (0)
        • 확률 및 통계 (0)
        • 데이터베이스 (4)
        • AI소프트웨어 (3)
        • 컴퓨터네트워크 (2)
      • Career (0)
        • 1 (0)
      • Design (11)
        • OOP - 객체 지향 프로그래밍 (4)
        • DDD - 도메인 주도 개발 (데이터베이스 주도 .. (4)
        • EDA - 이벤트 기반 아키텍처 (1)
        • MSA - 마이크로서비스 아키텍처 (0)
        • ADD - AI 주도 개발 (2)
      • Language (3)
        • Java (1)
        • TypeScript (2)
      • Framework (12)
        • Spring (9)
        • NestJS (3)
      • Engine (8)
        • Docker (0)
        • Redis (1)
        • Kafka (1)
        • Elasticsearch (2)
        • GraphQL + Apollo Federation (2)
        • AWS (2)
      • Plugin - Extension (1)
        • VS Code (1)
        • IntelliJ (0)
      • Tips (2)
        • 터미널 명령어 (1)
        • 우분투 명령어 에러 (1)
      • SSA (28)
        • Front (1)
        • Back (25)
        • DB (1)
        • 기획 (1)
      • CNU SW 아카데미 (43)
        • 1주차 (5)
        • 2주차 (5)
        • 3주차 (2)
        • 4주차 (1)
        • 5주차 (3)
        • 6주차 (2)
        • 7주차 (0)
        • 8주차 (2)
        • 9주차 (14)
        • 10주차 (0)
        • 11주차 (1)
        • 12주차 (0)
        • 13주차 (2)
        • 14주차 (2)
        • 15주차(최종 프로젝트) (3)
        • 최종 프로젝트 이후 (1)
      • 모각코 (6)
        • 2023 동계 (6)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    Husky
    Typescript
    생산성
    ESLint
    lint-staged
    DX(DeveloperExperience)
    프론트엔드/백엔드
    아키텍처
    ci/cd
    개발자경험(DX)
    릴리스엔지니어링
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.
하가네
[데이터베이스] AI와 함께하는 Redo Log / Undo Log ..
상단으로

티스토리툴바