///
Search
Duplicate
📙

[요약] 구글 엔지니어는 이렇게 일한다

이 문서는 토스페이먼츠 프런트엔드 챕터에서 Learning Share의 일환으로 공유되는 문서입니다.
작성자: @한재엽
Updated: 22.6.26
 Frontend Chapter
Table of Contents
총평

Part I. 전제

Chapter 1. 소프트웨어 엔지니어링이란?

소프트웨어 엔지니어는 시간의 흐름과 언젠가 변경될 가능성에 더 신경써야 한다.
소프트웨어 기대 생애 동안 요구되는 모든 가치 있는 변경에 대응할 수 있다면 그 프로젝트는 지속 가능하다. 라고 할 수 있다.
소프트웨어 엔지니어링이란 여러 버전의 프로그램을 여러 사람이 참여해 개발하는 것이다.
“기발한”이 칭찬으로 느껴지면 프로그래밍이라 하고, 질책으로 느껴진다면 소프트웨어 엔지니어링이라고 한다.
개발 프로세스, 업무 프로세스는 눈치채기 어렵게 천천히 나빠지는 경향이 있다. “끓는 물 속 개구리가 되지 않도록 주의하자”
비욘세 규칙 (The Beyonce Rule)
인프라를 변경하여 서비스가 중단되는 등의 문제가 발생하더라도, 같은 문제가 지속적 통합 시스템의 자동 테스트에서 발견되지 않는다면 인프라 팀의 책임이 아니다.
⇒ 네가 좋아했다면 CI 테스트를 준비해뒀어야지.
원점 회귀?
개발 과정에서 문제를 일찍 발견할수록 비용이 적게 든다.
타임라인에서 문제 발견 시점을 왼쪽으로 이동시킬수록 수정 비용이 줄어든다.
개념잡기 → 설계 → 구현 → 리뷰 → 테스트 → 커밋 → 카나리 → 배포
비용이란?
경제적 비용 (돈)
리소스 비용 (하드웨어)
인적 비용 (엔지니어링)
거래 비용 (실행에 옮기는 비용)
기회 비용 (실행에 옮기지 않는 비용)
사회적 비용 (선택이 사회 전체에 미치는 영향에 대한 비용)
좋은 엔지니어링 결정이란 가용한 모든 근거 자료에 적절한 가중치를 부여하고 이러한 지식을 바탕으로 균형점을 잡는 일.
반드시 해야 하는 일 (법적 요구사항, 고객 요구사항)
근거에 기반하여 내릴 수 있는 최선의 선택
Action Item
 원점회귀 할 수 있는 시스템 만들기
Design review request (or Pre-commit review)
Pair programming time
Testing Study
 테스트 환경 구축과 테스트 문화 만들기 (진정한 지속적 통합 환경 만들기)
테스트 scaffolding
learning share
best practice

Part II. 문화

Chapter 2. 팀 워크 이끌어내기

인간은 간헐적 버그들의 집합에 가깝다.
혼자 일하려 한다면 실패할 위험성을 불필요하게 키우고 자신의 성장 잠재력을 속이는 것이다.
조기 공유?
이미 구현된 선례가 있는 것은 아닌지 파악할 수 있다.
초기 설계에 숨겨져 있는 근본적인 실수를 방지할 수 있다.
혼자하는 것보다 아무튼 더 빠르게 할 수 있다.
프로젝트의 버스 지수(Bus factor)를 높일 수 있다.
사회적 상호작용의 세 기둥
겸손(Humility)
당신은 모든 것을 알지도 완벽하지도 않습니다. 겸손한 사람은 배움에 열려 있습니다.
존중
함께 일하는 동료를 진심으로 생각합니다. 친절하게 대하고 그들의 능력과 성취에 감사해합니다.
신뢰
동료들이 유능하고 올바른 일을 하리라 믿습니다. 필요하면 그들에게 스스로 방향을 정하게 해도 좋습니다.
우리 자존감을 우리가 작성한 코드와 동일시해서는 안 됩니다. 나는 내 코드가 아님을 명심하세요.
자신과 만든 것을 구분짓고 자신을 믿고 동료를 믿으세요.
Action Item
코드 리뷰 가이드 만들어보기

Chapter 3. 지식 공유

다음 두 가지가 먼저 자리 잡아야 지식이 전파될 수 있다.
모르는 것을 인정할 수 있도록 돕는 심리적 안전
배우고자 하는 배움의 문화
안티패턴
거짓된 놀람 금지: 뭐? useCallback이 뭔지 모른다고?
세세하게 고쳐주기 금지: 자신을 뽐내려는 무의식에 기인하는 경향이 있다.
뒷자석 운전 금지: 토론 중 적절한 발언권 없이 끼어들어 의견 제시하지 말기
지식 공유는 질문에서부터
쿠도스 제도 (공개칭찬)
동료의 기여를 공개적으로 인정하는 제도
Action Item
심리적 안전을 위한 환경이 구축될 수 있도록 고민하기
Weekly I Learned 라는 코너?

Chapter 4. 공정 사회를 위한 엔지니어링

편견에서 벗어날 수 없다.
이를 인정하고 의식적으로 개선하려 하자.
다양한 사용자 층을 포용하기 위해선 조직 구성에 있어서도 다양성을 갖춰야 한다.
자신을 솔직하게 바라보고 성찰하자
모두를 위해 만들지 말자. 모두와 함께 만들자
제품을 이용하기 가장 어려운 이들을 위해 설계하자
가정하지 말고, 시스템 전반의 공정성을 측정하자
변할 수 있다
일부 사용자에게 해를 끼칠 수 있는 제품이라면 출시를 늦추는 것이 맞다
Action Item
 인터뷰어 풀 신경쓰기
 접근성 공부하고 라이트닝 톡 준비하기

Chapter 5. 팀 이끌기

Manager: 사람을 이끈다.
엔지니어링 관리자 (EM)은 구성원의 성과, 생산성, 행복을 책임지면서 제품의 사업적 요구까지 충족시켜야 한다.
Tech Lead: 기술과 관련된 책임을 진다.
직접 나서서 일을 빠르게 처리하기도 하고
다른 팀원에게 위임할지 판단한다.
규모와 역량이 커질수록 위임하는 편이 낫다.
테크 리드 매니저 = Manager + Tech Lead
바나나를 재배하면서 사과를 세는 함정에 빠지지 말 것
관리 업무는 효과가 나타나기까지 보통 더 긴 시간을 인내해야 한다.
피터의 법칙
자신의 무능력이 드러나는 직급까지 승진하는 경향
Servant Leadership
마치 집사가 가정의 안녕과 건강을 챙기듯, 팀을 떠받드는 것
관리하려는 충동을 이겨내는 것
무슨 일을 처리할지 고민하고(What) 어떻게 처리할지는 팀에게 믿고 맡긴다.
안티패턴
안티패턴 1. 만만한 사람 고용하기
좌지우지할 수 있는 사람을 고용해서 권위와 위치를 공고히 한다
안티패턴 2. 저성과자 방치
기대를 충족해주지 못하는 사람을 다루는 것이 가장 고난이도 문제
팀은 누가 저성과자인지 정확하게 알고 있다
저성과자를 방치하는 것은 고성과자가 팀에 합류하는 것을 막고 고성과자가 팀을 떠나게 하는 요소가 된다.
기간을 정하고 구체적인 목표를 제시할 것.
점진적이고 측정가능한 목표.
안티패턴 3. 사람문제 무시하기
사회적 문제 / 기술적 문제 둘 다 신경쓸 것
안티패턴 4. 만인의 친구되기
안티패턴 5. 채용 기준 타협하기
안티패턴 6. 팀을 어린이처럼 대하기
올바른 패턴
자존심 버리기
대신 집단으로서의 자존심과 정체성 강화하기
마음 다스리기
평정심 유지하기
사람들을 고무시키는 것
스스로 문제를 해결하도록 질문하고 직접 해결하기는 가장 마지막에 택하기
촉매재가 되기
팀원간의 상호작용을 만들기
장애물 치우기
정확한 답을 알고 있기 보다 올바른 사람을 알고 연결해주기
꼭 멈춰야 된다고 생각되는 열차만 선택해서 멈추기
선생이자 멘토되기
멘티에게 도움이 얼마나 필요한지 측정하고 적절하게 input 넣기
명확한 목표 세우기
사명감
정직하기
피드백을 칭찬 속에 숨기지 말기
행복한지 확인하기
경력 관리 챙겨주기
새로운 것 배우기
의미있는 제품, 서비스 론칭
똑똑한 사람들과 일하기
등을 성취할 수 있도록 고민하기
위임하되 곤란한 일은 직접 처리하기
대신할 사람을 찾기
혼란으로부터 팀을 보호하되 정직하기
가능한 한 많은 정보를 팀과 공유하되 업무에 방해받지 않도록 하기
Action Item
엔지니어 경력 프레임워크 만들어서 경력 개발 1on1 하기
 프런트엔드 챕터의 목적 생각해보기
 플랫폼 팀의 이니셔티브 정의하기

Chapter 6. 성장하는 조직 이끌기

Always Be Deciding (늘 결정하라)
이 결정대로 시도해보고 어떻게 되는지 지켜보자. 상황을 보고 그 때 또 결정해보죠.
Always Be Leaving (늘 떠나기)
스스로 single point of failure 되지 않도록 하기
이 문제를 처리할 수 있는 사람이 정말 나뿐일까?
업무 크리티컬 패스 상에서 내가 사라지도록 하기
관찰과 경청 9%, 절묘하고 시의적절한 개입 5%
Always Be Scaling (늘 확장하라)
상황을 주도하는 능동형 일보다 상황에 맞춰 대응하는 반응형 일의 비중이 커진다.
급한 문제와 중요한 문제가 있는데, 급한 문제는 중요하지 않고 중요한 문제는 급하지 않다.
나만이 할 수 있는 일을 처리해야 한다.
따로 blocking 시간을 준비해둘 것.
정말 중요한 20% 남기고 나머지 80%는 버릴 것.
Action Item
 최대한 위임하기
 blocking 시간 마련하기

Chapter 7. 엔지니어링 생산성 측정하기

조직이 2배 커지면 소통 비용은 제곱으로 늘어난다. - 맨먼스 미신
선별하라. - 측정할 가치가 있는가?
어떤 결과를 기대하고, 왜 그런가?
데이터가 기대한 결과를 뒷받침 한다면 어떤 조치를 취하겠는가?
딱히 액션이 없다면 측정할 가치가 없다. (현상 유지 편향)
부정적인 결과가 나온다면 적절한 조치를 취할 것인가?
대부분의 경우 이미 정해진 진로를 잘 틀지 않는다.
결과가 부정적이더라도 딱히 액션이 없다면 측정할 가치가 없다.
결과에 따른 조치는 누가 결정하고, 언제 수행하는가?
결과, 결정에 따라 수행할 여유가 있는가?
결과가 상대적으로 긴 시간동안 유의미한가?
측정 결과를 단순히 계획의 뒷받침 용도로 쓰려고 하는가?
측정할 수 있는 지표들이 문제를 평가하기에 충분히 정확한가?
GSM 프레임워크 기반의 선별
Goal (목표): 원하는 최종 결과를 고차원 어휘로 표현한다.
Signal (신호): 최종 결과를 이뤘는지 판단하는 방법
Metric (지표): 실제로 측정하는 대상
엔지니어링 생산성을 구성하는 다섯가지 요소, 퀀츠(QUANTS)
코드 품질 (Quality of the code)
엔지니어들의 몰입도 (Attention from engineers)
지적 복잡성 (Intellectual complexity)
박자와 속도 (Tempo and velocity)
만족도 (Satisfaction)
Action Item
측정하고자 하는 대상이 있는지, 있다면 GSM 기반으로 분석해보고 측정 시작하기
생산성을 개선할 수 있는 요소가 있는지 살펴보기

Part III. 프로세스

Chapter 8. 스타일 가이드와 규칙

규칙은 좋은 행동을 장려하고 나쁜 행동을 억제하기 위해 필요하다.
이루고자 하는 목표를 명확히 했을 때, 규칙이 따라온다.
규칙을 만들 땐,
규칙의 양을 최소화 해야 한다.
코드를 읽는 사람에게 맞춰야 한다.
일관되어야 한다.
예상치 못한 동작을 유발하는 구조는 피해야 한다.
실용성을 생각해 예외를 허용한다.
코드는 작성되는 횟수보다 읽히는 횟수가 더 많으며 시간이 지날수록 더 벌어진다.
쓰기에 간편함보다 읽기에 간단한 쪽에 가치를 둔다.
주석?
문서화 주석구현 주석으로 나뉜다.
문서화 주석은 jsdoc을 생각하면 된다.
구현 주석은 뻔하지 않은 선택을 한 이유를 명시하기 위해 사용된다.
일관성
코드가 일관되면 의미 단위로 잘 구분되어 분석하기 쉬워진다.
어떻게 구현할지 고민하는 대신 무엇을 수행하느냐에 집중할 수 있다.
모듈화하기도 쉽다.
규모가 커지면서…
완전히 일관되는 일은 없을 것이며 그것을 목표로 삼지 않게 되었다.
완벽한 일관성을 추구하기에는 얻는 것보다 비용이 큰 단계에 도달한 것이다.
jscodeshift 같은 도구로 일괄 변경해도 완벽하지는 않기 때문이다.
스타일 가이드의 목적
위험을 피하기 위함인가?
모범 사례를 적용하기 위함인가?
일관성을 보장하기 위함인가?
규칙은 고정불변이 아니다.
다른 결론에 도달할 수 있는지를 다시 평가할 수 있다.
투표가 아니라 합의로 이뤄진다.
개인 취향은 무시한다.
트레이드 오프 평가에 기초하여 의사결정한다.
다수결이 아니다.
가능한 규칙들은 ‘자동으로' 적용되게끔 해야 한다.
Action Item
운영중인 ADR을 스타일 가이드로 수정하고 근거가 되는 스레드를 추가한다.
UX Engineering 부분도 살펴보자.
규칙을 변경할 수 있는 프로세스를 고민해본다.
GitHub Discussion?
자동화 영역이 남아있는지 확인해본다.

Chapter 9. 코드 리뷰

코드 리뷰는 작성자 이외의 사람이 코드를 비판적으로 검토하는 프로세스이다.
구글에서 코드 리뷰는 소프트웨어 엔지니어라면 모두가 반드시 따라야 하는 몇 안 되는 전사적인 프로세스이다.
코드는 부채다
코드가 그 자체로 부채임을 인정해야 한다.
존재만으로 어느 순간 누군가가 유지보수해야 할 대상이 된다.
밑바닥부터 만들고 있다면 뭔가 잘못하고 있는 것이다.
누군가 비슷한 코드를 이미 작성해놓았을 가능성이 크다.
새로운 걸 설계할 때는 작성 전에 챕터에서 이야기하면 좋다.
무엇을 검토하는가?
정확성
이해 용이성
가독성
고민
이 코드는 유지보수하기 쉬운가?
내게 기술 부채를 안겨주나?
우리 팀원 중에 이 코드를 유지보수해줄 전문가가 있나?
뭐가 좋지?
코드가 정확한지 확인한다.
일반적으로 변경 작성자가 선택한 방식을 존중해준다.
완벽하다고 합의될 때까지 기다리지 않고 코드베이스를 개선한다고 인정되면 변경을 승인한다.
완벽할 필요가 없다.
변경된 코드를 다른 엔지니어도 잘 이해한다.
지속해서 유지 가능한 코드인지 검토한다.
코드베이스가 일관되게 관리된다.
일정한 표준을 따라야 조직 안에서 이해되고 유지보수될 수 있다.
팀이 소유권을 더 강하게 느낀다.
리뷰 프로세스로 모노레포는 조직의 공동 소유물임일 인식시킨다.
지식이 공유된다.
코드 리뷰 자체의 기록이 남는다.
모범 사례
방식에 결함이 있을 때만 대안을 제시한다.
방식이 잘못되었다고 가정하기 전에 그렇게 처리하게 된 이유가 무엇인지부터 물어본다
신속하게 피드백한다.
제안한 변경은 팀의 소유임을 잊지 말아야 한다.
작성자 또한 왜 그렇게 처리했는지 설명할 준비를 해둬야 한다.
리뷰어가 단 댓글은 모두 할일로 취급해야 한다.
작성자와 리뷰어 모두에게 배움의 기회임을 기억해야 한다.
요청자 입장에서,
작게 만들어야 한다.
200줄 이하
변경에 대한 설명을 잘 써야 한다.
무엇을 왜 변경하는지,
리뷰어는 최소한으로
가능한 자동화 한다.
코드 리뷰의 종류는?
그린필드 리뷰 (신규 프로젝트 또는 새로운 기능)
초기에 내린 가정들이 변해도 여전히 유지보수하기 쉬워야 한다.
설계 리뷰를 강도 높게 진행한다.
소유자를 명확히 한다.
동작 변경, 개선, 최적화
버그 수정 (롤백)
기능 추가가 포함되어선 안 된다.
롤백을 유발할 수 있는 모든 변경은 가능한 작고 원자적이어야 한다.
리팩터링과 대규모 변경
Action Item
코드 리뷰 가이드 만들어보기
코드 리뷰 관련해서 계속 개선해나갈 working group 만들기

Chapter 10. 문서

문서도 코드와 같다.
문서에 정책과 규칙이 있어야 한다.
버전 관리 시스템에 등록해 관리해야 한다
관리 책임자를 명시해야 한다
변경 시 리뷰를 거쳐야 한다
주기적으로 평가해야 한다.
최신 정보 반영 여부가 확인되어야 한다.
하나의 문서는 하나의 목적에 집중해야 한다.
종류
참조용 문서 자료
설계 문서
튜토리얼
개념 설명 자료
랜딩 페이지
문서화
누가: 대상 독자가 누구인지 문서 안에서 명확히 밝혀줘야 할 때가 있다.
무엇: 목적
언제: 문서가 생성되고, 리뷰되고, 갱신된 날짜가 명시되어 있어야 한다.
어디에: 장소
왜: 목적, 문서에 대한 소개에 들어가곤 한다.
좋은 문서
의도한 역할을 잘 수행하는 문서
폐기
신선도 보증 기간
마지막으로 리뷰한 날짜를 기준으로 3개월 동안 갱신되지 않을 시 알림 메일을 보낸다.
문서 자료를 테스트와 같은 수준으로 취급해야 할지는 모르겠다.
하지만 문서는 조직의 규모가 커질수록 중요해진다.
Action Item
문서 쓸 때는 작성자와 날짜 남기는 습관 들이기
GitHub에서 문서를 관리해야 하나 싶기도…

Chapter 11. 테스트 개요

테스트는 엔지니어에게 신뢰를 줄 때만 가치가 있다.
작성한 테스트는 수시로 실행될 수 있어야 한다.
Why?
디버깅 감소
코드의 존속 기간 전체로 봤을 때, 결함이 줄어든다.
자신있게 변경 할 수 있다.
리팩터링을 통해 코드 품질을 끊임없이 개선할 수 있다.
더 나은 문서자료
애플리케이션의 행위를 기술함으로써 문서로써의 역할을 한다.
더 단순한 리뷰
리뷰할 때도 동작을 예측하기 쉽다
설계
테스트를 잘 작성하면 잘못된 설계를 바로잡을 수 있다.
불필요한 노출 등을 숨기면서 더 응집도 높은 설계가 만들어진다.
테스트를 작성하는 것과 ‘잘' 작성하는 것은 별개이다.
테스트를 작성하고 맨날 깨진다고 하는 것은 테스트를 잘못 작성했기 때문이다.
대개 테스트에 대한 공부없이 테스트를 작성하곤 한다.
테스트의 장점을 크게 누리지 못한 사람들이 부정적인 견해를 드러내곤 한다.
테스트는 두 가지 기준으로 분류할 수 있다.
크기: 테스트 케이스 하나를 실행하는데 필요한 자원 (메모리, 프로세스, 시간)
(LOC가 아니라) 프로세스 하나, 기기 하나, 여러 기기에서 테스트가 돌아감을 기준으로 크기를 구분짓는다.
전통적인 단위 테스트, 통합 테스트 대신 크기로 구분짓는다.
큰 테스트는 가장 복잡하고 검증하기 어려운 시나리오에만 제한적으로 활용한다.
범위: 검증하려는 코드 경로
크기에 따른 테스트
작은 테스트
하나의 프로세스에서 실행되어야 하는 테스트 ( → 스레드 )
테스트도 테스트 대상 코드와 같은 프로세스에서 실행되어야 한다.
네트워크와 디스크에 접근하는 블로킹 호출을 사용해선 안 된다.
필요한 경우 테스트 대역을 사용한다.
강한 의존성을 가벼운 인프로세스 의존성으로 대체해주는 수단
Why?
블로킹 호출이 작은 테스트에 포함되면 전체적인 테스트 수행 속도가 느려진다.
외부와 의존하게 되면서 불규칙한 결과가 나오고 이로 인해 테스트 수행 결과가 비결정적이 된다.
범위와 상관없이 언제나 작은 테스트를 작성하길 권장한다.
중간 테스트
블로킹 호출을 이용할 수 있으나(로컬호스트) 외부 시스템과의 통신은 불허한다.
흔히 말하는 통합테스트: 웹 UI와 서버 코드의 조합도 테스트 할 수 있다.
외부 요인이 개입되므로 성능과 결정성을 온전히 우리 스스로가 보장할 수 없다.
큰 테스트
여러 개의 기기를 활용할 수 있다.
비결정성으 크게 높아지기 때문에 몇 가지 용도에 한정해서 활용한다.
end to end test는 설정을 검증하는게 주된 목적이다.
빌드나 릴리스 때만 수행되도록 하여 개발 워크플로우에 영향을 주지 않도록 한다.
크기와 상관없이 테스트의 공통 특성
1.
하나의 테스트 suite는 밀폐되어 있어야 한다.
setup, execute, tear down 하는데 필요한 모든 정보를 담고 있어야 한다.
테스트 수행 순서 같은 외부 환경에 관해서는 가능한 한 아무것도 가정하지 않아야 한다.
2.
확인하려는 행위를 수행하는 데 필요한 정보’만’ 포함해야 한다.
3.
무엇을 검사하는지가 명확해야 한다.
a.
정확성 검사는 사람이 직접해야 하기 때문에 조건문이나 순환문 같은 제어문은 쓰지 않는게 좋다.
b.
복잡해질수록 버그가 발생할 수 있으며 실패 원인을 파악하기 힘들어진다.
4.
테스트는 오직 실패했을 때만 들여다봐야 한다.
범위에 따른 테스트
좁은 범위 테스트: 보통 단위 테스트
중간 범위 테스트: 보통 통합 테스트
넓은 범위 테스트: 보통 기능, 종단간 테스트
구글은 되도록 작은 테스트, 좁은 범위 테스트를 추구한다.
크기, 범위 별로 80:15:5 비율을 유지한다.
커버리지는 테스트되지 않은 코드가 어디인지 알려줄 수 있지만 시스템이 얼마나 제대로 테스트되었느냐를 판가람하는 지표로는 적합하지 않다.
구글의 테스트 혁명
오리엔테이션 수업
테스트 인증 프로그램
화장실에서도 테스트
Action Item
테스트 혁신 진짜 해야겠다

Chapter 12. 단위 테스트

단위테스트는
빠르고 결정적이어서 개발자들이 수시로 수행하며 피드백을 즉각 얻을 수 있다.
작성하기 쉽다.
실패 시 원인을 파악하기 쉽다.
자연스럽게 예제 코드가 되며 문서 역할을 하게 된다.
1원칙: 테스트는 유지보수하기 쉬워야 한다. (maintainability)
무엇이 테스트를 신뢰하지 못하게 하는가?
검증 대상과 관련 없는 변경 때문에 실패하는 ‘깨지기 쉬운 테스트’ 때문에 (brittle)
깨지면 무엇을 고쳐야 하는지 파악하기 어려운 ‘불명확한 테스트' 때문에 (unclear)
깨지기 쉬운 테스트 예방하기
실제로 버그가 없음에도 상관없는 변경 때문에 실패하는 테스트
테스트가 변경에 영향을 덜 받도록 해주는 패턴을 찾자.
테스트는 시스템의 요구사항이 바뀌지 않는 한 수정할 일이 없어야 한다.
행위를 의도적으로 변경하는 경우에는 테스트도 함께 갱신해줘야 한다.
이 경우, 작성된 테스트를 먼저 수정해도 좋다.
리팩터링 시 테스트가 깨졌다면?
리팩터링 중 기능이 변경되진 않았는지 살펴보자
테스트의 추상화 수준이 적절하지 못하진 않았는지 살펴보자
세부 구현에 의존하고 있진 않았는지?
공개 API를 이용해 테스트 한다.
공개 API란 서드파티에 노출한 API를 말한다.
테스트 코드도 다른 사용자가 시스템을 호출하는 방식과 똑같은 방식으로 시스템을 호출한다.
“사용하듯이”
private 접근자를 제거하고 노출시킨다음 테스트하고 싶은 유혹을 떨쳐낼 것.
보조하는 용도가 다인 메서드나 클래스라면 독립된 단위로 생각하지 않는 것이 좋다.
고민) 한 컴포넌트에서만 사용되는 hooks는 독립된 단위가 아니기 때문에 따로 테스트하지 않고 이를 사용하는 컴포넌트를 통해서 테스트되도록 테스트 케이스를 구성한다????????????
다방면으로 유용한 기능을 제공하도록 설계된 패키지나 클래스는 직접 테스트해야 하는 단위이다.
hooks라도 유틸성 hooks는 테스트 대상이다.
상호작용이 아니라 상태를 테스트하자.
대부분의 상황에서, 상호작용 테스트는 상태 테스트보다 깨지기 쉽다.
상태 테스트는 결과가 “무엇인지”에 집중하고 (What)
상호작용 테스트는 시스템이 “어떻게 작동하냐”를 확인하려 하기 때문이다. (How)
상태 테스트: 메서드 호출 후 시스템 자체를 관찰
상호작용 테스트: 호출을 처리하는 과정에서 다른 시스템과 협력하여 기대한 일련의 동작을 수행하는지 확인할 때
상호작용 테스트가 만들어지는 가장 큰 원인은 모의 객체 프레임워크에 지나치게 의존하기 때문
가짜 객체는 변한값을 반영하지 않기 때문
명확한 테스트를 작성하자.
명확한 테스트란 존재 이유와 실패 원인을 엔지니어가 곧바로 알아차릴 수 있는 테스트를 의미한다.
완전하고 간결한 테스트를 작성하면 된다.
테스트 코드를 읽는 사람 입장에서 이 테스트를 이해하는 데 필요한 모든 정보를, 테스트 케이스 본문에 담고 있는 테스트를 말한다.
이와 동시에 관련없는 정보는 담지 않아야 한다.
관련없는 정보가 포함되어 있다가 상관없는 변경으로 인해 테스트 케이스가 깨지기 마련이다.
공통 객체를 사용하는 대신에, 헬퍼 메소드를 사용하여 값 객체를 만들자.
메서드가 아니라 행위를 테스트하자
행위란 특정 상태에서 특정한 일련의 입력을 받았을 때, 시스템이 보장하는 ‘반응'을 뜻한다.
메서드 당 테스트 케이스 1개일 필요가 없다. 1:N의 관계이다.
메서드가 여러개만 N:N의 관계인 것이다.
테스트 케이스 하나에서 하나의 행위만 테스트하자.
코드가 많아지지만, 더 좁은 범위이기 때문에 실패했을 때 그 원인을 좀 더 빠르게 파악할 수 있다.
테스트 명세가 한 가지만 드러내므로 더 파악하기 쉽다
테스트의 구조는 행위가 부각되어야 한다.
given, when, then으로 구분지어서 표현하기도 한다.
given: 시스템 설정을 정의한다.
when: 시스템이 수행할 작업을 정의한다.
then: 결과를 검증한다.
여러 단계로 진행되는 작업은 교대로 when, then을 정의해도 된다.
긴 블록의 경우 and로 연결해줄 수도 있다.
테스트 명세는 행위 중심이 되어야 한다.
동작과 예상 결과를 모두 담아야 한다.
테스트 이름에 “그리고”가 들어가면 테스트 케이스를 나눠야 하나? 하는 의심을 할 수 있다.
테스트에 논리를 넣지 말자
약간의 중복을 허용하더라도 순회문이나 조건문은 배제하자
직설적인 코드로 작성하자
DRY대신 DAMP(Descriptive And Meaningful Phrase)
공유 도우미 메서드와 공유 검증 메서드
테스트용 값을 생성하는 코드 부분을 공유 도우미 메서드를 사용할 수 있다.
검증을 공유 검증 메서드로 처리한다면?
버그 하나로 인해 여러 테스트가 동시다발로 실패할 수 있다.
공유 검증 메서드는 단 하나의 개념적 사실만을 검증해야 한다.
Action Item
테스트 혁신 가즈아!

Chapter 13. 테스트 대역

테스트 대역을 사용하면 실제 구현을 테스트 대역으로 교체하여 테스트할 수 있게 됩니다.
하지만 잘못사용하면 깨지기도 쉽고 복잡하고 효율도 나쁜 테스트로 전락합니다.
그렇기 때문에 되도록 실제 구현을 이용하시길 권합니다.

Part IV. 도구

트렁크 기반 개발, 모노레포, 정적분석 등 대부분 이미 토스에서 하고 있는 것들이라 메모가 적음. (테스트가 메모가 많은 것도 동일한 이유)

Chapter 16. 버전 관리와 브랜치 관리

트렁크 기반 개발 짱
트렁크 기반 개발과 뛰어난 소프트웨어 조직 사이에는 양의 상관관계가 존재
운 없는 엔지니어는 빌드 마스터, 병합 관리자, 콘텐츠 관리 엔지니어 같은 타이틀을 달고 조직 내의 모든 이질적인 브랜치를 병합하는 책임을 떠맡는다.
완벽하지 않거나 테스트되지 않는 기능은 비활성화하는 방향
Feature Flag를 적극 활용하고 모든 변경사항은 main branch로 집어넣는다.
(완전 동의)
개발 브랜치를 만들지 말고, 만들더라도 매우 짧게 쓰고 없애야 한다.
진행 중인 작업을 줄일 것
원 버전 정책
모든 코드는 모노레포에.
모듈들은 하나의 버전
개발자가 이 구성요소는 어떤 버전을 사용해야 하죠?라고 묻는 상황을 만들지 않아야 한다.
빌드 호라이즌 정책
프로덕션 환경에서 구동 중인 모든 제품은 최대 6개월 안에 다시 빌드하여 재배포해야 한다.
모노리포
일관성 덕분에 도구를 새로 도입하거나 코드를 최적화한 혜택이 조직 전체에 훨씬 빠르게 전파된다.
Action Item
Feature flag 활성화 방안 생각해보기

Chapter 17. Code Search

사내 모노리포 검색 툴, 좋다는 자랑!
왜?
이 코드가 왜 추가되었는가? 왜 이런 식으로 동작하는가? 에 대한 답을 찾기 위해 검색 목적으로 사용
특정 시점의 코드베이스 상태를 찾기 위해
새로 추가한 코드가 실패할 경우, 몇 분 전 추가된 변경을 살펴볼 때 사용

Chapter 18. 빌드 시스템과 빌드 철학

빌드?
의존 관계를 생각해서
각 조각을 올바른 순서로
그 조각에 적합한 도구를 이용하여
해야 하는 것
Not 태스크 기반의 빌드 시스템, But 아티팩트 기반의 빌드 시스템
원격 캐싱
공통의 원격 캐시 서비스를 참조 (레디스 or GCP)
때로는 엔지니어의 힘과 유연성을 제한해야 생산성을 높일 수 있다.
의존성의 버전 관리는 너무 어렵다
작은 모듈 방식이 굵직한 모듈 방식보다 잘 확장된다.

Chapter 19. 구글의 코드 리뷰 도구, Critique

토스에서 사용하고 있는 프론트엔드 종달새 bot이 더 잘해주고 있음.

Chapter 20. 정적 분석

skip. 우리 챕터는 이미 너무 잘하고 있음

Chapter 21. 의존성 관리

안하는 것이 최선이다.
모노레포에서 라이브러리, 서비스를 한꺼번에 관리하고 있어서 아직 필요성을 크게 느끼지 못하고 있음.
필요하다면 외부 서드파티 라이브러리에 대한 의존성 관리가 필요함
라이브러리 분리는 아직 고려하지 않고 있음.

마무리