생각하는 대로 코딩하기
예상 시간: 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 나누기 |
| 클로저로 상태 캡처 | makeCaptureLogger의 rows |
| 의존성 주입 | clock, sleeper 주입 |
| 결정 위임 | policy.shouldRetry() |
실제 연습법
- 작은 문제 선택 (LeetCode Easy, 간단한 유틸 함수)
- 종이나 노트에 한글로 로직 적기
- 코드로 옮기기
- 안 되면 어디서 막혔는지 기록
- 답이나 해설 보고 내 생각과 뭐가 달랐는지 비교
- 반복
핵심
생각을 코드로 바꾸는 건 타고나는 게 아니다. 반복으로 익히는 근육이다. 처음엔 느려도 계속하면 빨라진다.
처음엔 코드 읽기 70%, 쓰기 30% 정도가 좋다. 좋은 패턴을 충분히 본 후에 쓰는 게 효율적이다.