Recent Posts
Recent Comments
try anything chris!
KODE VICIOUS 개발지옥 본문
728x90

Chapter 1. 손 안의 코드
# 자원 관리
소프트웨어 엔지니어링에서 당신과 저에게 한없는 좌절감을 안겨주는 부분이 트레이드오프를 알아가는 과정입니다. 엔지니어들이 그들이 당시에 가정했던 사항들을 매년 또는 격년 주기로 다시 살펴보는 것은 중요합니다. 우리가 작업하고 있는 시스템은 매우 빠르게 변화하니까요.
메모리 같은 자원을 아무런 자각 없이 낭비하는 건 당연히 어리석은 행동입니다. 이런 경우는 엔지니어링 관점의 트레이드오프조차 아닙니다. 프로그래머가 그들이 사용하는 장치가 그냥 동작만 하면 된다고 생각한다면 그건 프로그래밍이 아닙니다. 그런 건 그저 타이핑에 불과한 겁니다. 소프트웨어 엔지니어가 좋은 의자에 앉고 비싼 급여를 받는 이유는 그들이 자원 낭비를 원치 않는 이들이기 때문입니다. 따라서 그들은 최고, 최악의 시나리오로 시스템의 다른 사용자들에게 줄 영향에 대해서 알아내야 합니다.
# 친절한 코드
만약 사람들이 당신의 라이브러리를 사용하고자 한다면, 왜 그들이 자꾸 접근하는지 알아내야 하고 그들의 요구사항을 충족시켜야 합니다. 라이브러리는 당신을 위한 것이 아니라 바로 그들을 위한 것이기 때문이죠.
# 코드 남용
이제 작성한 API 의 적절한 사용을 명확하게 문서화했다고 했지만 문서화를 통한 경고는 뉴욕의 무단횡단자들에게 보내는 노란색 주의 테이프 정도에 불과합니다. 앞을 가로막는 불타는 해자가 없는 이상 이들은 몸을 숙여 이 경고테이프를 무시하고 넘어갈 겁니다.
당신이 처음에 무엇을 의도했든지와 상관없이, 그 API 가 범용적 쓰임이 가능한 것처럼 표현되어 있고 다른 코더들이 별 생각 없이 어둠 속을 헤매다 그것을 조우할 수 있게 방치해 둔다면, 그 이후에 다시 보게 되었을 때 당신조차 못 알아볼 지경으로 사용되고 있을지도 모릅니다.
# 질식할 것만 같은 변경사항들
커다란 커밋을 쪼개야 하는 마지막 이유는 그래야지 누군가가 당신의 작업에서 작은 문제점을 찾았을 때 그에 해당하는 작은 변경만 롤백하고 나머지 당신의 작업은 보존할 수 있기 때문이다.
# 강요된 예외
규칙에 대한 집착은 경우에 따라 좋을 수도, 나쁠 수도 있지만 검증되지 않은 것에 대한 집착이 문제를 유발하곤 합니다.
대부분의 사람들이 '코드'라는 것을 동작하는 부분으로만 오해하고 있습니다. 심지어 누군가가 이런 편협한 시야를 요구하는 것도 아닌데 말입니다. 그 이유는 에러를 취급하는 부분이 코드를 작성하는 사람이 원하는 결과를 얻는 부분에서 주된 관심사가 아니기 때문입니다.
# 로그 남기기
디버거가 여러분의 프로그램의 어느 곳에서 충돌이 발생하는지 알려 준다면, 로그 출력물은 충돌 직전에 무슨 일이 벌어졌는지를 보여 줍니다. 좋은 로깅 시스템은 단순히 어느 지점에서 충돌이 발생했는지 알려 주는 것에 그치지 않고 한발 더 나아가 좋은 시스템 대시보드를 구성하는 데 필요한 초석이 되기도 합니다. 반면 나쁜 로깅 시스템은(대부분이 이쪽이죠.) 거기에 못 미치거나, 아니면 아예 로그 자체를 남기지 않는 편이 더 나을 정도입니다. 그런 시스템은 여러분을 잘못된 장소로 이끌어 여러분이 시스템의 진정한 이슈를 찾느라 시간을 낭비하게 만들기도 합니다.
로그 출력을 업데이트할때에는 아주 그럴싸한 이유가 있는 편이 아니라면, 새로운 정보는 항상 마지막에 추가하는 편이 좋습니다. 또 다른 조금 덜 공격적인 수단이 있습니다. 로그 출력에 완전히 새로운 정보를 제공하는 별도의 라인을 추가해서 기존 스크립트가 과거의 로그를 가능한 한 오랫동안 그대로 사용할 수 있게 하는 방법입니다.
# 복사하기
문제는 사람들이 코드나 문서를 복사하면서 그들의 이름이나 회사 이름을 강제로 때려 넣을 때 발생합니다. 만약 여러분의 코드나 아이디어의 출처를 모른다면, 여러분의 작업은 여러분 자신과 그 서비스를 사용하는 이들에게 심각한 불안을 야기할 수 있습니다.
"복사하고 붙여넣기 전에 생각부터 하세요!"
복사의 편리함은 두 개의 전혀 다른 문제를 유발하게 되었습니다. 첫 번째 문제는 복제된 버그 문제로, 문제의 코드가 제품의 코드 열 군데 이상에 존재하게 되어 중복 관리하게 된 것입니다. 그리고 두 번째 문제는 이 제품 코드를 전체 복사해 가며 만든 새로운 제품에도 버그가 포함된 문제입니다. 두 제품에서 발생하는 버그는 연관은 있지만 미묘하게 달라서 이제 다른 쪽의 버그를 고치려면 하나씩 고쳐나가는 수밖에 없습니다.
# 코딩할때 짜증나는 다섯 가지
코드는 항상 현재 시스템이 어떠한지 보여 주어야 하는 것이지 과거에 어떠했는지를 보여 주는 것이 아닙니다.
명심하세요. 정말, 정말, 정말 필요할 때만 전역 변수를 사용하는 겁니다.
# 언어들 속에서 길을 잃다
쉘 스크립트, 때론 영리하고 유용한 수단이지만 관리하기는 매우 까다롭습니다. 이 녀석들로 100줄 넘어가는 코드는 절대로 작성하지 않습니다. 대부분의 사람은 '1회성 작업(또는 2회성 작업인데, 처음에는 절대로 동작하기 않기 때문)'을 '그저 무언가 동작하게끔' 하려고 작성합니다. 불행하게도 이런 스크립트들은 프로젝트 집안의 천덕꾸러기들입니다. 이것들은 한번 레포지터리에 추가되고 나서 문제가 생기기 전까지는 무시당하다가 문제가 한번 벌어지면 소리가 날 정도로 두드려 맞고 비명을 지르고 절뚝거릴 때까지 놔두지 않습니다.
# 체크인 주석
체크인 주석은 코드에 남기는 주석과 같은 제약을 받습니다. 첫째, 실제로 주석이 있어야 합니다. 둘째, 주석은 유용해야 합니다.
Chapter 2. 코딩 수수께끼
# 캐시 미스가 뭐죠?
코드의 명료성과 소소한 최적화의 경쟁에선 명료성이 거의 항상 이깁니다. 명료성이 부족한 코드는 버그의 온상이 되는데, 굳이 그런 빠르지만 잘못된 코드를 가질 이유는 없기 때문입니다. 코드에서 중요한 건 일단 틀리지 않는 게 먼저고 그 다음이 성능 보장인데, 이는 제정신인 개발자라면 당연히 따르는 우선순위입니다.
# 입력 검증
사용자 입력을 제어하는 첫 번째 규칙은 '아무도 믿지 말 것!' 이고, 특히 사용자는 더더욱 믿어서는 안 됩니다.
두 번째 규칙은 '당신 스스로도 믿지 말 것!' 입니다. 이 말은 당신이 한 작업의 결과에서 놓친 게 없는지 꼭 확인해야 한다는 말입니다.
만약 당신이 사용자에게 보낸 웹 폼에서 데이터를 받아오는 거라면, 모든 폼을 검사하는 편이 좋습니다. 다만 검사를 위해 블랙리스트의 문제는 관리가 어렵다는 점입니다. 그래서 가급적 화이트리스트를 이용하는 편이 좋습니다. 화이트리스트를 사용하는 방식으로 변경해 사용자가 제공 가능한 입력 항목을 매우 제한적으로 하는 것입니다. 좀 가혹해 보이겠지만, 당신의 코드를 사용자들과 스파게티 코드로 변모하는 것에서 지키는 가장 좋은 수단임에는 분명합니다.
# 문서화 흥정하기
사람들이 자신의 코드나 디자인을 문서화하는 데 어려움을 느끼는 이유는 좋은 글귀나 소설과 수필, 함수 블록, 하드웨어 기능에까지 내러티브가 필수라는 사실을 받아들이지 못했기 때문입니다. 내러티브 없이는 독자들에게 아무런 정보도 제공 못하고 그저 글귀를 흩뿌리는 것에 불과합니다.
여러분들이 하나의 함수에 대해서 문서화를 시도할 때 다음 네 가지 질문에 답변을 하면 좋은 문서화가 될 겁니다.
* 입력은 무엇인가?
* 입력은 어떠한 변화를 겪게 되는가?
* 어떠한 형태로 출력이 나오는가?
* 적절하거나 부적절한 경우 어떠한 (에러) 반환 값이 있는가?
문서화 실패의 주요 원인은 독자가 그들이 모르는 지식들을 알고 있을 거라 섣불리 전제하는 것에 있습니다. 요컨대, 문서를 작성할 때는 여러분이 어떠한 전제를 하고 있는지를 고려해야 합니다.
많은 프로그래머가 코드는 그 자체만으로 해석할 수 있어야 한다고 주장하지만, 스스로 의미를 명확하게 전달하는 코드는 몹시 드뭅니다.
API 문서가 한데 모여, '전체 시스템이 어떻게 구성되어 있는지', '어떻게 사용하면 되는지와 안 되는지'를 다루는 것이 좋은 문서의 두 가지 중요한 특징입니다.
# Foo 필드에는 뭔가 있는 거야?
대부분의 엔지니어가 소프트웨어나 하드웨어에 대한 문서를 작성할 때 그들이 설득해야 하는 대상인 사람들이 글을 읽기 시작할 때 이미 전체적인 수준의 컨텍스트를 가지고 있다고 가정하는 것 같습니다. 그런 경우에 문서는 레퍼런스(참조) 문서이지 가이드 문서는 아닙니다.
모든 소프트웨어와 하드웨어 개발자는 시스템을 개발할 때 다음과 같은 질문에 답해야 합니다.
1. 이것을 왜 추가했는가? (필드, 기능, API)
2. 이 필드, 기능, API 는 어떻게 사용하는가? 예시를 제공하시오.
3. 당신이 제공하는 것으로 인해 다른 필드, 기능, API 가 어떠한 영향을 받는가?
# 성깔 있는 테스터
테스트하는 것에서 가장 중요한 것은 사고방식 아니면 태도와 관련된 것일 겁니다. 첫 단계로 좋은 습관은 테스트를 과학적 방법으로 접근하는 것입니다. 그 다음 단계는, 아마 대부분 이게 가장 어려울 텐데, 바로 코드에 대한 당신의 섣부른 가정을 내려놓는 것입니다.
어리석은 테스트 증후군
무엇이 퇴스트되어야 하는지, 어떤 것이 중대한 위험인지를 저울질하지 않고 전부 테스트할 것을 요구하는 문제.
어테증을 예방하려면 몇 가지가 필요합니다. 먼저 두뇌가 필요합니다. 두 번째로 필요한 것은 시스템을 디자인하고 구현하는 사람들과의 관계입니다. 가장 위험한 영역에 대한 질문은 당신 스스로 직접 물어볼 수 있어야 합니다. 단순하고 쉽게 이해되는 작업을 수행하는 라이브러리의 인터페이스를 테스트하는 것은 큰 의미가 없습니다. 반면에 10,000줄이 넘는 실험적인 코드나 그냥 봐도 이상한 코드, 또는 회사의 매우 중요한 영업 비밀 같은 코드들은 꼭 테스트해 봐야 합니다. 제 경험상 좋은 테스트를 작성하는 기술은 서로 조금 다르긴 해도 좋은 코드를 작성하는데 필요한 기술만큼이나 값어치가 있습니다.
# 테스트 방법
어떤 종류의 테스트이건 체득하려면 적절성과 반복성이라는 두 가지 선행조건을 충족시켜야 합니다. 문제를 포착하는 테스트를 작성하기 위해 테스트 개발자는 소프트웨어가 동작하는 테스트와 실패하는 테스트를 고안할 수 있도록 도메인에 익숙해져야 합니다.
# 유지보수 모드
리팩토링이란 건 작은 변경으로 다른 프로그램에서 함수나 클래스를 사용할 수 있음을 의미합니다.
당신이 유지보수하는 동안, 아니 제 말은 리팩토링하는 동안, 뭐를 바꾸건 간에 테스트를 꼭 하세요. 당신이 비록 'API 의 정말 자그마한 필드 하나를 추가' 했을지라도 변경에 대한 테스트를 하지 않은 것에 대한 변명이 되지 않습니다. 만약 당신이 테스트를 하지 않는다면, 제가 장담하건대 옛날 방식의 소프트웨어 유지보수를 하고 있는 거라고 말할 수 있습니다.(버그 수정이요)
# 일찍 머지하기
먼저 당신이 하려는 작업을 완료하고 메인 브랜치의 고통을 당신 것으로 받아들이세요. 저는 제 작업을 먼저 완료해서 기분이 좋아진 다음에 이런 종류의 머지를 하는 것을 선호합니다. 그러면 적어도 기분 좋은 상태에서 시작할 수 있을 테니까요. 그러고 나서 제 브랜치에 발생하는 문제를 고치다 보면 다시 중립적인 상태에 접어들 수 있습니다.
언제 머지된 코드를 트리에 반영하는 게 최선의 선택일까요? 그건 당신이 무엇을 머지하느냐에 따라 다릅니다. 버그를 고치는 것이라면 다른 사람들이 그 영향을 받을 수도 있으니 테스트가 끝나는 대로 가능한 한 빠르게 반영해야 합니다. 기능 추가라면, 테스트가 다 끝나고 나서 사용하는 데 지장이 없을 때 머지하는 게 좋습니다.
Chapter 3. 시스템 디자인
# 추상화
프로그래밍 기술은 많은 경우의 수를 정복하고 끔찍한 혼란을 가능한 한 효율적으로 회피하는 것을 통해 복잡성을 정리하는 기술이기도 합니다.
적절한 추상화는 좋은 시스템 디자인의 핵심입니다. 추상화를 올바르게 하지 않으면 두 컴포넌트 사이에 오해가 생기게 됩니다. 그리고 오해는 버그를 유발하고, 버그는 시스템 실패를 유발합니다. 그렇지만 추상화를 향한 시도가 계속해서 작게 쪼개는 작업으로 되다 보면 제논의 역설처럼 추상화가 쓸모없어지게 되는 상황이 생깁니다.
우리가 코드나 데이터 관점의 추상화를 살펴본다면, 반드시 다음 세 가지 질문에 답해야 합니다. 이 추상화가 다른 프로그래머들에게 사용성이 있는가? 이 추상화가 스스로 테스트할 수 있는가? 이 추상화를 사용하는 코드를 유지보수하게 된다면 간접적인 영향이 어디까지 발생되는가?
# 가역적 변경(Changative Changes)
한 가지 제안하고 싶은 건 버전 번호의 의미를 조금 더 엄밀하게 하라는 것입니다. 메이저 번호는 완전히 호환성이 깨질 때만 증가시키고, 마이너 번호는 하위 호환성이 깨질 때 증가시키고, 마지막 숫자인 패치 번호는 각 패치나 사소한 변경이 있을 때 증가시키는 겁니다.
# 크로스 사이트 스크립트
입력의 유효성 검사 메타 문제는 사용자 입력을 처리할 때 시스템 디자인에서 세 가지 중요한 점을 제공합니다.
* 입력을 실행하는 영역에 사용자 입력을 그대로 전달하지 마세요.
* 모든 사용자 입력은 알려진 양호한 패턴과 일치시키세요.
* 당신이 사용하는 언어에 내재된 위생 절차를 준수하세요.
# UI 디자인
시스템 구성 초기에 프로그래머나 소프트웨어 아키텍트에게 가장 중요한 것을 하나 꼽자면, 사용자 인터페이스에 표시되는 정보와 핵심 시스템에서 데이터가 저장되고 취급되는 방법을 분리해 여기저기 질질 끌려다니지 않도록 만드는 것입니다. 사용자 인터페이스를 수정하는 것이 무언가를 컴파일하게 해서는 안 됩니다.
Chapter 5. 사람과 사람
# 무슨 색깔이게...?
당신이 목격한 건 불행하게도 코드베이스를 수정할 때 종종 발생하는 일상적인 반응입니다. 혹시 누군가가 복잡하거나 때론 끔찍하기까지 한 코드를 올렸는데도 다들 침묵하는 경우를 본 적이 있나요? 이건 단순히 사람들이 해당 코드를 리뷰할 시간이 없어서 그럴 수도 있습니다만, 불행하게도 대부분의 사람들은 10줄에서 50줄 정도의 변경만 리뷰하는 데 시간을 할애하고, 커다란 코드에서 결점을 찾지 않으면 죄책감이 드는지 작은 거라도 찾아서 트집 잡게 됩니다.
<파킨슨의 법칙> 만약 당신이 복잡한 것을 만들고 있다면 소수의 사람들만이 당신이 무엇을 하고 있는지 이해할 수 있기 때문에 당신과 논쟁할 것이라고 했습니다. 반대로 당신이 단순한 것을 만들다면(이를테면 자전거 창고 같은 것들) 아마 누구라도 만들 수 있을 것이기에 많은 이들이 저마다의 의견을 가질 겁니다.
# 디자인 리뷰(설계 리뷰)
개인에 대한 리뷰와 객관화된 리뷰를 구별하는 명확한 방법은 다음과 같은 표현들입니다.
"무엇이 당신으로 하여금 x라고 생각하게 하였나요", "왜 당신이 y를 구현하였나요?" 는 명백하게 개인적이고 비난하는 표현입니다.
디자인 자체에 관심을 보이는 문장은 "이 두 컴포넌트 간의 결합이 더 효율적이라는 것을 보여 줄 데이터가 무엇입니까?", "이 시스템의 확장은 어떻게 할 계획입니까?" 의 형태에 가깝습니다.
디자인 리뷰(설계리뷰)를 할 때 주의사항은 코드 리뷰로 변질되면 안 된다는 점입니다. 목표는 큰 틀에서의 그림을 이해하는 것이지 상세한 내용을 이해하는 것이 아님을 명심해야 합니다.
불쾌감을 주지 않으려면 다음 몇 가지 유용한 규칙에 따라 실행하는 것이 좋습니다. 첫째로 끝없는 질문으로 사람을 망치지 마세요. 당신이 하려는 일은 디자인 영역을 협동적인 자세로 탐험하려는 것임을 잊어서는 안 됩니다. 이건 취조가 아니란 걸 기억하세요. 둘째로, 함께 일하는 사람들이 생각할 수 있게 여유를 두어야 합니다. 침묵은 그들이 모른다는 걸 의미하지 않습니다.
# 면접 진행
어떤 면접이건 면접의 목표는 면접관과 지원자 양쪽 모두가 조직문화 안에서 서로 융화될 수 있는지 확인하는데 있습니다. 아무리 훌륭한 프로그래머여도 제가 절대로 채용하지 않는 사람들이 여럿 있습니다. 그들의 인간적 결함이 다른 팀원들에게 미치는 해로운 영향이 코더로서의 능력보다 더 큰 사람들이죠.
직무에 필요한 기초 지식이 있다고 확인된다면, 그 다음에는 지원자가 어떻게 상위의 문제를 해결했는지를 알아보는 겁니다. 지원자에게 그들에게 친숙한 시스템에 대해서 프로그래밍 작업을 블록 다이어그램의 형태로 표현해 보라고 하는데, 만족스럽게 느낄 정도로 잘 표현해 냈다면, 그 뒤에 "만약 시간이 더 있었다면 어디를 고치거나 어떤 기능을 더 했을까요? 와 같은 열린 결말의 질문을 합니다. 이 질문에 대해 답할 수 없는 사람은 단순히 다른 사람의 의지를 따르는 수동적 태도를 취할 가능성이 매우 높습니다.
또 다른 방법은 어떤 이유에서건 동작하지 않는 코드를 제공하고 그들에게 버그를 찾아내게 하는 것입니다. 많은 프로그래머들의 일과시간은 디버깅으로 소요됩니다. 따라서 저는 버그가 없는 코드를 작성하는 능력만큼이나 그 능력을 높게 평가합니다. 비록 프로그래머들이 버그가 없는 코드를 작성할지라도 그건 매우 드문 일일 것이고, 다른 사람들의 코드와 함께 협업하기 때문에, 그들이 작성한 코드가 아닐지라도 빠르게 코드를 분석하는 능력은 중요합니다.
# 구닥다리 코더
일단 프로그래머로 일을 시작한다면, 의도된 경우보다 우연히 새로운 기술을 습득해야 하는 경우가 더 많을 겁니다. 우리는 어떻게 우리 분야에서 전문성을 유지할 수 있을까요? 전문성을 유지하는 건 평생의 과업입니다. 당신이 전문성을 유지하고자 노력을 제대로 하고 있다면, 그 노력은 영원히 끝마칠 수 없을 겁니다.
어떻게 당신이 과잉 전문화의 늪에 빠졌는지 알 수 있을까요? 가장 쉬운 식별법은 당신의 작업이 끝없이 반복적으로 같은 일만 하며, 그 할 일이 다른 누군가에 의해 설계되는지 확인하는 겁니다. 만약 당신이 의사결정을 할 수 있을 만큼 광범위한 식견을 갖지 못한다면 다른 사람들이 사용하는 도구로 전락할 것이고, 도구는 언젠간 대체되기 마련입니다.
당신이 조직에서 가치가 있는 사람이라는 걸 어떻게 증명해야 하는지 말해보겠습니다.
원할한 운영을 책임지는 시스템 관리자나 이 분야에 속한 모든 이들은 다음과 같은 심각한 두 가지 장애물로 인해 고통받고 있습니다.
첫 번째 장애물은 사람들이 일련의 시스템들이 정상 작동하기 위해 필요한 것들은 이해하지 못한 채 '그냥 되는' 걸 기대한다는 겁니다.
두 번째 고통스러운 장애물은 대부분의 비즈니스에 속한 사람들이 당신 노동의 가치를 알아차리지 못한다는 점입니다.
이 장애물들을 거의 같은 방식으로 다뤄져야 합니다. 바로 대화를 통해서 말이죠. 당신의 사용자들에게 그들의 업무가 조금 더 쉬워졌다고 알리기만 하면 되고, 거기에는 무엇이 더 나아졌는지 명확하게 설명하는 한 페이지 분량의 이메일만 있으면 됩니다. 광범위한 주제에 관심을 두고 계속해서 지식을 쌓으면서 자신의 역할을 정의하며, 사용자들에게 당신이 하는 일과 그것이 왜 일상 생활에 중대한 영향을 미치는지 소통할 수 있다면, 당신이 구닥다리가 될 위험은 확실히 낮아질 겁니다.
728x90
Comments