Devin.KR

COBOL · 기본

데이터 처리로 배우는 COBOL

문자열 처리 - STRING·UNSTRING·INSPECT

STRING DELIMITED BY, UNSTRING 으로 나누기, INSPECT TALLYING·REPLACING, 참조 수정(항목(시작:길이)), 내장 함수 FUNCTION TRIM·UPPER-CASE

개발자KR · 원고 갱신

이 장에서 배우는 것

지금까지 만든 프로그램은 숫자와 고정 길이 코드를 주로 다뤘다. 실무 입력에는 글자가 섞인 한 줄짜리 텍스트도 많다. 창구에서 올라온 메모, 쉼표로 나뉜 전송 데이터, 소문자와 대문자가 섞인 이름이 그런 예다. 이 장은 글자 데이터를 쪼개고, 고치고, 다시 붙이는 도구를 다룬다. 마지막에는 거래 한 줄을 읽어 보고서용 한 줄로 바꾸는 프로그램을 만든다.

  • STRING 으로 여러 조각을 하나의 항목에 이어 붙이고, 끝 위치를 포인터로 알아낸다.
  • UNSTRING 으로 구분자 기준으로 한 줄을 여러 항목에 나누고, 몇 개가 채워졌는지 센다.
  • INSPECT 로 특정 글자를 세고(TALLYING) 바꾼다(REPLACING).
  • 참조 수정(reference modification)으로 항목의 일부분만 읽고 쓴다.
  • FUNCTION TRIM 과 FUNCTION UPPER-CASE 로 공백을 정리하고 대문자로 통일한다.

문제 상황

조합의 지점 창구에서 하루 거래 내역을 텍스트 한 줄씩 올려 보낸다고 하자. 한 줄은 이름, 계좌번호, 거래 종류, 금액을 쉼표로 이어 놓은 모양이다.

kim minsu,110-2345-01,DEP,00150000
  park jiho ,110-7788-02,WDR,00045000
choi,330-4500-01

이 줄에는 다루기 까다로운 점이 여럿 있다.

  • 이름이 소문자이고, 어떤 줄은 앞뒤에 공백이 붙어 있다.
  • 금액은 앞에 0이 채워진 여덟 자리 글자다.
  • 계좌번호 맨 앞 세 자리는 지점 코드다. 보고서에는 계좌번호를 가려서 찍어야 한다.
  • 세 번째 줄처럼 항목이 모자란 줄이 섞여 들어오기도 한다.

목표는 이런 줄을 KIM MINSU [********-01] DEPOSIT 150000 같은 보고서용 한 줄로 바꾸는 것이다. 모자란 줄은 걸러서 건너뛴다. 한 줄 안의 글자를 나누고, 세고, 바꾸고, 붙이는 일을 모두 해야 한다.

STRING 으로 이어 붙이기

STRING 은 보내는 조각들을 받는 항목 하나에 차례로 이어 붙인다. 각 조각 뒤에는 DELIMITED BY 로 어디까지 보낼지 적는다.

STRING 조각1 DELIMITED BY SIZE
       조각2 DELIMITED BY SPACE
       INTO 받는항목
       WITH POINTER 위치
       ON OVERFLOW 문장
END-STRING
  • DELIMITED BY SIZE는 조각 전체를 보낸다.
  • DELIMITED BY SPACE는 첫 공백 앞까지만 보낸다. 이름 속 공백에서 잘리므로 "KIM MINSU" 같은 값에는 쓰면 안 된다.
  • WITH POINTER의 변수는 다음에 쓸 칸의 번호다. 1 로 시작하고, 조각을 하나 쓸 때마다 늘어난다. 모든 조각을 붙인 뒤 이 값에서 1 을 빼면 실제로 쓴 길이다.
  • ON OVERFLOW는 받는 항목이 모자라 다 붙이지 못했을 때 실행할 문장이다.

STRING 은 받는 항목을 지우지 않는다. 쓴 칸만 덮어쓰고 나머지는 이전 내용 그대로 둔다. 그래서 STRING 앞에서 받는 항목을 공백으로 채우고 포인터를 1 로 두는 것이 습관이 되어야 한다. 아래 그림은 완성 코드의 STRING 이 레이블을 채우는 모습이다.

STRING 은 조각을 앞에서부터 차례로 쓰고 포인터는 마지막에 쓴 칸의 다음 번호인 39 에서 멈춘다

그림의 ·는 공백 한 칸이다. 칸 위아래 숫자는 그 조각을 쓰기 직전의 포인터 값이다.

글자 수는 바이트로 센다

GnuCOBOL 3.2 에서 PIC X(10) 은 열 글자가 아니라 10 바이트다. 한글은 UTF-8 에서 한 글자가 3 바이트라서, 한글 이름을 다루려면 칸을 넉넉히 잡고 잘리지 않는지 확인해야 한다. 이 장의 예제는 영문 이름으로 구성했다.

UNSTRING 으로 나누기

UNSTRING 은 STRING 의 반대 방향이다. 한 항목을 구분자 기준으로 잘라 여러 항목에 나누어 담는다.

UNSTRING 원본 DELIMITED BY ","
    INTO 항목1 COUNT IN 길이1
         항목2
         항목3
    TALLYING IN 개수
END-UNSTRING
  • COUNT IN은 그 항목에 옮겨진 글자 수를 길이 변수에 담는다.
  • TALLYING IN은 값이 들어간 받는 항목의 수를 더한다. 입력 줄에 항목이 몇 개 있었는지 알 수 있다.
  • 구분자가 연달아 나올 때 하나로 취급하려면 DELIMITED BY ALL "," 로 쓴다.

UNSTRING 이 건드리는 것은 값을 받은 항목뿐이다. 줄이 짧아서 끝까지 가지 못하면 남은 항목은 이전 값 그대로다. TALLYING 변수도 0 으로 되돌려 주지 않고 더하기만 한다. 두 가지 모두 UNSTRING 앞에서 직접 초기화해야 한다.

UNSTRING 은 쉼표를 경계로 원본을 네 조각으로 나누고 쉼표 자체는 어느 항목에도 넣지 않는다

INSPECT 로 세고 바꾸기

INSPECT 는 항목의 글자를 훑으면서 세거나(TALLYING) 바꾼다(REPLACING). 항목 자체를 늘리거나 줄이지는 않는다.

INSPECT 의 주요 형태와 뜻
형태뜻예
TALLYING ... FOR ALL "-"모든 하이픈의 개수를 센다계좌번호의 구분 기호 수
TALLYING ... FOR CHARACTERS BEFORE INITIAL "-"첫 하이픈 앞의 글자 수를 센다지점 코드의 길이
REPLACING LEADING "0" BY SPACE맨 앞에 연속된 0 만 공백으로 바꾼다금액 앞의 채움 0 제거
REPLACING ALL "-" BY "."모든 하이픈을 마침표로 바꾼다표기 통일

REPLACING 에서 바꾸기 전과 후의 글자 수는 같아야 한다. 글자를 지워서 줄이는 용도로는 쓸 수 없다. 앞의 0 을 지울 때도 지우는 대신 공백으로 바꾸고, 뒤에 FUNCTION TRIM 으로 공백을 정리한다. TALLYING 의 카운터는 INSPECT 도 초기화해 주지 않으므로 앞에서 0 으로 만들어 둔다.

참조 수정과 내장 함수

참조 수정

항목 이름 뒤에 (시작:길이)를 붙이면 그 항목의 일부분만 가리킨다. 시작은 1 부터 센다. 길이를 생략하면 시작 위치부터 끝까지다.

WS-ACCT(1:3)     *> 계좌번호 맨 앞 3글자
WS-ACCT(5:)      *> 5번째부터 끝까지
MOVE ALL "*" TO WS-MASKED(1:8)

마지막 줄처럼 쓰기 대상에도 쓸 수 있다. 시작과 길이는 변수여도 된다. 범위를 벗어났는지는 기본 설정에서 검사하지 않는다. 컴파일할 때 cobc 에 -debug 를 더하면 실행 중 검사하고 멈춘다.

FUNCTION TRIM 과 UPPER-CASE

내장 함수(intrinsic function)는 FUNCTION 이라는 예약어로 호출하는, 값을 돌려주는 기능이다.

이 장에서 쓰는 내장 함수
함수하는 일비고
FUNCTION TRIM(항목)앞뒤 공백을 뗀 글자를 돌려준다LEADING 이나 TRAILING 을 붙이면 한쪽만 뗀다
FUNCTION UPPER-CASE(항목)영문 소문자를 대문자로 바꿔 돌려준다원래 항목은 바뀌지 않는다
FUNCTION LENGTH(값)글자 수(바이트)를 돌려준다TRIM 결과에 쓰면 공백을 뗀 길이다

함수는 MOVE 의 보내는 쪽, STRING 의 조각, COMPUTE 의 식에 쓸 수 있고 서로 겹쳐서 쓸 수도 있다. 완성 코드의 FUNCTION UPPER-CASE(FUNCTION TRIM(...)) 는 공백을 먼저 떼고 그 결과를 대문자로 바꾼다.

완성 코드

입력은 프로그램 안에서 네 줄을 직접 채워 넣는다. 파일 읽기는 앞 장들의 주제이므로 여기서는 문자열 처리에만 집중한다. 줄마다 UNSTRING 으로 나누고, INSPECT 로 세고 바꾸고, STRING 으로 레이블을 만든다.

main.cob

       IDENTIFICATION DIVISION.
       PROGRAM-ID. MAIN.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  WS-RAW-TABLE.
           05  WS-RAW-LINE      PIC X(40) OCCURS 4 TIMES.
       01  WS-IDX               PIC 9     VALUE 0.
       01  WS-FIELD-CNT         PIC 9     VALUE 0.
       01  WS-OK-CNT            PIC 9     VALUE 0.
       01  WS-BAD-CNT           PIC 9     VALUE 0.
       01  WS-NAME-RAW          PIC X(20).
       01  WS-ACCT              PIC X(12).
       01  WS-TYPE              PIC X(3).
       01  WS-AMT               PIC X(20).
       01  WS-NAME-LEN          PIC 99    VALUE 0.
       01  WS-TRIM-LEN          PIC 99    VALUE 0.
       01  WS-HYPHENS           PIC 9     VALUE 0.
       01  WS-BR-LEN            PIC 99    VALUE 0.
       01  WS-NAME-CLEAN        PIC X(20).
       01  WS-MASKED            PIC X(12).
       01  WS-KIND              PIC X(8).
       01  WS-LABEL             PIC X(60).
       01  WS-PTR               PIC 99    VALUE 1.
       01  WS-USED              PIC 99    VALUE 0.
       PROCEDURE DIVISION.
       MAIN-PARA.
           PERFORM LOAD-DATA
           PERFORM VARYING WS-IDX FROM 1 BY 1 UNTIL WS-IDX > 4
               PERFORM PARSE-LINE
           END-PERFORM
           DISPLAY "PROCESSED " WS-OK-CNT " SKIPPED " WS-BAD-CNT
           STOP RUN.

       LOAD-DATA.
           MOVE "kim minsu,110-2345-01,DEP,00150000"
               TO WS-RAW-LINE(1)
           MOVE "  park jiho ,110-7788-02,WDR,00045000"
               TO WS-RAW-LINE(2)
           MOVE "lee seoyeon,220-1002-03,DEP,03200000"
               TO WS-RAW-LINE(3)
           MOVE "choi,330-4500-01"
               TO WS-RAW-LINE(4).

       PARSE-LINE.
           MOVE SPACES TO WS-NAME-RAW WS-ACCT WS-TYPE WS-AMT
           MOVE 0 TO WS-FIELD-CNT WS-NAME-LEN
           UNSTRING WS-RAW-LINE(WS-IDX) DELIMITED BY ","
               INTO WS-NAME-RAW COUNT IN WS-NAME-LEN
                    WS-ACCT
                    WS-TYPE
                    WS-AMT
               TALLYING IN WS-FIELD-CNT
           END-UNSTRING
           IF WS-FIELD-CNT < 4
               ADD 1 TO WS-BAD-CNT
               DISPLAY "LINE " WS-IDX " FIELDS " WS-FIELD-CNT
                       " SKIPPED"
           ELSE
               PERFORM BUILD-LABEL
           END-IF.

       BUILD-LABEL.
           MOVE 0 TO WS-HYPHENS WS-BR-LEN
           INSPECT WS-ACCT TALLYING WS-HYPHENS FOR ALL "-"
           INSPECT WS-ACCT TALLYING WS-BR-LEN
               FOR CHARACTERS BEFORE INITIAL "-"
           INSPECT WS-AMT REPLACING LEADING "0" BY SPACE
           COMPUTE WS-TRIM-LEN =
               FUNCTION LENGTH(FUNCTION TRIM(WS-NAME-RAW))
           MOVE FUNCTION UPPER-CASE(FUNCTION TRIM(WS-NAME-RAW))
               TO WS-NAME-CLEAN
           MOVE WS-ACCT TO WS-MASKED
           MOVE ALL "*" TO WS-MASKED(1:8)
           EVALUATE WS-TYPE
               WHEN "DEP"
                   MOVE "DEPOSIT" TO WS-KIND
               WHEN "WDR"
                   MOVE "WITHDRAW" TO WS-KIND
               WHEN OTHER
                   MOVE "UNKNOWN" TO WS-KIND
           END-EVALUATE
           MOVE SPACES TO WS-LABEL
           MOVE 1 TO WS-PTR
           STRING FUNCTION TRIM(WS-NAME-CLEAN) DELIMITED BY SIZE
                  " [" DELIMITED BY SIZE
                  WS-MASKED DELIMITED BY SPACE
                  "] " DELIMITED BY SIZE
                  FUNCTION TRIM(WS-KIND) DELIMITED BY SIZE
                  " " DELIMITED BY SIZE
                  FUNCTION TRIM(WS-AMT) DELIMITED BY SIZE
                  INTO WS-LABEL
                  WITH POINTER WS-PTR
                  ON OVERFLOW DISPLAY "LABEL OVERFLOW"
           END-STRING
           COMPUTE WS-USED = WS-PTR - 1
           ADD 1 TO WS-OK-CNT
           DISPLAY "LINE " WS-IDX " FIELDS " WS-FIELD-CNT
                   " RAW-LEN " WS-NAME-LEN " TRIM-LEN " WS-TRIM-LEN
                   " HYPHENS " WS-HYPHENS
           DISPLAY "  " WS-LABEL(1:WS-USED)
           DISPLAY "  BRANCH " WS-ACCT(1:WS-BR-LEN).

줄별 해설

자료 정의

WS-RAW-TABLE 은 40바이트짜리 줄 네 개를 담는 테이블이다. WS-NAME-RAW, WS-ACCT, WS-TYPE, WS-AMT 는 UNSTRING 이 나누어 담을 항목이다. WS-NAME-LEN 은 COUNT IN 이, WS-FIELD-CNT 는 TALLYING IN 이 채운다. WS-HYPHENS 와 WS-BR-LEN 은 INSPECT 의 카운터다. WS-PTR 과 WS-USED 는 STRING 의 포인터와 사용 길이다.

MAIN-PARA 와 LOAD-DATA

메인 문단은 데이터를 채운 뒤 1 부터 4 까지 PARSE-LINE 을 부르고 건수를 찍는다. LOAD-DATA 는 입력 네 줄을 MOVE 로 테이블에 넣는다. 두 번째 줄에는 이름 앞뒤에 공백이 붙어 있고, 네 번째 줄은 항목이 둘뿐이다.

PARSE-LINE

먼저 받는 항목을 공백으로, 카운터를 0 으로 되돌린다. UNSTRING 은 이전 줄의 값을 지워 주지 않기 때문이다. UNSTRING 은 쉼표 기준으로 나눈다. 첫 항목의 글자 수는 WS-NAME-LEN 에 들어가고, 값을 받은 항목의 수는 WS-FIELD-CNT 에 쌓인다. 4 보다 작으면 잘못된 줄로 보고 건너뛴다.

BUILD-LABEL: 세고 바꾸기

INSPECT 첫 문장은 하이픈 개수를, 둘째 문장은 첫 하이픈 앞의 글자 수를 센다. 계좌번호 "110-2345-01" 에서 각각 2 와 3 이 나온다. 셋째 INSPECT 는 금액의 앞쪽 0 을 공백으로 바꾼다. "00150000" 이 " 150000" 이 된다.

BUILD-LABEL: 이름과 가림

COMPUTE 는 공백을 뗀 이름의 길이를 구한다. 이어서 TRIM 으로 공백을 떼고 UPPER-CASE 로 바꾼 이름을 WS-NAME-CLEAN 에 담는다. 계좌번호는 WS-MASKED 에 복사한 뒤 참조 수정 (1:8) 에 "*" 를 채워서 앞 여덟 자리를 가린다. 원본 WS-ACCT 는 그대로 남는다. EVALUATE 는 거래 코드를 읽기 쉬운 단어로 바꾼다.

BUILD-LABEL: STRING 과 출력

STRING 앞에서 WS-LABEL 을 공백으로, 포인터를 1 로 되돌린다. 이름, " [", 가린 계좌번호, "] ", 거래 종류, 공백, 금액 순서로 붙인다. 가린 계좌번호에만 DELIMITED BY SPACE 를 쓴 것은 그 값에 공백이 없어서 뒤쪽 빈칸만 잘라 내기 위해서다. 나머지는 SIZE 로 전체를 보낸다. 끝난 뒤 포인터에서 1 을 뺀 값이 사용한 길이이고, DISPLAY 에서 WS-LABEL(1:WS-USED) 로 그 길이만큼만 출력한다. 마지막 줄은 WS-BR-LEN 을 길이로 써서 지점 코드만 꺼낸다.

실행 결과

$ cobc -x -Wall main.cob
$ ./main
LINE 1 FIELDS 4 RAW-LEN 09 TRIM-LEN 09 HYPHENS 2
  KIM MINSU [********-01] DEPOSIT 150000
  BRANCH 110
LINE 2 FIELDS 4 RAW-LEN 12 TRIM-LEN 09 HYPHENS 2
  PARK JIHO [********-02] WITHDRAW 45000
  BRANCH 110
LINE 3 FIELDS 4 RAW-LEN 11 TRIM-LEN 11 HYPHENS 2
  LEE SEOYEON [********-03] DEPOSIT 3200000
  BRANCH 220
LINE 4 FIELDS 2 SKIPPED
PROCESSED 3 SKIPPED 1

두 번째 줄에서 RAW-LEN 은 12, TRIM-LEN 은 9 다. 앞뒤 공백 세 칸이 TRIM 으로 사라진 것이다. 금액은 앞의 0 이 지워져 "45000" 이 되었다.

실무에서 자주 틀리는 것

이름 속 공백에서 잘린다

틀린 코드:

STRING WS-NAME-CLEAN DELIMITED BY SPACE
       " [" DELIMITED BY SIZE
       INTO WS-LABEL
END-STRING

"KIM MINSU" 가 첫 공백 앞에서 끊겨 "KIM [" 만 붙는다. 이름 항목은 20칸 중 뒤쪽이 공백이라, TRIM 으로 뒤쪽 공백을 떼고 SIZE 로 보낸다.

STRING FUNCTION TRIM(WS-NAME-CLEAN) DELIMITED BY SIZE
       " [" DELIMITED BY SIZE
       INTO WS-LABEL
END-STRING

STRING 앞에서 대상과 포인터를 초기화하지 않는다

틀린 코드:

STRING "LEE SEOYEON" DELIMITED BY SIZE INTO WS-LABEL
STRING "PARK" DELIMITED BY SIZE INTO WS-LABEL

두 번째 STRING 은 앞 네 칸만 덮어쓴다. WS-LABEL 은 "PARKSEOYEON" 이 된다. 포인터를 쓴다면 이전 값에서 이어 붙게 된다. 매번 지우고 1 로 되돌린다.

MOVE SPACES TO WS-LABEL
MOVE 1 TO WS-PTR
STRING "PARK" DELIMITED BY SIZE
       INTO WS-LABEL WITH POINTER WS-PTR
END-STRING

UNSTRING 과 INSPECT 의 카운터를 0 으로 두지 않는다

틀린 코드:

UNSTRING WS-RAW-LINE(WS-IDX) DELIMITED BY ","
    INTO WS-NAME-RAW WS-ACCT WS-TYPE WS-AMT
    TALLYING IN WS-FIELD-CNT
END-UNSTRING

WS-FIELD-CNT 는 이전 줄의 4 에서 계속 더해진다. 항목이 모자란 줄도 "4 이상" 으로 보여서 걸러지지 않는다. 받는 항목도 이전 줄 값이 남아 있다. 실행 전에 둘 다 초기화한다. INSPECT 의 카운터도 마찬가지다.

MOVE SPACES TO WS-NAME-RAW WS-ACCT WS-TYPE WS-AMT
MOVE 0 TO WS-FIELD-CNT

참조 수정의 길이가 0 이 된다

틀린 코드:

INSPECT WS-ACCT TALLYING WS-BR-LEN
    FOR CHARACTERS BEFORE INITIAL "-"
DISPLAY WS-ACCT(1:WS-BR-LEN)

계좌번호가 "-" 로 시작하면 WS-BR-LEN 은 0 이다. 길이 0 의 참조 수정은 잘못된 범위지만 기본 설정에서는 검사하지 않아서, 엉뚱한 글자가 나오거나 조용히 지나간다. 길이를 확인한 뒤 쓰고, 개발 중에는 -debug 로 컴파일한다.

IF WS-BR-LEN > 0
    DISPLAY WS-ACCT(1:WS-BR-LEN)
END-IF

한눈에 보기

문자열 처리 문장과 쓰는 때
문장·기능하는 일사용 전에 할 일
STRING ... DELIMITED BY SIZE조각을 이어 붙인다대상을 공백으로, 포인터를 1 로
UNSTRING ... INTO구분자 기준으로 나눈다받는 항목을 지우고 TALLYING 변수를 0 으로
INSPECT TALLYING글자를 센다카운터를 0 으로
INSPECT REPLACING같은 길이의 글자로 바꾼다바꾸기 전후 길이를 맞춘다
항목(시작:길이)일부분을 읽고 쓴다범위와 길이 0 을 확인한다
FUNCTION TRIM, UPPER-CASE공백 정리, 대문자 변환없음

연습 문제

  1. WS-BR 은 PIC X(3) 이고 "110", WS-NM 은 PIC X(10) 이고 "KIM" 이 들어 있다. WS-OUT 에 "110/KIM" 이 만들어지도록 STRING 문을 쓰라. WS-NM 뒤의 빈칸은 들어가면 안 된다.
  2. WS-NAME 은 PIC X(20) 이고 "LEE SEO YEON" 이 들어 있다. INSPECT WS-NAME TALLYING WS-CNT FOR ALL SPACE 를 하면 2 가 아니라 10 이 나온다. 이유를 설명하고, 2 가 나오도록 고치라.
  3. WS-DATE 는 PIC X(10) 이고 "2026-10-02" 이다. 연, 월, 일을 WS-Y(X(4)), WS-M(X(2)), WS-D(X(2)) 로 나누는 UNSTRING 문을 쓰라.
  4. WS-MASKED 에 "110-2345-01" 이 들어 있다. 가운데 네 자리만 "XXXX" 로 바꾸는 문장을 한 줄로 쓰고, 결과를 적으라.

정답과 해설

  1. MOVE SPACES TO WS-OUT
    STRING WS-BR DELIMITED BY SIZE
           "/" DELIMITED BY SIZE
           WS-NM DELIMITED BY SPACE
           INTO WS-OUT
    END-STRING

    WS-NM 은 이름 속 공백이 없으니 DELIMITED BY SPACE 로 뒤쪽 빈칸을 잘라낼 수 있다. 이름에 공백이 있다면 TRIM 과 SIZE 를 쓴다. 결과는 "110/KIM" 이다.

  2. WS-NAME 은 20칸이어서 뒤쪽 8칸의 빈칸까지 모두 공백으로 세어진다. 단어 사이 공백 2개와 뒤쪽 8개를 합친 10 이다. 실제 글자 길이를 먼저 구해 그 범위만 검사하면 된다.

    MOVE 0 TO WS-CNT
    COMPUTE WS-LEN =
        FUNCTION LENGTH(FUNCTION TRIM(WS-NAME TRAILING))
    INSPECT WS-NAME(1:WS-LEN) TALLYING WS-CNT FOR ALL SPACE

    WS-LEN 은 12 이고 WS-CNT 는 2 다. 단어 수는 2 + 1 = 3 이다.

  3. UNSTRING WS-DATE DELIMITED BY "-"
        INTO WS-Y WS-M WS-D
    END-UNSTRING

    결과는 WS-Y "2026", WS-M "10", WS-D "02" 다. 줄 끝에서 남는 글자가 없으니 마지막 항목까지 정확히 채워진다.

  4. MOVE "XXXX" TO WS-MASKED(5:4)

    다섯 번째 글자부터 네 칸이 바뀌어 "110-XXXX-01" 이 된다. 참조 수정의 시작은 1 부터 센다.

오탈자·오류 제보 비공개로 접수되어 원고 수정에 반영됩니다

이메일 등 개인정보는 받지 않습니다. 답변이 필요한 질문은 아래 댓글을 이용해 주세요.

READER FEEDBACK

질문·의견

내용에 관한 질문이나 더 나은 설명을 위한 의견을 남겨 주세요. 오탈자는 위의 제보 양식이 더 빨리 반영됩니다. 이 댓글은 원래 게시글과 같은 자리에 쌓입니다.

댓글 0

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

댓글을 남기려면 로그인이 필요합니다.