'그건 제 담당이 아닙니다' — 방어형 개발자의 생존 전략
'그건 제 담당이 아닙니다' — 방어형 개발자의 생존 전략
"내 코드는 완벽합니다. 버그는 다른 팀 API에서 온 겁니다."
방어형 개발자의 탄생
모든 방어형 개발자는 처음부터 방어형이 아니었음. 첫 직장에서 눈을 반짝이며 "뭐든 해볼게요!"라고 했던 그 사람이, 3년 후 "그건 제 담당이 아닌데요"라고 말하게 되는 데는 이유가 있음.
방어형 개발자 생성 조건
다음 조건이 충족되면 약 2-3년 내에 방어형 개발자가 생성됨:
- 범위가 불명확한 업무 할당 ("이것도 해주세요, 저것도 해주세요")
- 다른 사람의 실수를 떠안아야 하는 경험 반복
- 성과 평가에서 "내 일 + 떠안은 일"이 구분 안 됨
- 야근의 원인이 항상 "남의 일을 대신 해줘서"
- 보상 없는 헌신이 당연시되는 문화
방어형 개발자의 진화 단계
Stage 1: 순수한 신입 (0-1년차)
"저 뭐든 할 수 있어요! 배우고 싶어요!"
→ 다른 팀 버그도 고쳐줌
→ 문서도 써줌
→ 배포 스크립트도 만들어줌
Stage 2: 번아웃의 시작 (1-2년차)
"이건 원래 제 일이 아닌데... 근데 해야겠죠?"
→ 다른 팀 버그 고쳐줬는데 내 성과로 안 잡힘
→ 배포 스크립트 만들었는데 유지보수가 내 일이 됨
→ 문서 썼는데 아무도 안 읽음
Stage 3: 방어 본능 발현 (2-3년차)
"죄송한데 그건 제 담당이 아닙니다"
→ 명확한 경계 설정 시작
→ JIRA 티켓 없으면 안 함
→ 슬랙 DM으로 부탁하면 "티켓 만들어주세요" 응답
Stage 4: 완전체 방어형 (3년차+)
"그건 저 아니고요, 백엔드팀한테 물어보세요"
→ 모든 요청에 "그건 내 일이 아님"이 디폴트 응답
→ 본인 담당 범위를 극도로 좁게 정의
→ 회의에서 침묵하고 본인 이슈만 처리
방어형 개발자가 생기는 구조적 원인
개인의 성격 문제가 아니라 조직의 구조적 문제가 방어형 개발자를 만듦.
1. 책임과 권한의 불일치
// 현실의 조직 구조
interface Developer {
responsibilities: string[]; // 엄청 많음
authority: string[]; // 거의 없음
accountability: string[]; // 엄청 많음
reward: string[]; // 거의 없음
}
const 방어형이_되기_전: Developer = {
responsibilities: [
"프론트엔드 개발",
"API 연동",
"코드 리뷰",
"주니어 멘토링",
"배포 프로세스 관리",
"모니터링 대시보드 유지",
"레거시 코드 마이그레이션",
"장애 대응 (새벽 2시 콜)",
"다른 팀 API 변경에 맞춰 수정",
"기획서에 없는 예외 케이스 처리",
],
authority: [
"... 음... 코드 스타일 정도?",
],
accountability: [
"위에 나열된 모든 것에 대한 책임",
"+ 다른 팀이 일으킨 장애에 대한 연대 책임",
],
reward: [
"연봉 인상 3%",
"연말 회식 때 칭찬 한마디",
],
};
// 2년 후...
const 방어형_개발자: Developer = {
responsibilities: ["프론트엔드 개발 (내 JIRA 티켓에 있는 것만)"],
authority: ["내 코드에 대한 모든 결정"],
accountability: ["내 JIRA 티켓에 있는 것만"],
reward: ["마음의 평화"],
};
2. "유능한 사람이 더 많은 일을 하는" 역설
// 유능함의 벌
// 1분기: 김개발, 일 잘함
// → 보상: "고마워요! 이것도 부탁할게요"
// 2분기: 김개발, 일을 더 잘함 (남의 일까지)
// → 보상: "역시 김개발! 이것도 좀..."
// 3분기: 김개발, 3명분 일을 함
// → 보상: "김개발 없으면 안 돼요" (연봉 인상은 없음)
// 4분기: 김개발, 번아웃
// → 피드백: "요즘 좀 기운이 없어 보이네요?"
// 다음 해 1분기: 김개발 → 방어형 개발자로 전환
// "그건 제 JIRA 티켓에 없는데요"
// 반면에:
// 박개발: 처음부터 "그건 제 일이 아닌데요" → 아무도 추가 업무 안 줌
// 박개발: 성과 평가 B+, 김개발: 성과 평가 A- (3배 일하고 반 등급 차이)
// → 이걸 보고 방어형이 안 되면 오히려 그게 비정상임
유능함의 역설
조직에서 '잘하는 사람'에게 계속 일이 몰리는 건 자연스러운 현상임. 하지만 보상 없이 책임만 늘어나면, 유능한 사람이 무능한 척하거나 방어형이 됨. 이건 개인의 문제가 아니라 조직의 인센티브 구조 문제임.
3. 모호한 경계와 '그레이 존'
// "이거 프론트엔드가 해야 하나요 백엔드가 해야 하나요?"
// 대한민국 IT 회사의 영원한 떡밥
// 그레이 존 1: API 응답 포맷
// 프론트: "API에서 정렬해서 주세요"
// 백엔드: "클라이언트에서 정렬하세요"
// → 누가 이기든 진 쪽이 방어형이 됨
// 그레이 존 2: 데이터 검증
// 프론트: "서버에서 검증하잖아요?"
// 백엔드: "클라이언트에서 먼저 검증해야죠?"
// → 둘 다 안 하면 보안 취약점
// → 둘 다 하면 "그건 이중 작업인데..."
// 그레이 존 3: 에러 메시지
// 프론트: "에러 코드 좀 정리해주세요"
// 백엔드: "에러 메시지 프론트에서 관리하세요"
// PM: "그런 거 사용자가 보나요?"
// → 아무도 안 함 → 장애 시 "에러가 발생했습니다" 만 나옴
// 그레이 존 해결 실패 → 다 같이 방어형이 됨
// "제 담당이 아닙니다" 의 무한 루프
"내 코드만 돌아가면 됨" 마인드셋의 문제
방어형 개발자의 극단적인 형태: 내 컴포넌트/모듈만 동작하면 끝이라는 사고방식.
사례 1: 인터페이스 경계에서의 방어
// 방어형 프론트엔드 개발자의 코드
interface UserApiResponse {
// "API 스펙은 백엔드 담당이니까 나는 any로 받음"
data: any;
}
async function fetchUsers(): Promise<any> {
try {
const response = await fetch('/api/users');
const json = await response.json();
return json;
} catch (error) {
// "API 에러는 백엔드 담당"
return [];
}
}
// 결과:
// - 타입 안전성 제로
// - API 스펙 변경 시 런타임 에러
// - 에러 발생 시 아무도 모름 (조용히 빈 배열 반환)
// - "내 코드에서는 에러 안 나는데요?"
// → 기술적으로 맞음. 에러를 삼켰으니까.
사례 2: "내 PR은 통과했으니까"
// 방어형 개발자의 PR 전략
// Step 1: 최소한의 변경만 포함
// 영향 범위를 줄이면 내 책임도 줄어듦
// Step 2: 테스트는 내 코드만
describe('MyComponent', () => {
it('renders without crashing', () => {
// 다른 컴포넌트와의 통합은 테스트 안 함
// "통합 테스트는 QA 담당"
render(<MyComponent data={mockData} />);
expect(screen.getByText('test')).toBeInTheDocument();
});
});
// Step 3: PR 설명에 면책 조항
// "이 PR은 UserCard 컴포넌트만 수정합니다.
// 다른 컴포넌트에서 발생하는 이슈는 별도 티켓으로 처리해주세요."
// Step 4: 리뷰어가 "이 변경이 X에도 영향 줄 수 있지 않나요?" 하면
// "좋은 지적이네요. 별도 티켓으로 만들겠습니다."
// (별도 티켓은 만들지 않음)
사례 3: 장애 대응에서의 방어
// 프로덕션 장애 발생 시
// 정상적인 대응:
// 1. 장애 범위 파악
// 2. 원인 분석
// 3. 핫픽스 배포
// 4. 포스트모템
// 방어형 개발자의 대응:
// 1. "제 서비스 로그 확인했는데 에러 없습니다" (끝)
// 2. "이건 네트워크 팀 문제 아닌가요?"
// 3. "제가 마지막으로 배포한 게 3일 전이라..."
// 4. "포스트모템 회의 때 제가 꼭 참석해야 하나요?"
// 장애 대응 슬랙 채널 실황:
// 백엔드: "프론트에서 잘못된 파라미터 보내고 있음"
// 프론트: "API 스펙대로 보냈는데요?"
// 백엔드: "스펙이 변경됐는데 공유 안 했나?"
// 프론트: "저한테 공유된 적 없는데요"
// PM: "... 다 같이 미팅합시다"
// 전원: (각자의 방어선을 준비하는 중)
방어가 만든 장애
실제 사례: A팀과 B팀 사이의 API 연동에서 타임존 이슈가 있었음. A팀: "우리는 UTC로 보냅니다. B팀에서 변환하세요." B팀: "우리는 KST 기준입니다. A팀에서 변환해서 보내세요." 아무도 변환을 안 해서 모든 예약이 9시간 어긋남. 고객 CS 3,000건 들어온 후에야 수습됨. 양쪽 다 "그건 우리 담당이 아니었습니다"라고 함.
오너십과 방어의 경계
여기서 중요한 질문: 그러면 모든 일에 오너십을 가져야 하는 건가?
답: 아니.
오너십은 좋지만, 무분별한 오너십은 번아웃의 지름길임. 핵심은 건강한 경계 설정임.
건강한 경계 vs 방어적 경계
// 방어적 경계 (나쁜 예)
class DefensiveDeveloper {
handleRequest(request: WorkRequest): Response {
if (!this.isMyJiraTicket(request)) {
return { status: 'REJECTED', reason: '제 담당이 아닙니다' };
}
if (this.mightCauseTrouble(request)) {
return { status: 'REJECTED', reason: '리스크가 있어서 별도 검토 필요' };
}
// 최소한의 작업만 수행
return this.doMinimumWork(request);
}
}
// 건강한 경계 (좋은 예)
class HealthyBoundaryDeveloper {
handleRequest(request: WorkRequest): Response {
// 1. 내 담당이면 바로 처리
if (this.isMyResponsibility(request)) {
return this.handleWithOwnership(request);
}
// 2. 내 담당은 아니지만 도움을 줄 수 있으면
if (this.canHelp(request) && this.haveCapacity()) {
return this.helpAndRedirect(request);
// 도와주되, 담당자를 명확히 지정
}
// 3. 도움을 줄 수 없으면 적절한 담당자를 안내
return this.redirectToRightPerson(request);
// "이건 OO팀의 XX님이 담당이에요. 연결해드릴까요?"
// ← "그건 제 담당 아닙니다" 와의 결정적 차이
}
}
건강한 경계 설정 가이드
건강한 경계 설정 5원칙
1. 명확한 소유권 정의: 팀/개인의 담당 범위를 문서화하기. 모호한 영역은 미리 합의하기. 그레이 존이 방어형을 만듦.
2. "No"라고 말하되 대안을 제시: "제 담당이 아닙니다" 대신 "이건 XX 팀 담당인데, 제가 연결해드릴게요"
3. 도움은 주되 소유권은 넘기지 않기: "이거 좀 봐줄 수 있어요?"에 "네, 방향만 잡아드릴게요. 구현은 담당 팀에서 해주세요."
4. 기록 남기기: 내가 한 추가 작업은 기록으로 남기기. 성과 평가 때 근거가 됨.
5. 반복되는 요청은 프로세스화: 같은 종류의 "그건 누구 담당이죠?"가 반복되면, 담당 매트릭스를 만들어서 팀 전체에 공유.
조직이 해결해야 할 문제
방어형 개발자는 개인의 문제가 아니라 조직의 증상임.
방어형 개발자가 많은 조직의 특징
// 진단 체크리스트
interface OrganizationHealth {
// 이 중 3개 이상이면 방어형 개발자 양산 조직
vagueResponsibilities: boolean; // 담당 범위가 불명확
noRewardForExtraWork: boolean; // 추가 업무에 보상 없음
blameFixedOnIndividuals: boolean; // 장애 시 개인에게 책임 전가
noDocumentedOwnership: boolean; // 소유권이 문서화 안 됨
heroicCultureExpected: boolean; // "야근해서라도" 문화
crossTeamCollabPainful: boolean; // 팀 간 협업이 고통스러움
}
// 해결 방법:
interface OrganizationFix {
// 1. RACI 매트릭스 도입
// R(Responsible), A(Accountable), C(Consulted), I(Informed)
// 모든 업무에 대해 누가 뭘 하는지 명확히 정의
// 2. 추가 업무에 대한 인센티브
// "다른 팀 도와줬으면 성과에 반영"
// → 도움을 주는 게 커리어에 플러스가 되어야 함
// 3. 온콜 로테이션 (특정 사람에게 몰리지 않게)
// → 장애 대응이 1-2명에게 집중되면 그 사람들만 방어형이 됨
// 4. 포스트모템 문화 (비난 없는 회고)
// → "누구 잘못이냐"가 아니라 "어떤 시스템 문제가 있었나"
}
담당 매트릭스 예시
| 영역 | 담당 팀 | 백업 팀 | 결정권자 |
|-------------------|-----------|------------|-----------|
| 사용자 인증 | 플랫폼팀 | 백엔드팀 | 플랫폼TL |
| 결제 처리 | 결제팀 | 백엔드팀 | 결제TL |
| UI 컴포넌트 | 프론트팀 | - | 프론트TL |
| API 게이트웨이 | 인프라팀 | 백엔드팀 | CTO |
| 모니터링/알림 | SRE팀 | 인프라팀 | SRE TL |
| API 스펙 변경 | 변경 주체 | 영향 팀 | 합의 |
→ "그건 제 담당이 아닌데요" 를 막는 유일한 방법은
"그건 XX의 담당이다" 를 명확히 정의해두는 것.
방어에서 협업으로: 전환 가이드
개인 레벨의 전환
// Before: 방어형
// "그건 제 일이 아닌데요"
// "JIRA 티켓 있나요?"
// "스펙에 없는 건데요"
// After: 협업형
// "그건 XX팀 담당인데, 같이 미팅 잡을까요?"
// "일단 급한 부분은 제가 임시로 처리하고,
// 정식으로는 담당 팀에서 맡아주세요"
// "스펙에는 없지만 사용자 경험상 필요해 보여서
// PM한테 확인해볼게요"
// 핵심 차이:
// 방어형 = 벽을 세움
// 협업형 = 다리를 놓음
// 방어형은 "내 일이 아닙니다"에서 끝나지만
// 협업형은 "내 일은 아니지만, 이렇게 하면 해결됩니다"까지 감
팀 레벨의 전환
// 인터페이스 계약 (Interface Contract) 도입
// 프론트엔드와 백엔드 사이의 계약
interface ApiContract {
endpoint: string;
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
requestSchema: ZodSchema;
responseSchema: ZodSchema;
errorCodes: Record<string, string>;
owner: 'frontend' | 'backend';
lastUpdated: string;
breakingChangePolicy: 'semver' | 'notify-2-weeks';
}
// 이런 계약이 있으면:
// 1. "이건 누구 담당이죠?" → 계약서 보면 됨
// 2. "API 스펙이 바뀌었는데 왜 안 알려줬어요?" → 계약에 정책이 있음
// 3. "에러 코드가 문서에 없는데요" → 계약 위반이므로 수정 요청 가능
// 계약이 없으면 방어만 남음.
// 계약이 있으면 협업할 근거가 생김.
방어형 개발자에게 보내는 메시지
당신이 방어형이 된 건 당신 잘못이 아닐 수 있음. 시스템이 당신을 그렇게 만들었을 가능성이 높음.
하지만 방어형에 머무르면 당신의 성장도 멈춤. "그건 제 일이 아닙니다"를 100번 말하는 사이에, 기술도, 인간관계도, 커리어도 좁아짐.
완벽한 오너십을 가질 필요는 없음. 다만 "다리를 놓는 사람"이 되면, 조직에서의 가치가 기술 실력 이상으로 올라감.
그리고 그게 시니어의 진짜 의미이기도 함.
마무리: 경계는 전략이다
방어 자체가 나쁜 건 아님. 명확한 경계 없이는 모든 게 무너짐.
하지만 벽을 세우는 방어와 다리를 놓는 경계는 다름.
벽을 세우는 사람:
"그건 제 담당이 아닙니다" → 대화 종료
다리를 놓는 사람:
"이건 XX팀 담당인데요" → 담당자 연결
→ 맥락 전달 → 필요하면 같이 논의
→ 대화 계속
결과적으로 다리를 놓는 사람이:
- 더 많은 신뢰를 얻고
- 더 많은 맥락을 이해하고
- 더 좋은 성과 평가를 받고
- 더 빨리 시니어가 됨
벽을 세우는 사람은:
- 안전하지만
- 성장하지 못함
경계는 나를 보호하는 도구지, 나를 가두는 감옥이 되면 안 됨.
"'그건 제 담당이 아닙니다'는 때로는 건강한 경계이고, 때로는 조직의 실패를 보여주는 증상이다. 차이를 구분하는 게 진짜 실력."