이번 장은 내용이 참 많다 ... 하지만, 어디 하나 빼놓을 부분이 없다 .ㅜ
공부하자 .. 공부하자 ..
![](https://t1.daumcdn.net/keditor/emoticon/niniz/large/044.gif)
🧑🏻💻 오늘 TIL 3줄 요약
- 우리는 행운과 우연한 성공에 의존하는 프로그래밍을 하지 않아야 한다. 대신 '의도적으로 프로그래밍'해야 한다.
- 소프트웨어 개발은 건축보다 정원 가꾸기에 더 가깝다. 딱딱하기보다는 유기적인 활동이다.
정원의 건강 상태를 지속적으로 관찰하며, 필요하면 토양, 식물, 정원 배치를 조정한다.
- 일정의 압박은 리팩터링을 하지 않는 단골 핑계다. 하지만 이는 설득력이 떨어진다. 지금 리팩터링을 하지 않으면 일이 더 진척되었을 때, 즉 신경 써야 할 의존성이 더 많아졌을 때 문제를 고쳐야 하고, 따라서 훨씬 더 많은 시간을 투자해야 한다.
TIL (Today I Learned)
- 2022. 4. 2.
📕 오늘 읽은 범위
- 7장. 코딩하는 동안
🙂 책에서 기억하고 싶은 내용
- 운전을 안전 하게 잘하는 사람은 언제나 자기 상황을 검토하고, 잠재적인 문제들을 점검 하며, 예상하지 못한 일이 생길 때에도 잘 대처한다. 코딩도 똑같다. 대부분 은 반복적인 일이지만 정신을 늘 기민하게 유지하면 재앙을 막을 수 있다. _p.275
Topic 37. 파충류의 뇌에 귀 기울이기 _p.275
- 프로그래머로서 경 험이 늘어 갈수록 여러분의 뇌에는 암묵적인 지식이 켜켜이 쌓인다. 잘 되는 방법, 잘 안되는 방법, 오류 형태별로 가능한 원인 등 일하는 동안 보고 듣고 느끼는 모든 것이 쌓인다.
- 첫 번째 원인은 파충류의 뇌가 여러분에게 무언가 할 말이 있어서다. 인식 의 지평 바로 밑에 도사리고 있는 모종의 의심이 있다. 이런 의심은 중요하다. (중략..)
다른 원인은 좀 더 진부한데, 여러분은 그저 실수할까 봐 두려운 것일 수 있다.
- Tip 61. 여러분 내면의 파충류에게 귀 기울여라.
- 일단, 하고 있는 일을 멈춰라. 여러분의 뇌가 정리를 좀 할 수 있도록 약간의 시간과 공간을 확보하라. 코드에 대해 생각하지 말고 키보드에서 떨어져서 잠깐 머리를 비운 채로 할 수 있는 일을 하라. 산책을 하고 점심을 먹고 다른 사람과 수다를 떨어라. 아예 하룻밤 자면서 생각해 봐도 된다. 생각이 저절 로 여러분의 뇌 층층이 스며들도록 놔둬라. 억지로 쑤셔넣을 수는 없다. 언 젠가는 다시 생각이 의식의 영역으로 올라와서 ‘아하!’하는 순간이 찾아올 것 이다.
- 여러분의 뇌에게 여러분이 하려는 일은 별 문 제가 없다고 알려줘야 한다. 바로 프로토타이핑을 하면 된다.
- 다른 사람의 코드를 기계적으로 읽으면서 중요해 보이는 대목은 메모해 가며 묵묵히 시간을 투자할 수도 있다. 따분한 일이기는 하지만 가능한 일이다. 아니면 실험을 해 볼 수도 있다. 처리 방식이 이상해 보이는 부분이 눈에 띄면 적어 놓아라. 계속 작업하면서 패턴을 찾아보라. 만약 그런 식으로 코드를 작성해야만 했던 원인을 찾아낼 수 있다면 코드를 이해하는 일이 훨씬 더 쉬워질지도 모른다. 다른 사람들이 은연중에 적용한 패턴을 여러분은 의식적으로 적용할 수도 있다.
- 직감에 귀 기울이는 방법은 계속 갈고닦아야 할 중요한 기술이다. 그런데 이 기술은 더 많은 일에 적용할 수 있다. 가끔은 설계가 왠지 이상하게 느껴질 수 도 있고, 어떤 요구 사항이 마음을 불편하게 할 수도 있다. 하던 일을 멈추고 그 느낌을 분석하라. 여러분의 목소리에 귀를 기울여 주는 환경에 있다면 적 극적으로 표현하라.
- 도전해 볼 것 !
여러분이 해야 한다는 것은 알지만 약간 무섭고 어려워 보여서 미뤄둔 일이 있는가? 이번 항목의 기법을 적용해 보라. 시간을 한 시간, 혹은 두 시간으로 제한해 두고 타이머가 울리면 여러분이 만든 것을 모두 지우기로 약속하라. 여러분은 무엇을 배웠는가?
Topic 38. 우연에 맡기는 프로그래밍 _p.282
- 우리는 우연에 맡기는 프로그래밍, 곧 행운과 우연한 성공에 의존하는 프로그래밍을 하지 않아야 한다. 대신 ‘의도적으로 프로그래밍’해야 한다.
- 왜 코드가 망가졌는지 프레드가 모르는 까닭은 애초에 코드가 왜 잘 돌아 가는지도 몰랐기 때문이다. 프레드가 제한적으로 ‘테스트’를 했을 때는 코드 가 잘 돌아가는 것처럼 보였지만, 그것은 단지 그때 운이 좋았을 뿐이다. 근 거가 없는 확신을 가지고 프레드는 계속 앞으로 나아갔고, 그 결과 대실패를 맛보았다.
- 다른 루틴을 호출할 때도 문서화된 동작에만 의존하라. 어떤 이유로든 그 럴 수 없다면 추측을 문서로 상세히 남겨라.
- 가정하지 말라. 증명하라.
- Tip 62. 우연에 맡기는 프로그래밍을 하지 말라.
- 의도적으로 프로그래밍하기
- 언제나 여러분이 지금 무엇을 하고 있는지 알아야 한다.
- 더 경험이 적은 프로그래머에게 코드를 상세히 설명할 수 있는가?
- 자신도 잘 모르는 코드를 만들지 말라. 완전히 파악하지 못한 애플리케이 션을 빌드하거나, 이해하지 못한 기술을 사용하면 우연의 함정에 빠질 가 능성이 높다. 이것이 왜 동작하는지 잘 모른다면 왜 실패하는지도 알 리가 없다.
- 계획을 세우고 그것을 바탕으로 진행하라.
- 신뢰할 수 있는 것에만 기대라. 가정에 의존하지 말라. 무언가를 신뢰할 수 있을지 판단하기 어렵다면 일단 최악의 상황을 가정하라.
- 가정을 기록으로 남겨라. 자신의 마음속에서 가정을 명확하게 하는 데 도움이 될뿐더러, 다른 사람 과 그에 대해 소통하는 데에도 도움이 된다.
- 코드뿐 아니라 여러분이 세운 가정도 테스트해 보아야 한다. 어떤 일이든 추측만 하지 말고 실제로 시험해 보라.
- 노력을 기울일 대상의 우선순위를 정하라. 중요한 것에 먼저 시간을 투자 하라. 중요한 부분이 가장 어려운 부분이기도 한 경우가 많다.
- 과거의 노예가 되지 말라. 기존 코드가 앞으로 짤 코드를 지배하도록 놓아 두지 말라. 더는 적절한 코드가 아니다 싶으면 어떤 코드라도 교체할 수 있다. (중략...)언제나 리팩터링할 자세가 되어 있어야 한다.
Topic 39. 알고리즘의 속도
- 단순반복 O(n), 중첩반복 O(n^2), 반씩자르기 O(logn), 분할정복 O(nlogn), 조합적
- Tip 63. 사용하는 알고리즘의 차수를 추정하라.
- Tip 64. 여러분의 추정을 테스트하라.
- 가장 빠른 알 고리즘이 언제나 가장 좋은 알고리즘은 아니다. 입력값의 규모가 작다면 단 순한 삽입 정렬도 퀵 정렬과 비슷한 성능을 낸다.
- 그리고 ‘성급한 최적화premature optimization’9를 조심하라. 언제나 어떤 알고리 즘을 개선하느라 여러분의 귀중한 시간을 투자하기 전에 그 알고리즘이 정말 로 병목인지 먼저 확인하는 것이 좋다.
Topic 40. 리팩터링
- 코드는 정적인 존재가 아니다. 코드는 발전해야 한다.
- 소프트웨어 개발은 건축보다 정원 가꾸기에 더 가깝다. 딱딱하기보다는 유기적인 활동이다.
정원의 건강 상태를 지속적으로 관찰하며, 필요하면 토양, 식물, 정원 배치를 조정한다.
- 소프트웨어 개발의 현실은 정원 가꾸기 메타포에 훨씬 더 가깝다. 어떤 루틴이 너무 크게 자라거나 너무 많은 것을 하려고 할지도 모른다. 그러면 둘로 나눠야 한다. 계획한 대로 잘 되지 않는 것들은 잡초 제거하듯 뽑아내거나 가지치기를 해야 한다.
- 리팩터링은 잡초 제거나 갈퀴질처럼 위험하지 않은 작은 단계들을 밟는 일상 활동이다. 무질서하게 대규모로 코드를 다시 쓰는 것이 아니라, 정확한 목적을 가지고 정밀하게 접근하는 활동이다. 그래서 코드를 바꾸기 쉽게 유지하는 것이다.
- 리팩터링은 여러분이 무언가를 알게 되었을 때 한다. 여러분이 작년이나 어제, 심지어 10분 전과 비교해서 더 많이 알게 되었다면, 리팩터링을 한다. 어쩌면 코드가 더는 잘 맞지 않아서 장애물에 부딪혔을 때, 두 가지가 사실은 하나로 합쳐져 있어야 한다는 것을 발견했을 때, 무엇이든 ‘잘못’되었다는 생각이 들 때가 있을 것이다. 주저하지 말고 변경하라. 언제나 바로 지금이 최적기다. 코드를 리팩터링할 이유는 아주 많다.
- 중복 : DRY 위반
- 직교적이지 않은 설계 : 더 직교적으로 변경할 무언가를 발견
- 더 이상 유효하지 않은 지식 : 코드는 지금 상황에 뒤떨어지지 않아야 함
- 사용 사례 : 어떤 기능은 예전에 생각했던 것보다 더 중요하고, “꼭 필요하다”고 생각했던 기능은 그렇지 않은 경우도 있다는 것을 깨닫게 됨
- 성능 : 성능을 개선하려면 시스템의 한 영역에서 다른 영역으로 기능을 옮겨야 함
- 테스트 통과 : 리팩터링은 작은 규모의 활동이고, 좋은 테스트가 뒷받침되어야 한다. 코드를 조금 추가한 후 추가한 테스트가 통과했을 때가, 방금 추가한 코드로 다시 뛰어들어 깔끔하게 정리하기에 최고의 타이밍이다.
- 일정의 압박은 리팩터링을 하지 않는 단골 핑계다. 하지만 이는 설득력이 떨어진다. 지금 리팩터링을 하지 않으면 일이 더 진척되었을 때, 즉 신경 써야 할 의존성이 더 많아졌을 때 문제를 고쳐야 하고, 따라서 훨씬 더 많은 시간을 투자해야 한다.
- Tip 65. 일찍 리팩터링하고, 자주 리팩터링하라.
- 요구 사항이 바뀐다면 언제라도 재설계의 대상이 될 수 있다. 하지만 그렇다 고 거대한 규모의 코드를 닥치는 대로 헤집어 놓으면, 나중에는 리팩터링 전 보다 더 안 좋은 처지에 놓일지도 모른다.
- 마틴 파울러의 리팩터링 몇가지 조언
1. 리팩터링과 기능 추가를 동시에 하지 말라.
2. 리팩터링을 시작하기 전 든든한 테스트가 있는지 먼저 확인하라.
3. 단계를 작게 나누어서 신중하게 작업하라. 단계를 작게 나누고, 한 단계가 끝날 때마다 테스트를 돌린다면 기나긴 디버깅 작업을
피할 수 있다.
- 탄탄한 회귀 테스트를 유지하는 것이야말로 안전한 리팩터링의 비결이라는 것이다.
- 리팩터링만으로는 부족해서 결국 외부에서 보이는 동작이나 API를 바꿔야 한다면, 일부러 빌드를 깨트려 보는 것이 유용할 수도 있다. 리팩터링 대상 코드에 의존하는 옛날 코드들은 컴파일이 안 되게 만드는 것이다. 이렇게 하면 고쳐야 하는 부분이 어디인지 알아낼 수 있다.
- 깨진 창문을 그대 로 놓아두지 말라.
Topic 41. 테스트로 코딩하기
- Tip 66. 테스트는 버그를 찾기 위한 것이 아니다.
- Tip 67. 테스트가 코드의 첫 번째 사용자다.
- 이것이 테스트가 주는 가장 큰 이득일지 모른다. 테스트는 우리의 코딩을 인도하는 필수 피드백이다.
- 무언가 를 테스트하기 좋게 만들면 결합도도 낮아진다.
- 테스트 주도 개발 TDD Test-Driven Development
1. 추가하고 싶은 작은 기능 하나를 결정한다.
2. 그 기능이 구현되엇을 때 통과하게 될 테스트를 하나 작성한다.
3. 테스트를 실행한다. 다른 테스트는 통과하고 방금 추가한 테스트 딱 하나만 실패해야 한다.
4. 실패하는 테스트를 통과시킬 수 있는 최소한의 코드만 작성한다. 그리고 이제는 모든 테스트가 통과하는지 확인한다.
5. 코드를 리팩터링한다. 방금 작성한 테스트나 함수를 개선할 수 있는 부분이 없는지 살펴본다. 개선한 후에도 테스트가 계속
통과하는지 확인한다.
- 테스트 작성을 이제 막 배우기 시작한 사람에게 TDD는 큰 효과가 있다. TDD 작업 방식을 따르면 여러분의 코드에 언제나 테스트가 있을 수 밖에 없다. 그리고 이는 언제나 테스트에 대해 생각하게 된다는 의미다.
- 어떻게든 TDD를 실천하라. 하지만 도중에 이따금 멈추어 큰 그림을 살피는 것을 잊지 말라. 초록색 “테스트 통과” 메시지에 중독된 나머지 진짜 문제 해 결에는 보탬이 안되는 코드를 한 무더기나 쓰게 되기 쉽다.
- 전체 문제를 완전히 파악 하기 힘들 때 한 번에 테스트 하나씩 작은 단계들을 밟는 것이다. 하지만 이 런 접근 방법이 여러분을 잘못된 길로 인도할 수도 있다.
- Tip 68. 상향식이나 하향식이 아니라 끝에서 끝까지 end-to-end 만들어라.
- 복잡한 칩과 시스템은 몇 가지 기본적인 수준의 진단을 내부적으로 수행하는 내장 자체 검사Built-In Self Test, BIST 기능이나, 외부 환경에서 칩에 신호를 주고 그 반 응을 수집할 수 있는 테스트 장치인 테스트 접근 메커니즘Test Access Mechanism, TAM을 갖추기도 한다.
- Tip 69. 테스트할 수 있도록 설계하라.
- 로그 파일에 쌓이는 추적 trace 메시지가 이런 메커니즘 가운데 하나다. 로그 메시지는 반드시 규칙적이고 일관된 형식이어야 한다. 프로그램의 처리 시 간이나 프로그램이 택한 논리 경로를 추론하기 위해 로그를 자동으로 파싱하 고 싶을 때가 있기 때문이다. 형식이 좋지 않거나 일관성이 없다면 진단 메시 지는 읽기 어렵고 현실적으로 파싱하기도 힘든 그냥 ‘내뱉은 것’에 불과하다.
- Tip 70. 여러분의 소프트웨어를 테스트하라. 그러지 않으면 사용자가 테스트하게 된다.
- 테스트, 설계, 코딩, 이 모든 것이 프로그래밍이다.
Topic 42. 속성 기반 테스트
- 우리는 코드가 지켜야 하는 ‘계약’ 을 코드에 포함하자고 이야기했다. 선행 조건에 맞추어 입력을 넣으면 코드 가 생산하는 출력이 주어진 후행 조건에 맞음을 보장해 준다.
- 이렇게 코드에 존재하는 계약과 불변식을 뭉뚱그려서 ‘속성 property’이라고 부른다. 코드에서 속성을 찾아내서 테스트 자동화에 사용할 수 있는데, 이것을 ‘속성 기반 테스트 property-based testing’라 한다.
- Tip 71. 속성 기반 테스트로 가정을 검증하라.
- 속성 기반 테스트가 강력한 까닭은 그저 입력을 생성하는 규칙과 출력을 검증하는 단정문만 설정한 채 제멋대로 작동하도록 놔두기 때문이다. 정확히 어떤 일이 일어날지 절대 알 수 없다. 테스트가 통과할 수도, 단정문이 실패할 수도 있다. 아니면 코드가 주어진 입력을 제대로 처리하지 못하고 중간에 멈춰버릴 수도 있다. 좌절감은 정확히 무엇이 실패했는지 찾아내기 까다로울 수도 있다는 것이다.
- 속성 기반 테스트가 실패했다면 테스트 함수가 어떤 매개 변수를 사용했는 지 알아낸 다음 그 값을 이용하여 별도의 단위 테스트를 정식으로 추가하는 것이 좋다.
- 속성 기반 테스트는 여러분이 코드를 불변식과 계약이라는 관점으로 바라보게 한다. 여러분은 무엇이 변하지 않아야 하고, 어떤 조건을 만족해야 하는지 생각하게 된다. 이런 관점으로 보면 코드에 마법과 같은 효과가 일어난다. 경계 조건은 줄어들고, 데이터의 일관성을 해치는 함수는 더 도드라진다.
Topic 43. 바깥에서는 안전에 주의하라
'좋은 울타리가 좋은 이웃을 만든다.'
- 로버트 프로스트, <담장 고치기>
- 고된 오르막길을 오르는 동안 고비와 난관을 여럿 거치고 나면 자신에게 이렇게 말하기 일쑤다. “휴, 이제 된다!” 그러고는 코드가 완성 되었음을 선포한다. 물론 아직 완성되지 않았다. 여러분은 90% 완성한 것이 다. 하지만 이제는 나머지 90%를 고려해야 한다.
- 내부에서 발생하는 오류뿐 아니라 외부 에서 시스템을 망가트리려 하는 시도까지 고려해야 한다.
- 바깥세상은 거대하 고 대부분 연결되어 있다. 지구 반대편에 사는 따분한 시간을 어쩔 줄 몰라 하는 아이일 수도 있고,테러지원국이나 범죄 조직, 기업 스파이, 헤어진 옛 애인일 수도 있다. 모두 암약하며 당신을 노리고 있다. 패치를 적용하지 않은 구식 시스템이 맨몸으로 인터넷에서 생존할 수 있는 시간은 겨우 몇 분 정도다. 그보다 짧을 수도 있다. 조용히 숨어 있는 것으로 보안을 대신하려는 생각은 통하지 않는다.
- 개발하고 배포 하는 환경에 따라 제각각 보안을 위해 해야 할 일들이 있겠지만, 우리가 언제 나 명심해야 하는 기본 원칙이 몇 가지
1. 공격 표면을 최소화하라.
- 코드의 복잡성은 공격 매개체 attack vector를 유발한다.
- 입력 데이터는 공격 매개체다.
- 인증이 없는 서비스는 공격 매개체다.
- 인증을 요구하는 서비스도 공격 매개체다.
- 출력 데이터는 공격 매개체다.
- 디버깅 정보는 공격 매개체다.
2. 최소 권한 원칙.
- 최소한의 권한만을 꼭 필요한 시간만큼만 제일 짧게 부여하라는 게 또다른 핵심 원칙이다.
3. 안전한 기본값.
4. 민감 정보를 암호화하라.
- 우리는 프로젝트에 필요한 모든 것을 버전 관리 시스템에 넣으라고 강력히 추천했다. 사실 거의 모든 것이다.
이 규칙에 중요한 예외가 하나 있다.
- 암호나 API 키, SSH 키, 암호화 비밀번호, 그 밖의 다른 인증 정보를 소스 코드용 버전 관리 시스템에 넣지 말라.
5. 보안 업데이트를 적용하라.
- Tip 72. 단순함을 유지하고 공격 표면을 최소화하라.
- Tip 73. 보안 패치를 신속히 적용하라.
- 암호학 cryptography에 있어서는 여러분의 상식이 맞지 않을 수 있다는 점을 명심해야 한다. 암호화에 있어서 첫 번째 규칙이자 가장 중요한 규칙은 절대 직접 만들지 말라는 것이다.
- 신뢰할 수 있는 것에만 의지하라. 많이 검토하고, 철저하게 검사하고, 잘 유지 보수되며 자주 업데이트되는 라이브러리와 프레 임워크를 사용하라. 가급적 오픈 소스가 좋다.
- 비밀번호나 생체 정보를 이용한 로그인 인증을 구현하려면 해시와 솔트 salt 가 어떻게 동작하는지, 해커가 레인보우 테이블 rainbow table 같은 도구를 어떻게 사용하는지, 왜 MD5나 SHA1을 더는 쓰면 안 되는지 등 다양한 문제를 이해 해야 한다.
Topic 44. 이름 짓기
- 아무리 좋은 이름을 짓기 위해 노력하더라도 모든 것은 변한다. 코드는 리팩 터링되고, 사용 방식은 바뀌고, 의미는 미묘하게 달라진다. 부지런히 이름을 계속 바꾸지 않으면 악몽 같은 상황에 빠지게 된다. 무의미한 이름보다 더 고 약한 잘못된 이름을 사용하는 코드가 되는 것이다.
- Tip 74. 이름을 잘 지어라. 필요하면 이름을 바꿔라.
🤔 오늘 읽은 소감은?
- '일정의 압박은 리팩터링을 하지 않는 단골 핑계다. 하지만 이는 설득력이 떨어진다. 지금 리팩터링을 하지 않으면 일이 더 진척되었을 때, 즉 신경 써야 할 의존성이 더 많아졌을 때 문제를 고쳐야 하고, 따라서 훨씬 더 많은 시간을 투자해야 한다.' 코딩을 함에 있어서 시대를 관통하는 메세지인 것 같다. 코드를 나쁜 상태로 두는 것은 부패하는 음식물 쓰레기를 버리지 않고 방치하여 방안에 온갖 피해를 입히는 것과 비슷하게 나머지 코드들도 부패시킨다.
- 이 책은 읽으면 읽을 수록 주변에 커뮤니티가 부족한 나같은 비전공자 개발자들에게 코딩과 사이가 더 돈독해지도록, 서서히 줄어가는 열정의 불씨를 더 지필 수 있도록 도와주는 든든한 친구같은 역할을 해준다. 특히나 이번 장은 코딩을 시작함에서 마무리까지 개발자라면 취해야할 일반적인 부분(그래서 양이 어마무시하다)들을 조목조목 설명해준다. 여러 회차 읽어야겠지만 참 든든한 기분이 든다.
😅 궁금한 내용이 있거나, 잘 이해되지 않는 내용
• Thrashing
과도한 메모리 사용으로 인하여 지속해서 페이지 폴트가 발생하는 상황을 말한다. 그 결과 시스템의 성능이 급격하게 떨어진다.
• 왜 MD5나 SHA1을 더는 쓰면 안 되는지?
- 한국인터넷진흥원 "암호이용활성화" 웹 사이트에서 제공하는 <암호기술 구현 안내서> 에서 기본적인 내용 학습 가능
https://naleejang.tistory.com/218
🤓 도서 추천
◦ 로버트 세지윅 Robert Sedgewick - <<알고리즘>>
◦ 도널드 커누스 Donald Knuth - <<The Art of Computer Programming>>
◦ 마틴 파울러 - <<리팩터링>> // <<테스트 주도 개발>>(인사이트, 2014)
'도서 > 실용주의프로그래머_#bookclub#TIL' 카테고리의 다른 글
실용주의 프로그래머 #18일차(Mission) (0) | 2022.04.04 |
---|---|
실용주의 프로그래머 #17일차 (0) | 2022.04.04 |
실용주의 프로그래머 #12일차 (0) | 2022.03.30 |
실용주의 프로그래머 #9일차 (0) | 2022.03.28 |
실용주의 프로그래머 #7일차 (0) | 2022.03.24 |