본문으로 바로가기
제품데스크톱 도구TASTECAD도면 확인TASTEFILES파일 관리TASTEFTP파일 전송TASTESSH원격 작업공간TASTEZIP압축과 해제개발 도구TASTECODERust 통합 개발 환경TASTESTUDIO통합 개발·테스트 환경TASTEETL데이터 통합(ETL)서버TASTEREMOTE원격 데스크톱 서버TASTEGEO공간정보 서버TASTEMAIL메일 작업공간시작하기다운로드문서구매모든 제품
마켓플레이스
소식
개발소식오늘의 개발 소식개발 문서프로그래밍 언어RustTypeScriptJavaScriptPythonGoC#JavaCC++KotlinDart프런트엔드 프레임워크Next.jsReactVue.js · NuxtSvelteKitAngular서버 프레임워크Spring BootDjangoFastAPIASP.NET CoreNestJS · Express앱 · 데스크톱 프레임워크TauriFlutterReact NativeElectron알고리즘알고리즘 기초알고리즘 핵심알고리즘 심화실무 알고리즘
커뮤니티프로젝트개발 로그프롬프트AI 도구 이슈쇼케이스커뮤니티 안내
협업기술 전수홈페이지 구축데스크톱 앱 구축릴리스·결제 파이프라인판매 파트너문의
서비스원격 데스크톱설치 패키지 커스텀
TASTEDEV
제품

데스크톱 도구

TASTECAD복잡한 도면을 가볍게 열다TASTEFILES필요한 파일만, 가장 빠르게TASTEFTP파일이 오가는 가장 단정한 길TASTESSH서버와 나 사이, 더 단단한 연결TASTEZIP더 빠르게 묶고, 더 안전하게 풀다

개발 도구

TASTECODERust 앱을 편집 · 빌드 · 디버깅 · 테스트까지 한 창에서TASTESTUDIO편집부터 원격 테스트와 승인 기반 AI 수정까지TASTEETL값을 보며 데이터를 옮깁니다

서버

TASTEREMOTE우리 회사 서버로 운영하는 원격 데스크톱TASTEGEOGeoServer 호환 공간정보 서버를 Rust로 다시 세웁니다TASTEMAIL메일의 주도권을 다시 내 손에

시작하기

다운로드모든 제품 최신 판문서제품 사용법구매구독 · 영구 라이선스모든 제품모든 제품 한눈에
모든 제품
마켓플레이스소식
개발

소식

오늘의 개발 소식언어 · 프레임워크 · GitHub · AI 공식 발표개발 문서언어 · 프레임워크 · 알고리즘 안내서

프로그래밍 언어

RustTypeScriptJavaScriptPythonGoC#JavaCC++KotlinDart

프레임워크

프런트엔드 프레임워크Next.jsReactVue.js · NuxtSvelteKitAngular
서버 프레임워크Spring BootDjangoFastAPIASP.NET CoreNestJS · Express
앱 · 데스크톱 프레임워크TauriFlutterReact NativeElectron

알고리즘

알고리즘 기초복잡도 분석 · 정렬 · 탐색 · 기본 자료구조 · 트리와 힙알고리즘 핵심그래프 탐색 · 최단 경로와 최소 신장 트리 · 동적 계획법 · 탐욕 알고리즘 · 분할 정복 · 백트래킹알고리즘 심화문자열 알고리즘 · 수학과 정수론 · 비트 연산 · 구간 트리 · 유니온 파인드실무 알고리즘코딩 면접 풀이 전략 · LRU 캐시 · 레이트 리미터 · 일관된 해시
개발 문서 전체 보기
커뮤니티
프로젝트빌더와 작업 발견개발 로그결정과 시행착오프롬프트재사용 가능한 지시AI 도구 이슈Claude · Codex · Gemini 문제와 우회법쇼케이스완성된 결과커뮤니티 안내공개하고 함께 만드는 방식
협업
기술 전수Rust·egui 네이티브 앱 만들기홈페이지 구축10개 언어, 계정, 문서·다운로드데스크톱 앱 구축Rust·egui, WebView 없이릴리스·결제 파이프라인서명 · MSI·deb·rpm·AppImage · 해시판매 파트너소개하고 결제액의 30% 받기문의구축 · 제휴 · 투자 문의
서비스
원격 데스크톱브라우저로 내 컴퓨터에 접속설치 패키지 커스텀필요한 기능만, 설정은 미리
구매
KO
한국어EnglishDeutschEspañolFrançaisItalianoPortuguês (Brasil)日本語简体中文繁體中文
로그인
로그인
TASTEDEV

작은 도구부터, 더 좋은 개발까지.

support@tastedev.netTASTEDEV 후원하기
제품제품군구매문서다운로드마켓플레이스고객 지원
커뮤니티프로젝트개발 로그프롬프트AI 도구 이슈쇼케이스
정책개인정보처리방침이용약관구독 약관환불 정책커뮤니티 운영 정책
계정로그인가입하기
방문자
오늘
012345678901234567890123456789012345678901234567890123456789
어제
012345678901234567890123456789012345678901234567890123456789
누적 조회
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
상호
지엑스소프트
대표자
최영구
사업자등록번호
853-44-00368
주소
인천광역시 미추홀구 경인로 351 9층 V24
전화
+82-10-4404-1523
이메일
whitecalvin@tastedev.net
개인정보 보호책임자
최영구

© 2026 TASTEDEV제품 정보는 현재 검증된 개발 소스를 기준으로 합니다.출시·고도화 중

백트래킹 문서
백트래킹
백트래킹의 개념동작 원리구현복잡도연습 문제실무 활용
토론

백트래킹 안내서 · 1/6

백트래킹의 개념

백트래킹(backtracking)은 답을 한 번에 만들지 않고 한 칸씩 채워 가다가, 지금까지 고른 것이 조건을 어기면 바로 앞 단계로 돌아가 다른 선택을 시도하는 탐색 기법입니다. 모든 경우를 끝까지 만들어 본 뒤 검사하는 완전 탐색과 달리, 가망이 없는 길은 중간에 잘라 내므로 같은 문제를 훨씬 적은 시도로 풀 수 있습니다. 이 장에서는 백트래킹을 설명할 때 쓰는 용어와 기본 틀, 그리고 언제 백트래킹을 고르는지 정리합니다.

상태 공간 트리

백트래킹이 탐색하는 공간은 상태 공간 트리(state-space tree)로 그리면 이해하기 쉽습니다. 루트는 아무것도 고르지 않은 빈 상태이고, 한 단계 내려갈 때마다 선택을 하나씩 더합니다. 리프에 도착하면 완성된 후보 하나가 만들어집니다. 예를 들어 [1, 2, 3]의 순열을 만드는 트리는 다음과 같습니다.

                 []
       /         |         \
     [1]        [2]        [3]
    /   \      /   \      /   \
 [1,2] [1,3] [2,1] [2,3] [3,1] [3,2]
   |     |     |     |     |     |
[1,2,3] ...                    [3,2,1]

백트래킹은 이 트리를 깊이 우선 탐색(DFS)으로 내려가되, 어떤 노드가 더 내려가 봐야 해가 될 수 없다고 판단되면 그 아래 가지 전체를 건너뜁니다. 이것을 가지치기(pruning)라고 합니다.

꼭 알아야 할 용어

  • 부분해(partial solution): 지금까지 고른 선택들의 목록입니다. 보통 path 같은 리스트로 들고 다닙니다.
  • 후보(candidate): 현재 상태에서 다음에 고를 수 있는 값들입니다.
  • 유망성(promising): 현재 부분해를 더 늘려서 해에 도달할 가능성이 남아 있는지 여부입니다.
  • 가지치기: 유망하지 않은 노드에서 탐색을 멈추고 돌아가는 일입니다.
  • 제약 조건(constraint): 해가 반드시 지켜야 하는 규칙입니다. 같은 열에 퀸을 두 개 놓지 않는다, 합이 목표를 넘지 않는다 같은 것들입니다.

선택 · 탐색 · 되돌리기

거의 모든 백트래킹 코드는 세 동작의 반복입니다. 후보를 하나 선택(choose)해 부분해에 넣고, 그 상태에서 재귀로 탐색(explore)한 뒤, 돌아와서 넣었던 것을 되돌립니다(unchoose). 되돌리기가 있어야 하나의 path 리스트를 모든 가지가 함께 쓸 수 있습니다.

def backtrack(path, choices, result):
    if is_solution(path):
        result.append(path[:])      # 복사해서 저장
        return
    for c in candidates(path, choices):
        if not is_valid(path, c):   # 가지치기
            continue
        path.append(c)              # 선택
        backtrack(path, choices, result)  # 탐색
        path.pop()                  # 되돌리기

result.append(path[:])에서 복사를 빼먹으면, 나중에 path가 비워질 때 저장해 둔 결과도 같이 바뀌어 빈 리스트만 남습니다. 백트래킹에서 가장 흔한 실수 가운데 하나입니다.

작은 예: 부분집합

각 원소를 넣을지 말지 두 갈래로 나누면 부분집합 트리가 됩니다. 원소가 n개면 리프가 2^n개입니다.

def subsets(nums):
    result, path = [], []

    def dfs(i):
        if i == len(nums):
            result.append(path[:])
            return
        path.append(nums[i])   # nums[i]를 넣는 가지
        dfs(i + 1)
        path.pop()
        dfs(i + 1)             # 넣지 않는 가지

    dfs(0)
    return result

print(subsets([1, 2, 3]))
# [[1, 2, 3], [1, 2], [1, 3], [1], [2, 3], [2], [3], []]

가지치기가 있는 예

길이 n의 0/1 문자열 가운데 1이 연속으로 붙지 않는 것만 만들어 봅니다. 마지막 글자가 1이면 다음에 1을 고르지 않는 것이 가지치기입니다. 잘못된 문자열을 다 만든 뒤 걸러 내는 것보다 훨씬 적게 탐색합니다.

def no_adjacent_ones(n):
    out = []

    def dfs(s):
        if len(s) == n:
            out.append(s)
            return
        dfs(s + "0")
        if not s.endswith("1"):   # 1 다음 1은 시도하지 않음
            dfs(s + "1")

    dfs("")
    return out

print(no_adjacent_ones(3))  # ['000', '001', '010', '100', '101']

언제 백트래킹을 쓰나

  • 조건을 만족하는 해를 모두 나열해야 할 때: 순열, 조합, 부분집합, 경로 목록.
  • 제약 충족 문제(CSP)를 풀 때: N-Queens, 스도쿠, 색칠 문제, 일정 배치.
  • 입력이 작아서(대략 n이 20 안팎 이하) 지수 시간이라도 감당할 수 있을 때.
  • 하위 문제가 겹치지 않아 동적 계획법(DP)으로 결과를 재사용하기 어려울 때.

반대로 개수만 세면 되고 같은 하위 문제가 반복된다면 DP가, 매 단계의 최선 선택이 전체 최적을 보장한다면 그리디가 더 알맞습니다. 이 비교는 복잡도 장에서 자세히 다룹니다.

정리

  • 백트래킹은 상태 공간 트리를 깊이 우선으로 탐색하면서 유망하지 않은 가지를 잘라 내는 기법입니다.
  • 코드는 선택 → 탐색 → 되돌리기의 반복이고, 해를 저장할 때는 부분해를 복사합니다.
  • 가지치기 조건을 얼마나 일찍, 얼마나 강하게 거느냐가 성능을 좌우합니다.
이 장에 대해 질문이 있나요?
다음 장동작 원리

댓글 0개

인기 댓글순최신순

로그인 · 로그인하면 댓글을 남길 수 있습니다.