에이전트별 작업 큐와 중앙 제어 구조 도입을 통한 쓰레드 폭증 문제 개선
📘 SyncMon
1. 개요
SyncMon은 다수의 에이전트가 독립적으로 JOB을 수행하는 구조를 가지고 있었습니다. 초기에는 이 방식이 단순하고 구현 부담이 적어 빠르게 동작하는 데에는 문제가 없었습니다. 그러나 에이전트 수와 JOB 수가 함께 증가하기 시작하면서, 작업 유입량이 곧바로 실행 쓰레드 수 증가로 이어지는 구조적 한계가 드러났습니다.
문제의 본질은 단순히 쓰레드가 많아졌다는 데 있지 않았습니다. 더 큰 문제는 시스템이 감당 가능한 동시 실행량을 스스로 통제하지 못하는 구조였다는 점입니다. 에이전트가 늘고 특정 시점에 JOB이 집중되면, 실행 경로가 동시에 열리면서 CPU 스케줄링 부담, 메모리 사용량 증가, 컨텍스트 스위칭 비용 증가가 함께 발생했습니다. 운영 관점에서는 순간 부하를 예측하기 어려웠고, 장애가 발생했을 때도 어느 구간에서 병목이 생겼는지 파악하기가 쉽지 않았습니다.
이번 개선의 목표는 단순히 쓰레드 개수를 줄이는 것이 아니었습니다.
핵심은 다음 두 가지였습니다.
첫째, JOB 유입량과 실제 실행 동시성을 분리해 시스템이 감당 가능한 수준 안에서만 작업이 처리되도록 만드는 것.
둘째, 전체 작업 흐름을 관찰 가능하고 제어 가능한 구조로 바꾸는 것이었습니다.
이를 위해 SyncMon은 각 에이전트별 작업 큐를 두고, 에이전트당 동시 실행 수를 제한하는 방식으로 실행 모델을 재구성했습니다. 또한 중앙 제어 역할을 담당하는 관리 쓰레드를 두어, 작업 분배와 실행 상태를 한 곳에서 관리하도록 변경했습니다.
2. 기존 구조의 한계
기존 구조는 에이전트가 증가할수록 전체 동시 실행 수 역시 자연스럽게 증가하는 형태였습니다. 이 방식은 에이전트 수가 적고 JOB 유입이 완만할 때는 큰 문제가 드러나지 않았지만, 운영 규모가 커질수록 몇 가지 한계가 명확해졌습니다.
우선, 작업 유입과 실행이 사실상 직접 연결되어 있었습니다.
즉, JOB이 늘어나면 이를 흡수할 완충 구간 없이 실행 쓰레드가 즉시 증가하는 형태였습니다. 이 구조에서는 순간적인 JOB 집중이 발생할 경우 시스템 부하가 짧은 시간 안에 급격히 치솟을 수밖에 없습니다.
또한 이 방식은 자원 사용량을 예측하기 어렵다는 문제가 있었습니다. 쓰레드 수가 부하에 따라 크게 흔들리면 CPU 사용량과 메모리 사용량 역시 안정적으로 관리하기 어렵습니다. 특히 컨텍스트 스위칭 비용은 단순히 쓰레드 수만 많다고 끝나는 문제가 아니라, 실제 처리량 대비 비효율을 키워 전체 시스템 응답성을 떨어뜨리는 원인이 됩니다.
운영 측면의 문제도 컸습니다. 작업이 개별 에이전트 단위에서 분산적으로 실행되다 보니, 전체 처리 흐름을 한눈에 보기 어려웠습니다. 특정 시점에 어느 에이전트가 얼마나 바쁜지, 작업이 왜 지연되는지, 병목이 어디서 발생하는지 파악하려면 개별 상태를 따로 추적해야 했습니다. 다시 말해, 실행은 되고 있었지만 통제 가능한 구조는 아니었습니다.
정리하면 기존 구조의 한계는 다음과 같았습니다.
- JOB 증가가 곧바로 쓰레드 증가로 이어지는 결합 구조
- 순간 부하에 취약한 실행 모델
- 자원 사용량의 예측 가능성 부족
- 전체 작업 흐름에 대한 관찰성과 제어성 부족
이 문제는 단순 튜닝으로 해결할 수 있는 성격이 아니었고, 실행 구조 자체를 다시 정리할 필요가 있었습니다.
3. 개선 방향
개선 방향을 잡을 때 가장 먼저 본 것은 “어떻게 더 빨리 처리할 것인가”가 아니라, 어떻게 통제 가능한 구조로 만들 것인가였습니다.
이번에 선택한 방식은 다음과 같습니다.
에이전트마다 독립적인 작업 큐를 두고, 각 에이전트는 동시에 최대 2개의 작업만 실행할 수 있도록 제한했습니다. 이렇게 하면 특정 에이전트에 JOB이 몰리더라도 실행 동시성은 상한이 정해져 있기 때문에, 부하가 시스템 전체로 무분별하게 번지는 것을 막을 수 있습니다. 대기할 JOB은 큐에 쌓이고, 실제 실행은 제한된 슬롯 안에서만 이뤄집니다.
여기에 중앙 관리 쓰레드를 두어 전체 에이전트의 상태를 확인하고, 작업이 끝난 에이전트에만 후속 JOB을 분배하도록 구성했습니다. 이 구조의 장점은 실행 책임과 제어 책임을 분리할 수 있다는 데 있습니다. 실제 작업 수행은 각 에이전트가 맡고, 언제 어떤 작업을 투입할지는 중앙에서 판단하게 함으로써 전체 흐름을 일관되게 다룰 수 있게 됩니다.
여기서 중요한 점은, 이번 개선이 “모든 것을 중앙에서 처리하는 구조”를 지향한 것은 아니라는 점입니다. 중앙 관리 쓰레드는 작업 그 자체를 수행하지 않고, 실행 가능 상태를 판단하고 분배를 조율하는 제어 지점으로만 동작합니다. 즉, 작업 수행은 분산되어 있고, 실행 정책만 중앙에서 관리하는 형태입니다.
4. 왜 이 구조를 선택했는가
이 문제를 해결하는 방식은 하나가 아니었습니다. 예를 들어 전역 쓰레드 풀 하나로 모든 작업을 흡수하는 방식도 고려할 수 있습니다. 구현 자체는 단순할 수 있지만, 이 경우 특정 에이전트의 작업이 전체 풀을 점유하면서 다른 에이전트 작업까지 지연시키는 문제가 생길 수 있습니다. 즉, 전체 최적화는 쉬워 보여도 에이전트 단위의 독립성과 공정성이 깨질 가능성이 있습니다.
반대로 각 에이전트가 완전히 자율적으로 쓰레드를 관리하도록 두면 독립성은 높지만, 전체 동시 실행량을 통제하기 어려워집니다. 기존 구조가 바로 이 한계를 드러냈습니다.
이번에 선택한 에이전트별 큐 + 동시 실행 제한 + 중앙 제어 구조는 이 두 극단 사이에서 현실적인 균형을 맞추기 위한 선택이었습니다.
- 에이전트 단위의 독립성은 유지하되
- 실행 동시성에는 상한을 두고
- 전체 작업 흐름은 중앙에서 관찰하고 조정할 수 있게 만든 것
물론 이 구조에도 trade-off는 있습니다. 동시 실행 수를 제한하면 순간 처리량만 놓고 보면 더 공격적인 실행 모델보다 느릴 수 있습니다. 하지만 SyncMon에서 더 중요했던 것은 피크 순간의 최대 처리량보다, 전체 시스템이 무너지지 않고 예측 가능한 방식으로 지속적으로 동작하는 것이었습니다. 운영 시스템에서는 평균 성능보다 최악의 순간을 얼마나 통제할 수 있는지가 더 중요할 때가 많고, 이번 개선도 그 관점에서 접근했습니다.
5. 개선된 동작 방식
개선 이후의 흐름은 다음과 같습니다.
각 에이전트는 자신만의 작업 큐를 가집니다. JOB이 유입되면 해당 큐에 적재되고, 에이전트는 동시에 최대 2개의 작업만 실행합니다. 실행 가능한 슬롯이 없으면 JOB은 큐에서 대기합니다. 이로써 작업 유입량이 많아져도 실행 쓰레드 수가 무제한으로 증가하지 않도록 막을 수 있습니다.
중앙 관리 쓰레드는 전체 에이전트의 상태를 주기적으로 확인합니다. 특정 에이전트에서 작업이 완료되어 실행 슬롯이 비면, 중앙 관리 쓰레드는 그 시점에 다음 JOB을 할당합니다. 이 방식의 핵심은 작업을 “많이 넣는 것”이 아니라, 실행 가능한 시점에만 넣는 것입니다.
결국 구조는 다음처럼 정리됩니다.
- 작업은 에이전트별 큐에 적재된다.
- 실행 동시성은 에이전트별로 제한된다.
- 중앙 제어부는 작업 완료와 실행 가능 상태를 기준으로 후속 JOB을 분배한다.
- JOB 유입량과 실행 동시성이 분리되어, 부하가 시스템 전체로 직접 전파되지 않는다.
이 구조로 바뀌면서 전체 시스템은 이전보다 훨씬 예측 가능한 방식으로 동작하게 되었습니다.
6. 개선 효과
이번 개선의 가장 큰 효과는 쓰레드 수를 줄였다는 사실 자체보다, 쓰레드 수를 통제 가능한 변수로 바꿨다는 데 있습니다.
기존에는 에이전트 수와 JOB 유입 패턴에 따라 실행 쓰레드 수가 크게 흔들릴 수 있었습니다. 반면 개선 이후에는 에이전트별 동시 실행 수에 상한이 있기 때문에, 시스템이 감당해야 하는 실행 부하의 범위를 훨씬 명확하게 예측할 수 있게 되었습니다. 이는 곧 CPU와 메모리 사용량을 보다 안정적으로 관리할 수 있다는 의미이기도 합니다.
운영 측면에서도 이점이 있었습니다. 작업 실행 흐름이 큐와 중앙 제어를 기준으로 정리되면서, 어떤 에이전트가 바쁜지, 어떤 작업이 대기 중인지, 어디서 병목이 발생하는지를 구조적으로 설명할 수 있게 되었습니다. 즉, 단순히 “돌아가는 시스템”에서 “설명 가능한 시스템”으로 한 단계 정리된 셈입니다.
또한 특정 에이전트에 JOB이 몰리는 상황에서도, 그 영향이 전체 시스템 불안정으로 곧바로 번지지 않도록 완충 구간을 확보했다는 점도 중요합니다. 운영 시스템에서는 순간 최대 처리량보다, 부하 집중 시에도 서비스가 무너지지 않는 구조가 더 중요할 때가 많습니다. 이번 개선은 바로 그 지점을 겨냥한 조치였습니다.
다만 이 구조가 모든 문제를 해결하는 것은 아닙니다. 에이전트별 동시 실행 수를 보수적으로 제한한 만큼, 작업 대기 시간이 길어질 수 있는 상황은 여전히 존재합니다. 따라서 이후에는 에이전트별 큐 길이, 평균 대기 시간, 작업 완료 시간 등을 함께 관찰하면서 동시 실행 제한값이 현재 운영 환경에 적절한지 지속적으로 검토할 필요가 있습니다. 구조를 통제 가능하게 만든 뒤에는, 그다음 단계로 관측 지표를 기준으로 정책을 조정하는 작업이 따라와야 합니다.
7. 결론
이번 개선은 단순한 쓰레드 수 축소 작업이 아니었습니다.
본질적으로는 JOB 유입, 실행 동시성, 전체 작업 제어를 분리해 시스템을 운영 가능한 구조로 재정리한 작업에 가깝습니다.
기존 구조는 에이전트 수와 JOB 증가에 따라 실행 쓰레드 수가 함께 증가하는 방식이었고, 그 결과 자원 사용량과 시스템 안정성을 일관되게 관리하기 어려웠습니다. 이를 해결하기 위해 각 에이전트별 작업 큐를 두고, 동시 실행 수를 제한했으며, 중앙 관리 쓰레드를 통해 전체 작업 흐름을 조율하도록 구조를 변경했습니다.
그 결과 SyncMon은 단순히 쓰레드 수를 줄인 것이 아니라, 부하를 흡수하는 방식과 실행을 제어하는 방식을 분리함으로써 더 안정적이고 예측 가능한 시스템으로 개선될 수 있었습니다.
운영 시스템에서 중요한 것은 언제나 최대 성능만이 아닙니다.
더 중요한 것은 부하가 몰리는 순간에도 구조가 무너지지 않고, 문제가 생겼을 때 어디를 봐야 하는지 설명할 수 있는 상태를 유지하는 것입니다. 이번 개선은 그 방향으로 구조를 한 단계 정리한 사례라고 볼 수 있습니다.
1. 개요
SyncMon은 다수의 에이전트가 독립적으로 JOB을 수행하는 구조를 가지고 있었습니다. 초기에는 이 방식이 단순하고 구현 부담이 적어 빠르게 동작하는 데에는 문제가 없었습니다. 그러나 에이전트 수와 JOB 수가 함께 증가하기 시작하면서, 작업 유입량이 곧바로 실행 쓰레드 수 증가로 이어지는 구조적 한계가 드러났습니다.
문제의 본질은 단순히 쓰레드가 많아졌다는 데 있지 않았습니다. 더 큰 문제는 시스템이 감당 가능한 동시 실행량을 스스로 통제하지 못하는 구조였다는 점입니다. 에이전트가 늘고 특정 시점에 JOB이 집중되면, 실행 경로가 동시에 열리면서 CPU 스케줄링 부담, 메모리 사용량 증가, 컨텍스트 스위칭 비용 증가가 함께 발생했습니다. 운영 관점에서는 순간 부하를 예측하기 어려웠고, 장애가 발생했을 때도 어느 구간에서 병목이 생겼는지 파악하기가 쉽지 않았습니다.
이번 개선의 목표는 단순히 쓰레드 개수를 줄이는 것이 아니었습니다.
핵심은 다음 두 가지였습니다.
첫째, JOB 유입량과 실제 실행 동시성을 분리해 시스템이 감당 가능한 수준 안에서만 작업이 처리되도록 만드는 것.
둘째, 전체 작업 흐름을 관찰 가능하고 제어 가능한 구조로 바꾸는 것이었습니다.
이를 위해 SyncMon은 각 에이전트별 작업 큐를 두고, 에이전트당 동시 실행 수를 제한하는 방식으로 실행 모델을 재구성했습니다. 또한 중앙 제어 역할을 담당하는 관리 쓰레드를 두어, 작업 분배와 실행 상태를 한 곳에서 관리하도록 변경했습니다.
2. 기존 구조의 한계
기존 구조는 에이전트가 증가할수록 전체 동시 실행 수 역시 자연스럽게 증가하는 형태였습니다. 이 방식은 에이전트 수가 적고 JOB 유입이 완만할 때는 큰 문제가 드러나지 않았지만, 운영 규모가 커질수록 몇 가지 한계가 명확해졌습니다.
우선, 작업 유입과 실행이 사실상 직접 연결되어 있었습니다.
즉, JOB이 늘어나면 이를 흡수할 완충 구간 없이 실행 쓰레드가 즉시 증가하는 형태였습니다. 이 구조에서는 순간적인 JOB 집중이 발생할 경우 시스템 부하가 짧은 시간 안에 급격히 치솟을 수밖에 없습니다.
또한 이 방식은 자원 사용량을 예측하기 어렵다는 문제가 있었습니다. 쓰레드 수가 부하에 따라 크게 흔들리면 CPU 사용량과 메모리 사용량 역시 안정적으로 관리하기 어렵습니다. 특히 컨텍스트 스위칭 비용은 단순히 쓰레드 수만 많다고 끝나는 문제가 아니라, 실제 처리량 대비 비효율을 키워 전체 시스템 응답성을 떨어뜨리는 원인이 됩니다.
운영 측면의 문제도 컸습니다. 작업이 개별 에이전트 단위에서 분산적으로 실행되다 보니, 전체 처리 흐름을 한눈에 보기 어려웠습니다. 특정 시점에 어느 에이전트가 얼마나 바쁜지, 작업이 왜 지연되는지, 병목이 어디서 발생하는지 파악하려면 개별 상태를 따로 추적해야 했습니다. 다시 말해, 실행은 되고 있었지만 통제 가능한 구조는 아니었습니다.
정리하면 기존 구조의 한계는 다음과 같았습니다.
- JOB 증가가 곧바로 쓰레드 증가로 이어지는 결합 구조
- 순간 부하에 취약한 실행 모델
- 자원 사용량의 예측 가능성 부족
- 전체 작업 흐름에 대한 관찰성과 제어성 부족
이 문제는 단순 튜닝으로 해결할 수 있는 성격이 아니었고, 실행 구조 자체를 다시 정리할 필요가 있었습니다.
3. 개선 방향
개선 방향을 잡을 때 가장 먼저 본 것은 “어떻게 더 빨리 처리할 것인가”가 아니라, 어떻게 통제 가능한 구조로 만들 것인가였습니다.
이번에 선택한 방식은 다음과 같습니다.
에이전트마다 독립적인 작업 큐를 두고, 각 에이전트는 동시에 최대 2개의 작업만 실행할 수 있도록 제한했습니다. 이렇게 하면 특정 에이전트에 JOB이 몰리더라도 실행 동시성은 상한이 정해져 있기 때문에, 부하가 시스템 전체로 무분별하게 번지는 것을 막을 수 있습니다. 대기할 JOB은 큐에 쌓이고, 실제 실행은 제한된 슬롯 안에서만 이뤄집니다.
여기에 중앙 관리 쓰레드를 두어 전체 에이전트의 상태를 확인하고, 작업이 끝난 에이전트에만 후속 JOB을 분배하도록 구성했습니다. 이 구조의 장점은 실행 책임과 제어 책임을 분리할 수 있다는 데 있습니다. 실제 작업 수행은 각 에이전트가 맡고, 언제 어떤 작업을 투입할지는 중앙에서 판단하게 함으로써 전체 흐름을 일관되게 다룰 수 있게 됩니다.
여기서 중요한 점은, 이번 개선이 “모든 것을 중앙에서 처리하는 구조”를 지향한 것은 아니라는 점입니다. 중앙 관리 쓰레드는 작업 그 자체를 수행하지 않고, 실행 가능 상태를 판단하고 분배를 조율하는 제어 지점으로만 동작합니다. 즉, 작업 수행은 분산되어 있고, 실행 정책만 중앙에서 관리하는 형태입니다.
4. 왜 이 구조를 선택했는가
이 문제를 해결하는 방식은 하나가 아니었습니다. 예를 들어 전역 쓰레드 풀 하나로 모든 작업을 흡수하는 방식도 고려할 수 있습니다. 구현 자체는 단순할 수 있지만, 이 경우 특정 에이전트의 작업이 전체 풀을 점유하면서 다른 에이전트 작업까지 지연시키는 문제가 생길 수 있습니다. 즉, 전체 최적화는 쉬워 보여도 에이전트 단위의 독립성과 공정성이 깨질 가능성이 있습니다.
반대로 각 에이전트가 완전히 자율적으로 쓰레드를 관리하도록 두면 독립성은 높지만, 전체 동시 실행량을 통제하기 어려워집니다. 기존 구조가 바로 이 한계를 드러냈습니다.
이번에 선택한 에이전트별 큐 + 동시 실행 제한 + 중앙 제어 구조는 이 두 극단 사이에서 현실적인 균형을 맞추기 위한 선택이었습니다.
- 에이전트 단위의 독립성은 유지하되
- 실행 동시성에는 상한을 두고
- 전체 작업 흐름은 중앙에서 관찰하고 조정할 수 있게 만든 것
물론 이 구조에도 trade-off는 있습니다. 동시 실행 수를 제한하면 순간 처리량만 놓고 보면 더 공격적인 실행 모델보다 느릴 수 있습니다. 하지만 SyncMon에서 더 중요했던 것은 피크 순간의 최대 처리량보다, 전체 시스템이 무너지지 않고 예측 가능한 방식으로 지속적으로 동작하는 것이었습니다. 운영 시스템에서는 평균 성능보다 최악의 순간을 얼마나 통제할 수 있는지가 더 중요할 때가 많고, 이번 개선도 그 관점에서 접근했습니다.
5. 개선된 동작 방식
개선 이후의 흐름은 다음과 같습니다.
각 에이전트는 자신만의 작업 큐를 가집니다. JOB이 유입되면 해당 큐에 적재되고, 에이전트는 동시에 최대 2개의 작업만 실행합니다. 실행 가능한 슬롯이 없으면 JOB은 큐에서 대기합니다. 이로써 작업 유입량이 많아져도 실행 쓰레드 수가 무제한으로 증가하지 않도록 막을 수 있습니다.
중앙 관리 쓰레드는 전체 에이전트의 상태를 주기적으로 확인합니다. 특정 에이전트에서 작업이 완료되어 실행 슬롯이 비면, 중앙 관리 쓰레드는 그 시점에 다음 JOB을 할당합니다. 이 방식의 핵심은 작업을 “많이 넣는 것”이 아니라, 실행 가능한 시점에만 넣는 것입니다.
결국 구조는 다음처럼 정리됩니다.
- 작업은 에이전트별 큐에 적재된다.
- 실행 동시성은 에이전트별로 제한된다.
- 중앙 제어부는 작업 완료와 실행 가능 상태를 기준으로 후속 JOB을 분배한다.
- JOB 유입량과 실행 동시성이 분리되어, 부하가 시스템 전체로 직접 전파되지 않는다.
이 구조로 바뀌면서 전체 시스템은 이전보다 훨씬 예측 가능한 방식으로 동작하게 되었습니다.
6. 개선 효과
이번 개선의 가장 큰 효과는 쓰레드 수를 줄였다는 사실 자체보다, 쓰레드 수를 통제 가능한 변수로 바꿨다는 데 있습니다.
기존에는 에이전트 수와 JOB 유입 패턴에 따라 실행 쓰레드 수가 크게 흔들릴 수 있었습니다. 반면 개선 이후에는 에이전트별 동시 실행 수에 상한이 있기 때문에, 시스템이 감당해야 하는 실행 부하의 범위를 훨씬 명확하게 예측할 수 있게 되었습니다. 이는 곧 CPU와 메모리 사용량을 보다 안정적으로 관리할 수 있다는 의미이기도 합니다.
운영 측면에서도 이점이 있었습니다. 작업 실행 흐름이 큐와 중앙 제어를 기준으로 정리되면서, 어떤 에이전트가 바쁜지, 어떤 작업이 대기 중인지, 어디서 병목이 발생하는지를 구조적으로 설명할 수 있게 되었습니다. 즉, 단순히 “돌아가는 시스템”에서 “설명 가능한 시스템”으로 한 단계 정리된 셈입니다.
또한 특정 에이전트에 JOB이 몰리는 상황에서도, 그 영향이 전체 시스템 불안정으로 곧바로 번지지 않도록 완충 구간을 확보했다는 점도 중요합니다. 운영 시스템에서는 순간 최대 처리량보다, 부하 집중 시에도 서비스가 무너지지 않는 구조가 더 중요할 때가 많습니다. 이번 개선은 바로 그 지점을 겨냥한 조치였습니다.
다만 이 구조가 모든 문제를 해결하는 것은 아닙니다. 에이전트별 동시 실행 수를 보수적으로 제한한 만큼, 작업 대기 시간이 길어질 수 있는 상황은 여전히 존재합니다. 따라서 이후에는 에이전트별 큐 길이, 평균 대기 시간, 작업 완료 시간 등을 함께 관찰하면서 동시 실행 제한값이 현재 운영 환경에 적절한지 지속적으로 검토할 필요가 있습니다. 구조를 통제 가능하게 만든 뒤에는, 그다음 단계로 관측 지표를 기준으로 정책을 조정하는 작업이 따라와야 합니다.
7. 결론
이번 개선은 단순한 쓰레드 수 축소 작업이 아니었습니다.
본질적으로는 JOB 유입, 실행 동시성, 전체 작업 제어를 분리해 시스템을 운영 가능한 구조로 재정리한 작업에 가깝습니다.
기존 구조는 에이전트 수와 JOB 증가에 따라 실행 쓰레드 수가 함께 증가하는 방식이었고, 그 결과 자원 사용량과 시스템 안정성을 일관되게 관리하기 어려웠습니다. 이를 해결하기 위해 각 에이전트별 작업 큐를 두고, 동시 실행 수를 제한했으며, 중앙 관리 쓰레드를 통해 전체 작업 흐름을 조율하도록 구조를 변경했습니다.
그 결과 SyncMon은 단순히 쓰레드 수를 줄인 것이 아니라, 부하를 흡수하는 방식과 실행을 제어하는 방식을 분리함으로써 더 안정적이고 예측 가능한 시스템으로 개선될 수 있었습니다.
운영 시스템에서 중요한 것은 언제나 최대 성능만이 아닙니다.
더 중요한 것은 부하가 몰리는 순간에도 구조가 무너지지 않고, 문제가 생겼을 때 어디를 봐야 하는지 설명할 수 있는 상태를 유지하는 것입니다. 이번 개선은 그 방향으로 구조를 한 단계 정리한 사례라고 볼 수 있습니다.