요즘 우아한 개발 리뷰
우아한형제들 기술 블로그를 자주 보시나요?
알게 모르게 개발자라면 접할 겁니다.
우수한 글 품질과 흡입력 있는 구성은 물론,
특히 재치 있는 문구가 인상적인 블로그입니다.
'요즘 우아한 개발'은 우아한형제들 기술 블로그 포스팅을 망라했습니다.
엄선하여 온보딩, 개발, 문화, 이슈 관리 이야기를 담았습니다.
쉽게 읽을 수 있도록 코드를 최대한 제거했습니다.
기획자, 각 분야의 개발자 모두 라이트하게 읽을 수 있는 책입니다.
친구가 선물로 주더군요.
<육각형 개발자>와 <요즘 우아한 개발> 책이 있었는데,
'육각형 개발자'는 작년에 읽은 적이 있어 '요즘 우아한 개발' 책을 받았습니다.
흡입력 있는 개성 넘치는 문체는
다음 내용을 궁금하게 하고
빠르게 읽을 수 있게 만들었습니다.
글은 옴니버스 형식입니다.
언제든 어디서든 원하는 챕터만 간편하게 읽을 수 있습니다.
구성은 경험을 구체적이고 생생하게 소개합니다.
그를 통해 얻은 인사이트를 공유합니다.
저도 형광펜으로 얻고 싶은 인사이트를 메모했습니다.
개인 경험을 적고 인사이트를 짧게 정리했습니다.
업무에서 겪은 경험을 정리하고 앞으로 적용해 보면 좋은 점을 메모했습니다.
리뷰 글로 정리하려고 합니다.
#1. 계속 다니고 싶은 회사의 기술 문화를 만든다는 것
회사의 문화는 중요한 것 같아요.
동기 부여를 일으키고 소속감을 느끼게 해 줍니다.
심리적 안정감과 신뢰로 협업을 매끄럽게 합니다.
결국 밀도 높은 성장을 함께 이룹니다.
계속 다니고 싶은 기술 문화를 만든다.
최근 뵈었던 기술 리더분들의 공통 관심사였습니다.
회사의 매력이 되고 인지도가 높아지기 때문입니다.
구성원의 동기 부여가 높아져 업무 성과가 좋아지고
채용 시장에서의 경쟁력을 확보할 수 있습니다.
그만큼 기술 문화는 중요합니다.
저는 팀원의 입장입니다.
팀원, 즉 구성원으로서 어떻게 해야
좋은 문화를 리더와 다른 팀원에게 어떻게 설득하고 전파할 수 있을까,
를 고민하고 실험합니다.
사소한 것부터 챙기는 게 핵심입니다.
조그마한 것부터 시작합니다.
개발 업무를 하다 알게 된 지식을 잡담으로 나눕니다.
문서로 남겨 다른 팀원에게 공유하기도 합니다.
이를 위해 기록을 꼼꼼하게 티켓에 기록하게 됩니다.
실행, 기록, 잡담, 공유, 회고
무엇 하나 빠질 수 없는 중요한 요소입니다.
개인과 팀에게 선순환을 일으킵니다.
좋은 문화를 만드는 밑거름이 됩니다.
<요즘 우아한 개발>에서도 위 요소를 언급합니다.
그중 특히 '공유'를 중요시합니다.
메신저에 수많은 '공유' 채널이 있습니다.
- 오늘 무엇을 배웠는지(TIL, Today I Learned)
- 분야별(BE, FE, Mobile) 기술 블로그 공유
스스로 사소하다고 느낄 수 있는 학습 내용과 느낀 점을 수시로 공유합니다.
'이런 것까지 올려도 될까?' 싶은 것을 마음껏 올려도 되는
분위기를 형성하는 게 핵심인 것 같습니다.
#2. 좋은 온보딩 프로세스
1. '파일럿 프로젝트'
신규 입사자가 업무에 빠르게 적응하려면 어떻게 해야 할까요?
우아한형제들에선 '파일럿 프로젝트'를 지도합니다.
실제 업무와 같은 영역을 개발하게끔 합니다.
업무와 동일한 코드 품질을 맞추기 위해, 코드 리뷰를 강도 높게 합니다.
코드에 정답은 없습니다.
그러나 모든 팀원이 쌓은 경험과 규칙이 있을 뿐입니다.
업무에 적응한다는 건, 결국 기존의 규칙을 체화해야 한다는 점입니다.
자신의 낡은 것을 버릴 줄 알아야 하고
새로운 것을 재빠르게 흡수해야 합니다.
시니어라면 전자의 비중이 높을 거고
주니어라면 후자의 비중이 높을 겁니다.
아무런 문화 없이 신규 입사자에게
규칙을 '강요'하기는 참으로 어렵습니다.
자칫하면 존중받지 못한다는 감정의 문제로 번질 수 있습니다.
그러나 팀으로서 따라야 업무가 수월해집니다.
'파일럿 프로젝트'는 서로가 윈윈 할 수 있습니다.
입사자는 실제 업무가 아니라는 점에서 안정감을 느낄 수 있습니다.
실제 업무는 아니지만 도메인 지식과 팀의 업무 프로세스를 익힐 수 있습니다.
새로운 도메인 지식을 얻는 건 물론,
내 지식과 팀의 지식이 어떤 점이 다른지 확연히 느낄 수 있습니다.
팀에 녹아들고픈 동기 부여를 일으킵니다.
기존 팀원은 신규 입사자에게 팀의 규칙을 유도할 수 있습니다.
팀의 규칙을 따르게 하는 '명분'이 생깁니다.
'실제 업무'가 아니기에 지금껏 쌓은 코드 품질을 염려하지 않아도 됩니다.
서로 신뢰를 쌓을 수 있는 충분한 기간이 생깁니다.
물론 '파일럿 프로젝트'를 준비하는 데 시간이 걸리고
'규칙'을 따르게 하기 위한 코드 리뷰 시간도 있기 마련입니다.
본격적으로 협업하며 매끄러운 소통을 생각한다면
충분히 투자해 볼 만한 온보딩 프로세스인 것 같습니다.
저도 첫 회사에선 2주간 파일럿 프로젝트를 진행했습니다.
티켓 발급 방식과 깃 브랜치 방법,
특정 라이브러리와 미들웨어를 사용하는 등 기술 요구 사항을 준수하는 식으로 진행했습니다.
중간발표와 최종 발표가 들어갔고 코드 리뷰도 중간에 받았습니다.
물론 실제 업무에 들어가도
팀의 '규칙'에 맞게 피드백을 지속적으로 받고 훈련을 계속해야 하긴 합니다만,
업무의 이해도나 팀의 업무 방식을 초기에 파악할 수 있어
자연스레 팀에 녹아들 수 있었습니다.
현 회사에 재직한 지는 이제 2개월이 다 되어갑니다.
저 또한 도메인 지식이 부족하다고 느끼는데요, 업무 하면서 익히는 중입니다. 😁
어떻게 도메인 지식을 채울 수 있을까, 에 대한 답으로 '파일럿 프로젝트'를 개인적으로 해보자, 는 힌트를 얻었습니다.
또한 팀 문화적으로도 이렇게 개선하면 좋을 것 같다,라는 힌트도 얻었습니다.
요즘은 이 과정을 채용 과정으로 대체합니다.
'코딩(온라인 알고리즘 X) / 과제 테스트' 명목으로 진행합니다.
일정 수준의 '기술력'과 '도메인 지식'이 있고, '사내 규칙'에 적응하는 데 무리가 없는 사람인가? 를 평가하는 목적입니다.
온보딩 비용에 비하면 훨씬 저렴하긴 하나, 지원자는 피드백을 받을 수 없는 구조입니다.
도메인 분야가 전혀 다른 지원자 중 팀 문화에 꼭 맞는 지원자를 찾아내긴 힘들다고 봅니다.
'인재'의 정의는 각기 다르겠지만, '좋은 인재'를 찾기보단 바로 업무 할 수 있는 노동자를 찾는다는 인상을 줍니다.
이를 보완할 수 있는 방법은 무엇일까, 도 고민이 되네요.
2. 투명하고 상세한 문서화
문서화는 중요합니다.
다만 '문서' 그 자체에 집중하는 경우를 보곤 합니다.
<요즘 우아한 개발>에선 다음이 문서화 단계를 제시합니다.
- 1단계 : 프로젝트 / 피처의 대략적인 스케치 작성
- 프로젝트 배경 / 무엇을 어떻게 진행할지
- N단계 : 이슈 / 문제 해결 과정 등 히스토리를 작성
- 마지막 단계 : 프로젝트 / 피처의 작업 후 회고를 진행
- 1단계 내용을 바탕으로 성과 / 비교 중점으로 작성
이를 다른 곳에선 '테크 스펙'이라고 표현하기도 합니다.
핵심은 '투명'과 '상세'입니다.
'투명'은 누구에게나 쉽게 접근할 수 있음을 의미합니다.
'상세'는 일련의 의사 결정을 상세히 표현함을 의미합니다.
즉, 코드와 기능을 이해하는 데 드는 비용을 최소화하는 목적을 가집니다.
인수인계를 하거나 코드 리뷰를 할 때
단순히 코드 덩어리만을 보지 않습니다.
코드 동작을 이해하는 거와
코드가 만들어 낸 가치를 이해하는 건 전혀 다른 영역입니다.
코드를 작성하게 된 배경은 무엇이고,
어떤 기획 안에서 어떤 의사 결정이 오고 갔는지가
중요하게 작용하는 때가 많습니다.
배경을 모른다면 중요도를 판단할 수 없습니다.
의사 결정 이력을 모른다면 똑같은 실수를 반복합니다.
이는 제품 성숙도 발전에 병목을 만들어 냅니다.
제품 개발은 '이어달리기'입니다.
제대로 '바통'을 전달하지 못한다면 뒤처질 수밖에 없습니다.
팀으로서, 회사로서 경제적인 손해를 끼치게 됩니다.
이를 '문서화'로 해결해야 합니다.
'문서화'가 이 문제를 해결하고 있는지 늘 평가해야 하고,
그렇지 않다면 높은 우선순위로 개선해야 하지 않을까 싶습니다.
처음에 언급한, '문서' 그 자체에 집중하는 것보단
'문서'가 만들어 낸 가치가 제대로 동작하고 있는지
늘 지켜봐야 합니다.
적어도 '투명'과 '상세'만 지켜져도
미래의 누군가는 당신에게 고마워할 겁니다.
저 또한 요즘 많이 고마워하고 있습니다. 😁
티켓에 상세 히스토리를 적는 팀 문화가 있습니다.
예전 히스토리를 알아내는 데 도움이 많이 되고 있습니다.
저 또한 히스토리를 상세하고 적으려고 노력합니다.
정말 좋은 문화다,라고 생각했었는데
책에서도 열심히 소개해주고 있네요.
3. 확장 가능한 코드
내 코드가 얼마나 확장 가능한 코드인지 수시로 고민합니다.
'확장 가능하다'라는 건, 현재 기능에서 '보다 적은 노력'으로 기능을 추가 / 수정함, 을 의미합니다.
'보다 적은 노력'은 꼭 코드 양만을 의미하진 않습니다. 고민과 의사 결정의 수일 수도 있습니다.
코드를 확장하는 데 높은 신뢰성을 갖고 있고, 아무런 고민이 없다면 개발하는 데 얼마나 행복할까요?
극단적으로 '아무 생각 없이 코드 열 줄을 추가하는 것'과
'한 줄을 추가하지만 많은 고민과 의사 결정이 오고 가는 것'과의 피로감을 생각하면
이해가 됩니다.
단순히 '코드 구조'만을 생각하는 게 아니라
'피로감'(비용)에 주목합니다.
#3. 기술 스택 / 좋은 개발자
<요즘 우아한 개발>에서 우아한형제들의 기술 스택을 엿볼 수 있습니다.
엔터프라이즈 시스템에선 어떤 기술 스택을 갖고 있는지, 어떤 고민을 하고 있는지 알려줍니다.
- OOO팀 기술 스택
- 그레이들 기반 멀티 모듈 구조
- 모든 프로젝트에서 JPA 사용
- 젠킨스 통합 도구
- 테스트 코드 커버리지
- 스프링 부트 배치
- 실패 처리 전략, 테스트 케이스, 관리 방법 등
독자가 처한 기술 스택과 비교하며
어떤 기술을 선택해야 할지 좋은 선례를 알려줍니다.
한 챕터에서 '실력 있는 개발자'의 기준 중 한 가지를 소개합니다.
'새로운 기술을 얼마나 빠르게 베스트 프랙티스에 가깝게 적응하는가?'
단순히 '기술'에 초점이 아니라, '베스트 프랙티스'가 초점입니다.
적재적소의 상황에 기술을 적용했는지,
업계 표준 방식으로 코드나 아키텍처 따위를 구축했는지,
그것을 얼마나 빠르게 적응했는지,
를 실력 있는 개발자로 정의합니다.
책에서 소개한 능력자 분들의 사례입니다.
새 버전이 정식 릴리스되기도 전에 변경점을 파악하고,
업그레이드 시 주의할 점을 사내 위키에 정리한다고 합니다.
좋은 시니어 개발자라면, 최신 기술 동향을 트랙킹 하고 공유함을 배웠네요.
10 ~ 20년 전과 다르게 요즘 버전은 순식간에 지나갑니다.
(더 이상 보수적이고 경직된 배포는 없습니다. 대체제가 넘쳐나기 때문에 경쟁에서 뒤처집니다.)
버전 업데이트도 프로젝트 개발 범위로 고려해야 하고 매뉴얼 또한 필요성을 느끼곤 합니다.
모든 시니어 개발자가 뛰어난 개발 능력을 갖추진 않았을 겁니다.
물론, 주니어 / 중니어(인터미디엇) 보단 잘하는 건 당연하지만요.
시니어 개발자의 모습을 여러 차례 보여주며 가야 할 길을 알려줍니다.
누구나 다 처음엔 주니어였고
커리어의 모든 순간이 탄탄대로는 아니었을 겁니다.
좋은 선례를 많이 보고 따라 하려고 노력하며
각자의 위치에서 최선을 다하는 게 '좋은 개발자'가 아닌가 싶네요.
#4. 코드 관리
1. 코드의 의도를 알리자
앞서 '문서화'에서 설명했지만,
'문서'와 다르게 코드단에서 1차로 의도를 파악할 수 있다면
비용을 아낄 수 있습니다.
코드의 의도를 명확하고 분명히 합니다.
이는 코드 자체로 할 수 있고,
주석으로 표현할 수 있고,
테스트 코드로 달성할 수 있습니다.
한 가지 방법만이 아닌, 가능한 모든 수단을 동원합니다.
핵심은 '의도'를 빠르게 파악함에 있습니다.
비슷한 코드(코드 라인, 메소드, 클래스, 패키지 등)는 가깝게 위치시킵니다.
주석은 코드와 최대한 가까운 거리에 작성합니다.
링크가 필요하다면 기꺼이 첨부합니다.
테스트 코드로 동작과 의도를 명시합니다.
테스트 코드는 언제 어디서든 피드백을 가능케 합니다.
주석은 언어로 표현하기에 모호한 이해가 언제나 발생할 수 있습니다.
그러나 테스트 코드는 내 생각이 틀렸음을 빠르게 증명해 줍니다.
테스트 코드와 첨부된 주석만으로
옆에서 직접 설명하는 기분이 들어야 합니다.
충분한 히스토리도 알 수 있게 합니다.
이해한 내 생각이 맞았음을 피드백할 수 있어야 합니다.
업무 지시 사항을 들으면
내가 이해한 것이 맞는지 확인하곤 합니다.
물론 그럼에도 서로의 미스가 발생하는 일이 빈번하지만요.
실시간 대화가 아닌 글자 모음은 오죽할까요.
누군가가 적은 글자만으론 내 생각이 맞았음을 피드백하지 못합니다.
부족한 피드백을 '테스트 코드'로 보충합니다.
코드는 논리가 들어갑니다.
테스트 코드 또한 논리가 들어갑니다.
누군가를 '이해'한다는 건, 누군가의 사고의 흐름, 즉 '논리'를 따라가는 것입니다.
코드에 들어간 '논리'는 '테스트 코드'로 충분히 표현합니다.
'테스트 코드'를 봐야 제대로 된 '이해'가 아닌가 싶네요.
옳고 그름을 판단하는 건 '이해' 이후의 문제입니다.
<요즘 우아한 개발> 책을 읽으며
테스트 코드를 바라보는 시야가 넓어졌네요.
다른 사람에겐 테스트 코드는 어떤 의미인지 궁금합니다.
2. 코드 관리 주체를 명확히 하자
공용으로 사용하는 라이브러리를 관리하는 사람이 없다면 어떻게 될까요?
버그가 생기면 속수무책일 수밖에 없습니다.
당장 버그가 생기지 않는다고 안심하면 안됩니다.
의존된 버전이 변함에 따라 호환이 되지 않는 순간이 빠른 시일 내에 올 겁니다. (주변 경험담😅)
대응할 수 있는 방안이 떠오르지 않는 무기력함을 느낄 수도 있습니다.
하물며 같은 프로젝트라도 협업을 한다면
주체가 다양한 코드가 들어갑니다.
이 코드는 누가 고쳐야 하는가, 관리해야 하는가, 를 명확히 하는 건 중요합니다.
책임을 미뤄 아무도 관리하지 않는다면,
무법 지대의 코드로 방치되게 됩니다.
처음엔 '화초'로 관리하지만,
언젠가부터 관리되지 않는 '잡초'로 누구의 눈에 띄지 않게 존재합니다.
제품이 발전함에 따라 다양한 이유로 필연적인 버그가 발생합니다.
누구의 기억 속에 없는 '잡초'를 발견하기는 어렵기 마련입니다.
집요한 디버깅으로 찾을 수 있지만, 애초부터 관리 주체를 정하는 게 더 효율적입니다.
우선은 관리 주체가 없는 영역을 찾습니다.
사내에서 개발한 자체 라이브러리가 관리 주체가 없을 확률이 큽니다.
관리 주체를 명확히 설정하고 업무에 포함하는 것이 필요합니다.
퇴사자로 인한 부재도 신속히 해결해야 합니다.
관리되지 않는 '잡초'를 신속히 '화초'로 만드는 것,
미래의 고비용 버그를 해결하는 효과적인 예방 전략으로 보입니다.
물론 쉽지는 않겠지만, 결국 누군가는 해야 합니다.
이것이 곧 개발자로서 '오너십을 가진다'의 진정한 의미가 아닐까 합니다.
저도 사내 프로젝트, 라이브러리를 틈 날 때마다 살펴보며 오너십을 가져보려고 합니다.
#5. 백엔드
1. 외부 입력은 무조건 검증하기
외부 요청의 검증은 생각할 것도 없이 서버의 역할입니다.
외부 요청은 예측할 수 없으며 언제든 변조될 수 있습니다.
따라서 언제든 검증할 준비가 되어 있어야 합니다.
사례 중 페이지네이션의 pageSize를 예를 듭니다.
한 페이지에서 조회할 개수를 의미합니다.
외부에서 동적으로 개수를 조율할 수 있게 요청 값(URL 쿼리스트링)으로 두는 것이 일반적입니다.
pageSize를 1억으로 설정하면 어떻게 될까요?
데이터베이스에서 1억 개의 데이터를 가져오기 위해 커넥션을 오랜 시간 점유하고 자원을 빠르게 소모할 것입니다.
명백히 감당할 수 있는 스펙에 벗어나는 동작이기에, 반드시 막아야 합니다.
'검증의 역할을 서버는 무조건 가져가야 한다'가 주장입니다.
프론트엔드에서도 검증을 '선택'할 수 있지만, 서버에서의 검증은 '무조건'입니다.
어떤 입력값이든 자료형은 물론, 범위 또한 제한해야 합니다.
위 사례를 보며 저도 얼른 백엔드 서비스의 pageSize를 검증했습니다.
100개가 넘어간다면 프레젠테이션단에서 예외를 발생시켰습니다.
중요한 인사이트를 얻었네요.
2. 인증과 인가는 다르다
게이트웨이, BFF 서비스에서의 사례를 다룹니다.
인증은 동작했지만, 인가는 동작하지 않았다는데요.
요청을 전달하기만 하는 게이트웨이, BFF 서비스에서
특히 신경을 쓰라는 당부가 인상적이었습니다.
내부 보안의 책임을 게이트웨이, BFF 서비스에 옮기고
불필요한 내부 네트워크 트래픽을 방지할 수 있어 보입니다.
'인증'과 '인가'는 늘 구분해야 합니다.
'인증'은 누구인지 식별하는 과정이고,
'인가'는 접근할 수 있는 권한을 확인하는 과정입니다.
요즘은 '인증'은 정말 잘합니다.
그러나 '인가'에 관한 자료는 그에 비해 없는 것 같아요.
편의성을 위해 '*'으로 모든 패턴을 받거나, permitAll()으로 모든 권한을 주거나,
디테일하게 설정할 수 있는 베스트 프랙티스를 제공하는 자료를 보지 못했습니다.
'좋은 인증'의 논의는 활발하지만
'좋은 인가'는 많이 다루지는 않는 것 같아요.
사내에서도 '인가'를 특히 중요하게 생각하기에
조만간 '인가'에 대해서 정리해 보는 계기가 될 것 같네요.
3. 모든 종류의 재화 소비는 사용자가 알아야 한다.
재화는 실제 돈일 수도 있고, 가상일 수도 있습니다.
<요즘 우아한 개발>에선 가상 재화, 포인트, 를 소개했습니다.
가상 재화라도 사용자의 정확한 인증이 들어가야 하며,
소비됨을 알림 기능으로 즉시 알립니다.
이전 회사에서도 가상 재화를 다뤘습니다.
가상 재화를 얻는 건 기막히게 알렸지만,
막상 소모하는 부분을 세심하게 챙기지는 못해 반성했네요.
(물론 잘못 소모하면 바로 VoC로 인입됩니다.)
#6. 프론트엔드
1. 작은 컴포넌트 분리
최근에 프론트엔드의 관심도가 높아졌습니다.
업무에서 프론트엔드를 다뤄야 하기 때문인데요.
관심사를 분리하고 확장 가능한 좋은 구조를 찾고 있습니다.
너무 많은 컴포넌트는 개발 생산성에 해롭다,
라는 문제를 목격했습니다.
직접 유지보수를 담당하면서 느꼈던 건, 단순히 컴포넌트 개수보다는
좋은 추상화와 문서화가 안되어 있어 생산성이 저하된다고 느꼈습니다.
도서에서도 테스트가 용이한 작은 컴포넌트를 지향하고 있습니다.
용이한 테스트 작성에 큰 영향을 끼치는 건, '적은 코드 범위' 입니다.
추상화로 비즈니스 로직과 UI 퍼블리싱을 분리합니다.
불필요하고 명확하게 이해되지 않는 추상화는 코드 흐름을 따라가기 어렵게 만듭니다.
작고 간단하고 명확하게 추상화된 컴포넌트 구조로 구축하고
컴포넌트에 관한 위키, 문서로 충분히 해결할 수 있지 않을까 기대합니다.
저도 전문성이 있는 영역이 아니고, 사실상 책 한 권만 읽은 사람이지만...
좋은 구조로 만들고픈 욕심은 있습니다.
<요즘 우아한 개발>에서 예시로 든 사례들이
저희 서비스와 유사한 부분이 많은 것도
도움이 많이 되었습니다.
이렇게 나아가면 되겠구나,라는 빛을 목격했습니다.
마무리
컴퓨터 과학에서 '분할 정복'이라는 개념이 있습니다.
작은 문제로 잘게 나눠 큰 문제를 해결하는 전통적인 문제 해결 방식입니다.
위의 사례들 모두 사소하고 작은 문제부터 시작합니다.
작은 문제를 해결하기 시작하면 자연스레 큰 문제도 해결됩니다.
큰 문제를 해결하면 자신감과 노하우를 얻습니다.
앞으로 어떤 걸 생각하며 커리어를 이어 나가야 할지 알려주는 도서였습니다.
감사합니다.