💻 Dev

🛠️ 처음부터 만드는 Once — 함수를 한 번만 실행하기

Once란?


Once는 함수를 최대 한 번만 실행하도록 제한하는 유틸입니다. 두 번째 호출부터는 첫 실행의 결과를 반환합니다.

왜 필요할까?


초기화 로직, 권한 설정, 구독 해제 등 단 한 번만 실행되어야 하는 작업이 있습니다:
```javascript
const initializeApp = once(() => {
console.log('앱 초기화 중...');
return { ready: true };
});
initializeApp(); // '앱 초기화 중...' → {ready: true}
initializeApp(); // {ready: true} (초기화 스킵, 결과만 반환)
```

구현


```javascript
function once(fn) {
let called = false;
let result;
return function(...args) {
if (!called) {
called = true;
result = fn.apply(this, args);
}
return result;
};
}
```

동작 원리


1. `called` 플래그로 실행 여부 추적
2. 첫 호출: 함수 실행 → 결과 저장 → `called = true`
3. 이후 호출: 함수 스킵 → 저장된 결과만 반환

실제 사용 예


1. 데이터베이스 초기화


```javascript
const setupDB = once(async () => {
console.log('DB 연결 중...');
const conn = await connectDatabase();
return conn;
});
await setupDB(); // 실행
await setupDB(); // 캐시된 결과만 반환
```

2. 이벤트 리스너 등록


```javascript
const registerListener = once(() => {
window.addEventListener('scroll', handleScroll);
console.log('스크롤 리스너 등록됨');
});
registerListener(); // '스크롤 리스너 등록됨'
registerListener(); // 무시됨
```

주의사항


⚠️ 인자가 달라도 첫 결과 고정: `once`는 첫 호출 결과만 메모리에 저장합니다.
```javascript
const add = once((a, b) => a + b);
add(2, 3); // 5
add(10, 20); // 5 (인자 무시, 첫 결과)
```
인자마다 다른 결과가 필요하면 Memoize를 사용하세요.

한 단계 더 — 리셋 기능


필요하면 초기화를 다시 허용하는 리셋 메서드를 추가할 수 있습니다:
```javascript
function once(fn) {
let called = false;
let result;
const wrapper = function(...args) {
if (!called) {
called = true;
result = fn.apply(this, args);
}
return result;
};
wrapper.reset = () => {
called = false;
result = undefined;
};
return wrapper;
}
const init = once(() => 'initialized');
init(); // 'initialized'
init.reset();
init(); // 'initialized' (다시 실행됨)
```

참고 자료


  • [Lodash _.once](https://lodash.com/docs/#once) — 프로덕션 수준 구현

  • [Ramda R.once](https://ramdajs.com/docs/#once) — 함수형 프로그래밍 스타일

  • [이전 포스트: Memoize](https://example.com/memoize) — 함수 결과 캐싱
  • 💬 0
    👁 0 views

    Comments (0)

    💬

    No comments yet.

    Be the first to comment!