#5 Bend, or Break
5장 구부러지거나 부러지거나
💻 실용주의 프로그래머: Topic 28
결합도 줄이기 (Reduce Coupling)
1. 핵심 개념 — “서로 덜 연결될수록 더 바꾸기 쉽다”
“우리가 어떤 것 하나만을 골라내려 해도, 그것이 우주의 다른 모든 것과 얽혀 있음을 깨닫게 된다.” — 존 뮤어(John Muir)
결합도(Coupling)가 높은 코드는 바꾸기 어렵다. 그 이유는 한 부분의 변화가 다른 부분까지 연쇄적으로 영향을 미치기 때문이다. 코드를 수정할 때마다 여러 모듈을 동시에 수정해야 한다면, 이미 결합도가 높다는 신호다.
💡 좋은 설계란, 변경의 파급 범위가 좁은 설계다.
2. 개념 비유 — “단단한 연결 vs 유연한 연결”
단단하게 얽힌 구조(삼각형 그물망)는 하나만 바꿔도 전체가 흔들린다.
반대로 유연하게 연결된 구조(선형 연결)는 일부만 교체 가능하다.
소프트웨어도 마찬가지다. 모듈 간 연결을 최소화해 독립적 변경이 가능한 형태로 만들어야 한다.
3. Tip 44 — “결합도가 낮은 코드는 바꾸기 쉽다”
결합도가 높은 코드에서는 다음 문제가 반복적으로 발생한다.
연쇄 호출(Train Wreck): 객체를 계속 점으로 연결하며 내부 상태에 접근
글로벌 상태(Global State): 전역 변수나 싱글톤으로 인해 의존성 확산
상속 남용: 부모 클래스 변경이 모든 자식에게 파급
💬 “한 모듈의 변경이 시스템 전체로 퍼질 때, 그건 ‘결합도 폭발’이다.”
4. 사례 — “열차 사고(Train Wreck)”
이 코드의 문제:
고객(Customer), 주문(Order), 총합(Totals) 객체가 직렬로 연결되어 있음
변경이 발생하면 전부 수정해야 함
한 모듈의 수정이 여러 객체에 의존함
5. Tip 45 — “묻지 말고 말하라 (Tell, Don’t Ask)”
객체의 내부 상태를 묻고 직접 조작하지 말라. 대신 객체 스스로에게 무엇을 하라(Tell) 고 요청하라.
이 원칙은 캡슐화(encapsulation) 를 강화하고, 연쇄 호출을 없애며, 한 객체의 책임을 명확히 분리한다.
6. 데메테르 법칙 (Law of Demeter, LoD)
“메서드는 오직 가까운 친구와만 이야기해야 한다.”
LoD 원칙: 메서드 내에서는 다음 대상에게만 메시지를 보낼 수 있다.
같은 클래스의 메서드
파라미터로 받은 객체
자신이 직접 생성한 객체
전역 변수 (지양)
즉,
같은 코드는 LoD 위반이다.
7. Tip 46 — “메서드 호출을 얽지 말라”
“
.하나를 줄이는 것이 결합도를 낮추는 시작이다.”
이처럼 중간 접근을 캡슐화하면 결합도가 줄고 코드 변경 시 영향 범위가 작아진다.
8. 글로벌 상태의 해악
전역 변수나 싱글톤은 모든 코드가 공유하는 결합 지점이다. 이로 인해 테스트가 어려워지고, 변경 시 시스템 전체가 흔들린다.
💡 전역 데이터는 “코드의 진흙탕”이다. 모든 함수가 엉켜 있기 때문에 어디서 문제가 발생했는지 추적하기 어렵다.
9. Tip 47 — “전역 데이터를 피하라”
전역 변수 대신 의존성 주입(Dependency Injection) 을 사용하라.
테스트 중에는 Mock 객체로 대체하라.
전역 데이터를 쓸 수밖에 없다면, 접근을 제한하는 래퍼(wrapper) 를 만들어라.
10. 외부 리소스도 전역 데이터다
데이터베이스, 파일 시스템, 외부 API 등은 모두 전역 상태를 가진 리소스다. 이 리소스를 사용할 때는 항상 명시적으로 관리 객체를 통해 접근해야 한다.
예:
11. Tip 48 — “전역적이어야 할 만큼 중요하다면 API로 감싸라”
정말 모든 곳에서 접근해야 하는 전역 리소스라면, 직접 노출하지 말고 명시적인 API 계층으로 감싸라.
✅ “중요한 전역은 감추고, 공개할 땐 제어하라.”
12. 상속은 결합도를 높인다
상속은 부모의 변경이 자식에게 즉시 전파되는 구조적 결합이다. 상속 대신 조합(Composition) 을 우선 고려하라.
💬 “상속은 재사용의 도구가 아니라 결합의 덫이다.”
13. 결합도의 최종 결론 — “결합은 시스템의 부패를 부른다”
결합도가 높을수록
테스트가 어렵고,
리팩터링이 불가능하며,
변경 비용이 폭발한다.
결국 유지보수가 불가능한 시스템으로 이어진다.
“결합을 줄여라. 묻지 말고 말하라.” 느슨한 연결이 유연한 시스템을 만든다. Low coupling, high cohesion.
💻 실용주의 프로그래머: Topic 29
실세계를 갖고 저글링하기 (Program Close to the Real World)
1. 핵심 개념 — “세상은 동적이다. 코드도 그래야 한다”
“그냥 일어나는 일은 없다. 일어나도록 만들어진 것이다.” — 존 F. 케네디
과거에는 사람이 컴퓨터의 한계에 맞춰야 했다. 하지만 이제는 컴퓨터가 현실의 세계에 맞춰야 한다. 현실은 사건이 일어나고, 상태가 바뀌며, 사람들이 반응한다. 따라서 우리의 프로그램도 이 “동적인 세계의 리듬” 을 반영해야 한다.
💡 “반응형 시스템(Responsive System)”이란, 현실의 이벤트 흐름을 모델링하여 유연하게 반응하는 시스템이다.
2. 이벤트(Event)의 개념
이벤트란 “무언가가 일어났음”을 나타내는 신호이다.
버튼 클릭
데이터 갱신
네트워크 수신
센서 신호
계산 완료
즉, 프로그램은 입력값만 다루는 것이 아니라 “시간상 발생하는 사건” 에 반응해야 한다.
3. 이벤트 기반 설계의 필요성
“이벤트를 중심으로 코드를 설계하면, 프로그램은 현실의 시간 축과 나란히 흐를 수 있다.”
이벤트 기반 구조는 시스템을 더 유연하게 만들고, 비동기 환경에서도 직관적인 동작을 유지시킨다.
4. 이벤트 처리 전략 — 4가지 핵심 기법
유한 상태 기계 (Finite State Machine, FSM)
감시자 패턴 (Observer Pattern)
게시-구독 (Publish–Subscribe)
반응형 프로그래밍과 스트림 (Reactive Streams)
5. 유한 상태 기계 (FSM)
FSM은 “현재 상태(State)”와 “이벤트(Event)”에 따라 다음 상태로 전이(Transition)되는 구조다.
예시 👇 웹소켓 메시지 수신을 FSM으로 표현:
초기 상태: 대기 중
헤더 메시지 수신 → “메시지 수신 중”으로 전이
데이터 수신 → 계속 “수신 중” 유지
트레일러 수신 → “완료”로 전이
오류 발생 → “에러”로 전이
이 과정을 코드로 나타내면 다음과 같다:
FSM은 복잡한 분기문을 단순한 전이표(transition table) 로 표현한다. 상태별 로직을 독립적으로 유지할 수 있어 확장성이 좋다.
6. 감시자 패턴 (Observer Pattern)
“누군가가 무언가를 보고 있다.”
이벤트를 발생시키는 쪽은 감시 대상(Observable), 이벤트를 처리하는 쪽은 감시자(Observer) 다.
Ruby 예시:
👉 여러 콜백을 등록하고, 한 이벤트 발생 시 모두 호출된다. 하지만 모든 감시자가 등록되어 있어야 한다는 제약 때문에 결합도가 높아질 수 있다.
7. 게시-구독 (Publish–Subscribe)
감시자 패턴의 결합도를 낮춘 형태. 발행자(Publisher) 와 구독자(Subscriber) 가 직접 연결되지 않고, 채널(Channel) 을 통해 간접적으로 통신한다.
발행자: 특정 채널에 이벤트를 보냄
구독자: 관심 있는 채널을 구독함
메시지는 채널을 통해 비동기적으로 전달됨
이 구조는
느슨한 결합(loose coupling),
병렬 처리,
분산 시스템 이벤트 전달 에 모두 적합하다.
8. 반응형 프로그래밍과 스트림 (Reactive Programming & Streams)
“이벤트를 데이터처럼 다뤄라.”
이벤트가 연속적으로 발생한다면, 그것은 시간을 따라 흐르는 데이터 스트림(stream) 이 된다.
대표적인 구현이 RxJS.
📈 0.5초마다 동물 이름을 하나씩 출력하는 스트림이 만들어진다. 이벤트와 시간의 흐름이 “데이터 파이프라인”으로 결합된 형태다.
9. 비동기 스트림과 REST 결합
RxJS는 REST 호출도 스트림으로 연결할 수 있다:
여러 요청이 병렬로 실행되어, 각 응답이 독립적인 이벤트로 처리된다.
💡 동기/비동기를 하나의 추상화로 통합하는 것이 반응형 프로그래밍의 가장 큰 강점이다.
10. 어디에나 이벤트가 있다
이벤트는 단순히 UI 클릭만이 아니다.
로그인이 성공했다
파일이 수정되었다
센서가 감지했다
트랜잭션이 커밋되었다
모든 시스템은 “이벤트의 연쇄”로 움직인다. 이 이벤트를 중심으로 코드를 구성하면, 시스템은 실세계를 반영하는 유연한 흐름을 갖게 된다.
11. 관련 항목
Topic 28: 결합도 줄이기
Topic 36: 철판 (Concurrency & Synchronization)
“코드는 현실의 시간축 위에서 반응해야 한다.” 이벤트, 상태, 스트림을 저글링하라. Don’t fight the world. Model it.
🧩 변환 프로그래밍 — “프로그램은 결국 변환이다”
“자신이 하고 있는 일 하나의 과정으로 서술할 수 없다면, 자기가 뭘 하고 있는지 모르는 것이다.” – W. 에드워즈 데밍
✔️ 프로그래밍은 곧 변환 과정이다
우리는 코드를 짤 때 클래스 구조, 언어 문법, 알고리즘, 프레임워크 고민에 대부분의 시간을 쓴다. 하지만 정작 프로그램의 본질이 무엇인지는 생각하지 않는다.
📌 프로그램의 본질: 입력을 받아 출력으로 ‘변환’하는 것
파일을 읽고 →
특정 규칙을 적용하며 →
결과를 출력한다
이 단순한 흐름이 모든 프로그램의 근본이다.
하지만 이 본질을 잊으면, 코드는 불필요하게 복잡해지고 “왜 만든 기능인지”조차 불명확한 구조가 된다.
🔍 1970년대로 돌아가 파이프라인을 보자
옛 유닉스 환경에서는 에디터도 부실했고, C 컴파일러조차 불편했다. 그래서 *“잘게 나뉜 프로그램들을 파이프로 연결해 복잡한 작업을 완성”*하는 방식이 자연스럽게 발달했다.
대표적인 예:
이 명령은 여러 변환 단계를 연결해 원하는 결과를 만들어낸다.
단계별로 쪼개보면?
1) find . -type f
find . -type f→ 디렉터리 내 모든 일반 파일 목록을 출력
2) xargs wc -l
xargs wc -l→ 각 파일의 줄 수를 구한다
3) sort -n
sort -n→ 줄 수 기준 오름차순 정렬
4) tail -5
tail -5→ 가장 줄 수가 많은 다섯 개만 출력
이렇게 보면, 전체는 단순히 **연결된 변환들의 연속(line)**일 뿐이다.
📦 데이터 공장처럼 생각하기
책에서는 이 구조를 **“공장 조립 라인”**에 비유한다.
입력(원자재)을 넣으면 → 변환 단계를 거쳐 → 완성된 결과물이 나온다.
이 사고방식은 코드를 작성할 때도 그대로 적용된다.
🧠 변환 모델로 생각하기
책에서는 이를 파이프라인(pipeline) 철학으로 정리한다. 각 단계는 다음 작업의 입력이 되어 흐른다.
예시 그림 구성:
이 단계를 통해 **“가장 줄 수가 긴 파일 5개”**라는 결과가 나온다.
🧩 예제: 애너그램 탐색기 만들기
이제 실전 예제로 ‘애너그램(anagram)’ 프로그램을 만든다고 해보자. 입력된 단어로 만들 수 있는 조합, 사전 검색, 분류 작업을 변환 단계로 나눠본다.
변환 단계 요약
단계 0
초기 입력
"lyvin"
단계 1
모든 글자 조합 구하기
lv, ly, lvy, …
단계 2
각 조합을 정렬한 signature 만들기
ilv, ilny, …
단계 3
사전에서 signature에 맞는 단어 찾기
ivy, yin, vinyl …
단계 4
길이 기준으로 묶기
3→ivy, 4→liny, 5→vinyl
이 전체 흐름이 하나의 변환 파이프라인이다.
🧪 실제 코드 예시(엘릭서)
책에서는 엘릭서로 파이프라인을 구현한다.
예: 가능한 조합 생성
이런 식으로 각 단계를 하나의 변환 함수로 만들고 마지막에 연결해 하나의 파이프라인을 완성한다:
🛠 오류 처리는 어떻게?
세상은 완벽하지 않기 때문에 변환 도중 오류가 날 수 있다.
책은 이를 간단한 wrapper(튜플)로 처리한다:
성공:
{:ok, 결과}실패:
{:error, 이유}
변환 단계 중 어느 단계에서든 에러가 나면
그 이후 단계는 실행되지 않고 {:error, 이유}가 그대로 파이프라인을 지나간다.
이 방식은 명확하고, 테스트하기 쉽고, 확장이 용이하다.
🧭 왜 이것이 중요한가?
프로그램이 복잡해지는 이유는 대부분 “데이터 흐름”이 아니라 “구조, 클래스, 메서드 호출 관계”에 집착하기 때문이다.
하지만 책이 강조하는 핵심은 단 하나:
프로그램은 입력을 받아 출력으로 변환하는 과정이다.
이 관점으로 전환하면,
기능 설계 명확해지고
테스트가 쉬워지고
오류 처리 구조가 간단해지고
대규모 리팩토링이 쉬워진다
📝 실용 정리
✔️ 변환 중심으로 사고하라
입력 → 단계별 변환 → 출력 이 흐름만 명확하면 코드는 단순해진다.
✔️ 복잡도는 구조가 아니라 흐름에서 줄인다
결국 변환들이 잘 연결되어 있으면 프로그램은 자연스럽게 이해된다.
✔️ 파이프라인은 언어에 상관 없다
어떤 언어든 변환 철학만 있으면 적용 가능하다.
🧱 Topic 31 — 상속세: 상속은 왜 이렇게 위험한가
“당신이 원한 것은 바나나였지만, 당신이 받은 것은 바나나를 들고 있는 고릴라와 정글 전체다.” — 조 암스트롱
“객체지향 언어를 쓰면 당연히 상속을 써야 하지 않나?” 많은 개발자가 이렇게 생각한다. 하지만 현실에서 상속은 막강한 만큼 위험하고, 대부분의 경우 적합하지 않다.
이 글에서는 상속이 왜 문제를 일으키는지, 그리고 상속 없이도 더 깔끔하게 구조를 설계하는 방법을 살펴본다. 코드는 모두 10년차 코틀린 개발자 관점으로 재구성했다.
🕰️ 상속의 역사: Simula67이 의도한 것
처음 상속이 등장한 시절, 목적은 지금과 달랐다. Simula67에서 상속은 단순히 “여러 타입을 하나의 리스트에 담기 위한 편의 기능”이었다.
초기 개념은 대략 이런 느낌에 가까웠다:
여러 객체를 한 리스트에 넣고 싶다
공통 필드를 prefix로 갖고 있으면 편하겠다
그래서 “상속 비슷한 것”이 등장
지금 우리가 사용하는 “부모 클래스—자식 클래스” 구조는 그 이후 스몰토크와 C++에 의해 굳어진 형태다.
⚠️ 상속이 위험한 이유 1: 결합 폭발
상속을 쓰면 자식 클래스는 부모 클래스의 구현에 강하게 결합된다. 부모의 필드, 메서드, 내부 로직, 심지어 변경 이력까지 전부 자식에게 흘러들어온다.
아래는 책의 Ruby 예제를 코틀린 버전으로 재구성한 것이다.
❗ 잘못된 상속 예 (코틀린)
이 코드의 문제를 보자.
Vehicle의 moveAt() 구현이 변경되면 Car는 그대로 영향받는다
Car가 Vehicle의 내부 구조를 “상식적으로” 안다고 착각한다
Vehicle이 API를 바꾸면 Car는 바로 고장난다
Car는 Vehicle이라는 설계 결정에서 벗어날 수 없다
코드 재사용처럼 보이지만, 사실 결합도 급증이다.
⚠️ 상속이 위험한 이유 2: 타입 분류를 위해 상속을 쓰는 것은 부적절
많은 사람이 상속을 “타입 분류”라고 착각하지만, 현실의 도메인은 훨씬 복잡하다.
예를 들어 Car는 Vehicle이지만 동시에:
보험 대상(InsuredItem)
대출 담보물(Collateral)
회계상의 자산(Asset)
이 될 수 있다.
즉 단일 상속으로는 현실의 다중 정체성을 반영할 수 없다. 그래서 옛날 C++이 다중 상속을 만들었지만 그것은 더 큰 혼란만 만들었다.
🧩 상속의 대안 1 — 인터페이스 / 프로토콜
상속 없이도 타입을 통합할 수 있다. 코틀린에서는 **인터페이스 + 기본 구현(default method)**로 충분하다.
✔️ 다형성 목적이라면 인터페이스가 정답
장점
다중 구현 가능
필요 함수만 강제
상속 트리 없음
도메인 정체성 충돌 없음
🧩 상속의 대안 2 — 위임(Delegation)
코틀린은 위임을 언어 차원에서 지원한다 (by 키워드 제공).
✔️ Repository 기능을 상속하지 않고 위임으로 해결
장점
Account는 Persistence API 전체를 상속받지 않는다
필요한 메서드만 노출
Persistence 구현 변경시 Account 영향 없음
결합도 ↓, 유연성 ↑
🧩 상속의 대안 3 — 믹스인 / 트레이트 / extension
코틀린은 mixin은 없지만, interface + default method + 확장 함수 조합으로 믹스인을 충분히 구현할 수 있다.
공통 finder 기능 믹스인 예시 (코틀린 스타일)
mixin의 핵심 기능을 코틀린에서는 인터페이스 + 디폴트 메서드로 대체한다.
🧪 계층이 복잡해지면 위험은 기하급수적으로 증가한다
현실 시스템은 금방 복잡해진다.
검증 로직이 많아짐
정책마다 조건이 다름
API 규칙 다름
UI마다 제약 다름
상속 트리로 이 모든 것을 해결하려 하면 트리가 기괴하게 커진다.
책에서 나온 복잡한 상속 트리 그림은 코틀린 백엔드 개발자가 Spring에서 계층 구조를 잘못 설계했을 때 종종 보는 모습 그대로다.
🧩 도메인 검증의 현실: 상속보다 mixin/조합이 더 적합하다
예를 들어 "계정 검증"이라는 공통 기능이 있다고 하자.
코틀린에서는 이렇게 구현하는 것이 훨씬 자연스럽다:
➡️ 상속 트리가 늘어나지 않고, ➡️ 필요한 기능만 조립하며, ➡️ 검증 로직이 분리되며, ➡️ 변경의 충격이 국소적이다.
🎯 결론 — 상속이 답인 경우는 거의 없다
Topic 31이 전달하는 핵심 메시지는 매우 명확하다.
✔ 상속을 피하고 인터페이스·위임·믹스인을 먼저 고려하라
✔ 상속은 결합도를 급격히 증가시킨다
✔ 타입 정리는 상속 계층보다 조합(composition)이 맞다
✔ 공통 기능은 mixin/trait/interface default method로 해결하라
✔ 프레임워크가 강제하지 않는 이상 상속을 쓰지 마라
🧩 Topic 32 — 설정(Configuration): 코드 밖으로 빼라
“모든 물건은 제자리에 두고, 일은 모두 때를 정해서 하라.” — 벤저민 프랭클린
애플리케이션이 출시된 후, 바뀔 가능성이 있는 값에 코드가 직접 의존하고 있다면 그 값은 “코드 내부”가 아니라 **외부 설정(external configuration)**으로 관리하는 것이 올바르다.
환경이 다르면 값이 달라진다
고객마다 정책이 다를 수 있다
인프라 환경이 변경될 수 있다
서버 위치/로깅/포트/권한 같은 값은 실행 환경마다 다르다
따라서 설정을 외부로 빼두면 애플리케이션은 더 유연해지고, "코드가 환경에 종속되지 않는" 구조를 만들 수 있다.
🧭 Tip 55 — 외부 설정으로 애플리케이션을 조정할 수 있게 하라
일반적으로 설정 데이터에 들어가는 값들:
외부 API/DB 인증 정보
로그 레벨, 로그 저장 위치
포트 번호, IP 주소, 기계/클러스터 이름
특정 환경에서만 적용되는 검증 값
배송비 같은 정책성 매개변수
지역(국가/언어)에 따른 서식
라이선스 키
➡️ 이 값들이 코드 안에 박혀 있다면 애플리케이션은 환경 변화에 매우 취약해진다.
🏗️ 정적(static) 설정: 파일이나 DB로 관리
현대 애플리케이션 대부분은 다음 방식 중 하나로 정적 설정을 관리한다:
YAML (
application.yml)JSON
Properties 파일
데이터베이스 테이블
코틀린 + Spring이라면 자연스럽게 이러한 형태가 된다.
✔️ 실전 예 — application.yml
✔️ 실전 예 — Kotlin 구성 객체로 바인딩
이제 서비스 코드는 설정에 종속되지만 환경 파일만 바꾸면 애플리케이션 전체가 다른 정책으로 작동한다.
🚚 서비스형 설정(Configuration-as-a-Service)
기업 규모가 커지면, 설정을 단순 파일/DB로 관리하는 것만으로는 부족해진다. 이때 설정 서버(Config Server) 같은 별도 서비스가 등장한다.
예:
Spring Cloud Config
AWS AppConfig
Consul KV
etcd
Git 기반 설정 저장소
장점
여러 마이크로서비스가 설정을 공유
인증/권한 컨트롤 가능
인스턴스 전체 설정을 동시에 변경 가능
설정 변경을 실시간으로 동기화
실전 예 — 코틀린에서 설정 서버로부터 값 받기
이제 코드를 바꾸지 않고도 운영자가 AppConfig 값만 바꾸면 배송비 정책 전체가 바뀐다.
🦤 도도 코드를 작성하지 말라 (Dodo Code)
책에서는 “환경에 적응하지 못해 멸종된 도도새(Dodo)”를 비유로 사용한다.
➡️ 즉, 환경 변화에 반응하지 못하는 코드는 곧 죽은 코드다.
아래가 도도 코드:
설정을 하드코딩한다
값이 바뀔 때마다 코드 릴리즈가 필요
빌드 → 배포 → 재시작을 반복해야만 한다
여러 서비스가 다른 정책을 가져야 하는데 모두 코드로 박혀 있다
현대 백엔드 시스템에서 이런 코드는 생존할 수 없다.
🧾 실제 코틀린 서비스에서 자주 등장하는 설정 Anti-Pattern
❌ 1. 하드코딩된 URL, 포트, 토큰
❌ 2. 환경 별 if/else 분기
❌ 3. 운영 중 정책 변경을 배포로 해결
→ “배송비 좀 바꿔주세요” → 배포 필요 → 장애 위험 증가
이 모든 문제는 외부 설정화로 즉시 해결된다.
🛡️ 제대로 된 설정 구조를 설계하는 법
✔️ 1. 소스코드와 설정을 철저히 분리
설정은 YAML/DB/설정 서버에 두고 코드에서는 오직 “참조”만 한다.
✔️ 2. 모든 실행 환경에서 safe fallback 제공
설정 서버가 죽으면 local YAML 값 사용
존재하지 않는 키면 default 값 사용
✔️ 3. 설정 변경은 코드 배포 없이 반영
설정 서버
런타임 refresh
메시지 기반 변경 알림 (Kafka/SNS)
✔️ 4. 설정도 테스트해야 한다
설정을 잘못 넣으면 서비스 전체가 망가질 수 있다.
🧪 실전 예: 정책을 외부 설정으로 빼기 (코틀린)
기존 나쁜 코드
➡️ 정책이 바뀔 때마다 반드시 배포가 필요하다.
개선된 코드
환경 파일만 바꾸면 끝.
📌 결론: 설정을 코드 밖에 두어라
Topic 32 전체의 핵심 메시지는 단 하나다.
코드는 로직을 담고, 설정은 외부에서 조정된다. 두 역할을 섞지 마라.
✔ 설정을 외부로 빼면…
배포 없이 정책 변경 가능
고객/환경별 동작 분리
유지보수 비용 절감
개발과 운영 분리
재사용성, 이식성 증가
✔ 상시 변화하는 현대 서비스에는 필수다
마이크로서비스
서버리스
글로벌 서비스
고객별 정책
A/B 테스트
환경별 다양한 런타임
Last updated