Search
Duplicate

제어할 수 없는 것에 의존하지 않기

일정 VS 퀄리티

프로덕트 엔지니어는 일정이 중요하다고, 퀄리티를 모두 무시하는 행위도 반대로 퀄리티가 중요하다고 일정을 무시하는 행위도 해서는 안된다.
코드 커버리지의 타겟 퍼센티지를 지정하듯 최고는 아니지만 최선의 퀄리티를 균일하게 일정 내에 개발할 수 있어야 한다.

일정을 잘 지키는 사람들의 공통점

좋은 코드를 선택하는 방법을 잘 선택한다.
매번 최근에 본 개발 관련 서적이나 아티클등을 참고해서 좋은 코드를 선택하려 고민한다.
클린 코드를 봤으면, 리팩토링을 봤으면, 오브젝트를 봤으면….하면서 자신이 최근 봤던 책들을 기반으로 고민을 하게 된다.
우리가 A코드와 B코드 중 무엇을 선택할지 고민할 때 그들은 그동안 해왔던 기준과 원칙으로 빠르게 결정하고, 더 중요한 것에 집중한다.
기존의 기준이 100점짜리 코드에 부족한 80점~ 90점짜리 코드라는건 이미 감안하고 있다.
하지만 나머지 80점~90점은 그동안 해왔고 성공해왔던 경험하에 쌓여진 기준으로 선택한다.
무엇이 옳을까? 적어도 회사및 내 시간을 생각하면 후자가 맞지 않을까?

제어할 수 없는 것에 의존하지 않기

Developer Area
현실 세계의 변화와 설계 사이의 결합도를 줄여야 한다. 전화번호를 식별자로 사용하는가? 자신의 힘으로 제어할 수 없는 속성에 의존하지 말라. - 실용주의 프로그래머 중

불변이라 생각했지만 가변이였던

절대 변하지 않을 것이라 믿고 의존했던 속성(주민 등록 번호)이었지만, 변경이 발생해 대부분의 시스템의 주요키 변경이 발생했다.

그 이후…

외부에서 전달 받은 값은 절대 주요키로 선택하지 않는다.
애플리케이션의 중요한 키 혹은 식별자는 내가 직접 만들어 관리하는 키만 사용하겠다(Ex: 대리키)

그리고…

패스워드 발급시 단방향 암호화 등을 SQL에서 password등을 통해 암호화를 할 수 있다.
하지만, 이런 기능들은 성능을 끌어올리거나 분산환경에서 동일한 규칙으로 만들기 어렵다.
결국, 성능이나 환경등 제어할 수 없는 것에 의존할수록 변화에 쉽게 흔들리는 소프트웨어가 만들어진다.

코드로 살펴보는 제어할 수 는 코드

public class Order { private double amount; public void discount() { LocalDateTime now = LocalDateTime.now(); if (now.getDayOfWeek() == DayOfWeek.SUNDAY) { this.amount = this.amount * 0.9; } } }
Java
복사
일요일이면 할인되는 코드
이 코드는 내가 제어할 수 없는 코드이다.

어째서일까?

@Test void discountTest() { ProductOrder order = new ProductOrder(1_000); order.discount(); assertThat(order.getAmount()).isEqualTo(900); }
Java
복사
위와 같은 테스트 코드를 실행하면 성공할까? 일요일에만 성공하는 테스트코드다.
LocalDateTime.now() 메서드 호출은 개발자가 제어할 수 없는 코드다.
그래서 모킹을 이용해 무조건 now() 메서드가 일요일을 반환하도록 할 수 있긴 하다.
@Test public void testDiscountOnSunday() { // 가짜 시간 생성 LocalDateTime sunday = LocalDateTime.parse("2023-04-09T00:00:00"); Clock clock = Clock.fixed(sunday.atZone(ZoneId.systemDefault()).toInstant(), ZoneId.systemDefault()); LocalDateTime.now(clock); // 현재 시간을 가짜 시간으로 설정 }
Java
복사

그런데, 날짜 라이브러리나 테스트 프레임워크가 바뀐다면?

⇒ 기존에 모킹하고 있던 모든 코드를 변경해줘야 한다.

제어할 수 는 코드로 만들기

public class ProductOrder { private double amount; public ProductOrder(double amount) { this.amount = amount; } public void discount() { discount(LocalDateTime.now()); } public void discount(LocalDateTime now) { // <----- 시간을 외부에서 주입받게 변경 if (now.getDayOfWeek() == DayOfWeek.SUNDAY) { this.amount = this.amount * 0.9; } } public double getAmount() { return amount; } } @Test void discountTestForSunday() { ProductOrder order = new ProductOrder(1_000); order.discount(LocalDateTime.of(2023, 4, 9); assertThat(order.getAmount()).isEqualTo(900); } @Test void discountTestForElse() { ProductOrder order = new ProductOrder(1_000); order.discount(LocalDateTime.of(2023, 4, 8); assertThat(order.getAmount()).isEqualTo(1_000); }
Java
복사
제어할 수 없는 값을 제어할 수 있는 값으로 만들어 줬다.
일요일이 아닐 경우에 대한 에지 케이스도 테스트할 수 있다.

전염되는 제어할 수 없는 코드

제어할 수 없는 코드만 살펴보는게 아닌 좀 더 확장해서 제어할 수 없는 코드에 의존하는 메서드들이 늘어남에 따라 제어할 수 없는 범위가 전염되는 것을 볼 수도 있다.

Base Code

requestPg(course.title, payAmount); 메서드는 외부 API요청이다.
이 메서드를 메서드로 분리해서 리팩토링을 진행해보자.

Refactoring Code

pay, payAll이라는 두 개의 메서드로 기능을 분리해줬다.
여러 개의 강의에 대해 결제를 순회하면 진행하는 payAll
하나의 강의에 대한 결제를 진행하는 pay
두 메서드들을 호출하며 로직 오케스트레이션을 하는 payCourses
async/await 키워드가 모든 메서드에 접두사로 붙어있다.
모든 메서드가 외부 API를 모킹해야지만 테스트할 수 있는 메서드들이 되었다
분명 리팩토링하며 메서드를 순수함수로 만들었는데 의존성이 생긴걸까?

제어할 수 없는 함수에 의존하는 모든 코드가 제어할 수 없는 코드가 된다.

pay 메서드의 외부 API(requestPg)

제어할 수 는 것과 는 것

여기서 제어할 수 있는 것을 제어할 수 없는 것과 분리를 할 필요가 있다.

제어할 수 있는 것과 없는 것을 분리

강의의 할인을 적용해 반환하는 기능과, 결과 요금을 필터링해서 유효한 코스들을 추출해내는 메서드를 분리해 냈다.
async/await을 사용해 외부 API를 호출하는 메서드는 payAll하나의 반복문 내로 좁혀졌다.

제어할 수 없는 코드란?

내가 만들지 않은, 외부에서 사용하는 내가 핸들링하기 힘든 함수 혹은 객체들을 제어할 수 없는 코드라 지칭한다.

이제 우리가 해야할 일은?

UI

Back: Json결과물이나 HTML Template
Front: View layer

Business Logic

back, front: business logic…

Data

Back: ORM, Respository, …
Front: fecth, axios, …

제어 불가능한 영역을 최대한 밀어넣어 격리하자.

제어 가능한 영역을 최대한 늘려나가자

제어할 수 없는 것에 의존하지 않기

Company Communication Area
어떻게 좋은 개발자를 영입하고, 안나가게 할 수 있을까?

돈으로 다 해결하면 좋겠지만…

코로나 시즌 해외 투자가 정체되며 국내 투자로 돈이 흘러들어오며 스타트업들의 자금규모가 극적으로 커지면서, 개발자에 대한 대우도 드라마틱하게 올라갔다.
그래서 이런 흐름에 발맞춰 마냥 페이를 올려주기엔 부담이 크다.

그 여파로 인한 현재 winter is comming

요즘 투자금액이나 개발자에 대한 급여 대비 이익이 안나오면서 전체적인 구조조정 시즌
시니어 개발자들은 이런 상황에서 이직을 결심하기 더 힘들어져 영입이 더 힘들어진 상황

제어할 수 는 것과 는 것

내가 회사의 매출, 투자, 연봉, 생태계의 권고사직 분위기를 제어할 순 없다.

좋은 개발자 채용도 내가 제어할 수 없는 부분일 수 있다.

회사의 CTO가 100이라는 노력을 하면 100만큼의 인재가 들어온다는 보장이 있을까?
가비지 컬렉터의 destroy와 같이 어느정도 권유는 할 수 있지만 제어는 할 수 없다.

인프랩에서의 행보

1.
좋은 시니어 개발자 채용이 아닌 사내 강연
정기적인 외부 시니어 강연에 긍정적 피드백 사이클이 돌기 시작한 인프랩 직원들
2.
잦은 피드백을 줄 수 있는 환경 구성
→ 누가 코드 리뷰를 (여러 사정으로 인해) 못하는 환경에서도 피드백을 제공하기 위해 PR시
소나 큐브에 의한 정적 분석
테스트 코드
Lint
등의 도구를 이용해 피드백을 제공할 수 있는 환경을 제공한다.

다시 보는 제어할 수 는 것과 는 것

회사 내의 개발환경은 제어할 수 있는 범위에 있기에 이 부분을 집중한다.
할 수 있는 것에 집중하고 긍정적으로 상황을 판단하기

행복회로? No

우리 팀의 팀원이 이번에 네카라쿠배로 이직을 했네. 나도 해야하나? 여기 계속 남아 있어도 되는건가? 가야지 성장할 수 있는거 아닐까?
반대로 생각하면 네카라쿠배급의 회사에서도 우리의 개발방법, 개발자에 대해 긍정한다는 것이다.
개발문화나 프로세스가 잘못된게 아니다.

선택과 집중