위코드에서 공부하며 정리한 내용입니다.
기획이나 디자인이 변경되거나, 기능 추가로 코드를 수정해야 하는 상황은 자주 발생합니다. 그럴 때 기존 코드가 복잡해서 수정하기 어려운 상황을 방지하기 위해 관심사의 분리가 필요합니다. 관시사 분리란 작성한 코드가 하나의 관심사만 처리하도록 단위별로 잘게 나눠서 동작하게 만드는 것입니다. 그렇게 하면 문제가 생겼을 때 읽어야 하는 코드의 단위가 줄어들고, 해당 부분만 수정하므로 변화에 대한 내구성도 갖추게 됩니다. 컴퓨터 공학에서는 이런 기법을 관심사의 분리(SoC, Separation of Conserns)라고 부릅니다.
코드의 관심사 분리는 소프트웨어 개발 원칙인 KISS(Keep it Simple, Stupid) 과도 관련이 있습니다. 하나의 코드가 하나의 기능을 수행하면 해당 코드의 목적을 더 명확하게 알 수 있으므로 재사용이 쉽고 유지 보수도 용이합니다. 구현 코드의 작동 여부를 확인하는 테스트 코드 자성도 간단해집니다. 이 외에 관심사 분리가 적절히 구현된 코드에서는 Loose Coupling(낮은 결합도, 각각 코드가 얽히지 않고 독립적으로 분리)와 High Cohesive(높은 응집도, 유사한 내용끼리 비슷한 위치에 잘 모여 있는)와 같은 특징이 있습니다.
아래 코드는 id 와 pw 입력값에 따라 로그인 버튼의 스타일이 변경되는 로직으로 아직 관심사 분리가 되지 않은 코드입니다.
// login.js
const loginForm = document.getElementByClassName('loginForm')[0];
const loginBtn = document.getElementById('loginBtn');
const handleInput = () => {
const idValue = document.getElementById('id').value;
const pwValue = document.getElementById('pw').value;
const isIdValid = idValue.length > 1;
const isPasswordValid = pwValue.length > 1;
const isLoginInputValid = isIdValid && isPasswordValid;
loginBtn.disabled = !isLoginInputValid;
loginBtn.style.opacity = isLoginInputValid ? 1 : 0.3;
loginBtn.style.cursor = isLoginInputValid ? 'pointer' : 'default';
};
const init = () => {
loginForm.addEventListener('input', handleInput);
};
init();
위 코드를 관심사 별로 분리하면 아래와 같습니다.
// login.js
const loginForm = document.getElementByClassName('loginForm')[0];
const loginBtn = document.getElementById('loginBtn');
// 1 - 유효성 검사 함수
const validateForm = () => {
const idValue = document.getElementById('id').value;
const pwValue = document.getElementById('pw').value;
const isIdValid = idValue.length > 1;
const isPasswordValid = pwValue.length > 1;
return isIdValid && isPasswordValid;
}
// 2 - 로그인 버튼의 스타일만 변경하는 함수
const handleButtonActive = (isButtonActive) => {
loginBtn.disabled = !isButtonActive;
loginBtn.style.opacity = isButtonActive ? 1 : 0.3;
loginBtn.style.cursor = isButtonActive ? 'pointer' : 'default';
}
// 3 - 유효성 검사를 통해 버튼활성화를 실행하는 함수
const handleLoginInput = () => {
const isFormValid = validateForm();
handleButtonActive(isFormValid);
}
const init = () => {
loginForm.addEventListener('input', handleLoginInput)
}
init();