“GoTo 는 *해로 운가?”* — 1968 년 Dijkstra 의 짧은 편지 가 프로그래밍 의 *형태 를 *바꾸었다. 그 8 년 후 Wirth 의 책 — 알고리즘 + 자료구조 = 프로그램. 둘은 *별개 의 주제 *같지만 — *깊이 들여다 보면 *같은 *질문 의 *두 *얼굴. 이 글은 그 연결.


TL;DR

차원 구조적 프로그래밍 자료구조
본질 제어 흐름 (행위) 의 명확화 데이터 (상태) 의 형태 부여
시조 Dijkstra (1968) Knuth / Wirth (1968 ~ 76)
단위 순차 / 선택 / 반복 시퀀스 / 트리 / 그래프 / 해시
목적 증명 가능 한 *흐름 효율 적 *접근 / 변형
공통 복잡도 *분할 + *명명  

핵심 통찰 :

자료구조 가 *제어 구조 를 결정 한다 — 그 반대 도 같다. 둘은 *서로 의 *거울.


1. 구조적 프로그래밍 — Dijkstra 의 *짧은 *편지

1968 년의 역사 적 순간

Edsger Dijkstra 가 Communications of the ACM 에 한 페이지 편지 를 보냈다. 제목 — “Go To Statement Considered Harmful”.

요지 :

“goto 가 *프로그램 의 *동적 흐름 을 *예측 불가능 하게 만든다. 3 가지 제어 구조 — *순차 (sequence), *선택 (selection), *반복 (iteration) — 만 으로 모든 알고리즘 을 표현 가능 하다.”*

이 주장 이 프로그래밍 의 *방향 을 바꾸었다. FORTRAN / COBOL 의 *goto 지옥 시대* 가 끝나고 C 의 *블록 / for / while 구조 시대 로.

구조적 프로그래밍 의 *3 가지 구조

1. Sequence  — A; B; C;     (순차 실행)
2. Selection — if / case    (조건 분기)
3. Iteration — for / while  (반복)

이 3 가지 만으로 *Turing-complete. 즉 모든 계산 가능 한 알고리즘 을 goto 없이 *표현 가능. 수학적 *증명 도 함께 등장.

왜 *중요한가

  • 읽을 수 있는 *코드 — 위에서 아래로 흐름
  • 국 소 *추론 가능 — 함수 안 *만 *보면 동작 이해
  • 증명 + 테스트 가능 — 흐름이 *예측 가능
  • 버그 ↓

2. 자료구조 — Wirth 의 *공식

1976 년 Niklaus Wirth 의 유명한 책

“Algorithms + Data Structures = Programs”.

이 한 줄 공식 이 컴퓨터 과학 교육의 *기둥. 의미 :

프로그램은 *알고리즘 (행위) + 자료구조 (상태) 의 합. 둘 중 하나 만 으론 *불완전.*

자료구조 의 *5 가지 *기본

1. Array / Sequence   — 인덱스 접근
2. Linked List         — 순차 + 동적 크기
3. Tree                — 계층
4. Hash Table          — O(1) 키 접근
5. Graph               — 일반 관계

이 5 가지 + 변종 (스택, 큐, 우선순위 큐, 트라이, B-Tree, …) 이 컴퓨터 과학 의 *기본 어휘.

각 자료구조 의 *시간 복잡도

자료구조 검색 삽입 삭제
Array \(O(n)\) \(O(n)\) \(O(n)\)
Sorted Array \(O(\log n)\) \(O(n)\) \(O(n)\)
Linked List \(O(n)\) \(O(1)\) \(O(1)\)
Binary Search Tree (균형) \(O(\log n)\) \(O(\log n)\) \(O(\log n)\)
Hash Table (평균) \(O(1)\) \(O(1)\) \(O(1)\)
Heap \(O(1)\) min \(O(\log n)\) \(O(\log n)\)

복잡도 의 차이 가 현장 의 *성능 의 차이. 수 백 만 *데이터 에서 log n vs n 은 체감 100 배 *차이.


3. 둘은 *어떻게 *만나는가

자료구조 의 *형태 가 제어 구조 의 *모양 을 부른다.*

이게 핵심 명제. 예 :

Sequence (Array / List) → 순차 반복

for item in array:
  process(item)

Array 의 *순차 *접근 은 for 루프 와 자연 짝. 제어 와 *데이터 가 *같은 형태.

Tree → 재귀

def traverse(node):
  if node is None: return
  visit(node)
  traverse(node.left)
  traverse(node.right)

Tree 의 *재귀 구조 가 재귀 호출 과 짝. for 루프로 *Tree 순회 한다 면 명시 적 *스택 필요 — 자연 스럽지 않음.

Graph → BFS / DFS

def bfs(start):
  queue = [start]
  while queue:
    node = queue.pop(0)
    for neighbor in node.neighbors:
      queue.append(neighbor)

Graph 의 *복잡 관계 가 큐 + while 루프 와 짝. Tree 의 재귀 와 *비슷 하지만 *순환 가능 해 방문 표시 추가.

Hash Table → O(1) 직접 접근

if key in cache:  # O(1) 조회
  return cache[key]

해시 의 *직접 접근 은 조건문 의 *짧음 과 짝. 반복 없이 *답 으로 직행.


4. 역 방향 — 제어 구조 가 *데이터 *형태 를 *드러낸다

같은 명제 의 반대 방향 도 성립.

for 루프 → *시퀀스 의 *증거

for (int i = 0; i < n; i++) { ... }

이 코드 자체 가 “나는 0 ~ n-1 의 *시퀀스 를 처리한다” 라고 *자료구조 를 *드러낸다.

재귀 → 트리 / 분할 정복

int sum(int[] arr, int lo, int hi) {
  if (lo == hi) return arr[lo];
  int mid = (lo + hi) / 2;
  return sum(arr, lo, mid) + sum(arr, mid+1, hi);
}

분할 정복 의 *재귀 가 반복적 *반 *나누기 — 암묵 적 *Binary Tree.

while + 큐 → 그래프 탐색

위의 BFS 예제 — 코드 만 봐도 “그래프 가 그릴 수 있다”.

→ 좋은 코드 는 *자료구조 가 *읽힌다. 자료구조 가 읽히지 않는 *코드 는 나쁘다.*


5. 추상화 의 *두 *축

컴퓨터 과학 의 추상화 는 두 축 :

       제어 (행위)
            │
            │
            │
────────────┼──────────── 상태 (데이터)
            │
            │
            │
  • 구조적 프로그래밍 = 제어 축의 추상화 *질서
  • 자료구조 = 데이터 축의 추상화 *질서

둘은 직교 하지 않고 서로 *의존. 좋은 시스템 은 둘 다 *깊이 *고려.

OO — 두 축의 *합 친 *추상

class Stack<T> {
  private List<T> items;       // 자료구조 (상태)
  public void push(T x) { ... }  // 제어 + 상태
  public T pop() { ... }
}

객체지향 의 클래스 는 상태 + 행위 를 *함께 *캡슐화. Wirth 의 공식 의 *진화 한 형태.

FP (함수형) — 불변 데이터 + 순수 함수

sumTree (Leaf x) = x
sumTree (Node l v r) = sumTree l + v + sumTree r

자료구조 가 패턴 매칭 으로 직접 *해체. 제어 가 *자료구조 를 *반영. Wirth 공식 의 *극단적 *순수 형태.


6. 왜 *둘을 *함께 배워야 하는가

학생 의 흔한 오류

  • 자료구조 만 *외움 (리스트 / 트리 / 해시 등) — 언제 *어떻게 *적용 하는지 모름
  • 제어 흐름 만 *코드 짜기 — 데이터 *모양 의 최적 *놓침
  • 문제 해결 시 *자료구조 가 *떠 오르지 않음

통합 적 *훈련

문제 → *어떤 자료구조* 가 적합한가?
     → *그 자료구조* 의 *자연 스러운 *제어 흐름* 은?
     → *코드 *작성*

이 3 단계 가 알고리즘 풀이 의 *표준 순서.

예 — 최단 경로 찾기

  1. 그래프 자료구조 (인접 리스트)
  2. BFS 의 while + queue 제어
  3. 방문 표시 + 부모 추적 — 재구성

→ 문제 의 *모양 → 자료구조 → 제어 흐름 의 자연스러운 연결.


7. 현장 의 *증거 — 왜 *고급 개발자 가 *자료구조 직관이 *결정적

본인 9 년차 시점 에서 자료구조 직감 이 *결정적 *순간들 :

7.1. DB 인덱스 의 *왜 *빠른가

  • B-Tree 자료구조 가 log n 검색 보장
  • Hash Index 가 \(O(1)\) but 범위 검색 불가
  • 인덱스 선택 = 자료구조 선택

→ DB 인덱스 의 *근본 은 자료구조. 알면 명확. 모르면 암기.

7.2. Java HashMap 의 *충돌 처리

  • Java 8 부터 — 충돌 시 *Linked List → Tree 로 전환
  • Linked List 의 *worst case \(O(n)\) → Tree 의 \(O(\log n)\) 로 복원
  • 알고리즘 의 안 정 성 보장

이걸 알면 — HashMap 의 *성능 의 비밀 이 직 관.

7.3. Kafka 의 *Topic 의 *파티션

  • Topic = 그래프 의 *분할
  • Partition = 시퀀스 (offset 순서)
  • Consumer Group = 분할 정복

→ Kafka 는 *그래프 + 시퀀스 의 *조합. 자료구조 의 *언어 로 *Kafka 를 본다.

7.4. Elasticsearch 의 *역 색인 (Inverted Index)

  • 역 색인 = 단어 → 문서 ID 리스트 의 해시 + 소트 시퀀스
  • 검색 = *해시 조회 + 시퀀스 교집합

→ 이 자료구조 가 Elasticsearch 의 *모든 검색 성능 의 근본.


8. 추상 의 *수준 *높이기

입문 (1 년차)

  • for / while / if / 함수 등 기본 제어
  • Array / List / Map 의 기본 사용

중급 (3 년차)

  • 재귀 의 *자연 스러운 적용
  • Tree / Graph 의 *직접 구현 + 활용
  • Big-O 의 *직 관

고급 (5 년차+)

  • 자료구조 ↔ 제어 *연결 직 감 — 문제 보면 자료구조 와 제어 흐름 이 동시에 *떠 오름
  • 시스템 의 *자료구조 분석 — 내부 가 *어떻게 *구성 되어 있는지
  • 맞춤 자료구조 *설계 — 표준 자료구조 조합 / 변형

→ 연차 별 *능력 의 *연속선. 자료구조 + 제어 의 통합 적 직 감 이 시니어 의 *진짜 *능력.


9. 흔한 *오류 패턴

9.1. 자료구조 *선택 *잘못

// ❌ 자주 *contains 호출* 인데 List 사용
List<String> blacklist = ...;
if (blacklist.contains(item)) { ... }  // O(n)

→ HashSet 으로 변경 → \(O(1)\).

9.2. 불필요한 *복잡 자료구조

// ❌ *5 개 *원소* 인데 *Red-Black Tree*
TreeSet<Integer> small = new TreeSet<>();
small.add(1); small.add(2); ... // 5 개

→ Array 가 충분. Big-O 가 *작은 n 에서 *역효과.

9.3. Stream 의 *남용

// ❌ 단순 합 계
int sum = list.stream().mapToInt(i -> i).sum();

→ for 루프 가 더 명확. 작은 데이터 에선 오버헤드.

→ **자료구조 와 *제어 흐름 의 *균형 이 현장 의 *기술.


10. Refactoring *의 *진짜 *기준

리팩터링 시 질문 :

  1. 이 코드 의 *제어 흐름 이 자연 스러운가?
  2. 그 흐름 이 *어떤 자료구조 를 드러내고 있는가?
  3. 그 자료구조 가 *적합 한가?

이 3 질문 으로 대부분 의 *코드 의 *문제점 이 드러난다. 변수 명 / 함수 분할 / 인터페이스 같은 표면적 개선 보다 근본 적.


11. 역사 적 *교훈

60 년 의 *공통 점

  • 구조적 프로그래밍 (1968) → 복잡 한 흐름의 *제어
  • 자료구조 (1976) → 복잡 한 데이터 의 *모양 부여
  • 객체 지향 (1980s) → 상태 + 행위 통합
  • 함수형 (2010s 부활) → 불변 + 패턴 매칭
  • Reactive (2015+) → 비동기 시퀀스

→ 모두 *Dijkstra + Wirth 의 *연 장. 통제 + 자료 의 추상 화 진화.

현대 의 *연 장

  • 마이크로서비스 — 서비스 가 *데이터 단위
  • Event Sourcing — 상태 의 *시퀀스 표현
  • CQRS — 제어 (Command) vs 자료 (Query) 분리
  • Vector DB — 벡터 라는 *자료구조 의 전 면화

→ Wirth 의 공식 — *진화 만 *할 뿐 *틀린 적 없음.


12. 마치며

구조적 프로그래밍 과 자료구조 는 *두 *언어 의 같은 *문법. 제어 가 *데이터 를 *부르고 데이터 가 제어 를 *부른다.

3 줄 요약 :

  1. 자료구조 와 제어 의 *직 관 적 *연결 이 시니어 의 *능력 — 문제 보면 둘 다 *떠 오름.
  2. 새 시스템 (DB / Kafka / ES) 의 깊이 = *자료구조 의 *깊이 — 자료구조 모르면 시스템 도 *얕다.
  3. 리팩터링 의 진짜 기준 = *자료구조 의 *적합성 — 표면 변수 명 보다 훨씬 *중요.

9 년차 회고 :

“학부 시절 *자료구조 가 *왜 *중요한지 *몰랐다. 7년이 지난 지금 — *없으면 *어떤 시스템도 *얕다 는 게 몸 으로 *느낌.”*

다음 글 — 알고리즘 의 *직 관 *— Big-O 너머 의 *실 무 *비용 *지도. 같은 시리즈로.


본 글은 9년차 백엔드 엔지니어의 *학문 적 회고. 학문 의 분류 는 *나라 / 교재 마다 다르다. 해석은 *내 시각 일 뿐. Dijkstra, Wirth, Knuth 의 원전 을 직 접 읽으면 *더 깊은 *교훈.