이 글에서는 자바스크립트로 구현된 보드게임의 로직을 개선하는 과정을 다루며,
개선 과정은 함수명 개선 → 중복 제거 → 책임 분리의 단계로 이루어져 있다.
작동하지만 개선이 필요한 코드
주어진 코드는 기능적으로는 문제없이 동작했지만, 더 나은 방식을 고민하다 보니 여러 개선점을 찾을 수 있었다.
function checkLadder(position) {
switch (position) {
case 4: return 14;
case 8: return 30;
case 21: return 42;
// ...
default: return null;
}
}
function checkSnake(position) {
switch (position) {
case 32: return 10;
case 36: return 6;
case 48: return 26;
// ...
default: return null;
}
}
개선 1. 함수명으로 의도를 명확히 하기
가장 먼저 생각한 부분은 함수명이 모호하다는 것이다.
checkLadder, checkSnake는 해당하는 위치의 칸을 판별하고 규칙에 따라 특정 값을 반환하는 함수들인데, 이름만 봐서는 이 함수가 boolean을 반환할지, 숫자를 반환할지 예상하기 어려웠다.
그래서 함수가 하는 일을 구체적으로 표현하기 위해 동사 + 명사 조합인 getLadderDestination, getSnakeDestination으로 변경했다.
function getLadderDestination(position) {
switch (position) {
// ...
}
}
function getSnakeDestination(position) {
switch (position) {
// ...
}
}
이제는 이름만 봐도 각각의 함수가 목적지를 반환한다는 것을 알 수 있다.
개선 2. 중복 코드 제거하기
함수명을 개선하고 나니 코드의 구조적인 문제가 눈에 들어왔다. 두 함수가 데이터만 다를 뿐 동일한 패턴을 반복하고 있다는 생각이 들었다.
현재 구조의 문제점
- 동일한
switch패턴이 반복됨 - 새로운 특수 칸을 추가할 때마다 비슷한 함수를 또 만들어야 함
- 게임 규칙이 바뀔 때 여러 곳을 수정해야 함
그래서 반복되는 로직과 다뤄야 하는 데이터를 분리하기로 했다.
const GAME_DATA = {
ladders: { 4: 14, 8: 30, 21: 42, 28: 76, 50: 67, 71: 92, 80: 99 },
snakes: { 32: 10, 36: 6, 48: 26, 62: 18, 88: 24, 95: 56, 97: 78 }
};
function getSpecialDestination(position, destinationMap) {
return destinationMap[position] || null;
}
// 사용 예
getSpecialDestination(32, GAME_DATA.snakes); // 10
getSpecialDestination(1, GAME_DATA.ladders); // null
getSpecialDestination라는 하나의 함수를 통해 switch문을 여러 번 쓸 필요가 없어졌고, 게임의 규칙이 변경되거나 새로운 특수 칸이 추가될 경우 GAME_DATA만 수정하면 되니 코드가 더 깔끔해지고 확장성 측면에서도 좋아졌다.
개선 3. 책임을 명확히 분리하기
함수명과 중복 코드를 수정하고 나니 또 다른 개선점이 눈에 띄었다. getSpecialDestination 함수가 너무 많은 일을 하고 있었고, 그렇기 때문에 함수명을 정하기가 애매모호했다는 생각이 들었다.
현재 함수의 역할
destinationMap에서 해당position의 값을 조회하고- 값이 없을 경우
null을 반환한다
많은 개발자들이 좋은 코드를 논할 때 함수는 단일 책임의 원칙을 가져야 한다고 하는데, 이 사실을 머리로는 알면서도 막상 로직을 구현할 때 적용하는 것은 쉽지 않은 것 같다.
뭔가 모호하고 여러 일을 하는 것처럼 보이는 이 함수를 다음과 같이 각각의 책임으로 분리했다.
// 단순 값 조회만 담당
function getValueFromMap(position, map) {
return map[position];
}
// 특수 위치 존재 여부만 판단
function isSpecialPosition(position, map) {
return getValueFromMap(position, map) !== undefined;
}
// 목적지 반환만 담당
function getDestination(position, map) {
return getValueFromMap(position, map);
}
이제 각 함수는 명확한 하나의 책임만 가지게 되었다.
// 사용 예
function movePlayer(current, dice) {
const next = current + dice;
// 사다리 위치라면 해당 목적지로 이동
if (isSpecialPosition(next, GAME_DATA.ladders)) {
return getDestination(next, GAME_DATA.ladders);
}
// 뱀 위치라면 해당 목적지로 이동
if (isSpecialPosition(next, GAME_DATA.snakes)) {
return getDestination(next, GAME_DATA.snakes);
}
return next;
}
코드가 더 길어 보이지만 각 함수의 역할이 명확해져서 읽기 쉽고 유지보수하기 좋은 구조가 되었다.
'TIL' 카테고리의 다른 글
| Node.js와 Express.js를 이용한 서버 구축 (0) | 2025.11.10 |
|---|---|
| 상태 관리 설계 (0) | 2025.11.10 |
| 컴포넌트와 모듈 시스템 (0) | 2025.11.10 |
| JavaScript의 this와 MPA 구현 (0) | 2025.11.10 |
| innterHTML, innerText, textContent의 차이 (0) | 2025.11.10 |
