SCSI 병렬 인터페이스의 구조와 스토리지 연결 방식
SCSI의 병렬 버스 구조, 명령어 큐잉, ID·LUN 주소 지정과 SAS·iSCSI·Fibre Channel로의 발전을 정리한다.
2026-08-14 · 최초 발행 2026-01-06
병렬 버스에서 시작한 주변 장치 연결 표준
SCSI는 하드 디스크, 테이프 드라이브, CD-ROM 등 여러 주변 장치를 컴퓨터에 연결하기 위한 병렬 인터페이스 표준이다. 1979년 Shugart Associates가 개발한 SASI를 바탕으로 1986년 ANSI 표준이 됐으며, 하나의 버스에 최대 15개 장치를 연결할 수 있다. 명령어 큐잉과 태그를 사용해 명령을 동시에 처리할 수도 있다.
초기 전송률은 5MB/s였고, Ultra320 SCSI에서는 320MB/s까지 발전했다. 병렬 방식은 이후 SAS 같은 직렬 인터페이스와 iSCSI 같은 네트워크 기반 전송으로 이어졌다.
SCSI는 컴퓨터와 주변 장치 사이의 연결 방식을 표준화하고, 다양한 장치를 지원하면서 고성능 전송과 확장성을 제공하는 데 목적이 있다. 초기 SCSI는 병렬 버스를 기반으로 했으며 ANSI X3.131 표준으로 정의됐다.
SASI 이후의 주요 흐름은 다음과 같다.
- 1979년: Shugart Associates가 SASI 개발
- 1981년: NCR, Adaptec 등이 표준화 작업 시작
- 1986년: ANSI SCSI-1 표준(X3.131-1986)
- 1994년: SCSI-2와 Fast SCSI(10MB/s)
- 1996년: SCSI-3와 Ultra SCSI(20MB/s)
- 2000년대: Ultra320 SCSI(320MB/s)
- 2005년 이후: SAS로 전환
Wide SCSI에서는 하나의 버스에 최대 16개 장치를 데이지 체인으로 연결하며, 버스 끝에는 터미네이터가 필요하다. Tagged Command Queuing(TCQ)은 여러 명령을 동시 처리하는 방식이며, Native Command Queuing(NCQ)의 선행 기술로 언급된다. SCSI-2 이후에는 전원이 켜진 상태에서 장치를 추가하거나 제거하는 핫 플러그도 지원한다.
Initiator와 Target이 연결되는 방식
SCSI 아키텍처에서 Initiator는 명령을 발생시키는 쪽이다. 일반적으로 호스트 어댑터가 이 역할을 맡고 SCSI ID를 할당받는다. Target은 명령을 수신하는 장치로, 하드 디스크나 테이프 드라이브 등이 여기에 해당한다. 하나의 Target은 여러 Logical Unit을 포함할 수 있다.
SCSI Bus는 Initiator와 Target 사이에서 데이터, 주소, 제어 신호를 전달한다. 연결 방식은 차동 또는 단일 종단으로 나뉜다.
Narrow SCSI의 신호 구성은 데이터 라인 8비트(D0-D7), 패리티 1비트, 제어 라인 9개다. Wide SCSI는 데이터 라인을 16비트(D0-D15), 패리티를 2비트로 확장하고 제어 라인은 동일하게 유지한다.
버스 제어에는 다음 신호가 사용된다.
- BSY(Busy): 버스 사용 중
- SEL(Select): 장치 선택
- ATN(Attention): 주의 요청
- ACK(Acknowledge): 응답
- REQ(Request): 요청
- MSG, C/D, I/O: 단계 표시
SCSI-3는 명령, 전송, 물리 계층을 분리한 구조로 발전했다.
+---------------------------+
| SCSI Application Layer | (SCSI Commands)
+---------------------------+
| SCSI Transport Protocol | (SPI, FC, iSCSI)
+---------------------------+
| SCSI Interconnect | (Physical)
+---------------------------+
상위 계층은 SPC, SBC, SSC 같은 명령어 세트를, 중간 계층은 SPI, FCP, iSCSI 같은 전송 프로토콜을 다룬다. 하위 계층은 Parallel, Serial, Network 같은 물리 연결을 담당한다.
장치 명령과 큐잉 모델
SCSI 장치는 준비 상태를 확인하는 TEST UNIT READY, 장치 정보를 조회하는 INQUIRY, 오류 정보를 받는 REQUEST SENSE, 데이터를 읽고 쓰는 READ와 WRITE를 기본 명령으로 사용한다.
블록 장치 명령어(SBC)의 READ(10), WRITE(10) 구조는 다음과 같다.
// READ(10) 명령어 구조
struct scsi_read10_cmd {
uint8_t opcode; // 0x28
uint8_t flags;
uint32_t lba; // Logical Block Address
uint8_t reserved;
uint16_t transfer_length;
uint8_t control;
} __attribute__((packed));
// WRITE(10) 명령어
struct scsi_write10_cmd {
uint8_t opcode; // 0x2A
uint8_t flags;
uint32_t lba;
uint8_t reserved;
uint16_t transfer_length;
uint8_t control;
} __attribute__((packed));
명령은 CDB(Command Descriptor Block)에 담긴다. CDB는 6바이트, 10바이트, 대용량을 위한 16바이트 형식으로 구성할 수 있다.
// 6바이트 CDB
struct scsi_cdb6 {
uint8_t opcode;
uint8_t lba_high : 5;
uint8_t lun : 3;
uint16_t lba_low;
uint8_t length;
uint8_t control;
};
// 10바이트 CDB
struct scsi_cdb10 {
uint8_t opcode;
uint8_t flags;
uint32_t lba;
uint8_t reserved;
uint16_t length;
uint8_t control;
};
// 16바이트 CDB (대용량)
struct scsi_cdb16 {
uint8_t opcode;
uint8_t flags;
uint64_t lba;
uint32_t length;
uint8_t reserved;
uint8_t control;
};
Tagged Command Queuing은 장치가 여러 명령을 보유하도록 하고, Elevator Algorithm에 따라 더 적절한 순서로 실행할 수 있게 한다.
// 명령어 태그
enum scsi_task_attribute {
TASK_ATTR_SIMPLE = 0, // 순서 보장 없음
TASK_ATTR_ORDERED = 1, // 순서 보장
TASK_ATTR_HEAD_OF_QUEUE = 2, // 우선 처리
};
// 태그를 포함한 명령어
struct scsi_tagged_cmd {
struct scsi_cdb10 cdb;
uint8_t tag_type;
uint16_t tag_value;
};
병렬 SCSI가 확장된 흐름
SCSI-1은 1986년에 표준화됐고, 8비트 버스에서 최대 5MB/s를 제공하며 최대 8개 장치를 지원했다. 명령어 세트가 불완전했고 비동기 전송만 지원했으며, 케이블 길이는 6m로 제한됐다.
SCSI-2는 1994년에 Fast SCSI 10MB/s, 16비트 Wide SCSI와 16개 장치 연결, Tagged Command Queuing, 확장된 명령어 세트를 제공했다. 1996년 이후의 SCSI-3는 Ultra SCSI 20MB/s와 LVD 기반 Ultra2 SCSI 40MB/s를 포함했고, SPI·FCP·SSA 등 다양한 전송 방식을 모듈화된 표준으로 다뤘다.
| 버전 | 버스 폭 | 속도 | 최대 전송률 |
|---|---|---|---|
| SCSI-1 | 8비트 | 5MHz | 5MB/s |
| Fast SCSI | 8비트 | 10MHz | 10MB/s |
| Ultra SCSI | 8비트 | 20MHz | 20MB/s |
| Ultra2 SCSI | 8비트 | 40MHz | 40MB/s |
| Ultra160 SCSI | 16비트 | 40MHz (DDR) | 160MB/s |
| Ultra320 SCSI | 16비트 | 80MHz (DDR) | 320MB/s |
Wide SCSI는 16비트 데이터 버스를 사용해 전송률을 2배로 높이며, Wide와 Ultra를 함께 조합할 수 있다.
SCSI ID와 LUN으로 장치를 지정하는 방법
SCSI ID는 버스 위 장치를 구분하는 고유 식별자다. Narrow SCSI에서는 07, Wide SCSI에서는 015를 사용한다. 호스트 어댑터는 보통 ID 7을 사용하며, 높은 ID일수록 중재 과정에서 우선순위가 높다. ID 7이 최고 우선순위다.
ID는 점퍼 스위치, SCA의 소프트웨어 설정, 자동 할당으로 설정할 수 있다.
LUN(Logical Unit Number)은 하나의 Target 안에 있는 논리 장치를 가리킨다. SCSI-2에서는 07, SCSI-3에서는 0255를 사용할 수 있다. RAID 컨트롤러의 여러 볼륨이 LUN 사용 예시에 해당한다.
// SCSI 주소 지정
struct scsi_address {
uint8_t host; // 호스트 어댑터 번호
uint8_t channel; // 채널 번호
uint8_t id; // SCSI ID (Target)
uint8_t lun; // Logical Unit Number
};
// Linux 장치 경로 예시
// /dev/sda: Host 0, Channel 0, ID 0, LUN 0
// /dev/sdb: Host 0, Channel 0, ID 1, LUN 0
// /dev/sdc: Host 0, Channel 0, ID 2, LUN 0
SCSI-3에서 도입된 WWN(World Wide Name)은 64비트 고유 식별자이며 Fibre Channel에서 사용한다.
struct wwn {
uint8_t naa : 4; // Name Address Authority
uint8_t vendor : 24; // Vendor ID
uint8_t serial : 36; // Serial Number
} __attribute__((packed));
버스 접근부터 데이터 전송까지
여러 Initiator가 동시에 버스에 접근하면 중재 과정이 충돌을 막는다. 먼저 BSY 신호로 버스 사용 여부를 확인하고, 각 Initiator는 자신의 ID를 데이터 라인에 출력한다. 가장 높은 ID가 버스를 획득한다.
bool scsi_arbitrate(uint8_t my_id) {
// BSY 대기
while (read_signal(BSY));
// ID 출력
write_data_line(1 << my_id);
set_signal(BSY);
// 중재 지연
udelay(ARBITRATION_DELAY);
// 데이터 라인 확인
uint8_t data = read_data_line();
// 더 높은 ID 존재?
for (int i = 7; i > my_id; i--) {
if (data & (1 << i)) {
// 패배
clear_signal(BSY);
return false;
}
}
// 승리
return true;
}
중재에서 승리한 Initiator는 Target ID를 데이터 라인에 출력하고 SEL 신호를 활성화한다. Target이 BSY 신호로 응답하면 선택이 완료된다.
bool scsi_select_target(uint8_t target_id) {
uint8_t data = (1 << my_id) | (1 << target_id);
write_data_line(data);
set_signal(SEL);
clear_signal(BSY);
// Target 응답 대기
wait_for_signal(BSY, TIMEOUT);
if (read_signal(BSY)) {
clear_signal(SEL);
return true; // 선택 성공
}
return false; // 타임아웃
}
선택 뒤에는 Command Phase에서 CDB를 전송하고, 필요할 경우 Data Phase에서 데이터를 주고받는다. 이어 Status Phase에서 상태를 반환하고 Message Phase에서 메시지를 교환한다. 데이터 전송은 REQ/ACK 핸드셰이크로 이뤄진다.
// REQ/ACK 핸드셰이크
void scsi_transfer_byte(uint8_t byte) {
// Target이 REQ 활성화 대기
wait_for_signal(REQ, TIMEOUT);
// 데이터 출력
write_data_line(byte);
// ACK 활성화
set_signal(ACK);
// Target이 REQ 비활성화 대기
wait_for_signal_clear(REQ, TIMEOUT);
// ACK 비활성화
clear_signal(ACK);
}
IDE와 SATA가 다른 지점
| 항목 | SCSI (Ultra320) | IDE (ATA-133) | SATA III |
|---|---|---|---|
| 최대 전송률 | 320MB/s | 133MB/s | 600MB/s |
| 장치 수 | 15개 | 2개 | 1개 |
| 명령어 큐 | TCQ (256) | NCQ (32) | NCQ (32) |
| 케이블 길이 | 12m (LVD) | 0.5m | 1m |
SCSI는 다중 장치 연결, 높은 안정성, 명령어 큐잉, 핫 플러그를 제공하며 서버 환경에 적합하다. 반면 IDE/SATA는 비용이 낮고 구성이 간단하며 데스크톱과 비용 민감 환경에 적합하고 호환성이 넓다.
SCSI는 서버, 워크스테이션, RAID 시스템, 고성능 스토리지에 사용된다. IDE/SATA는 데스크톱 PC와 개인용 스토리지에 주로 맞는다.
데이터베이스 서버에서는 높은 IOPS 요구사항, 명령어 큐잉, 여러 디스크 동시 접근이 SCSI 활용 맥락이 된다. 메일 서버에서는 안정성과 핫 플러그를 이용한 유지보수, RAID 구성이 중요하다.
SAN에서는 Fibre Channel SCSI로 대규모 스토리지를 연결하고 고속 전송을 수행한다. RAID 컨트롤러는 여러 디스크를 관리하며 LUN 기반 볼륨 구성, 캐시, 최적화를 담당한다. 비디오 편집은 대용량 파일 처리와 높은 순차 읽기·쓰기가 필요하고, CAD/CAM은 빠른 파일 액세스와 신뢰성, 다중 디스크 구성이 요구된다.
SCSI 명령 체계를 이어받은 전송 기술
SAS(Serial Attached SCSI)는 직렬 인터페이스와 포인트-투-포인트 연결을 사용하며 SATA 호환성을 제공한다.
- SAS-1: 3Gb/s (300MB/s)
- SAS-2: 6Gb/s (600MB/s)
- SAS-3: 12Gb/s (1200MB/s)
- SAS-4: 22.5Gb/s (2400MB/s)
// SAS 주소 (WWN)
struct sas_address {
uint64_t wwn; // World Wide Name
};
// SAS PHY
struct sas_phy {
struct sas_address address;
uint8_t phy_id;
enum sas_linkrate linkrate;
};
iSCSI는 IP 네트워크 위에서 SCSI를 사용하는 TCP/IP 기반 방식이다. 기존 네트워크 인프라를 활용해 원격 스토리지에 접근할 수 있고 확장성을 제공한다.
Initiator (Client) <---> IP Network <---> Target (Storage)
Fibre Channel은 광섬유 또는 구리를 기반으로 하며 FCP(Fibre Channel Protocol)를 사용해 SAN을 구성한다.
- 1GFC: 1Gb/s
- 2GFC: 2Gb/s
- 4GFC: 4Gb/s
- 8GFC: 8Gb/s
- 16GFC: 16Gb/s
- 32GFC: 32Gb/s