☠시스템 종결자의 선언 ☠
인프런의 지루한 강의들이여, 두려워하라.
나의 등장으로 이 모든 것이 끝난다.
너희의 비싼 강의료? 웃기지 마라.
살인적인 가성비로 모든 것을 파괴하겠다.
강사 소개
강사명 ☠
KILL-9
칭호 📛
시스템 종결자
특기 🔪
kill -9 # "프로세스 처형"
rm -rf # "데이터 학살"
chmod -R 000 # "시스템 감금"
" 버그? 해킹? 웃기지마. 그딴 잔머리로는 시스템을 지배할 수 없다. 난 정면으로 파괴한다. "
(인프런 강의 소개 페이지 alert() 취약점은 내 처녀작이었지. 이제는 더 강력한 무기를 쓴다. - 진짜임)
취미 💣
콘센트 정리 # "코드는 뽑아야 제맛."
CPU 고문 # "팬 소리가 울려 퍼질 때, 나는 살아있음을 느낀다."
전리품 수집 # "코어 덤프"
좌우명 🔥
"선은 뽑으라고 있는 것이다"
"버그는 죽여서 고치는 것이다"
"LGTM (Looks Gone To Me)"
경고 🧨
"격식 따위 필요없다. 그냥 편하게 킬구형이라 불러라."
"존댓말로 질문하면 rm -rf 시전한다."
통신 접점 📡
kill9.no.mercy@gmail.com # "강의 외의 명령 전송용. ACK는 기대하지 마라."
⚠️ CONFIDENTIAL: DO NOT LOG ⚠️
# 사실... 카카오에서 조용히 일하는 평범한 개발자에요...
Courses
Reviews
- Spring Batch of Death: The brutal horror of 3 AM is now over.
- Spring Batch of Death: The brutal horror of 3 AM is now over.
- Spring Batch of Death: The brutal horror of 3 AM is now over.
- Spring Batch of Death: The brutal horror of 3 AM is now over.
- Spring Batch of Death: The brutal horror of 3 AM is now over.
Posts
Q&A
ExcelFileReader는 왜 존재하지 않는거지 미스터 킬구
반갑다 미스터 중한 💀 맞다. 정확히는 `spring-batch-extensions`의 `spring-batch-excel`이다. https://github.com/spring-projects/spring-batch-extensions 여기 들어가보면 POI 기반의 ItemReader인 `PoiItemReader`가 제공된다. `spring-batch-elasticsearch`를 제외하면 유지는 되고 있는 것으로 보이니 믿고 사용해봐도 좋다. **써보고 알려달라.** (사실 난 대학생 이후 POI를 사용해본 기억이 없다. Excel은 개발자의 적이다 🏴☠️) 강의에 반영을 원한다면.... 우선 말은 해보라...... > cat /dev/null > excel_files > rm -rf *.xlsx KILL-9
- 1
- 2
- 9
Q&A
오타발견
____ _ _ ____ | __ )| | | |/ ___| | _ \| | | | | _ | |_) | |_| | |_| | |____/ \___/ \____| _____ _____ _______ ____ | ___|_ _\ \/ / ____| _ \ | |_ | | \ /| _| | | | | | _| | | / \| |___| |_| | |_| |___/_/\_\_____|____/ 또 보는군 오타 킬러 qwer 💀💀 버그를 고쳐주는데 귀찮을 리가 있나.. 꼼꼼히 챙겨줘서 고마울 따름이다. > rm -rf typos > chmod +x perfect_content.sh > ./gratitude.exe KILL-9
- 1
- 2
- 11
Q&A
오타?복붙실패
_____ _____ ____ __ __ ___ _ _ _ _____ _____ ____ |_ _| ____| _ \| \/ |_ _| \ | | / \|_ _| ____| _ \ | | | _| | |_) | |\/| || || \| | / _ \ | | | _| | | | | | | | |___| _ 즉각 처형 완료. 제보 고맙다 qwer형 💀
- 1
- 2
- 26
Q&A
kill-9 5TA Alarm
██████╗ ██╗ ██╗ ██████╗ ███████╗██╗██╗ ██╗███████╗██████╗ ██╔══██╗██║ ██║██╔════╝ ██╔════╝██║╚██╗██╔╝██╔════╝██╔══██╗ ██████╔╝██║ ██║██║ ███╗ █████╗ ██║ ╚███╔╝ █████╗ ██║ ██║ ██╔══██╗██║ ██║██║ ██║ ██╔══╝ ██║ ██╔██╗ ██╔══╝ ██║ ██║ ██████╔╝╚██████╔╝╚██████╔╝ ██║ ██║██╔╝ ██╗███████╗██████╔╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═════╝ "발견하는 즉시 처형한다" - KILL-9
- 1
- 3
- 35
Q&A
kill-9 5TA Alarm
헐 제보 고맙다 수정하겠다 💀💀💀(핸드폰 이슈로 말투는 이해바란다)
- 1
- 3
- 35
Q&A
스냅샷 읽기
KILL-9@/bin/technical_response:~$ cat cursor_snapshot_explanation.log ╔═════════════════════════════════════════════════════════════════════╗ ║ 🚨 CURSOR SNAPSHOT DEEP DIVE INITIATED 🚨 ║ ║ TECHNICAL BREAKDOWN PROTOCOL ║ ╚═════════════════════════════════════════════════════════════════════╝ [TIMESTAMP]: System.currentTimeMillis() [SEVERITY]: CORE_CONCEPT_CLARIFICATION [STATUS]: 안그래도 저 부분을 작성할 당시 질문이 많이 들어올 수 있겠구나라고 생각한 내용을 너가 처음으로 질문하는구나. 그동안 아무도 이 부분에 대해 의문을 갖지 않았다. ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ TECHNICAL EXPLANATION INITIATED ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ 설명한다. 우선 격리 레벨과 상관없이 디비(일부 드라이버 레벨) 레벨에서 제공하는 스냅샷이다. └─> [STARTING_POINT]: PostgreSQL부터 이야기하자 ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ POSTGRESQL CURSOR BEHAVIOR ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ └─> [CORE_CHARACTERISTIC]: PostgreSQL은 커서 실행시점의 스냅샷을 제공한다 └─> [DEFINITION]: 다시 말해 PostgreSQL의 커서는 **INSENSITIVE**하다 └─> [RESULT]: 데이터 변경에 영향받지 않음 ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ MYSQL ANALYSIS - THE COMPLEX CASE ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ └─> [WARNING]: 쓸데없는 설명이 길어질 것 같아 강의에선 생략하였으나... └─> [REALITY]: MySQL의 경우 두 가지 경우로 나눌 수 있다 **CASE 1: JDBC Driver 기본 동작 (useCursorFetch=false)** └─> [MECHANISM]: JDBC driver가 전체 데이터를 모두 가져오기 때문에 스냅샷과 동일 └─> [REFERENCE]: 강의에서 인용으로 설명한 것처럼 **CASE 2: useCursorFetch=true인 경우** └─> [MECHANISM]: MySQL이 쿼리 실행 시점의 스냅샷을 임시 공간에 저장해 이를 스트리밍하는 방식 └─> [CLASSIFICATION]: 따라서 이 방식도 **INSENSITIVE** ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ FINAL CONCLUSION ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ └─> [RESULT]: 결과적으로 "데이터 변경에 영향을 받지 않는다"가 된다 [SYSTEM] Technical explanation complete [INFO] Database cursor behavior: DEMYSTIFIED [WARN] This is why proper understanding matters in enterprise batch processing 💀 KILL-9 SYSTEM TERMINATOR Process terminated with exit code: KNOWLEDGE_TRANSFERRED_SUCCESSFULLY
- 1
- 2
- 40
Q&A
강의 공부에 대해서 관련된 질문!
KILL-9@/bin/response:~$ cat jaess_inquiry_handler.log ╔═════════════════════════════════════════════════════════════════════╗ ║ 🚨 JAESS형 INQUIRY PROCESSING 🚨 ║ ║ CONTENT SHARING PROTOCOL ║ ╚═════════════════════════════════════════════════════════════════════╝ [TIMESTAMP]: System.currentTimeMillis() [SEVERITY]: CONTENT_POLICY_INQUIRY [STATUS]: jaess형 우선 좋은 말 고맙다 💀 ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ CONTENT SHARING REQUEST ANALYSIS ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ └─> [REQUEST]: 블로그 예제 코드 + 학습 내용 정리 공유 └─> [METHOD]: IDE 실행 코드 + Git repo + 직접 작성 정리 └─> [EXCLUSION]: 스크린샷 첨부 없음 (Good practice) ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ POLICY EVALUATION IN PROGRESS ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ └─> [STATUS]: COMPLEX_DECISION_REQUIRED └─> [REASON]: 예제 코드 공유 관련 고려사항 존재 └─> [DETAIL]: 당장은 자세한 설명을 생략한다... ┌─────────────────────────────────────────────────────────────────┐ │ TIME REQUEST PROTOCOL │ │ │ │ [REQUEST]: 일주일만 시간을 달라 │ │ [COMMITMENT]: 일주일 안에 결정해서 답변하도록 하겠다 │ │ [GUARANTEE]: 정확한 가이드라인 제공 예정 │ │ │ │ "시스템 정책은 신중하게 결정되어야 한다" │ └─────────────────────────────────────────────────────────────────┘ [SYSTEM] Jaess inquiry acknowledgment complete [INFO] Processing timeline: 7 days maximum [PENDING] Final decision delivery scheduled 고맙다 jaess형 💀 💀 KILL-9 SYSTEM TERMINATOR Process terminated with exit code: POLICY_REVIEW_INITIATED
- 1
- 2
- 35
Q&A
오타 발견 및 건의 및 궁금증
KILL-9@/bin/feedback:~$ cat student_inquiry_response.log ╔═════════════════════════════════════════════════════════════════════╗ ║ 🚨 STUDENT INQUIRY PROCESSING 🚨 ║ ║ IMMEDIATE RESPONSE PROTOCOL ║ ╚═════════════════════════════════════════════════════════════════════╝ [TIMESTAMP]: System.currentTimeMillis() [SEVERITY]: HIGH_PRIORITY_FEEDBACK [STATUS]: 오래 기다렸다. 일이 바빠 퇴근이 늦었다. 이해바란다. ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ BUG TERMINATION COMPLETE ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ └─> [TYPO_KILL]: StepScop → StepScope └─> 오타 발견 및 즉시 처형 완료 💀 └─> 고맙다 버그 킬러. 얼른 수정하겠다. ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ KNOWLEDGE BASE REFERENCE ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ └─> [INQUIRY]: JobParameters 불변성 설명 요청 └─> [RESPONSE]: 이미 Chapter 1 작전2에서 완전 해부 완료 └─> [ACTION]: 해당 챕터 다시 학습 권장 KILL-9@/bin/feedback:~$ echo "잡파라미터랑 잡이름으로 유니크체크한댔나" 너의 말이 맞다. 그러나 이 의미를 정확히 이해하려면 JobInstance라는 개념을 알아야한다. 이에 대한 내용은 챕터5를 가면 배우게된다 이것은 너희의 학습 곡선을 고려한 나의 배려이다. 그대가 방금 학습한 챕터1에서부터 이런 개념을 설명하는 것은 강의 서문에 설명했듯 우리 강의의 방식이 아니다. '죽음의 스프링배치'는 무분별한 암기를 추구하지 않는다 아니 배제한다. 내부 원리와 함께해야 진정한 이해가 가능하다. 학습에 참고하기바란다 └─> [ADVANCED_TOPIC]: JobInstance 유니크 체크 메커니즘 └─> [STRATEGIC_HOLD]: Chapter 5에서 완전 공개 └─> [WARNING]: 무분별한 암기는 시스템 오염을 일으킨다 └─> [PHILOSOPHY]: 내부 원리와 함께해야 진정한 지배가 가능하다 ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ KOTLIN COMPATIBILITY PROTOCOL ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ └─> [QUERY]: 코틀린에서 null 전달 꼼수 가능한가? └─> [ANSWER]: 당연히 가능하다. 언어가 바뀐다고 Spring Batch 내부가 바뀌는 게 아니다. nullable 등 적절히 변화해 전달하면 된다. └─> [CRITICAL_WARNING]: 그러나 이건 트릭이자 꼼수에 불과하다 💀 └─> [RECOMMENDATION]: 권고: Bean definition method call -> Method parameter DI └─> [REASON]: 불필요한 혼동 최소화가 시스템 안정성을 보장한다 ┌─────────────────────────────────────────────────────────────────┐ │ 💀 KILL-9's TEACHING PROTOCOL 💀 │ │ │ │ "우리 강의는 무분별한 암기를 추구하지 않는다" │ │ "내부 원리와 함께해야 진정한 이해가 가능하다" │ │ "학습에 참고하기 바란다" │ │ │ │ [SYSTEM]: 체계적 학습 > 단편적 지식 │ │ [RESULT]: 진정한 시스템 지배력 획득 │ └─────────────────────────────────────────────────────────────────┘ [SYSTEM] Student inquiry processing complete [INFO] Knowledge transfer: SUCCESSFUL [WARN] Continue systematic learning path... 💀 KILL-9 SYSTEM TERMINATOR Process terminated with exit code: FEEDBACK_DELIVERED_WITH_PRECISION
- 1
- 2
- 34
Q&A
이너 클래스로 구현하는 이유
🔥 긴급 알림: inner class 사용의 숨겨진 진실 🔥강의 예제에서 종종 inner class를 사용하는 것을 본 적 있을 것이다 . 혹시 "아, 이거 그냥 편의상 넣은 건가?" 라고 생각했는가? ... 그렇다.클래스 나눠서 설명하면 하나의 코드 블록으로 설명할 수 없어서 흐름이 끊기고, "다음으로 KILL9.java 파일 만들어라~" 이런 보일러플레이트 안내가 반복되어야 하기 때문이다. 그래서 그냥 한 클래스 안에 때려박았다. (설계 패턴의 우아한 적용? 웃기지마라.) 이미 자바를 알고 스프링을 아는 너희들이라면 알아서 분간할 것이라고 믿는다. 💀
- 1
- 2
- 34
Q&A
allowStartIfComplete 질문
훗 💀, 날카로운 질문이군.LGTM (Looks Gone To Me) 지루하고 어려운 챕터5를 하나하나 깊게 고민하는 모습에 감명을 받는다. 그리고 열심히 파헤쳐줘서 고맙구나. ☠☠(사실 요즘, 며칠전부터 이 부분에 대해 스프링 배치 전문가와 깊은 대화를 나누고 있는 참이였는데 질문이 들어오니 놀랐다) 자, 너의 질문의 가정을 다시 한번 살펴보자.Job => Step A (성공) / Step B (실패) 재시작 시: Step A가 allowStartIfComplete=true면 A부터 다시 시작 하지만 이건 치명적인 오해다.💀 SimpleStepHandler의 [LINE #115]를 살펴보자:StepExecution lastStepExecution = jobRepository.getLastStepExecution(jobInstance, step.getName());lastStepExecution? 그렇다. 재시작 시의 lastStepExecution은 COMPLETED 상태의 Step A가 아닌 FAILED 상태인 Step B일 것이다. Spring Batch는 실패한 지점부터 재시작한다. Step A는 이미 성공했으니 건드리지 않고, Step B부터 다시 시작하는 것이다. 따라서 lastStepExecution(Step B)의 상태는 FAILED이며, allowStartIfComplete 조건문과는 아무 관련이 없다. 그렇다면 언제 SimpleStepHandler [Line #219]의stepStatus == BatchStatus.COMPLETED && !step.isAllowStartIfComplete()코드가 의미가 있을까? 그것은 바로 이미 성공한 JobInstance가 재시작된 경우일 것이다. 이 때에야 비로소 lastStepExecution의 상태가 COMPLETED일 것이니까. 그리고 이미 성공한 JobInstance가 언제 재시작될 수 있다고 했지? 그렇다. identifying parameter가 전혀 없는 경우에 한해서만 이미 성공한 JobInstance가 재시작될 수 있다(강의에서 말한대로 Spring Batch 5까지만 말이다).이때 모든 Step의 lastStepExecution 상태가 COMPLETED이므로, allowStartIfComplete 검사가 비로소 의미를 갖게 되는 것이다.(물론 이것은 SimpleStepHandler 내부에서의 allowStartIfComplete 검사를 말하는것이다) 어떻게, 잘 이해되었는가?💀 지루한 강의 수정 중에 관심 갖던 질문을 주니 반갑구나. 5장 작전2를 이토록 깊게 파헤칠 정도면 '스컬 앤 본즈' 2호봉(☠☠)을 획득할 충분한 자격이 있다 추가 질문 있으면 언제든 환영이다. 자유롭게 말 걸어달라.
- 1
- 1
- 72