본문 바로가기
AUTOSAR 심화

AUTOSAR 통신 시스템: CAN 버스, 신호, COM 모듈의 관계

by 버그없는토마토 2025. 12. 16.

AUTOSAR 통신 시스템: CAN 버스, 신호, COM 모듈의 관계

CAN이란? COM이란?

CAN이란?


[Autosar Series]

더보기

1. 2025.12.14 - [AUTOSAR 기초] - 오토사(AUTOSAR)가 정확히 뭔가요? 개념부터 왜 배워야 하는지까지

 

오토사(AUTOSAR)가 정확히 뭔가요? 개념부터 왜 배워야 하는지까지

AUTOSAR란?AUTOSAR의 정의, 탄생 배경, 왜 배워야 하는지들어가며안녕하세요, 버그없는토마토입니다.여러분, 혹시 채용공고에서 "AUTOSAR 경험자 우대" 같은 문구를 봤나요?현대, LG이노텍, 기아, BMW, 아

jungposco.com

 

2.  2025.12.14 - [AUTOSAR 기초] - 오토사(AUTOSAR) Classic vs Adaptive: 어떤 차이? 알아야할까?

 

오토사(AUTOSAR) Classic vs Adaptive: 어떤 차이? 알아야할까?

오토사(AUTOSAR) Classic vs Adaptive: 어떤 차이?오토사(AUTOSAR) Classic이란?오토사(AUTOSAR) Adaptive란? 들어가며안녕하세요, 버그없는토마토입니다.지난 편에서 AUTOSAR가 뭔지 배웠어요.자동차 소프트웨어의

jungposco.com

 

3. 2025.12.14 - [AUTOSAR 기초] - AUTOSAR 계층 구조: ASW-RTE-BSW 완벽 이해

 

AUTOSAR 계층 구조: ASW-RTE-BSW 완벽 이해

AUTOSAR 계층 구조: ASW-RTE-BSW 완벽 이해AUTOSAR 계층 구조는?들어가며지난 두 편에서 AUTOSAR가 뭔지, Classic과 Adaptive의 차이가 뭔지 배웠어요. 이제 본격적으로 AUTOSAR의 내부 구조를 파헤칠 차례예요.조

jungposco.com

 

4. 2025.12.14 - [AUTOSAR 심화] - SWC와 Runnable이란? : AUTOSAR 소프트웨어의 기본 단위

 

SWC와 Runnable이란? : AUTOSAR 소프트웨어의 기본 단위

SWC와 Runnable이란? : AUTOSAR 소프트웨어의 기본 단위SWC와 Runnable이란?들어가며지난 세 편에서 AUTOSAR의 전체 구조를 배웠어요. Classic과 Adaptive의 차이, ASW-RTE-BSW 계층까지.이제 AUTOSAR 소프트웨어가 정

jungposco.com

 

들어가며

지난 네 편에서 AUTOSAR의 전체 그림을 배웟죠

거기까지가 기초과정이라고 할 수 있어요

전체적인 틀과 각 부품들에 대해 배운 것과 같으니까요
Classic vs Adaptive, 계층 구조, SWC와 Runnable까지요


이제 AUTOSAR 소프트웨어의 핵심적인 부분통신 시스템을 배워야 해요.

하루에도 수백번씩 듣고 보는 게 바로 CAN인데요

필수를 넘어서 동반자와 같다고 볼 수 있는 개념이죠

 

우리는 그 익숙함에 속아 소중함을 잃지 말아야합니다

CAN은 흔하지만 그렇다고 사소하지않아요.

정말 중요한 부분이거든요
 이제부터 그 CAN에 대해 알아보고 더 나아가 COM(BSW)까지 깊이 들어가 볼게요


자동차 ECU는 혼자 작동할 수 없어요.
엔진 ECU는 변속기 ECU와 통신해야 하고,
브레이크 ECU는 에어백 ECU와 통신해야 하고,
모든 ECU는 진단 시스템과 통신해야 하거든요.

이 모든 통신이 CAN 버스를 통해 일어나요.
그리고 AUTOSAR는 이 통신을 체계적으로 정리했어요.

이 글을 통해 CAN 버스가 뭔지, 신호가 어떻게 메시지로 변환되는지, COM 모듈의 역할을 구체적으로 설명할게요.


CAN통신 이해하기 쉽게 설명하기

🚌 CAN 버스: 자동차의 신경망

CAN이란?

CAN = Controller Area Network
자동차의 모든 ECU를 연결하는 통신 버스예요. 마치 신경망처럼, 모든 ECU가 이 버스를 통해 정보를 주고받아요.

자동차에서 CAN의 역할

자동차 내부 구조:

┌─────────────────────────────────────────────┐
│  CAN 버스 (자동차 신경망)                   │
├─────────────────────────────────────────────┤
│    │         │         │         │          │
│    ▼         ▼         ▼         ▼          │
│  ┌──┐      ┌──┐       ┌──┐     ┌──┐         │
│  │엔│      │변│       │제│     │에│         │
│  │진│ ───  │속│ ───   │동│ ─── │어│         │
│  │E │      │E │       │E │     │백│         │
│  │C │      │C │       │C │     │E │         │
│  │U │      │U │       │U │     │C │         │
│  └──┘      └──┘       └──┘     └──┘         │
│    │         │         │         │          │
└────┼─────────┼─────────┼─────────┼──────────┘
     │         │         │         │
  "엔진      "변속기      "제동     "에어백
  RPM 3000  높은         압력      작동!"
  전송!"    기어로"      300kPa"
           바꿔!"

모든 통신이 CAN 버스 한 곳에서!

CAN의 특징

1️⃣ 저속 하지만 견고함

CAN 속도:
- Standard CAN: 500 kbps (킬로비트/초)
- High-speed CAN: 1 Mbps (메가비트/초)

비교:
- Ethernet: 100 Mbps (느린 Ethernet) ~ 1 Gbps (빠른 것)
- Wi-Fi: 100+ Mbps
- CAN: 500 kbps (매우 느림!)

그런데 왜 느린 걸 쓸까?
→ 자동차는 "빠름"보다 "안정성"이 중요!
→ 노이즈, 전자파에 견고해야 함
→ 가격 저렴 (자동차 비용 절감)

2️⃣ 거리 제약이 적음

CAN 전송 거리:
- 최대 거리: 40m (표준), 100m 이상 가능
- 와이어 한 쌍으로 모든 ECU 연결 가능

자동차 (약 5m):
┌────────────────┐
│ 엔진실 (엔진ECU)│
│       │        │
│ 대시보드(진단)  │
│       │        │
│   트렁크(배터) │
└────────────────┘
     ↑
모두 한 CAN 버스로 연결!

3️⃣ 멀티플렉싱 (여러 신호를 한 메시지에)

CAN 메시지 (8바이트):
┌────────────────────────────────────────┐
│ ID: 0x100 (메시지 ID)                 │
├────────────────────────────────────────┤
│ Data[0:7] (8바이트 = 64비트)          │
│ ┌─────────────────────────────────────┐
│ │ Byte 0: 엔진 RPM (높은 자리)         │
│ │ Byte 1: 엔진 RPM (낮은 자리)         │
│ │ Byte 2: 엔진 온도                   │
│ │ Byte 3: 냉각수 온도                 │
│ │ Byte 4: 연료 압력                   │
│ │ Byte 5: 엔진 부하                   │
│ │ Byte 6-7: 예약                      │
│ └─────────────────────────────────────┘
│
└────────────────────────────────────────┘

하나의 메시지에 여러 신호가 담겨있어요!
(효율적!)

📡 신호와 메시지의 관계

신호 (Signal)란?

신호 = SWC가 주고받는 논리적 데이터

예시: 엔진 RPM 신호

SWC 계층:
EngineControlSWC: "엔진 RPM = 2500 rpm"

논리 단위:
- 부동소수점 숫자: 2500.0
- 단위: rpm (회전 분당)
- 범위: 0 ~ 8000 rpm

메시지 (Message)란?

메시지 = CAN 버스에서 전송되는 물리적 데이터

예시: CAN 메시지

물리 단위:
- ID: 0x100 (16진수 메시지 ID)
- 데이터: 0x0B, 0xB8, 0x5A, 0x64, ... (바이트들)
- 길이: 8바이트 (데이터 길이)

CAN 버스 상:
0x100 #0B B8 5A 64 00 00 00 00

신호 ↔ 메시지 변환

[SWC 계층] 신호
    ↓
EngineRPM = 2500 rpm
    ↓
[COM 계층] 변환
    ↓
설정: "EngineRPM은 ID 0x100의 Byte[0:1]"
      "스케일: 0.25, 오프셋: 0"
      "Intel 바이트 오더"
    ↓
계산:
신호값 = (물리값 - 오프셋) / 스케일
       = (2500 - 0) / 0.25
       = 10000
    ↓
16비트 정수로 변환:
10000 = 0x2710
    ↓
Intel 바이트 오더 적용:
높은 바이트: 0x27
낮은 바이트: 0x10
    ↓
CAN 메시지에 삽입:
Data[0] = 0x10 (낮은 바이트)
Data[1] = 0x27 (높은 바이트)
    ↓
[CAN 버스] 메시지
    ↓
CAN ID 0x100 전송!

구체적 계산 예시

상황: 엔진 온도를 CAN으로 전송하려고 함

설정:
- 신호명: EngineTemperature
- CAN ID: 0x200
- 시작 바이트: 2
- 길이: 8비트
- 스케일: 0.5
- 오프셋: -40
- 범위: -40 ~ 87.5 도씨

현재 엔진 온도: 90도씨

변환:
신호값 = (물리값 - 오프셋) / 스케일
       = (90 - (-40)) / 0.5
       = 130 / 0.5
       = 260

8비트로 표현:
260 = 0x104 (너무 크다!)
→ 범위 초과 오류!

올바른 데이터:
물리값 87도씨 사용 (범위 내)
신호값 = (87 - (-40)) / 0.5 = 254

CAN 메시지:
Data[2] = 0xFE (254)

수신측에서 복구:
물리값 = (신호값 × 스케일) + 오프셋
       = (254 × 0.5) + (-40)
       = 127 - 40
       = 87도씨 ✓

📋 DBC 파일: 신호와 메시지 정의

DBC 파일이란?

DBC (Database Class) = CAN 신호 및 메시지를 정의하는 파일
자동차 개발에서 가장 중요한 설정 파일 중 하나예요.

Candb라고 부릅니다

DBC 파일 구조

VERSION ""

NS_ : 
    NS_DESC_
    CM_
    BA_DEF_
    BA_
    VAL_
    CAT_DEF_
    CAT_
    FILTER
    BA_DEF_DEF_
    EV_DATA_
    ENVVAR_DATA_
    SGTYPE_
    SGTYPE_VAL_
    BA_DEF_SGTYPE_
    BA_SGTYPE_
    SIG_TYPE_REF_
    VAL_TABLE_
    SIG_GROUP_
    SIG_VALTYPE_
    SIGTYPE_VALTYPE_
    BO_TX_BU_
    BA_DEF_REL_
    BA_REL_
    BA_SGTYPE_REL_
    SG_MUL_VAL_

BS_:

BU_: EngineECU TransmissionECU BrakeECU

BO_ 100 ENGINE_DATA: 8 EngineECU
 SG_ EngineRPM : 0|16@1+ (0.25,0) [0|16383] "rpm" TransmissionECU
 SG_ CoolantTemp : 16|8@1- (0.5,-40) [-40|87] "C" TransmissionECU
 SG_ EngineLoad : 24|8@1+ (0.5,0) [0|127.5] "%" TransmissionECU

BO_ 200 TRANSMISSION_DATA: 8 TransmissionECU
 SG_ SelectedGear : 0|3@1+ (1,0) [0|7] "" EngineECU
 SG_ TorqueLimit : 8|16@1+ (1,0) [0|65535] "Nm" EngineECU

BO_ 300 BRAKE_DATA: 8 BrakeECU
 SG_ BrakePressure : 0|16@1+ (0.1,0) [0|6553.5] "kPa" TransmissionECU

VAL_ 200 SelectedGear 0 "Park" 1 "Reverse" 2 "Neutral" 3 "Drive" 4 "Sport" 7 "Fault" ;

DBC 파일 해석

BO_ 100 ENGINE_DATA: 8 EngineECU
│    │  │            │ │
│    │  │            │ └─ 송신 ECU
│    │  │            └─ 데이터 길이 (8바이트)
│    │  └─ 메시지 이름
│    └─ 메시지 ID (0x100 = 256)
└─ 메시지 정의 시작

 SG_ EngineRPM : 0|16@1+ (0.25,0) [0|16383] "rpm" TransmissionECU
 │   │          │ │ │ │  │      │ │         │      └─ 수신 ECU(들)
 │   │          │ │ │ │  │      │ │         └─ 단위
 │   │          │ │ │ │  │      │ └─ 범위: 0 ~ 16383
 │   │          │ │ │ │  │      └─ 스케일: 0.25, 오프셋: 0
 │   │          │ │ │ │  └─ Intel 바이트 오더, Unsigned
 │   │          │ │ │ └─ 길이: 16비트
 │   │          │ │ └─ 시작 비트: 0
 │   │          └─ 신호 정의 시작
 │   └─ 신호 이름
 └─ 신호 정의

바이트 오더:
@1+ = Intel (Little Endian, Unsigned)
@1- = Intel (Little Endian, Signed)
@0+ = Motorola (Big Endian, Unsigned)
@0- = Motorola (Big Endian, Signed)

🔄 COM 모듈: 신호 ↔ 메시지 자동 변환

COM 모듈이란?

COM = Communication Manager
AUTOSAR BSW의 핵심 모듈이에요. 신호와 메시지를 자동으로 변환해줘요.

ComM으로 불러요

COM 모듈의 역할

1️⃣ 신호 인코딩 (Signal Encoding)
신호 → CAN 메시지로 변환

예시: 엔진 RPM 전송

Step 1: SWC가 값 제공
Rte_Write_EngineRPM(2500) 호출

Step 2: COM이 DBC 규칙 적용
설정: "EngineRPM: ID 0x100, Byte[0:1], scale 0.25"

Step 3: 계산
신호값 = (2500 - 0) / 0.25 = 10000
16비트: 0x2710

Step 4: CAN 메시지 생성
Data[0] = 0x10
Data[1] = 0x27

Step 5: CAN 드라이버에 전달
"CAN ID 0x100 전송해!"

2️⃣ 신호 디코딩 (Signal Decoding)
CAN 메시지 → 신호로 변환

예시: 변속기에서 엔진 RPM 받기

Step 1: CAN 드라이버가 메시지 수신
Data[0] = 0x10
Data[1] = 0x27

Step 2: COM이 디코딩
ID 0x100 인식
"아, 이건 EngineRPM이네"

Step 3: 바이트 추출
16비트 값: 0x2710 = 10000

Step 4: 역계산
물리값 = (10000 × 0.25) + 0 = 2500

Step 5: SWC에 제공
Rte_Read_EngineRPM() → 2500 반환

3️⃣ 주기적 전송 (Periodic Transmission)
주기마다 자동으로 신호 전송

설정:
- EngineRPM: 10ms 주기로 전송
- EngineTemp: 100ms 주기로 전송

타임라인:
Time:     0ms  10ms  20ms  30ms  40ms  50ms  60ms  70ms  80ms  90ms  100ms
        ─────────────────────────────────────────────────────────────────

RPM:      ┌──┐  ┌──┐  ┌──┐  ┌──┐  ┌──┐  ┌──┐  ┌──┐  ┌──┐  ┌──┐  ┌──┐
          ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑   ↑

Temp:     ┌──────────────────────┐  ┌──────────────────────┐
          ↑                       ↑                        ↑

COM이 타이밍 관리!

4️⃣ 신호 필터링 (Signal Filtering)
변화가 없으면 전송하지 않음 (네트워크 효율)

EngineRPM 변화:
2500 → 2501 (1 증가)
→ 거의 변화 없음 → 전송 안 함!

설정:
"변화가 10 rpm 이상이면 전송"

2500 → 2512 (12 증가)
→ 충분한 변화 → 전송!

COM 모듈의 구조

┌─────────────────────────────────────────┐
│  COM (Communication Manager)             │
├─────────────────────────────────────────┤
│                                         │
│  신호 버퍼 (Signal Buffer)               │
│  ┌─────────────────────────────────────┐
│  │ EngineRPM: 2500                     │
│  │ CoolantTemp: 90                     │
│  │ BrakePressure: 250                  │
│  │ ...                                 │
│  └─────────────────────────────────────┘
│                 ↓
│  인코딩/디코딩 엔진                      │
│  ┌─────────────────────────────────────┐
│  │ DBC 규칙 적용                       │
│  │ 바이트 오더 변환                     │
│  │ 스케일 × 오프셋 계산                 │
│  └─────────────────────────────────────┘
│                 ↓
│  메시지 버퍼 (Message Buffer)            │
│  ┌─────────────────────────────────────┐
│  │ ID 0x100: [0x10, 0x27, 0x5A, ...]  │
│  │ ID 0x200: [0x03, 0x00, 0x00, ...]  │
│  │ ID 0x300: [0xFA, 0x00, 0x00, ...]  │
│  │ ...                                 │
│  └─────────────────────────────────────┘
│                 ↓
│  CAN 드라이버 (CAN Driver)
│
└─────────────────────────────────────────┘

📊 실제 신호 매핑 예시

예시: 현대 쏘나타 엔진 메시지

DBC 정의:

BO_ 0x100 ENGINE_INFO: 8 EngineECU
 SG_ EngineSpeed : 0|16@1+ (0.25,0) [0|16383] "rpm" Vector__XXX
 SG_ EngineLoad : 16|8@1+ (0.5,0) [0|127.5] "%" Vector__XXX
 SG_ CoolantTemp : 24|8@1- (0.5,-40) [-40|87.5] "degC" Vector__XXX
 SG_ ThrottlePos : 32|8@1+ (0.5,0) [0|127.5] "%" Vector__XXX
 SG_ FuelPressure : 40|8@1+ (10,0) [0|2550] "kPa" Vector__XXX

현재 자동차 상태:
- EngineSpeed: 3000 rpm
- EngineLoad: 60%
- CoolantTemp: 85도씨
- ThrottlePos: 50%
- FuelPressure: 350 kPa

COM 모듈의 변환 과정:

신호              계산                    바이트 결과
─────────────────────────────────────────────
EngineSpeed:    (3000 - 0) / 0.25        = 12000 = 0x2EE0
                Intel 바이트 오더:
                Data[0] = 0xE0
                Data[1] = 0x2E

EngineLoad:     (60 - 0) / 0.5           = 120 = 0x78
                Data[2] = 0x78

CoolantTemp:    (85 - (-40)) / 0.5       = 250 = 0xFA
                Data[3] = 0xFA

ThrottlePos:    (50 - 0) / 0.5           = 100 = 0x64
                Data[4] = 0x64

FuelPressure:   (350 - 0) / 10           = 35 = 0x23
                Data[5] = 0x23

CAN 메시지 최종:
ID: 0x100
Data: E0 2E 78 FA 64 23 00 00

수신측 (변속기 ECU):
받은 메시지 ID 0x100, Data: E0 2E 78 FA 64 23 00 00

COM 디코딩:
EngineSpeed = (0x2EE0 × 0.25) = 3000 rpm ✓
EngineLoad = (0x78 × 0.5) = 60% ✓
CoolantTemp = (0xFA × 0.5) - 40 = 85도씨 ✓
ThrottlePos = (0x64 × 0.5) = 50% ✓
FuelPressure = (0x23 × 10) = 350 kPa ✓

완벽하게 복구됨!

🔀 바이트 오더 (Byte Order)

CAN 신호를 저장할 때, 바이트 순서가 중요해요.

Intel 바이트 오더 (Little Endian)

낮은 바이트가 먼저 저장돼요.

신호값: 0x2710 (10000)

Intel 저장:
Data[0] = 0x10 (낮은 바이트)
Data[1] = 0x27 (높은 바이트)

읽을 때: Data[0] + Data[1] × 256 = 0x10 + 0x27 × 256 = 0x2710 ✓

아래에서 위로 쌓는 느낌!
Data[1] │ 0x27 │
Data[0] │ 0x10 │
        └──────┘

Motorola 바이트 오더 (Big Endian)

높은 바이트가 먼저 저장돼요.

신호값: 0x2710 (10000)

Motorola 저장:
Data[0] = 0x27 (높은 바이트)
Data[1] = 0x10 (낮은 바이트)

읽을 때: Data[0] × 256 + Data[1] = 0x27 × 256 + 0x10 = 0x2710 ✓

위에서 아래로 쌓는 느낌!
Data[0] │ 0x27 │
Data[1] │ 0x10 │
        └──────┘

바이트 오더 설정 실수

❌ 잘못된 경우:
DBC는 Intel로 정의했는데,
C 코드는 Motorola로 처리

결과: 신호값 역변환!
받은 값 0x2710이 0x1027로 읽혀서
물리값이 완전히 다르게 계산됨

→ 버그!

💡 CAN 통신 흐름 완전 정리

[시간 10ms]

┌─────────────────────┐
│ EngineControlSWC    │
├─────────────────────┤
│ 엔진 RPM 계산       │
│ rpm = 3000          │
│                     │
│ Rte_Write_EngineRPM(3000)
└──────┬──────────────┘
       │ (RTE 호출)
       ▼
┌─────────────────────┐
│ RTE (자동 생성)     │
├─────────────────────┤
│ EngineRPM 신호을   │
│ COM에 전달          │
└──────┬──────────────┘
       │
       ▼
┌─────────────────────┐
│ COM 모듈            │
├─────────────────────┤
│ 신호 인코딩:        │
│ 3000 rpm            │
│ → 신호값 12000      │
│ → 바이트 변환       │
│ → Data[0:1]에 저장 │
└──────┬──────────────┘
       │
       ▼
┌─────────────────────┐
│ CanIf              │
│ (CAN 인터페이스)   │
├─────────────────────┤
│ 메시지 라우팅      │
│ CAN1로 결정        │
└──────┬──────────────┘
       │
       ▼
┌─────────────────────┐
│ CAN 드라이버       │
├─────────────────────┤
│ CAN ID 0x100      │
│ 메시지 전송!      │
└──────┬──────────────┘
       │
       ▼
┌─────────────────────┐
│ CAN 버스           │
├─────────────────────┤
│ 0x100 #E0 2E ...  │
│ (물리 신호)        │
└──────┬──────────────┘
       │
       │ (다른 ECU에서 수신)
       ▼
┌─────────────────────┐
│ 변속기 ECU         │
│ CAN 드라이버       │
├─────────────────────┤
│ 메시지 0x100 수신  │
└──────┬──────────────┘
       │
       ▼
┌─────────────────────┐
│ COM 모듈           │
├─────────────────────┤
│ 신호 디코딩:       │
│ Data[0:1] = E0 2E │
│ → 신호값 12000    │
│ → 물리값 3000     │
└──────┬──────────────┘
       │
       ▼
┌─────────────────────┐
│ RTE (자동 생성)    │
├─────────────────────┤
│ TransmissionSWC에  │
│ EngineRPM = 3000  │
│ 전달              │
└──────┬──────────────┘
       │
       ▼
┌─────────────────────┐
│ TransmissionSWC     │
├─────────────────────┤
│ "엔진이 3000 rpm   │
│ 돌고 있네"         │
│ → 기어 선택 결정   │
└─────────────────────┘

정리: CAN 통신의 핵심

CAN 버스 모든 ECU를 연결하는 통신 네트워크 500 kbps, 노이즈 견고
신호 SWC가 주고받는 논리적 데이터 엔진 RPM = 2500 rpm
메시지 CAN 버스에 전송되는 물리적 데이터 ID 0x100, 8바이트
DBC 파일 신호와 메시지 정의 파일 스케일, 오프셋, 바이트 오더
COM 모듈 신호 ↔ 메시지 자동 변환 인코딩/디코딩, 필터링
바이트 오더 다중 바이트 신호의 저장 순서 Intel (Little Endian) vs Motorola (Big Endian)

마치며

이제 신호가 어떻게 CAN 메시지로 변환되고, COM 모듈이 어떻게 관리되는지 명확해졌나요?
Lin의 시대를 넘어 CAN의 시대로 그리고 CAN으로 모자라 CAN FD로 가고 그보다 더 빠른 CAN을 도입하려고 하고 있죠
이젠 CAN FD로만 구성되는 차가 대부분이 되어갑니다.
 
이번에 CAN을 배웠으니까!!
다음엔 또 다른것을 배워볼텐데요,
AUTOSAR BSW에는 이런 COM 모듈 외에도 5가지 중요한 모듈들이 있어요.
NvM (메모리), Dem (진단), CanIf (인터페이스)...
다음 편에서는 "AUTOSAR BSW: 가장 중요한 5개 모듈의 역할과 상호작용"을 주제로 포스팅해보겠습니다.
각 모듈이 정확히 뭐 하는지, 어떻게 협력하는지 명확하게 설명해볼게요
쉽게! 이해하기 좋게! 그림과 함