728x90

이전 이야기 : https://thepin.tistory.com/211 

제10화. 눈빛의 끝, 사람의 시작

계절이 두 번 바뀌었다.

그날의 ‘30만 접속 대란’은 넥솔브 개발팀의 전설이 되었다. 우리는 그 위기를 넘긴 후에도 수많은 버그와 싸웠고, 크고 작은 장애를 겪었다. 하지만 더 이상 누구도 서로를 탓하거나 절망하지 않았다.

우리에겐 시스템이 있었고, 서로에 대한 신뢰가 있었으니까.

“이한결 대리, 이번 분기 우수 사원 표창 축하해.”

박성우 팀장이 꽃다발을 건넸다. 사무실에 박수 소리가 울려 퍼졌다. 나는 얼떨떨한 표정으로 상패를 받아 들었다.

‘우수 사원 이한결.’

금박으로 새겨진 내 이름이 낯설게 빛났다. 1년 전, 면접장에서 ‘짐만 될 것’이라는 소리를 듣던 내가, 이제는 팀의 중심이 되어 있었다.

나는 화장실 거울 앞에 섰다. 찬물로 세수를 하고 고개를 들었다.

거울 속의 남자가 나를 쳐다보고 있었다. 나는 눈을 크게 뜨고 내 동공을 들여다보았다.

‘나와라.’

마음속으로 명령했다. 예전 같으면 감정이 요동칠 때마다 제멋대로 튀어나와 나를 집어삼키려던 보라색 광채였다.
하지만 지금은 고요했다. 깊은 갈색 눈동자는 잔잔한 호수처럼 흔들림이 없었다.

능력이 사라진 건 아니었다. 나는 느낄 수 있었다. 내 의식 깊은 곳, 아주 깊은 심연에 그 힘이 얌전히 웅크리고 있다는 것을. 언제든 내가 원하면 다시 꺼내어 세상을 속일 수 있다는 것을.

하지만 이제는 내가 주인이다. 내가 부르지 않는 한, 그것은 절대 수면 위로 올라오지 못한다.
나는 더 이상 불안이나 공포 때문에 능력을 꺼내 들지 않는다. 나를 지킬 무기는 이제 초능력이 아니다.
수천 번의 커밋(Commit), 수만 줄의 코드, 그리고 나와 등을 맞대고 있는 동료들. 그것들이 나를 지탱하는 진짜 힘이었다.


“아… 어떡하지?”

자리로 돌아오는데, 파티션 너머에서 절망에 가까운 앓는 소리가 들렸다. 지난달에 들어온 신입 사원, ‘김민재’였다. 그는 망분리 PC 앞에서 모니터를 부여잡고 사색이 되어 있었다.

“민재 씨, 무슨 일이야?”

내가 다가가자 민재 씨가 화들짝 놀라며 일어났다.

“대, 대리님! 죄송합니다! 제가… 제가 사고 친 것 같습니다.”

그의 얼굴은 1년 전의 나처럼 하얗게 질려 있었다. 핏기가 가신 입술이 파르르 떨렸다.

“데이터 추출 요청이 와서, 가이드대로 망분리 PC에서 운영 DB 조회 쿼리를 실행했는데… 쿼리가 끝나지도 않고, 관련 어드민 페이지가 전부 멈췄습니다.”

그의 눈동자는 공포로 가득 차 있었다. ‘내가 운영 서버를 죽였구나.’ 그 생각에 짓눌려 숨도 제대로 쉬지 못하는 듯했다.

옆자리의 최 주임이 혀를 찼다.

“야, 김민재. 너 또 WHERE 절 빼먹고 돌린 거 아니야? 사고 쳤네, 쳤어.”

최 주임의 목소리가 커지자 사무실의 시선이 집중됐다. 민재 씨는 금방이라도 울음을 터뜨릴 것 같았다.

나는 민재 씨의 어깨를 가볍게 눌러 자리에 앉혔다.

“괜찮아. 일단 심호흡부터 해.”

내 목소리에 그가 고개를 들었다. 나는 그의 눈을 피하지 않고 똑바로 마주 보았다. 과거의 나라면, 이 공포를 지우기 위해 능력을 썼을지도 모른다. 하지만 지금은 아니었다.

“하지만… 제가 다 망쳤습니다….”

“아니, 아직 아무것도 안 망쳤어. 네가 죽인 거 아니야. 같이 보자.”

나는 민재 씨 옆에 의자를 끌어와 앉았다. 터미널에 남아있는 쿼리 기록을 확인했다. JOIN이 여러 개 걸린 복잡한 SELECT 문이었다.

“음, 이 정도면 신입이 짜기엔 꽤 복잡한 쿼리인데. 아마 인덱스를 타지 못해서 풀 스캔(Full Scan)이 도는 바람에 DB에 부하가 간 것 같아. 락(Lock)이 걸린 거지.”

“그럼… 어떻게 해야 합니까?”

“DBA팀에 바로 연락해서, 지금 돌고 있는 이 쿼리 세션 좀 강제 종료해달라고 요청해야 해. 내가 같이 연락해줄게.”

나는 사내 메신저로 DBA팀 그룹에 메시지를 보냈다.
[개발2팀 이한결] 안녕하세요. 신입사원 교육 중 실수로 부하가 큰 쿼리가 실행되어 운영 DB에 락이 걸린 것으로 보입니다. 관련 세션 확인 및 프로세스 킬 부탁드립니다. 쿼리 내용은 아래와 같습니다.

몇 분 뒤, DBA팀으로부터 회신이 왔다.
[DBA팀] 조치 완료했습니다. 확인해주세요.

“어…? 된다.”

민재 씨가 멈춰 있던 어드민 페이지를 새로고침하자, 언제 그랬냐는 듯 화면이 정상적으로 나타났다. 그는 믿기지 않는다는 듯 입을 벌렸다.

“다음부터는 복잡한 쿼리는 바로 실행하지 말고, 앞에 EXPLAIN을 붙여서 실행 계획부터 확인하는 습관을 들여. 그럼 이런 사고 막을 수 있어. 알았지?”

내가 웃으며 말하자, 그제야 민재 씨의 얼굴에 혈색이 돌아왔다.

“감사합니다… 진짜 감사합니다, 대리님. 저 진짜 죽는 줄 알았어요.”

“처음엔 다 그래. 나도 입사 첫날에 데이터 다 날려 먹을 뻔했어.”

“에이, 대리님이요? 거짓말. 대리님은 처음부터 에이스셨다던데.”

민재 씨가 안도감에 농담을 던졌다. 나는 피식 웃으며 자리로 돌아가려 했다. 그때, 민재 씨가 나를 불렀다.

“저기… 대리님.”

“응?”

“사실 입사하기 전에 대리님 무섭다는 소문 들었거든요. 눈 마주치면 막 혼내고, 사람 멘탈 털어버린다고…. 눈빛만 봐도 기가 빨린다고요.”

과거의 내가 만든 업보였다. 나는 씁쓸하게 웃었다.

“그런데 겪어보니까 아니네요.”

민재 씨가 나를 똑바로 바라보며 말했다.

“그런데 겪어보니까 아니네요. 대리님 눈을 보면요, 이상하게 마음이 편해져요. 최면 걸린 것처럼 멍해지는 게 아니라… 뭐랄까, ‘아, 이 사람이랑 있으면 해결할 수 있겠구나’ 하는 든든한 생각이 들어요.”

순간, 가슴 한구석이 찡하게 울렸다.

그것은 내가 그토록 갈망하던 말이었다.
기억을 조작해서 억지로 심어놓은 가짜 안도감이 아니었다.
나라는 사람 자체가, 나의 실력과 태도가 만들어낸 진짜 신뢰였다.

나는 민재 씨의 눈을 마주 보았다. 내 눈동자에 비친 그는 더 이상 겁먹은 신입 사원이 아니었다. 앞으로 성장할, 나의 믿음직한 후배였다.

“그럼 그렇게 기억해 줘요.”

나는 부드럽게 말했다.

“무서운 사람이 아니라, 마음이 편했던 사람으로.”


퇴근길, 빌딩 숲 사이로 노을이 지고 있었다.

나는 넥타이를 느슨하게 풀고 걸음을 옮겼다. 심장은 여전히 남들보다 조금 약하게 뛰고 있었지만, 발걸음은 그 어느 때보다 가벼웠다.

이제 나는 안다.
세상을 바꾸는 건 초능력이 아니다.
나 자신을 믿고, 타인을 믿는 용기. 그리고 그 믿음을 증명해내는 땀방울이다.

나는 하늘을 올려다보며 눈을 감았다 떴다.
평범한 갈색 눈동자에, 따뜻한 저녁 노을이 가득 담겼다.

이것으로 충분했다.

 

 

 


 

다음 이야기 : https://thepin.tistory.com/213

 

소설001: 내 눈을 보면 안 돼 - 작가의 말 & 완결 후기

작가의 말 & 완결 후기작가의 말안녕하세요, 독자 여러분.의 여정을 함께해주셔서 진심으로 감사합니다.10화에 걸친 짧고도 긴 이야기가 드디어 막을 내렸습니다. 이 소설은 "만약 우리에게 타인

thepin.tistory.com

 

 

[부록] 신입사원을 위한 DB 쿼리 실행 핵심 주의사항

소설 속 민재와 같은 실수는 실제 현업에서도 빈번하게 발생하며, 때로는 심각한 장애로 이어질 수 있습니다. 이를 방지하기 위해 운영 DB에서 쿼리를 실행할 때 반드시 지켜야 할 핵심 주의사항입니다.

1. UPDATE, DELETE 전에는 반드시 BEGIN TRAN으로 시작하세요.

  • 목적: 실수로 잘못된 데이터를 수정하거나 삭제했을 때, 즉시 되돌릴 수 있는 안전장치입니다.
  • 사용법:
더보기

BEGIN TRAN; -- 트랜잭션 시작
UPDATE Customers SET Status = 'Dormant' WHERE LastLoginDate < '2023-01-01';
-- ROLLBACK; -- 실수를 확인했다면 즉시 롤백!
-- COMMIT; -- 결과가 정확하다면 커밋!

  • 습관: UPDATEDELETE 문을 작성하기 전에 BEGIN TRANROLLBACK을 먼저 써두는 습관을 들이면 실수를 크게 줄일 수 있습니다.

2. WHERE 절을 가장 먼저 작성하세요.

  • 목적: UPDATEDELETEWHERE 절을 빠뜨려 전체 테이블의 데이터를 변경하거나 삭제하는 최악의 참사를 막기 위함입니다.
  • 사용법:
    UPDATE Products
    SET Price = Price * 1.1
    WHERE ProductID = 789; -- SET보다 WHERE를 먼저 쓰는 습관!

3. 모든 SELECT 문에는 WITH (NOLOCK)을 습관화하세요.(mssql 한정)

  • 목적: 단순 조회 쿼리가 다른 중요한 UPDATEDELETE 작업을 막는 것을 방지합니다. (락 경합 방지)
  • 사용법:
    SELECT * FROM Users WITH (NOLOCK) WHERE UserId = 123;
  • 주의: NOLOCK은 데이터의 정합성을 100% 보장하지 않을 수 있으므로, 재무 데이터 등 극도로 민감한 조회에는 사용을 지양해야 합니다. 하지만 대부분의 일반적인 데이터 확인 작업에서는 필수적으로 사용됩니다.
    또, MSSQL(SQL Server) 환경에서 주로 사용하는 힌트입니다. 오라클이나 MySQL 등은 기본적으로 읽기 작업이 쓰기 작업을 차단하지 않으므로(MVCC), 이 힌트가 필요하지 않습니다. 데이터의 정합성을 100% 보장하지 않을 수 있으므로(Dirty Read), 재무 데이터 등 극도로 민감한 조회에는 사용을 지양해야 합니다.

이 세 가지 원칙만 철저히 지켜도, DB 관련 장애의 90% 이상을 예방할 수 있습니다.

728x90
Posted by 댕기사랑
,