티스토리 뷰
요새 인수인계를 받은 프로젝트가 있다. 지금은 내 입맛대로 수정할 수 있게끔 리팩토링 작업을 주로 하는데 OCP, SRP 원칙을 지키지 않은채로 구현된 부분들을 정리중이다.
최대한 리팩토링 잘해서 yaml 파일 같은데에 pipeline 을 파일 레벨에서 기술해서 동작하게 하고싶다.
지금은 배포환경이 다른 경우 하드 코딩돼있는 부분이 많다. 이걸 코드로 하드 코딩돼있는 게 그냥 내가 관리자가 된 입장에서 싫어가지고 위와 같은 작업을 진행하고 있다.
SRP 원칙을 Opus4.6에게 최대한 쉽게 알려달라고 했다.
🧱 "이 클래스, 왜 이렇게 뚱뚱해?" — SRP(단일 책임 원칙) 쉽게 이해하기
코드를 짜다 보면 하나의 클래스에 이것저것 기능을 넣게 됩니다. 처음엔 편하지만, 나중에 수정할 때 지옥이 펼쳐지죠. 오늘은 이런 문제를 막아주는 **SRP(단일 책임 원칙)**에 대해 이야기해 보겠습니다.
SRP가 뭔가요?
SRP는 Single Responsibility Principle, 우리말로 단일 책임 원칙입니다.
한 줄 요약하면 이렇습니다.
"하나의 클래스는 하나의 이유로만 변경되어야 한다."
이게 무슨 말일까요? 비유로 설명해 보겠습니다.
🍳 비유: 식당의 직원
동네에 작은 식당이 하나 있다고 상상해 보세요.
사장님이 직원 한 명에게 이렇게 말합니다.
- "너 요리도 해."
- "너 서빙도 해."
- "너 회계도 해."
처음엔 괜찮을 수 있습니다. 하지만 문제가 생기기 시작합니다.
- 메뉴가 바뀌면? → 요리법을 새로 배워야 합니다.
- 홀 배치가 바뀌면? → 서빙 동선을 새로 익혀야 합니다.
- 세금 정책이 바뀌면? → 회계 처리를 새로 공부해야 합니다.
한 사람이 세 가지 이유로 계속 바뀌어야 하니까 실수가 생기고, 일이 느려집니다.
SRP는 이걸 이렇게 바꾸라는 겁니다.
- 👨🍳 요리사 → 요리만 담당
- 🧑💼 서빙 직원 → 서빙만 담당
- 🧮 회계 담당 → 회계만 담당
각자 자기 일에만 집중하니까 한쪽이 바뀌어도 다른 쪽은 영향을 받지 않습니다.
코드도 똑같습니다.
💻 코드로 보는 SRP 위반
아래는 흔히 볼 수 있는 SRP 위반 코드입니다.
class Employee {
// 💰 급여를 계산한다 (재무팀이 관심 있는 기능)
public Money calculatePay() {
// 급여 계산 로직...
}
// 💾 데이터베이스에 저장한다 (개발팀이 관심 있는 기능)
public void save() {
// DB 저장 로직...
}
// 📊 보고서를 만든다 (운영팀이 관심 있는 기능)
public String generateReport() {
// 보고서 생성 로직...
}
}
Employee 클래스 하나가 세 가지 일을 동시에 하고 있습니다. 마치 요리도 하고, 서빙도 하고, 회계도 하는 그 직원처럼요.
💥 그래서 뭐가 문제인데요?
1. 고쳤더니 다른 데가 터진다
재무팀이 "급여 계산 방식을 바꿔주세요"라고 요청했습니다. calculatePay()를 수정했더니, 내부에서 같이 쓰던 코드 때문에 generateReport()의 숫자가 이상해졌습니다.
급여를 고쳤을 뿐인데 보고서가 깨진 겁니다. 😱
2. 코드 충돌이 잦아진다
개발팀은 save()를 고치고, 운영팀은 generateReport()를 고치고 싶습니다. 둘 다 같은 Employee.java 파일을 건드리니까 Git 충돌이 계속 납니다.
3. 테스트가 괴로워진다
급여 계산 로직 하나를 테스트하고 싶을 뿐인데, DB 연결도 준비하고 보고서 관련 설정도 해줘야 합니다. 테스트 하나 돌리려고 준비할 게 산더미입니다.
4. 재사용이 안 된다
다른 프로젝트에서 급여 계산 로직만 가져다 쓰고 싶은데, Employee 클래스를 통째로 가져와야 합니다. DB 저장 코드, 보고서 코드까지 전부 딸려옵니다.
✅ 이렇게 고치면 됩니다
책임별로 클래스를 나눠주세요.
// 💰 급여 계산만 담당
class PayCalculator {
public Money calculatePay(Employee e) {
// 급여 계산 로직...
}
}
// 💾 데이터 저장만 담당
class EmployeeRepository {
public void save(Employee e) {
// DB 저장 로직...
}
}
// 📊 보고서 생성만 담당
class ReportGenerator {
public String generateReport(Employee e) {
// 보고서 생성 로직...
}
}
이제 각 클래스는 딱 하나의 이유로만 변경됩니다.
클래스 변경되는 이유 요청하는 사람
| PayCalculator | 급여 정책이 바뀔 때 | 재무팀 |
| EmployeeRepository | DB 구조가 바뀔 때 | 개발팀 |
| ReportGenerator | 보고서 양식이 바뀔 때 | 운영팀 |
서로 영향을 주지 않으니 안심하고 수정할 수 있습니다.
🔍 "혹시 내 코드도 SRP 위반?" 체크리스트
아래 항목에 해당하면 SRP 위반을 의심해 보세요.
1) 클래스를 설명할 때 "그리고"가 들어간다
"이 클래스는 주문을 처리하고, 그리고 이메일을 보내고, 그리고 로그를 남겨요."
→ 책임이 3개입니다. 분리하세요.
2) 파일이 수백 줄을 넘어간다
보통 한 클래스가 300줄을 넘으면 여러 책임이 섞여 있을 가능성이 높습니다.
3) 서로 다른 팀이 같은 파일을 자주 고친다
Git 로그를 보세요. 여러 팀이 같은 파일을 건드리고 있다면 그 파일에 여러 책임이 뒤섞여 있다는 신호입니다.
4) 테스트를 작성할 때 mock이 5개 이상 필요하다
하나의 클래스를 테스트하는데 준비물이 너무 많다면, 그 클래스가 너무 많은 일을 하고 있는 겁니다.
⚠️ 주의: 너무 쪼개지 마세요
SRP를 처음 배우면 모든 걸 잘게 쪼개고 싶은 유혹이 생깁니다.
하지만 클래스가 지나치게 많아지면 오히려 코드를 읽기 어려워집니다. 파일 50개를 열어야 하나의 흐름을 이해할 수 있다면 그것도 문제입니다.
핵심은 "지금 이 코드에서 실제로 서로 다른 이유로 변경되는 부분이 있는가?"를 따져보는 것입니다.
변경 이유가 하나뿐이라면 굳이 쪼갤 필요가 없습니다. 현실적인 균형이 중요합니다.
📝 마무리
정리하면 SRP는 이렇습니다.
- 하나의 클래스는 하나의 책임만 가져야 한다.
- 여기서 "책임"이란 **"변경의 이유"**를 뜻한다.
- 위반하면 수정할 때 예상치 못한 곳이 터지고, 테스트와 협업이 어려워진다.
- 해결 방법은 책임별로 클래스를 분리하는 것이다.
- 단, 과도한 분리는 금물이다. 실제 변경 패턴을 보고 판단하자.
💡 코드를 작성할 때 스스로에게 물어보세요. "이 클래스가 바뀌어야 하는 이유가 몇 가지지?" 답이 2개 이상이라면, SRP 리팩토링을 고민할 때입니다.
이 글이 도움이 되셨다면 공유 부탁드립니다! 🙌
'기타' 카테고리의 다른 글
| linux 서버 계정 생성 및 Claude Code 설치 스크립트 (0) | 2026.02.19 |
|---|---|
| Claude Code 로 개발한 내 개인 사이트 0hye.com (0) | 2026.02.15 |
| 실제로 활발히 사용되는 프로그램 개발에 Claude Code를 사용한 사례, 오랜만에 Yolo_Label 프로젝트 업데이트 (0) | 2026.02.14 |
| Claude Code Permission이 작동하지 않는 이유: `:*` vs ` *` 패턴 문제 (1) | 2026.02.14 |
| Linux 서버 CPU 부하 테스트 가이드 (stress-ng) (0) | 2026.02.12 |
- Total
- Today
- Yesterday
- 조합
- 단축키
- C++ Deploy
- 문제집
- 백준 1766
- FairMOT
- PyCharm
- 백준
- 백준 11053
- 이분탐색
- MOT
- LCA
- 파이참
- 위상 정렬 알고리즘
- cosine
- 가장 긴 증가하는 부분 수열
- 자료구조
- ㅂ
- 순열
- 인공지능을 위한 선형대수
- 백트래킹
- 백준 11437
- Lowest Common Ancestor
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
