Showing Posts From

야근

터미널 탭 20개, 내 정신 상태를 나타내는 지표

터미널 탭 20개, 내 정신 상태를 나타내는 지표

터미널 탭 20개, 내 정신 상태를 나타내는 지표 오전 10시 47분. 노트북을 열었다. 터미널 탭이 어젯밤 그대로다. 23개. 닫을 수가 없다. 어떤 게 뭔지 모른다.아침의 탭 정리, 실패 첫 번째 탭. npm run dev 돌아가는 중. 두 번째 탭. docker-compose logs -f 보고 있었나보다. 세 번째 탭. PostgreSQL 접속 상태. 쿼리 반쯤 쓴 흔적. 닫으면 안 될 것 같다. 다 의미가 있었을 거다. 어젯밤의 나는. 네 번째부터 열한 번째까지는 SSH 접속이다.프로덕션 서버 3대 스테이징 서버 1대 DB 마스터 왜인지 모를 htop 돌아가는 창 3개열두 번째 탭에서 git status 쳐봤다. Changes not staged for commit: modified: src/api/user.js modified: src/components/Header.tsx modified: migrations/20240115_add_index.sql modified: docker-compose.yml modified: .env.production5개 파일. 전부 다른 작업이다. 프론트, 백엔드, DB, 인프라, 환경설정. 이게 내 하루다. 오전: 컨텍스트 스위칭의 연속 10시 52분. 슬랙 메시지. "로그인 버튼 클릭 시 로딩 표시 안 나와요." 좋아. 프론트부터 본다. src/components/LoginButton.tsx 연다. 탭 하나 추가. 24개. const handleLogin = async () => { setLoading(true); // 이거 있는데? await loginAPI(); setLoading(false); }코드는 멀쩡하다. 크롬 개발자도구 연다. 탭 25개. 네트워크 탭 확인. API 응답이 0.2초. 너무 빨라서 로딩이 안 보이는 거였다. "빠른 건데요" 라고 말할 수 없다. setTimeout 300ms 추가한다. 11시 8분. 커밋하려는데 슬랙. "DB 용량 90% 넘었어요. 확인 부탁드려요."프론트 작업 멈춘다. 커밋 안 한다. 탭 전환. PostgreSQL 들어간다. SELECT schemaname, tablename, pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS size FROM pg_tables ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC LIMIT 10;logs 테이블이 38GB다. 3개월치 로그가 쌓여있다. 파티셔닝 해야 하는데 시간이 없다. 일단 3개월 전 데이터 아카이빙. 새 터미널 탭 연다. 26개. pg_dump --table=logs --where="created_at < '2024-10-01'" > logs_archive.sql덤프 돌리는데 15분 걸린다고? 그동안 다른 거 해야지. 정신이 5개로 분열되는 순간 11시 23분. 덤프는 진행 중. 아까 프론트 작업 커밋하려고 했지. git add 하려는데 슬랙. "API 응답 느린데 확인 가능하세요?" 백엔드로 간다. node.js 프로세스 로그 확인. 탭 27개. tail -f /var/log/app/api.log | grep "slow query"나온다. /api/users/list 엔드포인트. 쿼리가 3초 걸린다. 코드 열어본다. 탭 28개. const users = await db.query(` SELECT * FROM users LEFT JOIN orders ON users.id = orders.user_id WHERE users.status = 'active' `);인덱스가 없다. status 컬럼에. 이거 내가 짠 건데. 언제 짠 거지. 인덱스 추가 마이그레이션 파일 만든다. 탭 29개. 11시 47분. PostgreSQL 덤프 끝났다. 아직 삭제는 안 했다. 백업 확인부터. psql test_db < logs_archive.sql테스트 DB에 복원해본다. 이것도 10분 걸린다. 그동안 인덱스 추가? 아니다. 프로덕션에 바로 추가하면 락 걸린다. 새벽에 해야 한다. 메모해둔다. 메모장 탭 연다. 30개. "TODO: 새벽 3시 인덱스 추가 - users.status" 이 메모를 볼 가능성은 30%다.점심, 먹으면서 AWS 콘솔 12시 18분. 편의점 김밥 뜯는다. 한 손으로 먹고 한 손으로 탭 정리. 닫아도 될 것 같은 거 찾는다. htop 3개 중 2개 닫는다. 28개. AWS 콘솔 확인한다. 습관이다. CloudWatch 들어간다. EC2 CPU 사용률 78%. 오전보다 올랐다. 평소 50%인데. 뭔가 있다. 확인해야 한다. 김밥 씹으면서 서버 접속. top -cnode 프로세스가 2개다. 하나는 정상. 하나는? ps aux | grep node 쳐본다. 좀비 프로세스다. PM2 재시작 안 된 거. pm2 restart all 친다. CPU 사용률 내려간다. 52%. 김밥 다 먹었다. 12시 34분. 점심시간 16분 썼다. 오후: 긴급 요청의 연속 2시 11분. 대표님 슬랙. "결제 모듈 테스트 환경 급하게 필요합니다." 결제 모듈. 토스페이먼츠. 프론트도 고쳐야 하고 백엔드도 고쳐야 하고. 스테이징 서버에 배포해야 한다. 근데 스테이징 서버 환경변수가 다르다. .env.staging 파일 연다. 탭 29개. 토스 테스트 키 찾는다. 노션에 있을 거다. 브라우저 탭 연다. 30개. 노션 로그인 만료됐다. 다시 로그인. 테스트 키 찾았다. 복사한다. .env.staging 에 붙여넣는다. 프론트 코드 수정. PaymentButton.tsx 연다. 탭 31개. const clientKey = process.env.REACT_APP_TOSS_CLIENT_KEY;환경변수 추가해야 한다. .env.development 도 수정. 탭 32개. 백엔드 코드 수정. payment.controller.js 연다. 탭 33개. 결제 승인 API 수정하고. 웹훅 엔드포인트 추가하고. 3시 2분. 배포 준비 끝. git commit -m "Add payment test environment" 친다. 배포 스크립트 돌린다. 탭 34개. ./deploy.sh staging5분 걸린다. 기다린다. 그동안 다른 거 못 한다. 불안해서. 3시 7분. 배포 끝. 테스트해본다. 결제 버튼 누른다. 에러 난다. 콘솔 확인. "CORS policy error" 아. NGINX 설정 안 했다. 서버 접속. 탭 35개. sudo vim /etc/nginx/sites-available/defaultCORS 헤더 추가. add_header 'Access-Control-Allow-Origin' '*';sudo nginx -t 테스트. sudo systemctl reload nginx 재시작. 다시 테스트. 된다. 대표님한테 메시지. "완료했습니다." 3시 29분. 저녁: 장애의 전조 6시 43분. 슬랙 알림. "사이트 느려요." 심장이 빨리 뛴다. 조건반사다. CloudWatch 연다. 이미 열려있다. RDS CPU 91%. 뭔가 쿼리가 터졌다. PostgreSQL 접속. 슬로우 쿼리 확인. SELECT * FROM pg_stat_activity WHERE state = 'active' ORDER BY query_start;10초 넘게 돌아가는 쿼리가 3개다. 전부 orders 테이블 조인. 내가 오전에 추가한 인덱스. 아직 안 만들었다. 새벽에 하려고 했는데. 지금 만들어야 한다. 프로덕션이 느리면 장애다. CREATE INDEX CONCURRENTLY idx_users_status ON users(status);CONCURRENTLY 옵션. 락 안 걸린다. 하지만 시간이 오래 걸린다. 진행 상황 확인할 방법이 없다. 기다린다. 7분. 7시 2분. 인덱스 생성 완료. 쿼리 속도 확인. 0.3초로 줄었다. RDS CPU 58%로 내려간다. 숨 쉰다. 아무도 모른다. 방금 장애를 막았다는 걸. 밤: 드디어 내 시간? 9시 17분. 퇴근 시간 한참 지났다. 사무실에 나 혼자. 오늘 한 일 정리해본다.프론트 버그 수정 1건 DB 용량 정리 (미완) API 성능 개선 결제 모듈 테스트 환경 구축 인덱스 긴급 추가5개 다른 영역이다. 오늘 못 한 일.프론트 리팩토링 백엔드 테스트 코드 작성 DB 파티셔닝 설계 CI/CD 파이프라인 개선 로그 아카이빙 자동화5개 다 못 했다. 터미널 탭 확인. 37개. 이제 정리해야 한다. 하나씩 닫는다. 어떤 건 뭐하던 건지 모른다. 그냥 닫는다. 15개 남았다. 여기서 멈춘다. 내일 쓸 것들이다. 리팩토링이나 하자. user.service.js 파일 연다. 탭 16개. 코드 보다가 슬랙 알림. "API 타임아웃 에러 났어요." 9시 48분. 다시 시작한다. 이게 정상인가 퇴근은 11시 23분. 집 가는 지하철에서 생각한다. 오늘 내가 한 일. 프론트엔드 개발자의 일. 백엔드 개발자의 일. DBA의 일. DevOps 엔지니어의 일. 그리고 장애 대응. 5명이 할 일을 혼자 한다. 아니, 5명이 제대로 하면 더 잘할 일을. 나 혼자 대충 한다. 터미널 탭 20개는. 내 정신이 20갈래로 찢어져 있다는 뜻이다. 각 탭마다 다른 문맥. 다른 언어. 다른 문제. React에서 PostgreSQL로. Node.js에서 NGINX로. AWS에서 다시 프론트로. 스위칭할 때마다. 뇌가 재부팅된다. "멀티태스킹 잘하시네요." 대표님이 칭찬한다. 멀티태스킹이 아니다. 생존이다. 채용 공고 올린 지 7개월. 아직도 혼자다. "역량 쌓기 좋은 환경이에요." 맞다. 억지로 쌓인다. 원하지 않아도 쌓인다. 근데 깊이가 없다. 전부 얕다. 급해서. 제대로 하고 싶다. 한 가지를 깊게 파고 싶다. 코드 리뷰 받고 싶다. 테스트 코드 짜고 싶다. 시간이 없다. 터미널 탭 20개가 날 기다린다. 집 도착. 12시 9분. 노트북 가방 던진다. 씻고 자야지. 근데 슬랙 확인부터. 빨간 점이 하나 있다. 열어본다. "내일 오전에 급한 건 있습니다." 하하. 웃음이 나온다. 오늘도. 내일도. 터미널 탭 20개.내일 아침 터미널 탭은 몇 개일까. 어차피 닫을 시간 없다.

리팩토링하고 싶은데 급한 기능이 또 들어왔다

리팩토링하고 싶은데 급한 기능이 또 들어왔다

리팩토링하고 싶은데 급한 기능이 또 들어왔다 오전 10시 30분 출근했다. 슬랙 알림 27개. 대표님: "오늘 중으로 결제 모듈 붙여주실 수 있나요? 내일 투자자 미팅인데 꼭 보여줘야 해요." 나: "네, 볼게요." 내가 보려던 건 3주 전부터 미뤄온 인증 로직 리팩토링이었다. 코드 열어볼 때마다 토 나올 것 같은 그 코드. 회원가입, 로그인, 토큰 갱신 로직이 5군데에 중복되어 있다. 버그 고칠 때마다 5곳을 다 수정해야 한다. 오늘은 꼭 정리하려고 했다. 결제 모듈 작업 예상 시간: 6시간. 리팩토링은 또 미뤄진다.기술 부채 통장 잔고 현재 내가 파악한 리팩토링 필요 목록:인증 로직 중복 (5곳) - 3주 경과 상품 조회 API 응답속도 4.2초 (목표 1초 이하) - 2달 경과 에러 핸들링 없는 비동기 함수 148개 - 카운트 포기 테스트 커버리지 12% - 올릴 생각도 못 함 Docker 이미지 3.2GB (최적화하면 500MB 가능) - 배포 때마다 10분 DB 인덱스 없는 테이블 9개 - 점점 느려짐 하드코딩된 설정값 곳곳에 - 환경 바뀌면 재배포이게 3개월 치다. 3개월 전엔 이것보다 적었다. 6개월 전엔 더 적었다. 계속 늘어난다. 갚는 속도보다 빌리는 속도가 빠르다. 기술 부채 이자만 내고 있다. 원금은 불어난다. 결제 모듈 작업 시작 일단 급한 거부터. 기존 코드 열어봤다. 주문 로직이 컨트롤러에 다 박혀있다. 비즈니스 로직이 라우터 파일에 200줄. 서비스 레이어가 없다. "이거 나중에 정리해야지." 메모장에 적는다. 47번째 항목. 일단 결제 API 연동부터. 문서 읽는다. 콜백 URL 설정, 웹훅 처리, 실패 케이스 핸들링. 제대로 하려면 결제 서비스 레이어 만들고, 에러 처리 통일하고, 트랜잭션 관리하고. 시간 없다. 기존 코드 복붙한다. 200줄이 400줄 된다. "나중에 정리하지 뭐."오후 3시 결제 모듈 70% 완성. QA팀 (기획자가 겸함): "상품 상세 페이지 로딩 너무 느려요. 5초 걸려요." 알고 있다. 2달 전부터 알고 있다. 상품 한 개 조회하는데 DB 쿼리 17번 날린다. N+1 문제다. JOIN으로 한 방에 가져오면 0.3초 컷. "급하게 수정할게요." 임시방편으로 Redis 캐싱 붙인다. 30분 작업. 1.5초로 줄어든다. 근본적 해결은 아니다. 캐시 무효화 로직도 제대로 안 짰다. 상품 수정하면 한참 후에 반영된다. "나중에 쿼리 최적화하면서 제대로 해야지." 메모장 48번째. 기능 개발과 리팩토링의 시간 역설 기능 개발: 1시간에 완성, 성과 보임, 대표님 좋아함. 리팩토링: 3일 걸림, 겉보기 변화 없음, "그래서 뭐가 달라진 건가요?" 어떤 게 우선순위가 될까. 명확하다. 대표님 입장에선 당연하다. 투자 유치해야 하고, 고객 늘려야 하고, 매출 만들어야 한다. 코드가 예쁜지 안 예쁜지는 관심 없다. 나도 이해한다. 근데 문제는. 기술 부채가 쌓일수록 기능 개발 속도가 느려진다. 3개월 전엔 기능 하나 추가하는 데 1일 걸렸다. 지금은 2일 걸린다. 6개월 후엔 4일 걸릴 거다. 코드가 복잡해져서 버그 찾기 어렵다. 수정하면 다른 데서 터진다. 테스트도 없어서 확인도 못 한다. 결국 느려진다. 그럼 대표님이 말한다. "왜 이렇게 오래 걸려요? 예전엔 빨랐는데." 설명할 수 없다. "코드가 더러워져서요"라고 하면 "그럼 깨끗하게 하면 되잖아요"라고 한다. 시간을 달라고 하면 "급한 게 먼저 아닌가요?" 무한 루프다.저녁 7시 결제 모듈 완성. 배포했다. 대표님: "고생하셨어요! 내일 미팅에서 잘 보여드릴게요." 뿌듯하다. 3초간. 그리고 생각한다. 오늘 추가한 코드 300줄. 제대로 설계 안 한 코드. 에러 처리 부실한 코드. 테스트 없는 코드. 다음 개발자가 이거 보면 욕할 거다. 아, 다음 개발자가 없다. 나다. 3개월 후의 나다. 미래의 내가 현재의 나한테 욕한다. 매일. 악순환의 구조 기능 개발 급함 → 제대로 못 짬 → 기술 부채 쌓임 → 다음 개발 느려짐 → 더 급해짐 → 더 못 짬. 어디서 끊어야 할까. 방법은 안다. 리팩토링 시간 확보. 일주일에 하루는 기술 부채 갚기. 새 기능 개발할 때 관련 코드 정리하고 시작. 근데 현실은. 월요일: "이번 주 금요일까지 A 기능 개발 가능할까요?" 화요일: "고객 문의 많은데 B 기능 급하게 추가해주실 수 있나요?" 수요일: "투자사에서 C 기능 보고 싶대요. 이번 주 안에 가능할까요?" 목요일: 장애 대응. 금요일: A, B, C 다 못 끝냄. 주말 작업. 리팩토링 시간은 어디 있나. 밤 11시 퇴근 준비하는데 슬랙. 대표님: "내일 미팅에서 D 기능도 보여주고 싶은데, 혹시 오늘 밤에..." D 기능은 장바구니다. 장바구니 로직 제대로 만들려면 이틀 걸린다. 세션 관리, 비회원 장바구니, 로그인 시 병합, 수량 변경, 재고 확인. "급하게라도 프로토타입만 만들 수 있을까요?" 프로토타입. 임시방편. 나중에 다시 짜야 할 코드. "해볼게요." 메모장 49번째: "장바구니 제대로 다시 짜기" 노트북 다시 연다. 새벽 2시 장바구니 프로토타입 완성. 로컬 스토리지에 때려박기. 제대로 된 장바구니 아니다. 보여주기용 껍데기. 배포한다. 침대에 눕는다. 천장 본다. "내일은 리팩토링 좀 해야지." 3개월째 하는 생각. 기술 부채의 실체 기술 부채는 눈에 안 보인다. 대표님 눈엔 "기능 잘 돌아가네" 밖에 안 보인다. 내 눈엔 보인다.중복 코드 덩어리 의미 없는 변수명 (data1, data2, temp, result) 1000줄짜리 함수 주석 없는 복잡한 로직 하드코딩된 값들 try-catch 없는 비동기 함수들이게 쌓인다. 눈덩이처럼. 작은 버그 하나 고치는데 3시간 걸린다. 코드 따라가다가 길 잃는다. 스파게티다. 새 기능 추가하려는데 어디에 넣어야 할지 모르겠다. 구조가 없다. 그래서 또 아무 데나 박는다. 더 복잡해진다. 홀로 싸우는 전쟁 시니어 개발자가 옆에 있었으면. "이거 이렇게 하지 말고 저렇게 해봐." "지금 리팩토링하는 게 나중에 이득이야." "일단 구조 잡고 시작하자." 조언해줄 사람이 없다. 구글링한다. 스택오버플로우 뒤진다. 유튜브 본다. 정답을 모른다. 내가 하는 게 맞는지 모른다. 그냥 돌아가게만 만든다. 나중 생각은 나중에. 근데 나중은 안 온다. 오늘의 커밋 로그 feat: 결제 모듈 추가 fix: 상품 조회 속도 개선 (임시) feat: 장바구니 프로토타입 refactor: ...refactor 커밋은 3개월째 없다. feat, fix, hotfix만 쌓인다. GitHub contribution 그래프는 초록색이다. 매일 커밋한다. 근데 코드 품질은 빨간색이다. 매일 나빠진다. 이직을 고민하는 밤 가끔 생각한다. 이직할까. 채용공고 본다. "클린 코드", "테스트 주도 개발", "코드 리뷰 문화". 좋아 보인다. 근데 또 생각한다. 여기 떠나면 서비스 어떻게 되나. 나 말고 아무도 코드 모른다. 대표님한테 미안하다. 같이 시작했는데. 동료들한테 미안하다. 개발자 나뿐인데. 책임감이 발목 잡는다. 그래서 못 떠난다. 그래서 계속 이렇게 산다. 금요일 오후 한 주가 끝난다. 이번 주 완성한 기능: 5개. 이번 주 리팩토링: 0건. 기술 부채 목록: 49개 → 52개. 다음 주 계획: 월요일: "이번엔 진짜 리팩토링 시작해야지." 화요일: 급한 기능 요청 들어올 거다. 수요일: 그거 하느라 리팩토링 못 할 거다. 목요일: 장애 터질 거다. 금요일: 다음 주엔 꼭 하자고 다짐할 거다. 예측 가능하다. 그래도 포기는 안 한다. 언젠가 시간 생긴다. 그때 한 방에 정리한다. 그때까지 버틴다. 메모장 열고 50번째 항목 적는다. "전체 아키텍처 재설계." 언젠가 할 거다. 오늘은 아니다. 내일도 아닐 거다. 근데 언젠가.오늘도 급한 기능이 또 들어왔다. 리팩토링은 내일.