Community

개발자 99% 커뮤니티에서 수다 떨어요!

← Go back
Assignment 12 - TIL (2022. 5. 28.)
by pksl
#pragmatic
2년 전
733

오늘의 TIL 3줄 요약

  1. ‘우연에 맡기는 프로그래밍’에서 벗어나, ‘의도적으로 프로그래밍’을 해야겠다.

  2. TDD 방식으로 개발해보자.

  3. [Topic 40. 리팩터링][Topic 43. 바깥에서는 안전에 주의하라]는 두고두고 읽어보자.

TIL (Today I Learned) 날짜

2022-05-28

오늘 읽은 범위

  • 7장. 코딩하는 동안 (p.273 ~ p.348)

책갈피

  • 운전을 안전하게 잘하는 사람은 언제나 자기 상황을 검토하고, 잠재적인 문제들을 점검하며, 예상하지 못한 일이 생길 때에도 잘 대처한다. 코딩도 똑같다. 대부분은 반복적인 일이지만 정신을 늘 기민하게 유지하면 재앙을 막을 수 있다. (p.275)

  • 우리는 우연에 맡기는 프로그래밍, 곧 행운과 우연한 성공에 의존하는 프로그래밍을 하지 않아야 한다. 대신 ‘의도적으로 프로그래밍’ 해야 한다. (p.282)

  • 잘 되는 듯한 답을 찾는 것과 올바른 답을 찾는 것은 다르다. (p.287)

  • 더 경험이 적은 프로그래머에게 코드를 상세히 설명할 수 있는가? 그렇지 않다면 아마 우연에 기대고 있는 것일 터이다. (p.288)

  • 사용하는 알고리즘의 차수를 추정하라. (p.296)

  • 여러분의 추정을 테스트하라. (p.297)

  • ‘성급한 최적화’를 조심하라. (p.298)

  • 코드를 리팩터링하는 것은 사실 ‘고통 관리’를 실천하는 것이다. (p.303)

  • 일찍 리팩터링하고, 자주 리팩터링하라. (p.304)

  • 테스트는 버그를 찾기 위한 것이 아니다. (p.307)

  • 상향식이나 하향식이 아니라 끝에서 끝까지 만들어라. (p.313)

  • 테스트할 수 있도록 설계하라. (p.317)

  • 속성 기반 테스트로 가정을 검증하라. (p.322)

  • 공격자는 엄청나게 똑똑하지도 않고, 어느 한구석 특별한 능력이 있는 것도 아니다. 모두 개발자가 부주의한 탓이다. (p.331)

  • 조용히 숨어 있는 것으로 보안을 대신하려는 생각은 통하지 않는다. (p.332) 중요

  • 단순함을 유지하고 공격 표면을 최소화하라. (p.335)

  • 보안 패치를 신속히 적용하라. (p.338)

  • 높은 무작위도를 갖는 길고 이해하기 힘든 암호를 권하고 싶을 것이다. 하지만 인위적인 제약을 걸면 무작위도를 낮추고 나쁜 비밀번호 습관을 부추겨서 사용자 계정 탈취를 도와주는 꼴이 될 뿐이다. (p.339)

  • 이름을 잘 지어라. 필요하면 이름을 바꿔라. (p.347)

오늘 읽은 소감

개인적으로 코딩하다가 막히게 되는 경우들은 보통 다음 두 케이스로 구분되는 것 같다.

  1. 구현하기 위해 어떻게 해야 할지 떠오르지 않을 때

  2. 의욕이 나지 않아 코딩이 손에 잡히지 않을 때

1번은 주로 기능이 거대해서 어디서부터 손을 대야 할지 모르겠는 경우나, 특정 로직을 어떻게 구현해야 할지 그림이 그려지지 않을 경우이다.

2번은 개인의 컨디션 문제나 확정된 사양(기획)을 납득하지 못하는 등의 경우에 많이 발생하고, 개발 도중 기획의 공백을 발견했는데 임의로 메워두기에는 연쇄적으로 신경 써야 할 로직이 많이 생겨날 때 개발 흐름이 끊겨서 발생하는 경우도 많다.

이렇게 막혔을 때 나는 [Topic 37. 파충류의 뇌에 귀 기울이기]에서 알려준 것처럼 예광탄 코드를 짜듯이(잘 풀렸을 때 실제로 바로 적용할 수 있도록) 프로토타이핑을 진행해왔다. 며칠 전에도 프로젝트에서 ‘유효기간이 있는 마일리지 기능 추가’ 로직을 구현하면서 뚜렷한 방법이 떠오르지 않았기에 프로토타이핑을 활용했다.

우선 목표를 최대한 작은 단위로 분할해두고 핵심이 되는 부분부터 하나씩 클리어해 나아간다. 이런 과정을 통해 정확히 어떤 부분에서 생각이 막혔던 건지 더 상세하게 분석할 수 있어 구글링(리서치)의 효율도 올라가게 된다. 또한 이 과정에서 시야도 한층 넓어지게 되고 습득하는 지식도 많다.

물론 큰 문제를 작게 분할해서 보기 시작하면 안 보이던 부분들을 분석할 수 있지만 그만큼 전체적인 그림을 놓치기도 쉽다. 따라서 작은 목표들을 클리어해 나아갈 때마다 ‘이런 식으로 접근하는 게 맞는 건가?’ 라는 식으로 끊임없이 회고해야만 설령 도착점이 최종 목표와 다른 곳이더라도 생각보다 많이 어긋나지 않게 되어 비교적 쉽게 되돌아갈 수 있다.

[Topic 38. 우연에 맡기는 프로그래밍]은 확실하지 않은 코드로 프로그래밍할 경우 마주하는 이슈들에 대해서 알려주고 있다. 이런 이슈들을 피하기 위해서는 다음과 같은 ‘의도적으로 프로그래밍하기’ 원칙을 잘 지켜야 한다고 한다.

  1. 언제나 지금 무엇을 하고 있는지 알아야 한다.

  2. 작성한 코드를 상세히 설명할 수 있어야 한다.

  3. 계획을 세우고 그것을 바탕으로 진행해야 한다.

  4. 늘 최악의 상황을 상정하고, 신뢰할 수 있는 것에만 기대라.

  5. 가정을 기반으로 코드를 작성한 경우 반드시 기록(주석)으로 남겨라.

  6. 어떤 일이든 추측만 하지 말고 실제로 시험해 보라. 단정문 작성이 좋은 방법이다.

  7. 중요한 것에 먼저 시간을 투자하라.

  8. 레거시 코드가 앞으로 짤 코드를 지배하도록 놓아두지 말라.

이 원칙들은 ‘프로그래밍’의 기본이 되는 내용인 것 같다. 물론 6번같이 잘 지켜지지 않는 경우도 더러 있지만, 내용을 읽어봤을 때 새로이 알려주는 원칙(개념)들이라고 생각되기보다, 당연하게 마땅히 지켜야 하는 것들로서 받아들여졌다. 회사 개발팀 위키의 메인에 옮겨 적어둬야겠다.

코드의 최적화는 중요하다. [Topic 39. 알고리즘의 속도]에서는 코드의 최적화를 위해 알고리즘의 기본부터 실제로 비지니스 로직에 적용된 ‘알고리즘을 개선하기 위해 해야 하는 방법’(알고리즘의 직접적인 개선이 아닌 개선 방향을 찾는 법)을 제시해주고 있다. 핵심은 책갈피에도 적어놓았듯이, 코드를 통해 ’사용하는 알고리즘의 차수를 추정하라.’ 와 프로파일링(벤치마크)을 통해 ‘여러분의 추정을 테스트하라.’ 이다.

하지만 실용주의 프로그래머라면, 본문에서 말했듯이 ‘성급한 최적화’는 경계하는 게 중요하다고 생각한다. 알고리즘을 개선하겠다고 코드를 되레 복잡하게 만들어두고는 성능이 별반 차이 없으면 시간만 날린 것이기 때문이다.

리팩터링은 코드의 기능을 바꾸지 않으면서 내부의 코드를 바꾸는 것으로, 코드의 유지보수에 있어 무엇보다 가장 중요한 작업이다. 리팩터링을 제때 하지 않고 기술 부채로서 쌓아두기만 한다면, 회사에서 지금 진행하는 프로젝트처럼 서비스 전면 리뉴얼을 마주하게 될 것이다. [Topic 40. 리팩터링]을 통해 리팩터링이 필요한 부분과 해야 하는 시점, 리팩터링을 안전하게 하는 방법을 확인할 수 있었다. 이 토픽의 내용들은 추후 리팩터링 작업 기간에 관해 논의할 즈음에 이 토픽을 다시금 읽어보고, 또 다른 구성원들도 납득할 수 있게 읽어 보는 걸 권장해야겠다.

구현과정에서 진행하는 단위테스트와 구현한 코드를 모아 진행하는 통합테스트만으로도 충분한데, 굳이 뻔히 눈에 보이는 케이스들만을 테스트하기 위해 코드까지 따로 작성해야 하는 이유를 이해하지 못했었다. RSpec같은 걸 활용해 TDD로 개발하게 되면 오히려 ‘테스트 코드 작성’에 잠식되어 업무 효율이 눈에 띄게 나빠질 것 같아 경계해왔다.

그랬던 내게 [Topic 41. 테스트로 코딩하기]는 테스트를 올바르게 하는 방법을 알려주어 테스트에 대한 새로운 시각을 가지도록 만들었고, TDD에 대한 긍정적인 면을 볼 수 있게 해주었다.

코딩의 시작부터 테스트를 염두에 두고 개발하는 방식이면 기존보다 부담이 덜어질 것 같다. 또한 가만히 생각해보니 기존처럼 테스트를 CLI 나 로컬 서버, 테스트 서버에서 수행하는 걸로 끝내는 게 아니라 테스트 코드까지 따로 작성해 둔다면 그 또한 나중에 다른 구성원이 보고 작동을 이해할 수 있게 도움을 주며, 나중에 이미 해뒀던 테스트를 반복하지 않게 시간을 절약할 수 있을 것으로 예상된다. 그리고 코드에서 발생하는 이슈(장애, 버그)들을 발견할 때마다 테스트 케이스로서 코드로 녹여내면 굳이 이슈트래커를 꺼내 보지 않더라도 해당 이슈들에 대해 알게 될 수 있을 것 같다.

[Topic 42. 속성 기반 테스트]에서는 눈에 보이는 케이스만 테스트하는 게 아니라 입력되는 데이터들을 랜덤하게 설정하는 접근법에 대해 알게 되었다. 이는 놓치기 쉬운 검증(Validation) 과정들을 집어낼 수 있도록 도와준다.

테스트를 멀리하다 보니 테스트 코드를 작성하는 법이나, 테스트를 염두에 둔 설계 같은 테스트 문화들을 당장 받아들이기엔 쉽지는 않을 것 같지만 가능한 것부터 바로 차근차근 적용해봐야겠다.

제일 중요한 내용이 나왔다. [Topic 43. 바깥에서는 안전에 주의하라]를 통해 기본 보안 원칙들을 체크해 볼 수 있었고 보안의 중요성에 대해 다시금 정리해 볼 수 있었다. Github같은 오픈된 공간에 AWS 인증정보를 한 번이라도 잘못 커밋하는 순간 크롤링 당해서 요금 폭탄을 맞게 될 수도 있다. CMS를 이용 중일 경우 보안패치를 제때 하지 않으면 취약점을 통해 모든 DB 정보들이 털리기도 한다. 방화벽을 제대로 걸어놓지 않으면 외부에서 쉴 새 없이 침입이 들어오는 모습을 볼 수 있다. 이런 식으로 늘 외부에서는 서비스의 빈틈을 뚫고 들어오기 위해 침입을 끊임없이 시도한다. 따라서 보안에 구멍이 생기지 않도록 늘 신경 써야 한다.

개인적으로는 보안에 관해서는 꼼꼼하게 챙길 여력이 없고, 지식도 부족해 직접 설정하거나 구현하지 않는 주의이다. 보안 대책이 잘 이루어진 외부의 서비스들을 비용을 치르고 적극적으로 활용 중이다. 몇 가지 예를 들면 다음과 같다.

  • AWS의 ELB를 활용해 분산 처리 기능과 함께 DDoS 방어와 같은 보안을 챙김

  • AWS RDS는 외부에서 직접 접근하지 못하게 하고 SSH 터널링을 통해서만 들어갈 수 있도록 설정 함

  • AWS S3는 외부에서 객체에 직접 접근하지 못하게 하고 Presigned URL을 통해서만 접근할 수 있도록 함

  • Firebase Authentication을 활용해 회원관리(회원가입, 로그인)를 하고 백엔드 서버에는 로그인된 계정의 JWT를 전달해서 인증함

7장에서는 [Topic 40. 리팩터링][Topic 43. 바깥에서는 안전에 주의하라]이 제일 중요한 내용으로서 잊을만하면 꺼내 봐야 할 중요한 토픽이라고 생각한다.

코딩할 때 무엇보다 가장 많은 시간을 소요하게 하는 게 바로 이름짓기라고 생각한다. [Topic 44. 이름 짓기]에서는 이름의 중요성에 대해 말하고 있다.

이름짓기는 각 언어나 프레임워크의 가장 잘 알려진 스타일 가이드를 준수하는 게 좋다고 생각한다. Typescript Style Guide, Python Style Guide 등 각각의 스타일 가이드 문서에서 변수명을 어떤 케이스로 표현해야 하는지 알려주며, 적절한 단어를 고르는 법같이 스타일 가이드만으로 부족한 부분은 Python Naming Convention 처럼 각각의 네이밍 규칙들을 검색해 보면 도움이 된다.

오늘 읽은 다른사람의 TIL

  • 6장 TIL 및 앞서 작성된 7장 TIL

참고 자료

  • 읽어볼만한 책

    • Robert Sedgewick 《알고리즘》, 《An Introduction to the Analysis of Algorithms(알고리즘 분석 입문)》