앱 개발에서의 카피파스타 — 무엇인가, 왜 위험한가, 어떻게 피할 것인가

저자: IT Sectr 게시일: 2026-07-27 읽는 시간: 10 분

카피파스타(복사-붙여넣기)는 코드 조각을 새 컨텍스트에 적응시키지 않고 한 곳에서 다른 곳으로 복사하는 관행입니다. 대부분의 경우 개발자는 기존 모듈에서 블록을 복사하고 최소한의 수정을 한 후 새 모듈에 붙여넣습니다. 버그, 오래된 주석, 불필요한 종속성까지 함께 말이죠. TIOBE Code Quality Survey(2025)에 따르면, 카피파스타 수준이 높은 프로젝트는 통합된 추상화를 가진 프로젝트보다 코드 1000줄당 결함이 3배 더 많습니다. 코드 중복은 기술 부채의 주요 원인입니다. 각 복사본은 별도의 유지보수가 필요하며, 한 곳에서 버그를 수정해도 다른 곳에서 수정된다는 보장이 없습니다.

주요 포인트

  • 카피파스타 — 이해나 적응 없이 코드를 복사하는 것, 기술 부채의 주요 원인.
  • 카피파스타의 위험: 버그가 프로젝트 전체에 증식하고, 하나의 복사본을 수정해도 나머지는 수정되지 않습니다.
  • DRY(Don't Repeat Yourself) — 카피파스타를 방지하는 기본 원칙.
  • 중복 탐지 도구: PMD CPD, SonarQube, 중복 규칙이 있는 ESLint.
  • 카피파스타 리팩토링 — 공통 코드를 함수, 클래스 또는 라이브러리로 추출.

카피파스타란?

카피파스타(복사-붙여넣기 프로그래밍)는 기존 코드를 약간만 변경하거나 전혀 변경하지 않고 새 위치로 이동하는 것입니다. 이 용어는 경멸적으로 사용됩니다. 개발자가 솔루션을 설계하는 것이 아니라 기성 블록을 기계적으로 복사하고 있으며, 종종 그것이 어떻게 작동하는지 완전히 이해하지 못하고 있음을 암시합니다.

카피파스타에는 두 가지 유형이 있습니다: 의도적인 것우발적인 것입니다. 의도적 — 개발자가 나중에 리팩토링할 계획으로 의도적으로 코드를 복사하는 경우입니다(하지만 계획은 종종 포기됩니다). 우발적 — 두 개발자가 독립적으로 다른 화면에 동일한 로직을 작성하는 등 중복이 눈에 띄지 않게 발생하는 경우입니다.

SonarQube State of Clean Code(2025) 보고서에 따르면, 상업용 프로젝트에서 중복 코드는 전체 코드 볼륨의 평균 12~18%를 차지합니다. 동시에 중복 코드에서 버그를 수정하는 비용은 단일 구현 코드보다 2.5배 높습니다. 개발자가 모든 복사본을 찾아서 수정해야 하기 때문입니다.

카피파스타에 대한 주요 도구는 DRY(Don't Repeat Yourself) 원칙입니다. 그러나 DRY를 절대시하는 것도 위험합니다. 두 복사본이 서로 독립적으로 진화해야 하는 경우 복사가 정당화될 수 있기 때문입니다. “우발적 중복”(제거해야 함)과 “필요한 중복”(문서화해야 함)을 구분하는 것이 중요합니다.

카피파스타가 위험한 이유

첫 번째이자 가장 중요한 위험은 버그의 전파입니다. 원본 코드에 결함이 있으면 코드와 함께 모든 새 위치로 복사됩니다. 결함이 발견되어 원본 모듈에서 수정되어도 복사본은 수정되지 않은 상태로 남습니다. 개발자는 버그가 5개의 다른 파일에 존재한다는 사실조차 모를 수 있습니다.

두 번째 위험은 불균등한 진화입니다. 동일한 알고리즘의 두 복사본은 시간이 지남에 따라 서로 다른 수정 사항을 축적합니다. 한 복사본은 경계값 검증을 추가하고, 다른 복사본은 출력 형식을 변경합니다. 몇 달 후에는 어떤 버전이 “올바른지” 알 수 없게 되고 프로젝트는 동작 일관성을 잃습니다.

세 번째 위험은 테스트 볼륨 증가입니다. 각 카피파스타 인스턴스는 자체 테스트가 필요합니다. 공통 로직이 단일 함수로 추출되면 하나의 테스트 세트로 커버하고 재사용할 수 있습니다. 중복이 있으면 각 복사본을 개별적으로 테스트해야 하며, CI 실행 시간과 유지 관리해야 할 테스트 베이스 크기가 몇 배로 증가합니다.

네 번째 위험은 생산성의 착각입니다. 카피파스타는 속도에 대한 잘못된 인식을 만듭니다. 개발자는 빠르게 코드를 붙여넣고 화면이 작동하는 것을 확인합니다. 그러나 이 “속도”는 기술 부채로 변하여 중복 블록에서 버그가 발견되거나 비즈니스 로직 변경이 필요할 때 이자를 붙여 갚아야 합니다.

개발자가 코드를 복사하는 이유

카피파스타의 이유를 이해하면 적절한 예방책을 세우는 데 도움이 됩니다. 대부분의 경우 개발자는 게으름 때문이 아니라 마감일 압박, 지식 부족, 또는 불편한 아키텍처 때문에 코드를 복사합니다.

첫 번째 이유는 마감일입니다. 이틀 안에 화면을 만들어야 하고 유사한 화면이 이미 존재하는 경우, 개발자는 그것을 통째로 복사하고 사용자가 보는 부분만 변경합니다. 공통 컴포넌트를 추출하여 리팩토링할 시간이 없습니다. 클라이언트가 결과를 요구하기 때문입니다. 결과적으로 80%의 공통 코드를 가지고 있지만 변경 이력이 독립적인 두 번째 화면이 생겨납니다.

두 번째 이유는 통합된 추상화의 부재입니다. 프로젝트에 일반적인 작업(예: 당겨서 새로고침이 있는 목록 화면)을 위한 공통 컴포넌트가 없으면 각 개발자가 자신의 구현을 작성하거나 옆 사람의 것을 복사할 것입니다. 프로젝트 시작 시 내려진 아키텍처 결정은 미래의 카피파스타 양에 직접적인 영향을 미칩니다.

세 번째 이유는 작동 중인 코드를 망가뜨릴 두려움입니다. 개발자는 기존 모듈이 작동한다는 것을 알고 있습니다. 공통 코드를 추출하기 위한 리팩토링은 기존 기능에 영향을 줄 수 있습니다. 테스트 커버리지가 낮으면 손상 위험이 리팩토링의 인지된 이점보다 크며, 개발자는 안전한 길인 복사를 선택합니다.

증상이 아닌 원인을 해결하세요. 프로젝트에 견고한 아키텍처 기반이 없다면 마감일을 단축하고 코드 리뷰를 도입해도 문제가 해결되지 않습니다. 초기 단계에서 재사용 가능한 컴포넌트를 만드는 데 시간을 투자하세요. 그것이 미래의 카피파스타 유혹을 줄이는 유일한 방법입니다.

중복 탐지 도구

카피파스타 탐지는 코드 조각을 비교하고 지정된 임계값 이상의 일치를 식별하는 자동 분석기에 의해 수행됩니다. 최고의 도구는 AST(추상 구문 트리) 수준에서 작동하며 서식, 변수 이름 및 주석을 무시합니다.

PMD CPD(Copy-Paste Detector)는 Java, Kotlin, Swift, JavaScript, Python 및 C++를 위한 가장 일반적인 도구입니다. CPD는 소스 코드 토큰을 분석하고 지정된 최소 토큰 수(기본값 100)보다 긴 중복을 찾습니다. 품질 결과를 얻으려면 임계값 구성이 중요합니다. 너무 낮은 임계값은 많은 거짓 긍정(import와 같은 일반적인 패턴)을 생성하고, 너무 높은 임계값은 실제 중복을 놓칩니다.

Gradle을 통해 PMD CPD 실행

groovy
plugins {
    id 'pmd'
}

pmd {
    toolVersion = '7.0.0'
    ruleSetFiles = files("pmd-rules.xml")
}

tasks.register('cpd') {
    doLast {
        exec {
            workingDir = projectDir
            commandLine 'cpd',
                '--minimum-tokens', '75',
                '--language', 'kotlin',
                '--files', 'src/main/kotlin',
                '--format', 'xml',
                '--failOnViolation', 'true'
        }
    }
}

SonarQube는 Quality Gate에 중복 탐지기를 직접 내장하고 있습니다. Duplicated Blocks(%) 규칙은 중복 코드의 백분율을 보여줍니다. 상업용 프로젝트에서는 5% 임계값이 건강한 것으로 간주됩니다. 이를 초과하면 릴리스 브랜치로의 승격이 차단됩니다. SonarQube는 또한 중복을 유형별로 그룹화합니다: 정확한 일치와 구조적 복사(이름이 변경된 식별자 포함).

JavaScript 및 TypeScript의 경우 중복은 ESLint의 eslint-plugin-sonarjs 플러그인(no-duplicate-string 규칙)과 jscpd 유틸리티를 사용하여 탐지됩니다. jscpd는 150개 이상의 언어를 지원합니다. jscpd는 특히 모노레포에 편리하며 단일 모듈 내에서뿐만 아니라 패키지 간의 중복도 찾습니다.

중복 코드 리팩토링 전략

카피파스타 리팩토링은 하나의 원칙으로 요약됩니다: 공통 부분을 추출하고 차이점을 매개변수화하는 것입니다. 구체적인 기술은 중복의 범위와 컨텍스트에 따라 다릅니다.

가장 간단한 경우는 단일 클래스 내의 중복입니다(예: 동일한 로직이지만 다른 타입을 가진 두 메서드). 해결책은 제네릭으로 일반화하거나 타입 매개변수가 있는 메서드를 재사용하는 것입니다. 중복이 여러 클래스에 걸쳐 있는 경우 공통 코드를 유틸리티 클래스나 확장 함수로 추출하세요.

더 복잡한 경우는 화면 또는 모듈 수준의 중복입니다. 이 경우 단순히 함수를 추출하는 것만으로는 충분하지 않습니다. UI 구조, 라이프사이클 로직, 데이터 바인딩이 모두 중복되어 있기 때문입니다. 해결책은 공통 기본 화면 클래스나 복합 뷰 컴포넌트를 만들고 매개변수나 프로토콜을 통해 차이점을 전달하는 것입니다.

swift
// before - two copies of the same UITableViewController
class UserListController: UITableViewController {
    private let viewModel = UserListViewModel()
    // 40 lines of code
}

class ProductListController: UITableViewController {
    private let viewModel = ProductListViewModel()
    // same 40 lines but with Product instead of User
}

// after - generic base class shared
class ListViewController<T: ListViewModel>: UITableViewController {
    let viewModel: T
    // 40 lines of code - once only

    init(viewModel: T) {
        self.viewModel = viewModel
        super.init(style: .plain)
    }
}

가장 복잡한 경우는 마이크로서비스 또는 라이브러리 간의 중복입니다. 공유 코드를 추출하면 순환 의존성이나 부당한 결합이 발생할 수 있습니다. 이러한 경우 카피파스타는 의식적인 결정일 수 있습니다. 두 팀이 독립적인 서비스를 유지 관리하고 공유 라이브러리가 해결하는 것보다 더 많은 문제를 만드는 경우입니다. 중요한 것은 그러한 결정을 문서화하고 복사본이 통합을 정당화할 만큼 충분히 분기되었는지 정기적으로 확인하는 것입니다.

팀 수준에서의 카피파스타 예방

카피파스타를 예방하는 것이 이미 중복된 코드를 리팩토링하는 것보다 효과적입니다. 주요 예방 조치는 기술이 아닌 개발 프로세스 조직에 있습니다.

첫 번째 조치는 중복에 초점을 맞춘 코드 리뷰입니다. 리뷰 체크리스트에는 “이 PR에 프로젝트에 이미 존재하는 코드가 포함되어 있습니까?”라는 항목이 포함되어야 합니다. 리뷰어가 카피파스타를 발견하면 공통 컴포넌트가 추출될 때까지 병합을 차단합니다. 이 요구사항은 팀의 Definition of Done의 일부여야 합니다.

두 번째 조치는 공유 컴포넌트 라이브러리입니다. 두 개 이상의 화면에 나타나는 모든 UI 패턴은 공통 모듈로 추출되어야 합니다. 프로젝트에 공유 모듈을 만들고 모든 UI 컴포넌트의 필수 진입점으로 만드세요. 컴포넌트가 존재하지 않으면 먼저 만든 후 화면에서 사용합니다.

세 번째 조치는 CI/CD의 자동화입니다. 파이프라인에 중복 코드 검사 단계(PMD CPD, jscpd, SonarQube)를 추가하세요. 임계값을 초과하면 빌드가 실패합니다. 개발자는 허용된 수준 이상으로 카피파스타 비율을 높이는 PR을 병합할 수 없습니다. 이는 책임을 코드 리뷰에서 자동화로 이동시키고 어떤 중복도 놓치지 않도록 보장합니다.

“하나의 구현 — 하나의 장소” 문화를 조성하세요. 재사용 기회가 보이면 리팩토링을 나중으로 미루지 마세요. “나중에” 남겨진 카피파스타는 증식하여 통제 불능의 기술 부채로 변합니다.

자주 묻는 질문

카피파스타는 항상 나쁜가요?

아니요, 의식적인 중복의 시나리오가 있습니다: 독립적으로 진화해야 하는 다른 마이크로서비스, 삭제 계획이 있는 실험을 위해 복사된 코드, 다른 API 버전을 위한 템플릿 DTO 등입니다. 중요한 것은 이유를 문서화하고 리팩토링을 위한 확인 기한을 설정하는 것입니다.

카피파스타와 건강한 재사용을 어떻게 구분하나요?

카피파스타는 코드의 두 부분이 같은 일을 하지만 공통 추상화가 없는 경우입니다. 건강한 재사용은 공통 코드가 함수, 클래스 또는 모듈로 추출되고 차이점이 매개변수화된 경우입니다. 로직 변경에 세 곳 이상의 수정이 필요한 경우 — 그것이 카피파스타입니다.

iOS 프로젝트에서 카피파스타를 탐지하는 도구는?

PMD CPD는 Swift와 Objective-C를 지원합니다. Xcode용으로는 SwiftCop 같은 플러그인과 AppCode에 내장된 중복 탐지기가 있습니다. SonarQube도 Swift 프로젝트를 분석하며 풀 리퀘스트에서 직접 중복 블록을 보여줍니다.

카피파스타가 이미 존재하고 리팩토링할 시간이 없으면 어떻게 하나요?

주요 복사본마다 리팩토링 기술 티켓을 만드세요. 우선순위를 설정하세요: 자주 변경되는 화면을 먼저, 안정적인 화면은 나중에. 중복 코드를 건드리는 각 새 PR에 대해 점진적 통합을 위해 15~20%의 시간을 할당하세요.

AI 도구가 카피파스타 탐지에 도움이 되나요?

네, 최신 AI 어시스턴트(GitHub Copilot, Codeium)는 컨텍스트를 분석하고 반복 패턴을 감지하면 공유 코드 추출을 제안할 수 있습니다. 그러나 자동 분석기를 대체하지는 않습니다. Copilot은 예방에, CPD/SonarQube는 탐지에 사용하세요.

요약

  • 카피파스타 — 적응 없이 복사하여 코드를 중복시키는 것, 기술 부채의 주요 원인.
  • 버그 전파: 하나의 복사본을 수정해도 나머지는 수정되지 않고 결함이 프로젝트 전체에 퍼집니다.
  • 주요 원인: 마감일, 공유 추상화 부족, 리팩토링 중 작동 코드 손상에 대한 두려움.
  • 탐지 도구: PMD CPD, SonarQube, jscpd, ESLint sonarjs/no-duplicate-string, SwiftCop.
  • 리팩토링: 공통 코드를 함수, 제네릭 클래스 또는 차이점을 매개변수화한 공유 컴포넌트로 추출.
  • 예방: 중복 확인이 포함된 코드 리뷰, 공유 컴포넌트 라이브러리, 중복에 대한 CI 검사.
  • 문화적 규칙: 하나의 구현 — 하나의 장소. 의식적인 중복을 문서화하고 정기적으로 모니터링하세요.

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의

더 읽어보기