Devin.KR

COBOL · 기본

데이터 처리로 배우는 COBOL

값 옮기기와 계산 - MOVE 의 자리 맞춤

MOVE 규칙(숫자는 소수점 기준 정렬·왼쪽 잘림, 문자는 왼쪽 정렬·공백 채움), ADD·SUBTRACT·MULTIPLY·DIVIDE GIVING, COMPUTE, ROUNDED, ON SIZE ERROR

개발자KR · 원고 갱신

이 장에서 배우는 것

앞 장에서는 PIC 절로 항목의 자릿수와 종류를 정했다. 이번 장에서는 그렇게 만든 항목들 사이에 값을 옮기고(MOVE), 더하고 빼고 곱하고 나누는(ADD, SUBTRACT, MULTIPLY, DIVIDE, COMPUTE) 방법을 배운다. 금액을 다루는 프로그램에서는 값이 어디로 옮겨지고 어디에서 잘리는지가 곧 결과의 정확성이다. 그래서 이 장은 문법보다 "자리"에 무게를 둔다.

  • MOVE 가 숫자 항목과 문자 항목을 각각 어떤 기준으로 맞추는지 설명할 수 있다.
  • ADD, SUBTRACT, MULTIPLY, DIVIDE 의 GIVING 형식과 GIVING 이 없는 형식의 차이를 구분한다.
  • COMPUTE 로 수식을 한 문장에 쓰고 연산자 우선순위를 적용한다.
  • ROUNDED 로 반올림하고, 쓰지 않으면 버림이 일어남을 확인한다.
  • ON SIZE ERROR 로 자릿수 넘침과 0 으로 나누기를 감지한다.

문제 상황

작은 신용협동조합의 야간 배치가 하루 거래를 반영한다고 하자. 어느 회원의 잔액이 1,250,000.50 원이고, 오늘 300,000.25 원이 입금되고 450,000.00 원이 출금되었다. 반영한 잔액에 연 2.75% 이자율을 적용해 연 이자를 구하고, 이를 365 로 나누어 하루치 이자를 계산한다. 그리고 이자소득세 15.4% 를 뺀 세후 이자까지 구한다.

계산 자체는 초등학교 산수다. 어려운 곳은 컴퓨터의 칸이 고정되어 있다는 점이다. 하루치 이자는 82.876767… 처럼 소수가 끝없이 이어지지만 받는 칸은 소수 둘째 자리까지만 있다. 잔액 칸이 정수 5자리인데 합계가 6자리가 되면 어떻게 되는가. 이런 일은 오류 메시지 없이 조용히 일어나서, 모르고 지나가면 장부가 어긋난다. 이 장은 그 규칙을 하나씩 확인한다.

MOVE 의 자리 맞춤

MOVE 는 보내는 항목의 값을 받는 항목에 복사한다. 이때 값을 "그대로" 붙이는 것이 아니라, 받는 항목의 PIC 에 맞춰 자리를 다시 배치한다. 규칙은 받는 항목의 종류에 따라 갈린다.

숫자 항목: 소수점을 기준으로 맞춘다

숫자 항목끼리의 MOVE 는 가상의 소수점(PIC 의 V 위치)을 맞춰 놓고 자리별로 옮긴다. 받는 쪽에 자리가 남으면 0 으로 채운다. 받는 쪽에 자리가 모자라면 넘친 자리를 버린다. 정수부는 높은 자리, 곧 왼쪽이 잘리고 소수부는 낮은 자리, 곧 오른쪽이 잘린다. 반올림은 하지 않는다.

숫자 MOVE 는 소수점 위치를 맞춘 뒤 받는 칸에 없는 왼쪽·오른쪽 자리를 버린다.

그림에서 원본 12345.67 은 소수점을 기준으로 놓인다. 넓은 항목에는 앞뒤가 0 으로 채워지고, 좁은 항목에서는 왼쪽의 1, 2 와 오른쪽의 7 이 사라진다. 사라진 자리에 대한 경고나 오류는 없다.

문자 항목: 왼쪽 정렬, 남으면 공백

문자 항목(PIC X)은 소수점이 없으므로 왼쪽 끝을 맞춘다. 받는 쪽이 더 길면 오른쪽 남은 칸을 공백으로 채우고, 더 짧으면 오른쪽이 잘린다. 숫자와는 잘리는 방향이 반대다. 숫자는 낮은 자리 쪽을 살리려고 왼쪽을 자르고, 문자는 앞글자를 살리려고 오른쪽을 자른다고 기억하면 쉽다.

받는 항목의 종류에 따른 MOVE 규칙
받는 항목맞추는 기준남는 칸모자랄 때
숫자 (PIC 9, S9)소수점 위치앞뒤를 0 으로 채움정수부는 왼쪽, 소수부는 오른쪽을 버림
문자 (PIC X)왼쪽 끝오른쪽을 공백으로 채움오른쪽을 버림

한 가지 더 알아 둘 점이 있다. 부호 있는 항목(PIC S9)의 값을 부호 없는 항목(PIC 9)으로 옮기면 부호가 사라지고 크기만 남는다. -300 이 300 이 되는 것이다. 받는 항목이 부호를 담을 수 없기 때문이다.

사칙연산 문장과 COMPUTE

GIVING 이 있는 형식과 없는 형식

COBOL 의 사칙연산 동사는 영어 문장처럼 읽힌다. 핵심은 결과가 어느 항목에 저장되는가다. GIVING 이 없으면 마지막에 적은 항목의 값이 바뀐다. GIVING 이 있으면 GIVING 뒤의 항목에 결과를 저장하고 피연산자는 그대로 둔다. 원래 값을 남겨야 하는 장부 계산에서는 GIVING 형식이 안전하다.

사칙연산 문장의 형식과 결과가 저장되는 곳
문장계산결과가 들어가는 항목
ADD A TO BB + AB
ADD A B GIVING CA + BC
SUBTRACT A FROM BB - AB
SUBTRACT A FROM B GIVING CB - AC
MULTIPLY A BY B GIVING CA × BC
DIVIDE A BY B GIVING CA ÷ BC
DIVIDE A INTO B GIVING CB ÷ AC

SUBTRACT 는 "A 를 B 에서 뺀다"이므로 FROM 뒤가 먼저 오는 수다. DIVIDE 는 BY 와 INTO 에서 나뉘는 수와 나누는 수의 위치가 서로 반대다. BY 앞이 나뉘는 수, INTO 앞이 나누는 수다. 이 순서는 뒤의 "자주 틀리는 것"에서 다시 다룬다.

COMPUTE: 수식 한 줄

COMPUTE 는 일반 수식을 쓸 수 있다. 연산자는 + - * / 와 거듭제곱 ** 이고, 곱셈·나눗셈이 덧셈·뺄셈보다 먼저 계산되며 괄호로 순서를 바꿀 수 있다. 등호 양옆, 연산자 양옆에는 반드시 공백을 둔다. 공백 없이 쓰면 A-B 가 하나의 이름으로 읽힐 수 있기 때문이다. 이 장의 예제는 세후 이자를 이렇게 구한다.

COMPUTE WS-NET-INT ROUNDED
        = WS-YEAR-INT - WS-YEAR-INT * 0.154

곱셈이 먼저 계산되어 이자소득세가 나오고, 거기서 연 이자를 뺀다. 여러 단계를 거치는 계산은 중간 결과를 별도 항목에 담지 말고 COMPUTE 한 문장에 쓰는 편이 정확하다. 중간 항목에 담을 때마다 자릿수가 잘리기 때문이다.

ROUNDED: 버림 대신 반올림

결과를 받는 항목의 소수 자리가 모자라면 기본 동작은 버림이다. 항목 이름 뒤에 ROUNDED 를 붙이면 마지막 남는 자리에서 반올림한다. 하루 이자 82.876767… 은 기본으로 82.87, ROUNDED 를 붙이면 82.88 이 된다. 반올림 규칙은 0.5 이상을 올리는 일반적인 방식이다.

같은 나눗셈 결과도 ROUNDED 가 없으면 82.87 로 버려지고 있으면 82.88 로 반올림된다.

ON SIZE ERROR: 넘침을 알아채기

계산 결과의 정수부가 받는 항목보다 길거나 0 으로 나누면 크기 오류(size error)가 된다. 연산 문장에 ON SIZE ERROR 를 쓰지 않으면 넘친 높은 자리는 조용히 버려진다. 99,000.00 에 2,000.00 을 더해 101,000.00 이 되었는데 받는 항목이 정수 5자리라면 01000.00 이 저장된다. ON SIZE ERROR 를 쓰면 받는 항목의 값은 바뀌지 않고 그 아래 문장이 실행된다. 정상일 때 실행할 문장은 NOT ON SIZE ERROR 에 쓴다. 문장의 끝은 END-ADD, END-DIVIDE 같은 끝맺음 낱말로 표시한다.

MOVE 에는 ON SIZE ERROR 가 없다. 자릿수가 모자란 MOVE 는 감지할 방법이 없으므로, 받는 항목의 PIC 를 처음부터 충분히 크게 설계하는 일이 먼저다.

완성 코드

아래 프로그램은 앞에서 설명한 규칙을 차례로 실행해 본다. GnuCOBOL 에서 숫자 항목을 DISPLAY 하면 V 자리에 점이 찍혀 나오지만, 기억 장소에 점이 저장되는 것은 아니다. 점과 쉼표를 넣어 읽기 좋게 만드는 방법은 다음 장에서 다루므로, 여기서는 출력의 끝 두 자리나 세 자리가 소수부라고 읽으면 된다.

main.cob

       IDENTIFICATION DIVISION.
       PROGRAM-ID. MAIN.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
      * MOVE 실험용 항목
       01  WS-SRC-AMT        PIC 9(5)V99   VALUE 12345.67.
       01  WS-WIDE           PIC 9(7)V9(3).
       01  WS-NARROW         PIC 9(3)V9.
       01  WS-INT-ONLY       PIC 9(4).
       01  WS-SRC-NAME       PIC X(10)     VALUE "HAN SOYEON".
       01  WS-LONG-NAME      PIC X(15).
       01  WS-SHORT-NAME     PIC X(6).
      * 잔액 계산용 항목
       01  WS-BALANCE        PIC 9(7)V99   VALUE 1250000.50.
       01  WS-DEPOSIT        PIC 9(7)V99   VALUE 300000.25.
       01  WS-WITHDRAW       PIC 9(7)V99   VALUE 450000.00.
       01  WS-NEW-BAL        PIC 9(7)V99.
       01  WS-AFTER-BAL      PIC 9(7)V99.
      * 이자 계산용 항목
       01  WS-RATE           PIC 9V9999    VALUE 0.0275.
       01  WS-DAYS           PIC 999       VALUE 365.
       01  WS-YEAR-INT       PIC 9(7)V99.
       01  WS-DAY-TRUNC      PIC 9(5)V99.
       01  WS-DAY-ROUND      PIC 9(5)V99.
       01  WS-NET-INT        PIC 9(7)V99.
      * 크기 오류 실험용 항목
       01  WS-LIMIT          PIC 9(5)V99   VALUE 99000.00.
       01  WS-ADD-AMT        PIC 9(5)V99   VALUE 2000.00.
       01  WS-WRAP           PIC 9(5)V99.
       01  WS-GUARD          PIC 9(5)V99.
       01  WS-ZERO           PIC 999       VALUE 0.
       PROCEDURE DIVISION.
       MAIN-PARA.
      * 1) MOVE 의 자리 맞춤
           MOVE WS-SRC-AMT TO WS-WIDE
           MOVE WS-SRC-AMT TO WS-NARROW
           MOVE WS-SRC-AMT TO WS-INT-ONLY
           DISPLAY "SRC: " WS-SRC-AMT
           DISPLAY "WIDE: " WS-WIDE
           DISPLAY "NARROW: " WS-NARROW
           DISPLAY "INT-ONLY: " WS-INT-ONLY
           MOVE WS-SRC-NAME TO WS-LONG-NAME
           MOVE WS-SRC-NAME TO WS-SHORT-NAME
           DISPLAY "LONG: [" WS-LONG-NAME "]"
           DISPLAY "SHORT: [" WS-SHORT-NAME "]"
      * 2) 입금과 출금 반영
           ADD WS-BALANCE WS-DEPOSIT GIVING WS-NEW-BAL
           SUBTRACT WS-WITHDRAW FROM WS-NEW-BAL
               GIVING WS-AFTER-BAL
           DISPLAY "NEW-BAL: " WS-NEW-BAL
           DISPLAY "AFTER: " WS-AFTER-BAL
      * 3) 이자 계산: 곱하기, 나누기, ROUNDED
           MULTIPLY WS-AFTER-BAL BY WS-RATE GIVING WS-YEAR-INT
           DIVIDE WS-YEAR-INT BY WS-DAYS GIVING WS-DAY-TRUNC
           DIVIDE WS-YEAR-INT BY WS-DAYS GIVING WS-DAY-ROUND
               ROUNDED
           DISPLAY "YEAR-INT: " WS-YEAR-INT
           DISPLAY "DAY-TRUNC: " WS-DAY-TRUNC
           DISPLAY "DAY-ROUND: " WS-DAY-ROUND
      * 4) COMPUTE 로 세후 이자
           COMPUTE WS-NET-INT ROUNDED
               = WS-YEAR-INT - WS-YEAR-INT * 0.154
           DISPLAY "NET-INT: " WS-NET-INT
      * 5) 크기 오류
           MOVE WS-LIMIT TO WS-WRAP
           ADD WS-ADD-AMT TO WS-WRAP
           DISPLAY "WRAP: " WS-WRAP
           MOVE WS-LIMIT TO WS-GUARD
           ADD WS-ADD-AMT TO WS-GUARD
               ON SIZE ERROR
                   DISPLAY "GUARD: SIZE ERROR"
               NOT ON SIZE ERROR
                   DISPLAY "GUARD: OK"
           END-ADD
           DISPLAY "GUARD-VAL: " WS-GUARD
           DIVIDE WS-YEAR-INT BY WS-ZERO GIVING WS-DAY-ROUND
               ON SIZE ERROR
                   DISPLAY "ZERO: DIVISOR IS ZERO"
           END-DIVIDE
           DISPLAY "DAY-ROUND AFTER: " WS-DAY-ROUND
           STOP RUN.

줄별 해설

DATA DIVISION 의 항목들. 금액 항목은 PIC 9(7)V99 로 통일했다. 정수 7자리에 소수 2자리라서 9,999,999.99 까지 담는다. 이자율 WS-RATE 는 PIC 9V9999 이므로 0.0275 처럼 소수 4자리까지 표현한다. 일수 WS-DAYS 는 소수 없는 3자리다. 이름 항목은 PIC X(10), X(15), X(6) 세 개로, 보내는 쪽이 받는 쪽보다 짧거나 긴 경우를 모두 만든다.

1) MOVE. WS-SRC-AMT 의 값 12345.67 을 세 항목에 옮긴다. 소수 3자리가 있는 WS-WIDE 에서는 0012345.670, 정수 3자리에 소수 1자리인 WS-NARROW 에서는 345.6 이다. 이 6 은 6.7 을 반올림한 7 이 아니라 7 을 버린 결과다. WS-INT-ONLY 는 소수부가 없고 정수 4자리라 2345 가 된다. 이름은 WS-LONG-NAME 에서 오른쪽에 공백 5칸이 붙고, WS-SHORT-NAME 에서는 앞 6글자만 남는다. 공백이 눈에 보이도록 DISPLAY 에서 대괄호로 감쌌다.

2) 입금과 출금. ADD WS-BALANCE WS-DEPOSIT GIVING WS-NEW-BAL 은 두 값을 더해 WS-NEW-BAL 에 담고 WS-BALANCE, WS-DEPOSIT 는 건드리지 않는다. 이어지는 SUBTRACT 는 WS-NEW-BAL 에서 출금액을 뺀 값을 WS-AFTER-BAL 에 따로 담는다. 문장이 두 줄에 걸치는 것은 72열을 넘지 않으려는 것이고, 문법상 줄바꿈은 아무 곳에나 해도 된다.

3) 이자. MULTIPLY 는 1,100,000.75 × 0.0275 = 30,250.020625 를 계산하지만 WS-YEAR-INT 는 소수 2자리라 30250.02 가 저장된다. 이어서 같은 나눗셈을 두 번 한다. 첫 번째는 ROUNDED 가 없어 82.87 이 되고, 두 번째는 ROUNDED 가 있어 82.88 이 된다. 정확한 값은 82.87676…이다.

4) COMPUTE. 30250.02 × 0.154 = 4658.50308 이고 30250.02 에서 이를 빼면 25591.51692 다. 소수 셋째 자리 이하는 6 이상이 이어지므로 ROUNDED 로 25591.52 가 된다. 이 계산이 한 문장 안에서 정확하게 이뤄지기 때문에 중간값 4658.50308 이 그대로 쓰인다. ROUNDED 가 없었다면 25591.51 이다.

5) 크기 오류. WS-WRAP 은 ON SIZE ERROR 없이 99000.00 + 2000.00 = 101000.00 을 받는다. 정수 5자리에 담기지 않으므로 맨 앞의 1 이 버려져 01000.00 이 저장된다. WS-GUARD 는 같은 계산에 ON SIZE ERROR 를 달았다. 넘침이 감지되어 첫 번째 DISPLAY 가 실행되고 WS-GUARD 는 원래 값 99000.00 으로 남는다. 마지막 DIVIDE 는 나누는 수가 0 이어서 크기 오류가 되고, WS-DAY-ROUND 는 앞의 값 82.88 을 유지한다.

실행 결과

$ cobc -x -Wall main.cob
$ ./main
SRC: 12345.67
WIDE: 0012345.670
NARROW: 345.6
INT-ONLY: 2345
LONG: [HAN SOYEON     ]
SHORT: [HAN SO]
NEW-BAL: 1550000.75
AFTER: 1100000.75
YEAR-INT: 0030250.02
DAY-TRUNC: 00082.87
DAY-ROUND: 00082.88
NET-INT: 0025591.52
WRAP: 01000.00
GUARD: SIZE ERROR
GUARD-VAL: 99000.00
ZERO: DIVISOR IS ZERO
DAY-ROUND AFTER: 00082.88

GnuCOBOL 은 숫자 항목을 DISPLAY 할 때 V 자리에 점을 찍어 보여 준다. 예를 들어 NEW-BAL 은 정수 7자리와 소수 2자리라서 1550000.75 로 나온다. IBM 메인프레임 COBOL 은 같은 값을 점 없이 155000075 처럼 자릿수만 이어서 내보내므로, 출력 모양은 컴파일러에 따라 다르다. 어느 쪽이든 기억 장소에 점이 저장되지는 않는다.

실무에서 자주 틀리는 것

DIVIDE 의 BY 와 INTO 를 거꾸로 쓴다

연 이자를 일수로 나누려고 했는데 순서가 뒤집혔다.

DIVIDE WS-DAYS BY WS-YEAR-INT GIVING WS-DAY-ROUND

이 문장은 365 ÷ 30250.02 를 계산해 0.01 이 된다. 오류도 경고도 없다. BY 앞이 나뉘는 수이므로 순서를 바꾼다.

DIVIDE WS-YEAR-INT BY WS-DAYS GIVING WS-DAY-ROUND

받는 항목에 소수 자리를 주지 않는다

이자를 PIC 9(7) 로 선언하면 소수가 전부 버려진다.

01  WS-YEAR-INT   PIC 9(7).
...
MULTIPLY WS-AFTER-BAL BY WS-RATE GIVING WS-YEAR-INT

결과는 30250 이고 0.02 원이 사라진다. 이 오차는 회원 수만큼 쌓인다. 소수 자리를 설계 단계에서 정해 둔다.

01  WS-YEAR-INT   PIC 9(7)V99.

크기 오류를 감지하지 않는다

합계 항목이 합계를 담을 만큼 크지 않은데 ON SIZE ERROR 도 없으면, 높은 자리가 조용히 사라진다.

ADD WS-ADD-AMT TO WS-WRAP

99000.00 에 2000.00 을 더하면 01000.00 이 된다. 넘칠 수 있는 합계에는 항목을 한 자리 넓히고, 한계가 있는 곳에는 ON SIZE ERROR 로 처리 경로를 둔다.

ADD WS-ADD-AMT TO WS-GUARD
    ON SIZE ERROR
        DISPLAY "GUARD: SIZE ERROR"
END-ADD

부호 있는 값을 부호 없는 항목으로 옮긴다

출금이 입금보다 큰 날의 차액을 담으려는 항목에 부호가 없다.

01  WS-DIFF   PIC 9(5)V99.
...
SUBTRACT WS-WITHDRAW FROM WS-DEPOSIT GIVING WS-DIFF

입금 1,000 에서 출금 1,500 을 빼면 -500 이어야 하지만 부호 없는 항목에는 500.00 이 저장된다. 음수가 나올 수 있는 항목은 PIC S9(5)V99 처럼 S 를 붙여 선언한다.

01  WS-DIFF   PIC S9(5)V99.

한눈에 보기

이 장의 요점
주제규칙예주의
숫자 MOVE소수점 기준 정렬12345.67 → 9(3)V9 는 345.6반올림 없이 버림
문자 MOVE왼쪽 정렬, 오른쪽 공백HAN SOYEON → X(6) 은 HAN SO짧으면 오른쪽이 잘림
GIVING결과를 GIVING 항목에 저장ADD A B GIVING CA, B 는 그대로
DIVIDEBY 앞이 나뉘는 수DIVIDE A BY BINTO 는 반대 순서
COMPUTE수식 한 줄, 곱셈 먼저X = A - A * 0.154연산자 양옆 공백
ROUNDED마지막 자리에서 반올림82.8767 → 82.88없으면 82.87
ON SIZE ERROR넘침과 0 나누기 감지99000 + 2000 → 5자리 초과없으면 높은 자리 소실, MOVE 에는 쓸 수 없음

연습 문제

  1. WS-A 가 PIC 9(4)V99 이고 값이 8765.43 이다. 이를 PIC 9(3)V9 와 PIC 9(6)V9(3) 항목에 각각 MOVE 하면 DISPLAY 결과는 어떻게 나오는가.
  2. PIC X(8) 항목에 SAVINGS 가 들어 있다. PIC X(4) 와 PIC X(10) 항목에 MOVE 한 결과를 대괄호를 붙여 적어 보라.
  3. 출금액 WS-WITHDRAW 가 1999.99 이고 수수료율 WS-FEE-RATE 가 0.0015 다. 수수료를 PIC 9(5)V99 인 WS-FEE 에 구하되 소수 셋째 자리에서 반올림하는 COMPUTE 문장을 쓰고, 결과를 적어 보라. ROUNDED 를 빼면 결과는 어떻게 되는가.
  4. PIC 9(3)V99 항목 WS-X 에 999.99 가 들어 있다. 여기에 0.01 을 더하는 ADD 를 ON SIZE ERROR 없이 썼을 때와 썼을 때의 WS-X 값을 비교하라.

정답과 해설

  1. 9(3)V9 는 정수부 8765 의 높은 자리 8 이 잘리고 소수부 43 의 3 이 버려져 7654 가 나온다. 9(6)V9(3) 은 정수부가 008765, 소수부가 430 이므로 008765430 이다. 정수부는 앞에서, 소수부는 뒤에서 0 이 채워지고 소수점 위치가 기준이다.
  2. PIC X(4) 는 [SAVI], PIC X(10) 은 [SAVINGS ] 다. 문자는 왼쪽 정렬이므로 짧으면 오른쪽이 잘리고 길면 오른쪽에 공백 3칸이 붙는다.
  3. COMPUTE WS-FEE ROUNDED = WS-WITHDRAW * WS-FEE-RATE 이다. 정확한 값은 2.999985 이므로 ROUNDED 로 3.00 이고 DISPLAY 하면 0000300 이다. ROUNDED 를 빼면 소수 셋째 자리 이하가 버려져 2.99 가 된다.
  4. ON SIZE ERROR 가 없으면 결과 1000.00 이 정수 3자리에 담기지 않아 높은 자리가 버려지고 WS-X 는 000.00 이 된다. ON SIZE ERROR 가 있으면 WS-X 는 999.99 로 바뀌지 않고 크기 오류 처리 문장이 실행된다. 조용히 0 이 되는 쪽이 장부에서는 훨씬 위험하다.

PIC, MOVE, 사칙연산의 동작은 GnuCOBOL 프로그래머 안내서에서 다시 확인할 수 있다: GnuCOBOL 공식 사이트.

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

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

READER FEEDBACK

질문·의견

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

댓글 0

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

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