1 / 1

생각하는 대로 코딩하기

예상 시간: 5분

생각하는 대로 코딩하기

머릿속 로직이 코드로 안 옮겨지는 건 흔한 고민이다. 나도 그랬고, 대부분의 개발자가 초반에 겪는다.


한글로 먼저 써보기

코드 치기 전에 주석으로 로직을 먼저 적는다:

async function pump() {
  // 대기 중인 sleep이 있는 동안 반복
  // 가장 빨리 끝나는 due 시간 찾기
  // 시계를 그 시간으로 이동
  // 해당 시간에 끝나는 것들 분리
  // 삽입 순서대로 정렬
  // 하나씩 resolve 실행
  // 다음 sleep이 등록될 수 있게 양보
}

그 다음 주석을 코드로 바꾼다:

async function pump() {
  // 대기 중인 sleep이 있는 동안 반복
  while (this.pending.length > 0) {
    // 가장 빨리 끝나는 due 시간 찾기
    let nextDue = this.pending[0]!.due;
    for (const p of this.pending) {
      if (p.due < nextDue) nextDue = p.due;
    }
    // ...
  }
}

작은 단위로 쪼개기

한 번에 큰 함수를 짜려고 하지 않는다:

// 한 번에 다 하려고 함
function processOrder(order) {
  // 50줄짜리 복잡한 로직...
}
 
// 작게 쪼갬
function validateOrder(order) { /* 5줄 */ }
function calculateTotal(items) { /* 5줄 */ }
function applyDiscount(total, coupon) { /* 5줄 */ }
function processOrder(order) {
  validateOrder(order);
  const total = calculateTotal(order.items);
  return applyDiscount(total, order.coupon);
}

50줄짜리 함수 하나보다 5줄짜리 함수 10개가 머릿속에서 다루기 쉽다.


구체적인 예시부터 시작

추상적으로 생각하면 어렵다. 구체적인 값으로 먼저 생각한다:

// "배열에서 최솟값 찾기"를 추상적으로 생각하면 막힘
 
// 대신 구체적으로:
// [100, 50, 100] 에서 최솟값?
// → 100부터 시작
// → 50 보니까 더 작네, 50으로 바꿈
// → 100 보니까 50보다 크네, 유지
// → 결과: 50
 
// 이제 코드로:
let min = arr[0];
for (const x of arr) {
  if (x < min) min = x;
}

타입부터 정의하기

"뭘 받아서 뭘 반환하는지"부터 정한다:

// 먼저 이것만 정의
type Pending = { due: number; resolve: () => void; seq: number };
 
function shouldRetry(err: AppError, attempt: number): { ok: boolean; reason: string }

타입이 명확하면 구현은 따라온다.


패턴을 읽고 익히기

좋은 코드를 많이 읽으면 패턴이 쌓인다:

패턴예시
배열 분리dueNow / rest 나누기
클로저로 상태 캡처makeCaptureLoggerrows
의존성 주입clock, sleeper 주입
결정 위임policy.shouldRetry()

실제 연습법

  1. 작은 문제 선택 (LeetCode Easy, 간단한 유틸 함수)
  2. 종이나 노트에 한글로 로직 적기
  3. 코드로 옮기기
  4. 안 되면 어디서 막혔는지 기록
  5. 답이나 해설 보고 내 생각과 뭐가 달랐는지 비교
  6. 반복

핵심

생각을 코드로 바꾸는 건 타고나는 게 아니다. 반복으로 익히는 근육이다. 처음엔 느려도 계속하면 빨라진다.

처음엔 코드 읽기 70%, 쓰기 30% 정도가 좋다. 좋은 패턴을 충분히 본 후에 쓰는 게 효율적이다.