안녕하세요! Devloo입니다. 오늘은 개발할 때 항상 염두에 두어야 할 7가지 소프트웨어 개발 원칙에 대해 이야기해보려고 합니다. 좋은 프로그래머가 되기 위해서는 기술과 상식을 조화롭게 활용하는 것이 중요합니다. 실용적이고 문제에 가장 적합한 해결책을 찾는 것이 핵심이죠. 도전에 직면했을 때 올바른 접근 방식을 선택하는 데 도움이 되는 몇 가지 소프트웨어 원칙이 있습니다.
이 원칙들은 모든 개발자가 알고 가끔씩 되돌아봐야 할 지침들입니다. 프로그래밍할 때 비장의 무기라고 생각하세요.
이 원칙들을 꾸준히 적용하면 중급에서 고급 소프트웨어 엔지니어로의 전환이 더 쉬워질 것입니다. 아마도 일부는 직관적으로 이미 적용하고 있을지도 모릅니다.
많은 원칙들이 있지만, 우리는 가장 중요한 7가지에 집중할 것입니다. 이 원칙들을 받아들이면 프로그래머로서 성장하고 더 나은 프로그래머가 될 수 있습니다.
1. You Aren’t Gonna Need It — YAGNI 원칙
이 원칙은 간단하고 명확하지만, 모든 사람이 따르는 것은 아닙니다. 코드를 추가할 때는 그것이 당장 필요한지 확인하세요. 나중에 유용할 것 같다는 이유로 코드를 남겨두지 마세요.
이 원칙은 리팩토링할 때도 적용됩니다. 메서드나 클래스, 파일을 리팩토링할 때 남아 있는 메서드를 제거하는 것을 주저하지 마세요. 과거에는 유용했을지 모르지만, 이제는 그렇지 않을 수 있습니다.
언젠가 다시 필요할 날이 올 수도 있습니다. 그때는 git 저장소를 통해 되살리면 됩니다.
2. Don’t Repeat Yourself — DRY 원칙
이 개념은 Andy Hunt와 Dave Thomas의 책 『실용주의 프로그래머: 초보자에서 마스터로』에서 처음 제시되었습니다.
이 아이디어는 단일 진실 공급원(single source of truth, SSOT)을 가지는 것에 중점을 둡니다. 그게 뭐냐고요?
“정보 시스템 설계와 이론에서 단일 진실 공급원(SSOT)은 모든 데이터 요소가 단 한 곳에서 마스터(또는 편집)되도록 정보 모델과 관련 데이터 스키마를 구조화하는 관행입니다. SSOT 시스템은 진정성 있고, 관련성 있으며, 참조 가능한 데이터를 제공합니다.”
— 위키백과
단일 진실 공급원을 유지하면 더 견고하고 명확한 코드베이스를 가질 수 있습니다.
중복된 코드는 낭비입니다. 두 곳에서 같은 논리를 유지해야 하고, 두 곳에서 테스트를 해야 하며, 한 곳이 변경되면 다른 곳도 변경해야 합니다.
대부분의 경우, 코드 중복은 시스템에 대한 지식 부족에서 비롯됩니다. 코딩하기 전에 실용적으로 생각해 보세요. 어쩌면 그 기능이나 비즈니스 로직이 다른 곳에 이미 구현되어 있을 수도 있습니다. 코드를 재사용하는 것은 항상 현명한 선택입니다.
3. Keep It Simple, Stupid — KISS 원칙
이 디자인 원칙은 1960년 미국 해군에 의해 처음 제시되었습니다. 이 원칙은 단순한 시스템이 가장 잘 작동하고 더 신뢰할 수 있다는 것을 의미합니다.
이 원칙은 1970년대의 “바퀴를 다시 발명하는 것”이라는 비즈니스와 광고의 은유와 많은 유사점을 가지고 있습니다.
소프트웨어 개발에 적용하면, 과도한 엔지니어링을 피하라는 뜻입니다. 때로는 가장 똑똑한 해결책이 가장 쉬운 것입니다. 단순하면서도 성능 좋고 효율적인 코드를 작성하는 것은 매우 아름다운 일입니다.
오늘날 흔히 저지르는 오류 중 하나는 단지 새로운 도구가 반짝인다는 이유로 사용하는 것입니다. 개발자는 최신 기술이 새롭기 때문에 사용하는 것이 아니라, 그 일이 적합하기 때문에 사용해야 합니다.
4. Big Design Up Front — BDUF 원칙
이 소프트웨어 개발 접근 방식은 매우 중요하지만 종종 무시됩니다. 구현 단계에 들어가기 전에 모든 것이 잘 계획되었는지 확인하세요.
“많은 경우, 사전에 충분히 생각하는 것이 나중에 심각한 개발 문제를 피하는 데 도움이 됩니다. 스펙에서 이 변경을 하는 데 한두 시간이 걸렸습니다. 만약 이 변경을 코드에서 했다면 일정에 몇 주가 추가되었을 것입니다. 저는 BDUF(Big Design Up Front)를 강력히 믿습니다. 익스트림 프로그래밍(XP)을 지지하는 사람들은 이를 기피하지만, 저는 BDUF를 사용하여 일관되게 시간을 절약하고 더 나은 제품을 만들었습니다. XP 지지자들이 뭐라고 하든 저는 자랑스럽게 BDUF를 사용하고 있습니다. 그들이 이 점에서 틀렸다는 것을 더 명확히 말할 수 없습니다.”
— 조엘 스폴스키
많은 개발자들이 코딩을 시작하지 않으면 진전을 이루지 못했다고 느낍니다. 그러나 이는 잘못된 생각입니다. 구체적인 계획을 세우면 처음부터 다시 시작해야 할 가능성을 줄일 수 있습니다.
때로는 디자인의 결함을 발견하기 위해 다른 사람들의 참여가 필요합니다. 이러한 대화가 빨리 이루어질수록 모두에게 더 좋습니다.
일반적으로 문제를 고치는 비용이 계획하는데 드는 시간보다 적다는 주장이 있지만, 이는 사실이 아닙니다. 사용자가 직면하는 버그나 불일치가 적을수록 사용자 경험은 향상됩니다. 다시 그들을 붙잡을 기회가 없을 수도 있습니다.
5. SOLID 원칙
SOLID는 가장 잘 알려진 소프트웨어 원칙입니다. (SOLID의 자세한 설명 보러가기)
SOLID는 다음의 약어로 구성되어 있습니다:
S) 단일 책임 원칙 (Single-responsibility principle)
이 원칙의 중요성은 아무리 강조해도 지나치지 않습니다. 모든 객체, 클래스, 메서드는 단일 책임을 가져야 합니다. 객체나 클래스, 메서드가 너무 많은 일을 하면 스파게티 코드가 됩니다. 예를 들어, 다음과 같은 메서드는 너무 많은 일을 하고 있습니다:
const saveTodo = async () => {
try {
response = await saveTodoApi();
showSuccessPop('Success');
window.location.href = '/successPage';
} catch (error) {
showErrorPopup(`Error: ${error} `);
}
}
이 메서드는 겉보기에는 무난해 보이지만, 실제로는 너무 많은 일을 하고 있습니다:
- 객체를 백엔드에 저장
- UI 알림 처리
- 네비게이션 기능
또 다른 문제는 테스트입니다. 얽혀 있는 기능을 테스트하는 것은 훨씬 더 어렵습니다.
O) 개방-폐쇄 원칙 (Open–closed principle)
소프트웨어 엔티티는 확장에는 열려 있어야 하지만 수정에는 닫혀 있어야 합니다. 즉, 필요한 기능을 추가하기 위해 메서드나 클래스를 오버라이드해서는 안 됩니다.
상속은 이를 해결하는 좋은 방법입니다. 자바스크립트에서는 주로 구성(composition)을 통해 이루어집니다.
💁 규칙: 엔터티를 확장 가능하도록 수정했다면, 처음에 그 원칙을 실패한 것입니다.
L) 리스코프 치환 원칙 (Liskov substitution principle)
이 원칙은 슈퍼클래스의 객체가 서브클래스의 객체로 대체될 수 있어야 하며, 애플리케이션은 여전히 예상대로 작동해야 한다는 것입니다.
I) 인터페이스 분리 원칙 (Interface segregation principle)
이 원칙은 Robert C. Martin이 Xerox에서 컨설팅할 때 정의한 명백한 원칙입니다.
“클라이언트는 사용하지 않는 인터페이스에 의존하도록 강요받아서는 안 됩니다.”
— Robert C. Martin
소프트웨어는 여러 독립적인 부분으로 나뉘어야 하며, 부작용을 최소화하여 독립성을 보장해야 합니다. 객체가 필요하지 않은 메서드를 구현하도록 강요하지 마세요. 예를 들어, 모든 동물이 날거나 걷거나 수영할 수 있는 것은 아닙니다.
interface Animal {
eat: () => void;
walk: () => void;
fly: () => void;
swim: () => void;
}
모든 동물이 날거나 걷거나 수영할 수 있는 것은 아니므로, 이러한 메서드는 인터페이스에 포함되지 않거나 선택적으로 제공되어야 합니다.
D) 의존성 역전 원칙 (Dependency inversion principle)
이 원칙의 중요성은 아무리 강조해도 지나치지 않습니다. 우리는 구체적인 구현이 아니라 추상화에 의존해야 합니다. 소프트웨어는 낮은 결합도와 높은 응집도를 가져야 합니다.
구현 방식이 아닌 작동 방식에 집중해야 합니다. 자바스크립트에서 날짜를 사용할 때 간단한 예가 있습니다. 자체 추상화 레이어를 구축할 수 있습니다. 이렇게 하면 나중에 날짜 공급자를 변경하더라도 한 곳만 변경하면 되고, 여러 곳을 변경할 필요가 없습니다.
때로는 추상화 레이어를 구축하는 데 노력이 필요하지만, 장기적으로는 그만한 가치가 있습니다. 예를 들어 date-io를 확인해 보세요. 여러 날짜 공급자와 함께 사용할 수 있는 추상화 레이어를 만듭니다.
6. “조기 최적화 회피” 원칙
조기 최적화는 필요성이 입증되기 전에 불필요한 최적화를 수행하도록 권장하는 관행입니다. KISS와 YAGNI 원칙을 적용하면 이러한 함정에 빠지지 않을 것입니다.
오해하지 마세요. 나쁜 일이 일어날 것을 예상하는 것은 좋지만, 구현 세부 사항에 들어가기 전에 그러한 최적화가 정말로 필요한지 확인해야 합니다.
아주 간단한 예로 확장이 있습니다. 새로운 앱이 바이럴할 것 같다고 해서 40대의 서버를 구매하지는 않을 것입니다. 대신 필요할 때 서버를 추가할 것입니다.
조기 최적화는 코드 지연을 초래할 수 있으며, 따라서 기능을 시장에 출시하는 시간을 늦출 수 있습니다.
많은 사람들은 조기 최적화를 모든 악의 근원으로 알고 있습니다.
7. “오컴의 면도날” 원칙
“오컴의 면도날(라틴어: novacula Occami), 또는 간결성의 법칙(라틴어: lex parsimoniae)은 ‘필요 없는 개체를 추가하지 말라’는 문제 해결 원칙입니다. 더 간단히 말하면, 가장 단순한 설명이 보통 맞는 설명이라는 것입니다.”
— 위키백과
프로그래밍 세계에서 이것이 의미하는 바는 무엇일까요? 필요하지 않은 개체를 만들지 말라는 것입니다. 실용적으로 생각하고, 그것들이 정말 필요한지 고민하세요. 그렇지 않으면 코드베이스의 복잡성만 증가할 수 있습니다.
마무리
이 원칙들은 매우 간단합니다. 사실, 그 단순함이 이 원칙들을 더욱 아름답게 만드는 것 같습니다. 처음에는 적용하기 어려울 수 있지만, 개발 일상에서 하나씩 적용해 보세요.
이 잘 알려진 원칙들을 따르면 더 나은 프로그래머가 될 수 있고, 왜 그렇게 해야 하는지 명확히 이해할 수 있습니다. 이미 직관적으로 많은 원칙을 적용하고 있다면, 왜 그렇게 했는지 깨닫게 되는 순간을 경험할 것입니다.
이번 시간에는 개발에 적용해야 할 7가지 소프트웨어 개발 원칙에 대해 알아보았습니다.
끝까지 읽어주셔서 감사합니다. 궁금한 점은 댓글로 남겨주세요. 🙂