COBOL 소스를 읽기 전에 알아 둘 최소 지식

· 업데이트: · · COBOL, 레거시 기술, 업무 시스템, 보수, Mainframe

수정 이력(6건, 최종 수정 2026년 09월 03일)

이 글에 적용한 변경 사항의 기록입니다. 보관해 둔 수정 전 버전은 DOI가 부여된 고정 URL에서 읽을 수 있습니다.

permalink·저자 표기·지식 맵 래퍼·깨진 내부 링크 등 CI가 지적한 표시용 수정을 반영했습니다. 본문의 기술적인 주장은 바꾸지 않았습니다.
일본어 원문의 완역으로 다시 번역했습니다. 기존 한국어판은 원문의 일부만 옮긴 축약본이라 절, 표, Mermaid 그림, 그림 설명, FAQ가 빠져 있었습니다. 일본어 원문에 맞춰 이들을 모두 복원했고, 기술적인 주장은 일본어판과 같습니다. 수정 전 버전 보기 (DOI: 10.5281/zenodo.21635181)
데이터 정의 읽는 법이나 처리 흐름, 외부 경계를 잡는 법을 그림으로도 따라갈 수 있도록, Mermaid 그림을 21점 추가했습니다(본문 500〜750자당 1그림 규약에 맞춘 것입니다). 본문 문장은 바꾸지 않았습니다.
글 맨 앞에 「이 글의 지식 맵」 절을 추가했습니다. 본문에서 다루는 개념과 그 관계를 요약·그림·상세 페이지 링크로 정리한 것입니다. 본문의 주장은 바꾸지 않았습니다.
외부 리뷰(1283건) 대응으로 본문을 갱신했습니다. 개별 변경 내용은 아래 이력을 참조하십시오.
COMP-3가 실제로 어떤 바이트 열이 되는지를, IBM에 실린 예와 도출을 붙여 추가했습니다(ASCII로 읽으면 원래 수치가 어디에도 나오지 않는다는 점도 보였습니다). 고정 형식의 열 구조 그림을 80열 눈금이 있는 것으로 바꾸고, 독해 연습을 6문항 추가했으며, 컴파일러 차이(문자 코드, `COMP-4`와 `COMP-5`의 자리 수 다루기 차이)를 덧붙였습니다.
최초 공개
이 글을 인용하기(DOI: 10.5281/zenodo.21635180)

이 글은 Zenodo에 보관되어 있습니다. 항상 최신 버전으로 연결되는 DOI와 지금 보고 있는 버전에 고정된 DOI를 아래에 함께 제시합니다.

Go Komura (2026). 「COBOL 소스를 읽기 전에 알아 둘 최소 지식」. 합동회사 코무라소프트. https://doi.org/10.5281/zenodo.21635180 https://comcomponent.com/ko/blog/cobol-minimum-reading-guide/

DOI(최신 버전)
10.5281/zenodo.21635180
DOI(이 버전)
10.5281/zenodo.22217461

인계, 장애 대응, 벤더 패키지 보수. 그런 상황에서 어느 날 갑자기 COBOL 소스가 날아오는 경우가 있습니다.

  • 파일 이름은 .cbl이나 .cpy
  • 변수 이름은 전부 대문자
  • 01, 05, 77, 88이 나열된다
  • PIC S9(7)V99 COMP-3처럼, 주문과 회계 소프트웨어의 중간 같은 표기가 나온다
  • 게다가 COPY 투성이라 연 파일만으로는 전체가 보이지 않는다

이 지점에서 대개 손이 멈춥니다.

다만, 읽기 위한 지도는 그리 크지 않습니다. COBOL에는 컴파일러나 제품마다 차이가 있지만, 기존 업무 시스템을 읽을 때 먼저 잡아야 할 골격은 꽤 공통입니다. 이 글에서는 IBM 계열이나 전형적인 업무 COBOL을 염두에 두고, 갑자기 소스를 읽게 된 사람을 위한 최소 세트를 정리합니다.

손이 멈추는 이유와 지도의 크기전부 대문자인 변수 이름이나 레벨 번호, PIC S9(7)V99 COMP-3 같은 표기, COPY 투성이라 전체가 보이지 않아 손이 멈추지만, 기존 업무 시스템을 읽기 위해 먼저 잡아야 할 골격은 꽤 공통이고 지도는 그리 크지 않음을 나타내는 그림.익숙하지 않은 표기 때문에 손이 멈춘다다만 골격은 컴파일러를 넘어 공통이다최소 세트의 지도만 먼저 가진다COPY 투성이라 전체가 보이지 않는다

그림1: 주문처럼 보이는 표기의 정체는 몇 개의 공통 개념으로 모아집니다.

1. 먼저 결론(한 마디로)

먼저 꽤 거칠지만, 실무에서 도움이 되는 말로 하면 이렇습니다.

  • COBOL은 로직의 언어이기 전에, 상당히 강하게 레코드 정의의 언어입니다
  • PROCEDURE DIVISION만 읽어서는 절반밖에 파악하지 못합니다. 먼저 DATA DIVISION을 봅니다
  • PIC항목의 형태, USAGE어떤 표현으로 가질지입니다
  • COMP-3는 packed decimal입니다. 금액이나 건수의 세계에서 자주 나옵니다
  • 88은 별도 변수라기보다, 직전 항목의 값에 이름을 붙인 조건명입니다
  • REDEFINES같은 메모리를 다른 형태로 보는 장치입니다. 복사가 아닙니다
  • COPY가 있다면, 지금 연 소스는 아직 미완성입니다. copybook을 보지 않으면 전체가 보이지 않습니다
  • PERFORM, IF, EVALUATE, READ, WRITE, CALL을 따라가면, 대체적인 흐름은 잡을 수 있습니다
  • 오래된 소스는 열 위치에 의미가 있는 고정 형식입니다. 겉모습의 공백이 단순한 장식이 아닙니다1

요컨대, DIVISION, PIC, USAGE, COMP-3, REDEFINES, OCCURS, 88, COPY, PERFORM. 이 부근이 읽히면 길을 잃을 확률이 꽤 내려갑니다.

이 글의 지식 맵

COBOL은 PROCEDURE DIVISION에 의한 처리 절차의 언어이기 전에 DATA DIVISION에서 레코드의 형태를 정의하는 언어이며, 각 데이터 항목은 PICTURE로 형을, USAGE로 COMP-3 같은 내부 표현을 지정합니다. COMP-3는 10진 숫자를 2자리씩 1바이트에 채워 넣는 packed decimal로, 텍스트로 열면 의미를 알 수 없는 바이트열로 보입니다. REDEFINES는 같은 영역을 다른 형태로 보고, OCCURS는 배열을, 88 레벨은 직전 항목의 값에 이름을 붙인 조건을 나타냅니다. COPY 문은 외부의 copybook을 컴파일 시점에 include하므로, 열려 있는 소스만으로는 전체 모습이 보이지 않으며, PERFORM 문과 scope terminator로 처리의 흐름을 따라가고 FILE STATUS나 EXEC SQL, EXEC CICS로 외부 경계를 파악할 필요가 있습니다.

COBOL 읽는 법COBOL이 DATA DIVISION과 PROCEDURE DIVISION을 기둥으로 하고, PICTURE·USAGE·COMP-3·REDEFINES·OCCURS·88 레벨·COPY 문 같은 데이터 정의 요소와, PERFORM 문이나 scope terminator 같은 제어 요소, EBCDIC이나 FILE STATUS·EXEC SQL·EXEC CICS 같은 외부 경계의 요소가 어떻게 관계되는지를 보여주는 그림이용한다이용한다이용한다이용한다이용한다이용한다이용한다이용한다이용한다이용한다이용한다이용한다이용한다이용한다이용한다이용한다이용한다이용한다이용한다이용한다이용한다COBOLDATA DIVISIONCOMP-3(packed decimal)PROCEDURE DIVISIONPICTURE 절(PIC)USAGE 절COMP-5REDEFINES 절OCCURS 절OCCURS DEPENDING ON88레벨(조건명)COPY문copybookPERFORM 문범위 종료자(scope terminator)MOVE 문고정 형식(참조 형식)IBM Enterprise COBOLEBCDICFILE STATUS절EXEC SQLEXEC CICS

그림의 실선은 항상 성립하는 관계, 점선은 조건이 붙는 관계입니다(성립 조건은 상세 페이지의 관계별 설명에 적혀 있습니다). 관계 전체 목록(총 21건, 근거와 확신도 포함)과 주요 개념의 정의는 지식 맵 상세 페이지에 정리되어 있습니다(일본어). 데이터: JSON-LD / Turtle

2. COBOL은 먼저 「데이터의 형태」의 언어라고 본다

C#이나 Java의 감각으로 읽으면, 처음에는 iffor나 함수 호출을 따라가고 싶어집니다. 하지만 COBOL은 그쪽으로 가기 전에 「이 프로그램은 어떤 레코드를 받고, 어떤 레코드를 만들며, 어떤 버퍼를 가지고 있는가」를 잡는 편이 빠릅니다.

전형적인 업무 COBOL은 대체로 다음 흐름입니다.

  1. 파일이나 DB에서 레코드를 읽는다
  2. WORKING-STORAGE 상의 항목으로 넣는다
  3. 조건 분기한다
  4. 다른 레코드로 다시 채운다
  5. 써 낸다

즉, 알고리즘보다 레이아웃이 먼저 서기 쉽습니다.

전형적인 업무 COBOL의 흐름파일이나 DB에서 레코드를 읽고, WORKING-STORAGE 상의 항목으로 넣고, 조건 분기하고, 다른 레코드로 다시 채워 써 낸다는, 전형적인 업무 COBOL의 흐름을 나타내는 그림.레코드를 읽는다WORKING-STORAGE로 넣는다조건 분기한다다른 레코드로 다시 채운다써 낸다

그림2: 주인공은 레코드의 흐름이고, 알고리즘은 그 사이에 끼어듭니다.

예를 들어 이런 골격입니다.

       IDENTIFICATION DIVISION.
       PROGRAM-ID. SAMPLE01.

       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT SALES-FILE ASSIGN TO ...

       DATA DIVISION.
       FILE SECTION.
       FD  SALES-FILE.
       01  SALES-REC.
           05  SALE-ID       PIC 9(8).
           05  SALE-AMOUNT   PIC S9(7)V99 COMP-3.

       WORKING-STORAGE SECTION.
       01  WS-EOF            PIC X VALUE 'N'.
           88  EOF           VALUE 'Y'.

       PROCEDURE DIVISION.
           PERFORM UNTIL EOF
               READ SALES-FILE
                   AT END
                       SET EOF TO TRUE
                   NOT AT END
                       PERFORM PROCESS-SALE
               END-READ
           END-PERFORM
           STOP RUN.

이 코드를 읽을 때, 먼저 봐야 할 것은 PERFORM보다 앞선 SALE-AMOUNT의 형이나 EOF의 의미입니다. COBOL은 그 순서로 읽으면 갑자기 조용해집니다.

3. 4개의 DIVISION을 먼저 본다

COBOL 소스는 먼저 크게 4개의 DIVISION으로 나뉩니다.

DIVISION 먼저 볼 것
IDENTIFICATION DIVISION 프로그램 이름, 오래된 주석, 유래
ENVIRONMENT DIVISION 파일, 외부 자원, 입출력의 전제
DATA DIVISION 레코드 정의, 작업 영역, 인수
PROCEDURE DIVISION 실제 처리 절차

특히 중요한 것은 이 부근입니다.

  • FILE SECTION 입출력 파일의 레코드 정의가 있다
  • WORKING-STORAGE SECTION 평소 쓰는 변수, 플래그, 카운터, 작업 버퍼가 있다
  • LOCAL-STORAGE SECTION 호출마다 초기화되는 영역이 있는 경우가 있다
  • LINKAGE SECTION 밖에서 넘겨받는 인수나, 서브프로그램의 입구가 있는 경우가 있다

LINKAGE SECTIONPROCEDURE DIVISION USING ...이 보이면, 그 프로그램은 단독으로 완결되지 않고, 밖에서 데이터를 받아 동작할 가능성이 높습니다.

LINKAGE SECTION이 가리키는 것LINKAGE SECTION과 PROCEDURE DIVISION USING이 보이면, 그 프로그램은 단독으로 완결되지 않고 밖에서 데이터를 받아 동작할 가능성이 높음을 나타내는 그림.LINKAGE SECTION이 있다밖에서 데이터를 받아 동작할 가능성PROCEDURE DIVISION USING이 있다단독 완결 프로그램이 아니다

그림3: 입구 정의가 보이면, 호출 측이 있다는 전제로 읽습니다.

4. 고정 형식의 겉모습에 겁먹지 않는다

오래된 COBOL에서는 소스 1행의 열 위치 그 자체에 의미가 있습니다. 이를 모른 채로 보면, 「왜 왼쪽에 이상한 여백이 있는지」를 영원히 알 수 없습니다. 1

고정 형식에서는 대략 이렇습니다.

  • 1 - 6열: 일련번호
  • 7열: indicator
  • 8 - 11열: Area A
  • 12 - 72열: Area B

7열은 특히 중요합니다.

  • * 또는 / : 주석 행
  • - : 연속 행
  • D : debugging line
  • *> : 중간에도 쓸 수 있는 주석

열과 내용의 대응을 눈금과 함께 보면 이렇습니다. 1행이 10의 자리, 2행이 1의 자리 눈금입니다.

         1         2         3         4         5         6         7         8
12345678901234567890123456789012345678901234567890123456789012345678901234567890
SSSSSSIAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB........
  • S = 일련번호 (1 - 6열)
  • I = indicator (7열)
  • A = Area A (8 - 11열)
  • B = Area B (12 - 72열)
  • . = 73열 이후. 컴파일러에 따라서는 식별란으로 쓰이지만, 프로그램의 의미에는 관여하지 않습니다

실제 소스에 대입하면 이렇습니다.

000100* 이 행은 7열이 *이므로 주석
000200 IDENTIFICATION DIVISION.
000300 PROGRAM-ID. SAMPLE01.
000400 DATA DIVISION.
000500 WORKING-STORAGE SECTION.
000600 01  WS-ORDER.
000700     05  WS-ORDER-ID    PIC 9(8).
000800     05  WS-LONG-NAME   PIC X(30) VALUE 'ABCDEFGHIJKLMNOPQRST
000900-    'UVWXYZ0123'.

읽는 포인트는 네 가지입니다.

  • 1 - 6열은 일련번호입니다. 위 예에서 000100처럼 붙어 있는 것이 그것이며, 프로그램 동작과는 관계가 없습니다. 공백인 경우도 있습니다.
  • 7열이 indicator입니다. *이면 주석, -이면 연속 행. 위 예의 000900 행이 그것이며, 앞 행 문자열 리터럴의 이어짐입니다.
  • 8 - 11열이 Area A입니다. DIVISION, SECTION, 단락 이름, FD, 그리고 0177의 레벨 번호는 여기서 시작합니다. 위 예의 IDENTIFICATION DIVISION.01 WS-ORDER.가 Area A 시작입니다.
  • 12 - 72열이 Area B입니다. 보통의 문과 05 같은 하위 레벨은 여기에 씁니다. 위 예의 05 WS-ORDER-ID가 Area B 시작입니다.

여기의 공백은 현대적 의미의 「정렬」이 아니라, 부분적으로 구문입니다. 에디터에서 탭 변환을 하거나, 왼쪽으로 붙이거나, 대충 복사해 붙이면 그대로 깨집니다. 오래된 소스를 볼 때는 먼저 그 파일이 fixed format인지 free format인지를 의심하십시오. fixed 형식 소스에 현대적인 자동 정렬을 걸면 Area A와 Area B의 경계가 무너져 컴파일이 통과하지 않습니다.

고정 형식 소스를 만지기 전에오래된 소스에서는 먼저 fixed format인지 free format인지를 확인하고, fixed 형식 소스에 현대적인 자동 정렬이나 탭 변환을 걸면 Area A와 Area B의 경계가 무너져 컴파일이 통과하지 않음을 나타내는 그림.fixed 형식free 형식오래된 소스를 열었다fixed인가 free인가열 위치 그 자체가 구문자동 정렬이나 탭 변환으로 깨진다열 제약은 느슨하다

그림4: 정렬보다 먼저, 그 파일의 형식을 확정합니다.

5. DATA DIVISION의 최소한

5.1 레벨 번호

COBOL의 데이터 정의는 들여쓰기가 아니라 레벨 번호로 계층을 만듭니다. 2

       01  WS-ORDER.
           05  WS-ORDER-ID    PIC 9(8).
           05  WS-AMOUNT      PIC S9(7)V99 COMP-3.
           05  WS-STATUS      PIC X.
               88  WS-OK      VALUE '0'.
               88  WS-ERROR   VALUE '9'.

       77  WS-COUNT           PIC 9(4).

최소한 이것만 기억해 두면 충분합니다.

  • 01 : 한 묶음의 최상위 레코드, 그룹
  • 02 - 49 : 그 아래 계층
  • 77 : 독립된 단일 항목
  • 88 : condition-name. 직전 항목의 값에 이름을 붙인다3
  • 66 : RENAMES용. 만날 확률은 높지 않지만 존재는 한다

중요한 것은 88bool의 별도 변수라고 생각하지 않는 것입니다. WS-OK라는 영역이 따로 있는 것이 아니라, WS-STATUS'0'일 때 WS-OK라는 이름으로 읽을 수 있다는 느낌입니다.

88 레벨의 정체88 레벨은 독립된 bool 변수가 아니라 직전 항목의 값에 이름을 붙인 조건명이며, WS-STATUS가 특정 값일 때 WS-OK라는 이름으로 읽을 수 있을 뿐임을 나타내는 그림.0일 때9일 때기저 항목 WS-STATUS값은 무엇인가WS-OK라는 이름으로 참이 된다WS-ERROR라는 이름으로 참이 된다다른 영역은 존재하지 않는다

그림5: 88은 변수가 아니라, 값에 붙인 읽기 쉬운 별명입니다.

또 하나 중요한 것은, 계층을 정하는 것은 공백이 아니라 레벨 번호라는 점입니다. 겉모습의 들여쓰기는 참고가 되지만, 최종적으로 믿어야 할 것은 01 / 05 / 10 / 88 쪽입니다. 2

5.2 PICTURE

PIC는 그 항목의 형태를 나타냅니다. 가장 자주 보는 것은 이 부근입니다.

표기 대략의 의미
X 문자
9 숫자
S 부호 있음
V 소수점은 논리상으로만 가진다
X(10) 10문자
9(5) 5자리 수치
S9(7)V99 부호 있음, 정수 7자리 + 소수 2자리

예를 들어,

  • PIC X(10) → 10문자
  • PIC 9(5)V99 → 5자리 정수 + 2자리 소수
  • PIC S9(7)V99 → 부호 있는 7자리 정수 + 2자리 소수

입니다.

여기서 특히 중요한 것은 V입니다. V실제 . 문자를 갖지 않습니다. PIC 9(5)V99는 「소수점 2자리의 수」로 다루어지지만, 데이터에 점 문자가 들어 있는 것은 아닙니다. 그래서 파일이나 덤프를 「겉모습의 문자열」로 해석하면 대개 실패합니다.

V는 논리상의 소수점PIC 9(5)V99의 V는 논리상의 소수점이며 실제 점 문자를 갖지 않고, 데이터에 점이 들어 있는 것은 아니므로 파일이나 덤프를 겉모습의 문자열로 해석하면 실패한다는 것을 나타내는 그림.PIC 9(5)V99소수점 2자리의 수로 다룬다데이터에 점 문자는 들어가지 않는다겉모습의 문자열로 해석하면 실패한다

그림6: 소수점은 정의 안에만 있고, 데이터 안에는 없습니다.

5.3 USAGE / DISPLAY / COMP / COMP-3

PIC가 형태라면, USAGE어떤 표현으로 유지할지입니다. 최소한 다음만 잡으면 꽤 읽을 수 있습니다. 45

표기 대략의 의미 읽을 때의 주의
DISPLAY 문자로 보이는 외부 십진 mainframe에서는 EBCDIC 전제인 경우가 있다6
COMP / BINARY 2진수 겉모습의 자리 수와 내부 표현은 별개
COMP-3 / PACKED-DECIMAL packed decimal 문자로 읽으면 깨져 보인다

예를 들어,

       01  WS-AMOUNT-DISP   PIC S9(7)V99.
       01  WS-AMOUNT-BIN    PIC S9(7) COMP.
       01  WS-AMOUNT-PACK   PIC S9(7)V99 COMP-3.

이 셋은 전부 「수치」이지만, 안의 가지는 방식이 다릅니다.

같은 수치라도 가지는 방식이 다르다같은 부호 있는 수치라도 DISPLAY는 문자로 보이는 외부 십진, COMP는 2진수, COMP-3는 packed decimal로, USAGE에 따라 안의 가지는 방식이 다름을 나타내는 그림.같은 형태의 수치 항목DISPLAY〔문자로 보인다〕COMP〔2진수〕COMP-3〔packed decimal〕문자로 읽으면 깨져 보인다

그림7: PIC가 같아도 USAGE가 바뀌면 바이트 열은 다른 것이 됩니다.

실무에서 가장 도움이 되는 것은 COMP-3를 본 순간의 반응입니다.

  • 그것은 packed decimal
  • 아마 금액, 세액, 건수, 레이트 계열
  • 텍스트로 보면 깨져 보이는 것이 정상
  • CSV나 UTF-8 감각으로 보면 사고가 난다

는 이해를 갖고 있으면, 덤프나 바이너리 파일의 보이는 방식 때문에 쓸데없이 당황하지 않아도 됩니다.

COMP-3를 본 순간의 반응COMP-3를 보면 packed decimal이며 아마도 금액이나 세액이나 건수나 레이트 계열 항목이고, 텍스트로 보면 깨져 보이는 것이 정상이므로 CSV나 UTF-8 감각으로 보지 않는다는 반응을 몸에 익히는 것을 나타내는 그림.COMP-3를 찾았다packed decimal임을 안다금액이나 건수 항목을 의심한다텍스트로 깨져 보여도 당황하지 않는다

그림8: 이 반사만으로, 덤프 앞에서 당황하는 횟수가 줄어듭니다.

COMP-3가 실제로 어떤 바이트 열이 되는지

여기는 한 번만 손으로 따라가면, 이후의 보이는 방식이 바뀝니다.

packed decimal의 규칙은 두 가지뿐입니다. 45

  1. 1바이트에 십진 숫자를 2자리씩 넣는다
  2. 다만 가장 오른쪽 바이트만, 하위 1자리와 부호로 1바이트를 쓴다

부호는 4비트 값으로 나타나며, C가 양, D가 음, F가 부호 없음입니다.

IBM 매뉴얼에 실려 있는 예로 확인합니다. 4

정의 바이트 열
PIC S9(4) PACKED-DECIMAL +1234 01 23 4C
PIC S9(4) PACKED-DECIMAL -1234 01 23 4D
PIC 9(4) PACKED-DECIMAL 1234 01 23 4F

1234는 4자리이므로, 규칙 2 때문에 1자리만큼의 빈 칸이 앞에 생깁니다. 그것이 앞의 0입니다.

같은 요령으로, 이 글에 여러 번 나온 PIC S9(7)V99 COMP-3를 따라가 봅니다.

  • S9(7)V99정수 7자리 + 소수 2자리 = 9자리
  • V는 소수점 위치만 나타내므로, 바이트를 하나도 소비하지 않습니다
  • 9자리를 2자리씩 넣으면 4바이트, 나머지 1자리와 부호로 1바이트. 합계 5바이트

값이 +12345.67이면, 9자리에 맞추면 001234567이므로 이렇게 됩니다.

값     : +12345.67
9자리 표현 : 0 0 1 2 3 4 5 6 7  과 부호
바이트  : 00 12 34 56 7C
                        ^ 부호 C = 양

음수 -12345.67이면, 마지막이 7D가 될 뿐입니다.

바이트  : 00 12 34 56 7D

이것을 텍스트로 열면 어떻게 보이는가가 본론입니다. 00 12 34 56 7C를 억지로 1바이트 1문자로 ASCII에 대응시키면,

  • 00은 NUL, 12는 제어 문자라 애초에 문자로 표시할 수 없습니다
  • 344, 56V, 7C|

가 됩니다. 즉 화면상은 「표시할 수 없는 문자가 몇 개 이어진 뒤에 4V|」처럼 보입니다. 12345.67이라는 나열은 어디에도 나타나지 않습니다.

이것이 「문자처럼 깨져 보이지만 깨진 것이 아닌」 정체입니다. 덤프를 열어 의미 없는 나열을 만나면, 먼저 그 항목의 USAGECOMP-3가 아닌지를 의심하십시오.

COMP-3 바이트 열이 만들어지는 방식packed decimal에서는 십진 숫자를 1바이트에 2자리씩 넣고 가장 오른쪽 바이트만 하위 1자리와 부호로 쓰므로, 9자리 수치는 5바이트가 되고 그것을 ASCII로 열어도 원래 수치의 나열은 어디에도 나타나지 않음을 나타내는 그림.십진 숫자를 2자리씩 1바이트로마지막 바이트는 하위 1자리와 부호9자리면 합계 5바이트ASCII로 열면 원래 수치는 나타나지 않는다깨진 문자처럼 보이지만 깨지지 않았다

그림9: 넣는 방식의 규칙 두 가지를 알면, 의미 없는 덤프가 읽을 수 있는 열로 바뀝니다.

덧붙여, 자리 수에서 바이트 수를 내는 한눈에 보는 표도 둡니다. 바이트 수는 「9의 수를 2로 나누어 소수를 버리고, 1을 더한다」로 구합니다.

PICTURE의 9의 수 COMP-3의 바이트 수
1 1
2 - 3 2
4 - 5 3
6 - 7 4
8 - 9 5
10 - 11 6
12 - 13 7

같은 바이트 수에 자리 수가 둘 나란히 있는 것은, 9의 수가 짝수일 때만 선두에 빈 1자리가 생기기 때문입니다. S9(4)01 23 4C의 3바이트가 되고, S9(5)도 같은 3바이트에 들어가는 것은 그 때문입니다.

외부 파일과의 레이아웃 맞춤에서는, 이 표가 없으면 1바이트씩 어긋나 갑니다.

하나 더 보충하면, DISPLAY라고 해서 반드시 ASCII 문자열인 것은 아닙니다. z/OS 계열에서는 EBCDIC이 전제가 되므로, 숫자가 문자로 보여도 바이트 값은 ASCII의 '0' - '9'와 다를 수 있습니다. 6

5.4 REDEFINES / OCCURS / COPY / FILLER

이 넷은 읽을 때 막히는 지점입니다.

REDEFINES

REDEFINES같은 영역을 다른 형태로 보는 장치입니다. 복사가 아닙니다. 7

       01  REC-BUF.
           05  REC-TYPE      PIC X.
           05  REC-DATA      PIC X(99).

       01  HEADER-REC REDEFINES REC-BUF.
           05  HDR-TYPE      PIC X.
           05  HDR-DATE      PIC 9(8).
           05  FILLER        PIC X(91).

이것은 C 계열에서 말하는 union적인 감각에 가깝습니다. 「하나의 100바이트를 다른 레코드 종류로 구분한다」 같은 쓰기 방식에서 자주 나옵니다.

REDEFINES는 같은 영역의 다른 해석REDEFINES는 복사가 아니라 같은 메모리 영역을 다른 형태로 보는 장치이며, 하나의 버퍼를 범용 레코드로도 헤더 레코드로도 읽을 수 있고, 한쪽을 쓰면 다른 쪽의 보이는 방식도 바뀜을 나타내는 그림.하나의 메모리 영역REC-BUF로 본다HEADER-REC로 본다한쪽을 쓰면 양쪽의 보이는 방식이 바뀐다

그림10: 정의가 둘이어도, 실체의 바이트 열은 하나뿐입니다.

OCCURS

OCCURS는 배열입니다. COBOL에서는 table이라고 부르는 경우가 많습니다.

       05  WS-ITEM OCCURS 12 TIMES.
           10  WS-PRICE    PIC 9(5).

여기에 OCCURS DEPENDING ON이 나오면 가변 길이 테이블입니다. 이 경우 후속 항목의 위치까지 영향을 받을 수 있으므로, 고정 길이 감각으로 따라가면 발을 헛디딥니다. 8

OCCURS DEPENDING ON의 주의OCCURS는 배열이며, OCCURS DEPENDING ON이 붙으면 가변 길이 테이블이 되어 후속 항목의 위치까지 값에 따라 움직일 수 있으므로, 고정 길이 감각으로 오프셋을 따라가면 헛디딘다는 것을 나타내는 그림.붙어 있지 않다붙어 있다OCCURS를 찾았다DEPENDING ON이 붙어 있는가고정 횟수의 테이블가변 길이 테이블후속 항목의 위치도 움직일 수 있다

그림11: DEPENDING ON 세 단어로, 오프셋 계산의 전제가 바뀝니다.

COPY

COPY는 compile time의 include입니다. 즉, 지금 연 소스는 아직 완성형이 아닐 수 있습니다. 9

       COPY CUSTOMER-REC.
       COPY ERROR-MAP.

레코드 정의, 공통 플래그, SQL용 host variable, 외부 인터페이스가 copybook에 들어가 있는 것은 꽤 흔합니다.

COPY가 많아서 읽기 어려울 때는 전개 후 소스나 compiler listing을 볼 수 없는지를 확인하는 편이 빠릅니다. IBM Enterprise COBOL에는 MDECK라는, 라이브러리 처리 후 입력 소스를 출력하기 위한 option도 있습니다. 10

COPY가 있는 소스의 읽는 법COPY는 컴파일 시의 include이며 연 소스는 완성형이 아닐 수 있으므로, copybook을 확인하거나 읽기 어려울 때는 전개 후 소스나 compiler listing, MDECK 옵션의 출력을 찾는 것을 나타내는 그림.읽기 어려울 때COPY를 찾았다연 소스는 미완성일 수 있다copybook을 열어 확인전개 후 소스나 listing을 찾는다

그림12: 지금 보이는 행 수가 그 프로그램의 전부는 아닐 수 있습니다.

FILLER

FILLER는 이름 없는 항목입니다. 다만 「참조하지 않으니 무의미」한 것은 아닙니다.

  • 예약 영역
  • 구 사양과의 호환용 구멍
  • 레코드 길이 맞춤
  • REDEFINES용 여백

으로서 실제로 역할을 합니다.

FILLER는 이름이 없을 뿐, 바이트 수로서는 존재합니다. 이것을 잊으면 외부 파일과의 매핑에서 1바이트씩 세계가 어긋나 갑니다.

FILLER를 세는 것을 잊으면 일어나는 일FILLER는 이름이 없을 뿐 바이트 수로서는 존재하고, 예약 영역이나 레코드 길이 맞춤으로 효력이 있으므로, 세는 것을 잊으면 외부 파일과의 매핑이 1바이트씩 어긋난다는 것을 나타내는 그림.넣었다잊었다FILLER는 이름 없는 항목바이트 수로서는 존재한다레이아웃 계산에 넣었는가외부 파일과 일치한다1바이트씩 어긋나 간다

그림13: 참조되지 않는 항목에도, 길이라는 역할이 있습니다.

6. PROCEDURE DIVISION의 최소한

DATA DIVISION이 지도라면, PROCEDURE DIVISION은 이동 경로입니다.

6.1 PERFORM

PERFORM은 COBOL의 기본적인 제어 이동입니다. 거칠게 말하면 처리를 호출하고 돌아온다입니다. 11

자주 보는 형태는 다음입니다.

       PERFORM INIT-PROC
       PERFORM UNTIL EOF
           PERFORM READ-PROC
           IF NOT EOF
               PERFORM EDIT-PROC
               PERFORM WRITE-PROC
           END-IF
       END-PERFORM

PERFORM에는 크게 두 계통이 있습니다.

  • 단락이나 절을 지정하는 out-of-line PERFORM
  • 그 자리에 블록을 쓰는 inline PERFORM ... END-PERFORM

나아가 오래된 코드에서는 PERFORM A-100 THRU A-199처럼 범위 지정도 평범하게 나옵니다. 이것은 편리하지만, 단락을 중간에 넣으면 범위에 의도치 않게 포함되는 사고가 나기 쉬우므로, 읽을 때는 범위의 끝을 제대로 봅니다.

PERFORM의 세 가지 형태PERFORM에는 단락이나 절을 지정해 호출하고 돌아오는 out-of-line과 그 자리에 블록을 쓰는 inline이 있고, 오래된 코드에는 THRU에 의한 범위 지정도 있어 범위 지정은 단락을 중간에 넣으면 범위에 의도치 않게 포함되는 사고가 나기 쉬움을 나타내는 그림.PERFORM을 찾았다단락을 호출하는 out-of-line그 자리에 쓰는 inlineTHRU의 범위 지정범위의 끝을 반드시 확인한다

그림14: 어떤 형태의 PERFORM인지에 따라, 따라가야 할 복귀처와 범위가 바뀝니다.

6.2 IF / EVALUATE / 스코프

조건 분기는 IF가 기본입니다. EVALUATEswitch/case적인 것이라고 생각하면 대체로 맞습니다.

주의해야 할 것은 스코프가 끝나는 방식입니다. 12

  • END-IF
  • END-PERFORM
  • END-READ

같은 명시적 종결이 있는 코드는 그래도 읽기 쉽습니다.

문제는 오래된 코드입니다. COBOL에서는 .암시적 scope terminator로 동작하며, 아직 닫히지 않은 문을 한꺼번에 끝냅니다. 12

즉, 마침표 하나면,

  • 어디까지가 IF인지
  • 어디까지가 PERFORM인지
  • 어디서 다음 sentence로 넘어가는지

가 바뀝니다.

나아가 NEXT SENTENCECONTINUE와 같지 않습니다. NEXT SENTENCE다음 마침표 뒤로 진행하므로, 후속 .의 위치에 따라 점프처가 바뀝니다. 12

오래된 COBOL을 읽을 때는 행 끝이 아니라 마침표를 본다 정도로 딱 맞습니다.

마침표의 무게END-IF 같은 명시적 종결이 있는 코드는 읽기 쉽지만, 오래된 코드에서는 마침표가 암시적 scope terminator로 동작해 아직 닫히지 않은 문을 한꺼번에 끝내므로, 마침표 하나로 IF나 PERFORM의 범위가 바뀜을 나타내는 그림.END-IF 등이 있다없는 오래된 코드명시적 종결은 있는가범위를 읽기 쉽다마침표가 암시적 종결하나 위치로 범위가 바뀐다행 끝이 아니라 마침표를 본다

그림15: 오래된 코드의 제어 흐름은 마침표 위치가 쥐고 있습니다.

6.3 READ / WRITE / CALL

업무 COBOL에서 자주 나오는 것은 이 부근입니다.

  • READ
  • WRITE
  • REWRITE
  • START
  • CALL

특히 READ ... AT END ...는 왕도입니다.

       READ IN-FILE
           AT END
               SET EOF TO TRUE
           NOT AT END
               PERFORM PROCESS-REC
       END-READ

CALL 'SUBPGM' USING ...이 있으면 다른 프로그램으로 점프합니다. 그때는 호출되는 쪽의 LINKAGE SECTIONPROCEDURE DIVISION USING을 보면, 주고받는 형태가 꽤 보입니다.

CALL을 찾았을 때의 따라가는 법CALL이 있으면 다른 프로그램으로 점프하므로, 호출되는 쪽의 LINKAGE SECTION과 PROCEDURE DIVISION USING을 보면 인수의 주고받는 형태가 보임을 나타내는 그림.CALL을 찾았다다른 프로그램으로 점프한다호출되는 쪽의 LINKAGE SECTION을 본다USING으로 주고받는 형태를 잡는다

그림16: 호출의 의미는, 호출되는 쪽의 입구와 세트로 읽습니다.

7. COBOL의 바깥에 있는 것

COBOL은 소스만으로 세계가 완결되지 않는 경우가 꽤 있습니다.

  • 파일 정의
  • 실행 환경
  • DB 연결
  • 트랜잭션 환경
  • job 제어

가 바깥에 나뉘어 있기 때문입니다.

최소한 다음은 잡으면 읽기 쉬워집니다.

파일과 FILE STATUS

ENVIRONMENT DIVISIONFILE-CONTROL과, DATA DIVISIONFILE SECTION / FD는 세트로 읽습니다. 13

       SELECT IN-FILE ASSIGN TO ...
           FILE STATUS IS WS-FS.

       FD  IN-FILE.
       01  IN-REC.
           05 ...

FILE STATUS가 있으면 각 I/O 후의 결과 코드가 들어갑니다. 파일 계열의 장애나 EOF 판정을 읽을 때는, 이것을 보지 않으면 시작되지 않습니다. 14

파일 정의는 세트로 읽는다ENVIRONMENT DIVISION의 FILE-CONTROL에 있는 SELECT와 DATA DIVISION의 FD는 세트로 읽고, FILE STATUS가 있으면 각 입출력 후 결과 코드가 들어가므로, 파일 계열의 장애나 EOF 판정은 여기서부터 읽는다는 것을 나타내는 그림.FILE-CONTROL의 SELECT세트로 하나의 파일 정의FILE SECTION의 FDFILE STATUS에 결과 코드가 들어간다장애와 EOF 판정 독해의 출발점

그림17: 파일의 모습은 두 DIVISION에 나뉘어 쓰여 있습니다.

EXEC SQL

이것이 나오면 임베디드 SQL입니다.

       EXEC SQL
           SELECT ...
       END-EXEC.

이 경우 COBOL은 「호스트 변수의 그릇」이고, 실제 취득 조건이나 갱신 대상은 SQL 쪽에 있습니다. 그래서 EXEC SQL의 내용을 보통 SQL로 읽는 것이 지름길입니다.

EXEC CICS

이것이 나오면 CICS의 트랜잭션 맥락입니다. 15

       EXEC CICS
           RECEIVE MAP(...)
       END-EXEC.

이 순간, 단순한 배치 독해가 아니게 됩니다. 화면, 트랜잭션, 응답 코드, COMMAREA 등, 외부 맥락을 포함해 읽을 필요가 있습니다.

JCL이나 실행 정의

mainframe batch에서는 실제로 어떤 데이터셋이 할당되는지어떤 순서로 job이 흐르는지가 COBOL 소스 바깥에 있는 것도 드물지 않습니다. 소스만 보고 「이 파일은 어디에 있는지」를 모를 때는, 코드가 나쁜 것이 아니라 보고 있는 범위가 아직 부족한 것뿐인 경우가 흔합니다.

소스 바깥에 있는 세계EXEC SQL이 나오면 실제 취득 조건은 SQL 쪽에, EXEC CICS가 나오면 화면이나 트랜잭션 등의 외부 맥락에, mainframe batch에서는 데이터셋 할당이나 job의 흐름이 JCL에, COBOL 소스 바깥에 세계가 나뉘어 있음을 나타내는 그림.EXEC SQL소스 바깥도 본다EXEC CICSJCL이나 실행 정의SQL의 조건·화면 맥락·job의 흐름

그림18: 모르는 것은 코드 탓이 아니라, 보고 있는 범위가 좁을 뿐인 경우가 있습니다.

컴파일러의 차이

이 글은 IBM 계열을 염두에 두고 쓰였지만, 실무에서는 Micro Focus나 Linux / Windows 위의 COBOL을 만나는 일도 있습니다. 골격은 공통이므로 읽는 법은 바뀌지 않지만, 「같은 쓰기 방식인데 결과가 다른」 포인트는 정해져 있으므로, 먼저 파악해 두면 사고가 나지 않습니다.

볼 곳 z/OS 계열(IBM Enterprise COBOL) 오픈 계열(Micro Focus, Linux / Windows 판 등)
문자 코드 EBCDIC이 전제6 ASCII가 전제6
참조 형식 fixed 형식이 전통적인 기본값. free 형식도 고를 수 있다1 fixed와 free를 모두 가지며, 기본값이 어느 쪽인지는 빌드 설정 나름1
copybook을 찾는 법 라이브러리 지정 컴파일러 옵션으로 검색 경로 지정
방언 「어느 컴파일러에 맞출지」를 바꾸는 옵션이 있다

특히 바로 효과가 있는 것이 문자 코드입니다. 같은 PIC X(10)이라도, z/OS에서 쓴 파일을 그대로 Windows 쪽에서 읽으면 숫자조차 다른 바이트 값이 됩니다. 「옮겨 왔더니 전부 깨졌다」의 상당수는 이것이며, COMP-3 이야기와는 다른 문제입니다.

하나 더, 수치의 내부 표현에도 차이가 나기 쉬운 곳이 있습니다. IBM Enterprise COBOL에서는 BINARY / COMP-4PICTURE에 쓴 자리 수에서 잘림이 일어나는 반면, COMP-52 / 4 / 8바이트라는 네이티브 2진수의 용량까지 값을 가지며, 잘림도 바이너리 크기 쪽에서 일어납니다. 16PIC S9(4) COMPPIC S9(4) COMP-5는 같아 보여도 들어가는 값의 상한이 다릅니다. 다른 시스템과 2진수 그대로 값을 주고받는 코드에서 COMP-5가 나오면, 일부러 그렇게 써 있는 것으로 생각하고 읽으십시오.

자기 환경과 대조할 때의 최단 절차는 이렇습니다.

  1. 빌드 정의(makefile, JCL, 프로젝트 설정)를 먼저 연다. 어느 컴파일러의, 어느 옵션으로 컴파일되고 있는지가 소스보다 먼저 보입니다.
  2. 참조 형식(fixed / free)을 확정한다. 여기를 틀린 채로 에디터에서 정렬하면 깨집니다.
  3. 문자 코드를 확정한다. EBCDIC인지 ASCII인지에 따라 덤프 읽는 법이 바뀝니다.
  4. COMP 계열 항목에 표시를 붙인다. 컴파일러 차이가 나는 곳은 거의 여기입니다.
자기 환경과 대조하는 최단 절차빌드 정의를 먼저 열어 어느 컴파일러와 옵션인지 확인하고, 참조 형식의 fixed인지 free인지를 확정하고, 문자 코드가 EBCDIC인지 ASCII인지를 확정하고, 컴파일러 차이가 나기 쉬운 COMP 계열 항목에 표시를 붙인다는 절차를 나타내는 그림.빌드 정의를 먼저 연다참조 형식을 확정한다문자 코드를 확정한다COMP 계열 항목에 표시를 붙인다

그림19: 소스를 읽기 전의 네 단계로, 컴파일러 차이의 사고를 막을 수 있습니다.

8. 최소한의 읽기 순서

갑자기 COBOL을 읽게 되었을 때는, 다음 순서가 안전합니다.

  1. COPY를 전부 훑는다 copybook을 열 수 있으면 연다. 안 되면 listing이나 전개 후 소스를 찾는다
  2. 01 레벨의 레코드 정의를 집어낸다 FILE SECTION, WORKING-STORAGE, LINKAGE SECTION의 최상위를 목록화한다
  3. PICUSAGE를 읽는다 금액, 날짜, 건수, 코드, 플래그를 식별한다
  4. READ / WRITE / REWRITE / CALL / EXEC SQL / EXEC CICS를 검색한다 입출력과 외부 경계를 먼저 잡는다
  5. 처음의 주 경로만 따라간다 PROCEDURE DIVISION의 선두부터 PERFORM 연쇄를 따라간다
  6. 88과 status 항목을 본다 EOF, 정상/이상, 종류 코드의 의미가 읽기 쉬워진다
  7. REDEFINES / OCCURS DEPENDING ON / COMP-3에 표시를 붙인다 나중에 반드시 쓰이므로, 먼저 위험물로 표시해 둔다
  8. 파일이면 FILE STATUS를 본다 I/O 오류 계열의 오독을 꽤 줄일 수 있다

이 순서면 갑자기 전문을 정독하지 않아도 됩니다. COBOL은 처음부터 100% 이해하려 하기보다, 레코드, 외부 경계, 주 경로의 세 점을 잡은 뒤 세부로 가는 편이 훨씬 편합니다.

안전한 읽기 순서COPY를 훑어 copybook을 확인하고, 01 레벨의 레코드 정의를 목록화하고, PIC와 USAGE로 항목의 형태를 읽고, 입출력과 외부 경계를 검색으로 잡은 다음, PROCEDURE DIVISION 선두의 PERFORM 연쇄로 주 경로를 따라가며 위험물에 표시를 붙인다는 읽기 순서를 나타내는 그림.COPY를 전부 훑는다01 레벨을 목록화한다PIC와 USAGE로 형태를 읽는다입출력과 외부 경계를 검색한다주 경로의 PERFORM 연쇄를 따라간다위험물에 표시를 붙여 둔다

그림20: 전문 정독이 아니라, 이 순서로 바깥부터 채워 갑니다.

8.1 연습: 이 레코드 정의를 읽어 보기

읽는 법 설명만으로는 자리 잡지 않으므로, 작은 레코드를 하나 둡니다. 먼저 스스로 답을 낸 다음 아래 해답을 보십시오.

       01  CUST-REC.
           05  CUST-ID          PIC X(8).
           05  CUST-NAME        PIC X(20).
           05  CUST-KBN         PIC X.
               88  CUST-NORMAL  VALUE '0'.
               88  CUST-VIP     VALUE '1'.
           05  CUST-BALANCE     PIC S9(7)V99 COMP-3.
           05  CUST-HIST OCCURS 3 TIMES.
               10  HIST-DATE    PIC 9(8).
               10  HIST-AMOUNT  PIC S9(5)V99 COMP-3.
           05  FILLER           PIC X(4).

문항

  1. CUST-REC는 전체로 몇 바이트입니까.
  2. CUST-BALANCE는, 레코드 선두부터 세어 몇 바이트째부터 시작합니까.
  3. 2건째의 HIST-AMOUNT는, 선두부터 몇 바이트째부터 시작합니까.
  4. CUST-KBN'1'이 들어 있을 때, 참이 되는 조건명은 무엇입니까.
  5. 이 파일을 텍스트 에디터로 열었을 때, 깨져 보이는 것은 어느 항목입니까.
  6. 이 정의만으로는 알 수 없는 것을 두 가지 들어 주십시오.

해답

  1. 74바이트입니다. 내역은 이렇습니다.

    항목 계산 바이트 수
    CUST-ID X(8) 8
    CUST-NAME X(20) 20
    CUST-KBN X 1
    CUST-BALANCE 9자리의 COMP-3 5
    CUST-HIST (8 + 4) × 3회 36
    FILLER X(4) 4
    합계   74

    88 레벨은 조건명이므로 바이트를 소비하지 않습니다. 여기를 세는 것이 흔한 실수입니다. FILLER는 이름이 없을 뿐, 4바이트는 분명히 존재합니다.

  2. 30바이트째부터입니다. 앞에 8 + 20 + 1 = 29바이트가 있으므로, 그다음부터 시작합니다.

  3. 55바이트째부터입니다. CUST-HIST가 시작하는 것은 35바이트째이고, 1건이 12바이트이므로, 1건째는 35 - 46바이트, 2건째는 47 - 58바이트. 그중 선두 8바이트가 HIST-DATE이므로, HIST-AMOUNT는 55바이트째부터입니다.

  4. CUST-VIP입니다. CUST-VIP라는 영역이 따로 있는 것이 아니라, CUST-KBN'1'일 때 그 이름으로 읽을 수 있을 뿐입니다.

  5. CUST-BALANCEHIST-AMOUNT입니다. 둘 다 COMP-3이므로, 문자로 읽으면 의미 없는 나열이 됩니다. HIST-DATEPIC 9(8)DISPLAY이므로, ASCII 환경이면 20260317처럼 숫자로 읽을 수 있습니다. 다만 EBCDIC 환경에서는 숫자로 보여도 바이트 값은 ASCII와 다릅니다.

  6. 예를 들어 다음과 같은 것입니다.

    • 이 정의 자체가 COPY로 들어와 있는지. copybook 쪽을 보지 않으면, 실제로 쓰이는 판인지 알 수 없습니다.
    • 파일의 문자 코드가 EBCDIC인지 ASCII인지. PIC XPIC 9 DISPLAY의 보이는 방식이 바뀝니다.
    • CUST-KBN'0''1' 이외가 들어오는 운용이 있는지. 조건명은 둘만 정의되어 있지만, 그 외의 값이 오지 않는다는 보증은 되지 않습니다.
    • 파일 자체의 속성(레코드 길이, 가변 길이 여부, FILE STATUS). 이것은 ENVIRONMENT DIVISIONFD를 보지 않으면 알 수 없습니다.

문항 1과 3을 틀렸다면, 5.3의 자리 수와 바이트 수 표로 돌아가십시오. COBOL의 오독은 대개 여기서 시작됩니다.

9. 자주 막히는 지점

마지막으로, 초보자가 꽤 높은 확률로 걸리는 곳을 정리합니다.

REDEFINES를 「다른 변수」라고 생각한다

아닙니다. 같은 영역을 다른 형태로 읽고 있습니다. 한쪽을 바꾸면, 다른 쪽의 보이는 방식도 바뀝니다. 7

88을 「독립된 bool」이라고 생각한다

아닙니다. 직전 항목의 값에 이름이 붙어 있을 뿐입니다. SET WS-OK TO TRUE는 실제로는 기저 항목에 대응 값을 넣습니다. 3

COPY를 무시하고 본문만 읽는다

연 파일은 아직 전체의 절반입니다. 필드 정의, 공통 플래그, host variable이 한꺼번에 바깥에 있는 것은 흔합니다. 9

MOVE를 단순 대입이라고 생각한다

MOVE는 단순한 memcpy가 아닙니다. 받는 쪽의 형에 따라 변환, 자리 맞춤, 제로 채움, 잘라 내기, 편집·역편집이 들어갈 수 있습니다. 17

.의 영향을 가볍게 본다

COBOL의 .은 상상보다 무겁습니다. 명시 종결이 없는 오래된 코드에서는, 이 마침표가 어디까지 닫히는지를 잘못 보면 제어 흐름을 오독합니다. 12

packed decimal이나 EBCDIC을 「깨진 문자」라고 생각한다

깨져 있다고 단정할 수는 없습니다. 처음부터 문자열이 아니거나, ASCII가 아닐 뿐인 경우가 꽤 있습니다. 46

OCCURS DEPENDING ON의 뒤를 고정 위치라고 생각한다

가변 길이 테이블의 후속 항목은 값에 따라 위치가 움직일 수 있습니다. 고정 길이라는 전제로 읽으면 오프셋 계산이 전부 어긋납니다. 8

10. 바로 보는 표

찾은 말 먼저 생각할 것
01 레코드나 그룹의 최상위. 여기서부터 전체 모습을 잡는다
88 플래그나 상태 코드의 의미 이름. 분기를 읽는 열쇠
PIC X(...) 문자 항목
PIC 9(...) / S9(...)V... 수치 항목. 자리 수와 소수 위치를 확인
COMP binary
COMP-3 packed decimal. 금액·건수일 가능성이 높다
REDEFINES 같은 영역을 다른 해석으로 보고 있다
OCCURS 배열·table
OCCURS DEPENDING ON 가변 길이. 후속 위치에도 주의
FILLER 이름은 없지만 길이는 있다
COPY copybook을 보지 않으면 완성형이 보이지 않는다
PERFORM 주 경로의 골격
READ / WRITE / REWRITE 파일 I/O
EXEC SQL DB 처리
EXEC CICS 트랜잭션 처리
FILE STATUS I/O의 결과 코드

11. 정리

COBOL은 오래되어서 어려운 것이 아닙니다. 데이터 정의, 외부 파일, 실행 맥락이 밀접하게 묶여 있어 처음 입구가 보이기 어려울 뿐입니다.

읽기 위한 최소 세트를 다시 정리하면 이렇습니다.

  • DIVISION으로 지도를 잡는다
  • DATA DIVISION을 먼저 읽는다
  • PICUSAGE로 항목의 형태를 읽는다
  • COMP-3, REDEFINES, OCCURS, 88, COPY에 표시를 붙인다
  • PERFORM, READ, WRITE, CALL을 따라간다
  • FILE STATUS, EXEC SQL, EXEC CICS로 외부 경계를 잡는다
  • .의 효력을 가볍게 보지 않는다

여기가 보이면 COBOL은 「수수께끼의 고대 마법」에서 「레코드 처리의 언어」로 바뀝니다. 레거시 기술은 이름이 오래되어 무서운 것이 아니라, 처음에 보는 축척을 잘못 잡으면 갑자기 알기 어려워질 뿐입니다. 지도의 축척이 맞으면 의외로 평범하게 읽을 수 있습니다.

축척을 맞춰 읽는다DIVISION으로 지도를 잡고, DATA DIVISION을 먼저 읽어 항목의 형태를 잡고, PERFORM이나 READ 등으로 흐름을 따라가며, FILE STATUS나 EXEC SQL이나 EXEC CICS로 외부 경계를 잡는 순서로 축척을 맞추면 COBOL은 레코드 처리의 언어로서 평범하게 읽을 수 있음을 나타내는 그림.DIVISION으로 지도를 잡는다DATA DIVISION으로 형태를 읽는다PERFORM과 입출력으로 흐름을 따라간다외부 경계를 잡는다수수께끼의 고대 마법이 레코드 처리의 언어가 된다

그림21: 어려움의 정체는 언어가 오래되었다는 점이 아니라, 처음 축척을 고르는 방식입니다.

12. 참고 자료

본문의 주요 참조처입니다. 본문의 위첨자 번호가 그대로 이 목록으로의 링크가 되어 있고, 각 항목 끝의 화살표에서 원래 위치로 돌아갈 수 있습니다.

같은 태그를 공유하는 최신 기사입니다. 더 가까운 주제로 지식을 넓힐 수 있습니다.

이 기사와 가까운 토픽 페이지입니다. 기사를 출발점 삼아 관련 서비스와 다른 기사로 이어집니다.

ActiveX 이관

COM / ActiveX / OCX 자산을 유지할지, 감쌀지, 교체할지의 단계적 판단을 정리한 토픽 페이지입니다.

이 기사는 다음 서비스 페이지로 이어집니다. 가까운 입구부터 확인해 주세요.

자주 묻는 질문

이 기사 주제에 대해 상담 시 자주 나오는 질문을 모았습니다.

COBOL 소스는 어디서부터 읽기 시작하면 되나요?
PROCEDURE DIVISION만 읽어서는 절반밖에 파악하지 못합니다. COBOL은 로직의 언어이기 전에 레코드 정의를 상당히 강하게 다루는 언어이므로, 먼저 DATA DIVISION을 봅니다. 안전한 읽기 순서는 COPY를 전부 훑어 copybook을 확인하고, 01 레벨의 레코드 정의를 목록화하고, PIC와 USAGE로 항목의 형태를 읽고, READ·WRITE·CALL·EXEC SQL·EXEC CICS를 검색해 입출력과 외부 경계를 잡은 다음, PROCEDURE DIVISION 선두의 PERFORM 연쇄로 주 경로만 따라가는 흐름입니다.
PIC S9(7)V99 COMP-3는 무슨 뜻인가요?
PIC는 항목의 형태, USAGE는 어떤 표현으로 유지할지를 나타냅니다. S9(7)V99는 부호 있는 정수 7자리+소수 2자리 숫자이지만, V는 논리상의 소수점이며 데이터에 점 문자가 들어 있는 것은 아닙니다. COMP-3는 packed decimal이며, 금액·세액·건수·레이트 계열 항목에서 자주 나옵니다. 텍스트로 보면 깨져 보이는 것이 정상이므로, CSV나 UTF-8 감각으로 덤프를 보면 사고가 납니다.
COBOL의 88 레벨이나 REDEFINES는 어떻게 이해하면 되나요?
88은 독립된 bool 변수가 아니라, 직전 항목의 값에 이름을 붙인 조건명(condition-name)입니다. SET WS-OK TO TRUE는 실제로는 기저 항목에 대응하는 값을 넣습니다. REDEFINES는 같은 메모리 영역을 다른 형태로 보는 장치이며, 복사가 아니라 C 계열의 union에 가까운 감각입니다. 한쪽을 바꾸면 다른 쪽의 보이는 방식도 바뀌므로, 하나의 영역을 레코드 종류마다 구분하는 쓰기 방식에서 자주 나옵니다.
COPY 문이 많아서 전체가 보이지 않을 때는 어떻게 하면 되나요?
COPY는 컴파일 시의 include이므로, 지금 연 소스는 아직 완성형이 아닐 수 있습니다. 레코드 정의, 공통 플래그, SQL용 host variable, 외부 인터페이스가 copybook에 들어가 있는 것은 꽤 흔합니다. 읽기 어려울 때는 전개 후 소스나 compiler listing을 볼 수 있는지 확인하는 편이 빠르고, IBM Enterprise COBOL에는 라이브러리 처리 후 입력 소스를 출력하는 MDECK 옵션도 있습니다.

저자 프로필

기사 저자의 프로필 페이지입니다.

Go Komura

합동회사 코무라소프트 대표

Windows 소프트웨어 개발, 기술 상담, 장애 조사를 중심으로 재현이 어려운 장애 조사와 기존 자산이 남아 있는 프로젝트에 강점이 있습니다.

블로그 목록으로 돌아가기