PLC 프로그램 규모가 커지면 모든 로직을 매 스캔마다 연산하는 구조가 비효율적일 수 있습니다. 특히 특정 조건에서만 필요한 비교, 문자열 처리, 데이터 검사, 에러 처리 루틴이 매번 실행되면 스캔 타임이 길어지고 입력 감지나 출력 응답 타이밍에 영향을 줄 수 있습니다. 이때 CJ 명령어를 사용하면 조건에 따라 불필요한 로직 구간을 건너뛰어 스캔 효율을 개선할 수 있습니다.
스캔 타임을 관리해야 하는 이유
PLC는 입력을 읽고, 프로그램을 연산하고, 출력을 갱신하는 과정을 반복합니다. 이 한 바퀴에 걸리는 시간이 스캔 타임입니다.
스캔 타임이 길어지면 단순히 PLC가 느려지는 문제가 아니라, 설비의 반응 타이밍이 늦어질 수 있습니다. 현장에서는 몇 ms 차이로 센서 감지, 정지 응답, 통신 처리 결과가 달라질 수 있습니다.
스캔 타임이 길어졌을 때 발생할 수 있는 문제는 다음과 같습니다.
| 문제 | 설명 |
|---|---|
| 입력 신호 누락 | 짧은 센서 신호가 스캔 주기 사이에 지나갈 수 있음 |
| 출력 응답 지연 | 정지, 차단, 다음 동작 신호가 늦게 나갈 수 있음 |
| 통신 주기 불안정 | 상위 장비, 인버터, 서보와의 통신 처리 타이밍이 흔들릴 수 있음 |
| 타이머·카운터 조건 지연 | 조건 판단이 늦어져 공정 흐름이 달라질 수 있음 |
| 디버깅 난이도 증가 | 어느 구간에서 시간이 걸리는지 찾기 어려워짐 |
스캔 타임 문제는 단순한 속도 문제가 아니라 설비의 입력과 출력이 언제 반응하느냐의 문제입니다. 따라서 프로그램이 커질수록 꼭 필요한 로직만 필요한 시점에 실행되도록 구성하는 것이 중요합니다.
본 글은 미쓰비시 MELSEC Q/R 시리즈 및 GX Works2/3 기준의 일반적인 내용을 바탕으로 작성했습니다. CJ 명령어의 세부 동작, 포인터 사용 범위, 제한 조건은 CPU 모델과 프로그램 구조에 따라 달라질 수 있으므로 실제 적용 전 매뉴얼을 확인해야 합니다.
CJ 명령어의 기본 개념
CJ는 Conditional Jump의 약자로, 조건이 성립했을 때 지정한 포인터 위치로 프로그램 실행 흐름을 이동시키는 명령어입니다.
예를 들어 특정 조건이 ON되면 현재 위치부터 지정된 포인터까지의 로직을 연산하지 않고 건너뜁니다. 조건이 OFF이면 점프하지 않고 아래 로직을 그대로 실행합니다.
CJ의 핵심은 출력 제어가 아니라 연산 구간 생략입니다.
| 구분 | 설명 |
|---|---|
| CJ 조건 OFF | 아래 로직을 그대로 실행 |
| CJ 조건 ON | 지정한 포인터 위치까지 점프 |
| 점프된 구간 | 해당 스캔에서 연산되지 않음 |
| 포인터 위치 | 점프 후 다시 실행이 이어지는 위치 |
CJ는 특정 출력을 끄는 명령이 아닙니다. CPU가 해당 구간을 읽지 않고 지나가게 만드는 명령에 가깝습니다. 이 차이를 이해하지 못하면 출력 HOLD 문제가 생길 수 있습니다.
CJ는 로직을 끄는 기능이 아니다
CJ를 사용할 때 가장 중요한 점은 CJ가 로직을 OFF시키는 기능이 아니라는 것입니다.
MC/MCR은 특정 구간을 상위 조건으로 묶어 일반 출력이 OFF되도록 만드는 구조로 사용할 수 있습니다. 반면 CJ는 조건이 성립하면 해당 구간의 연산 자체를 건너뜁니다.
즉, CJ로 건너뛴 구간은 그 스캔에서 판단되지 않습니다. 해당 구간 안에 출력 OFF 조건이나 RST 조건이 있어도, 점프가 걸리면 그 조건은 실행되지 않을 수 있습니다.
| 구분 | MC/MCR | CJ |
|---|---|---|
| 기본 성격 | 구간 제어 | 실행 흐름 이동 |
| OFF 처리 | 일반 출력 차단 구조로 사용 가능 | 구간을 연산하지 않고 건너뜀 |
| 내부 로직 | MC 조건에 따라 처리 | 점프 시 실행되지 않음 |
| 주의점 | SET/RST 위치 확인 필요 | 출력 HOLD와 RST 미실행 주의 |
CJ는 성능 개선에 유용하지만, 출력 차단이나 안전 인터락 목적으로 직접 사용하면 위험할 수 있습니다.
CJ를 사용하는 대표적인 상황
CJ는 매 스캔마다 실행할 필요가 없는 로직을 조건부로 처리할 때 효과적입니다.
예를 들어 다음과 같은 구간은 CJ 적용을 검토할 수 있습니다.
| 적용 구간 | 설명 |
|---|---|
| 자동운전 전용 로직 | 수동 모드일 때 자동 시퀀스 연산 생략 |
| 모델 변경 처리 | 모델 변경 요청이 있을 때만 레시피 복사 실행 |
| 문자열 비교 | 데이터 수신 완료 시에만 비교 루틴 실행 |
| 알람 분석 루틴 | 알람 발생 시에만 상세 분석 실행 |
| 대량 데이터 검사 | 검사 요청이 있을 때만 연산 실행 |
| 통신 송신 준비 | 송신 조건이 있을 때만 데이터 조립 |
반대로 매 스캔 반드시 확인해야 하는 안전 조건, 정지 조건, 비상정지 관련 최종 출력 조건은 CJ로 건너뛰지 않는 것이 좋습니다.
문자열 비교 루틴에 CJ를 적용하는 예
비전 장비나 바코드 리더기에서 문자열 데이터를 받아 기준 문자열과 비교하는 공정이 있다고 가정합니다. 수신되는 문자열이 길고 비교 항목이 많다면, 이 비교 루틴을 매 스캔 실행하는 것은 불필요할 수 있습니다.
기존 구조에서는 새 데이터가 들어오지 않아도 문자열 비교가 계속 실행됩니다. 데이터가 바뀌지 않았는데도 CPU는 같은 비교 연산을 반복합니다.
이런 경우에는 리딩 완료 비트가 ON되었을 때만 비교 루틴을 실행하도록 구성할 수 있습니다.
흐름은 다음과 같이 정리할 수 있습니다.
| 상태 | 처리 |
|---|---|
| 평상시 | 문자열 비교 루틴 생략 |
| 리딩 완료 | 비교 루틴 실행 |
| 판정 완료 | OK 또는 NG 결과 생성 |
| 결과 전송 | 상위 장비 또는 HMI로 결과 전달 |
| 완료 후 | 리딩 완료 비트 초기화 후 대기 |
이 구조를 사용하면 필요한 순간에만 연산이 실행되므로 스캔 효율이 좋아지고, 프로그램 흐름도 명확해집니다.
CJ와 MC 블록을 함께 볼 때 주의할 점
CJ가 MC 블록을 건너뛰는 구조에서는 MC가 OFF되어 꺼진 것인지, 아니면 MC 명령 자체가 연산되지 않은 것인지 구분해야 합니다.
예를 들어 CJ 조건이 ON되어 MC 구간 앞에서 포인터 위치로 점프했다면, CPU는 해당 스캔에서 MC 명령과 그 내부 로직을 실행하지 않습니다. 이 경우 MC가 OFF되어 내부 로직을 차단한 것이 아니라, 애초에 MC 구간 자체가 연산되지 않은 것입니다.
이 차이는 트러블슈팅에서 중요합니다.
MC가 OFF된 경우에는 MC 조건을 추적해야 하지만, CJ로 건너뛴 경우에는 점프 조건과 포인터 위치를 먼저 확인해야 합니다.
| 상황 | 확인할 것 |
|---|---|
| MC 조건 OFF | MC를 구동하는 상위 인터락 조건 확인 |
| CJ로 MC 구간 스킵 | CJ 조건과 점프 포인터 확인 |
| 내부 출력 미동작 | MC OFF인지, CJ 스킵인지 구분 |
| 내부 RST 미실행 | CJ로 RST 구간을 건너뛰었는지 확인 |
CJ가 적용된 로직에서는 단순히 접점 상태만 보지 말고, 해당 네트워크가 실제로 스캔되고 있는지도 확인해야 합니다.
출력 HOLD 현상을 반드시 확인해야 한다
CJ 사용 시 가장 주의해야 할 문제는 출력 HOLD입니다.
CJ는 구간을 연산하지 않고 지나갑니다. 따라서 점프되는 구간 안에 있던 출력이 이전 스캔에서 ON된 상태라면, 다음 스캔에서 해당 구간을 건너뛰는 동안 OFF 조건이 실행되지 않을 수 있습니다.
이 경우 출력이 의도와 다르게 ON 상태로 남아 있을 수 있습니다.
예를 들어 어떤 출력이 특정 조건에서 ON되었고, 그 출력을 끄는 조건이 같은 점프 구간 내부에 있다고 가정합니다. 이후 CJ 조건이 ON되어 해당 구간을 건너뛰면, 출력 OFF 로직도 실행되지 않습니다. 결과적으로 이전 출력 상태가 남을 수 있습니다.
CJ를 사용할 때는 다음을 반드시 확인해야 합니다.
| 확인 항목 | 설명 |
|---|---|
| 점프 구간 내 출력 | ON 상태로 남으면 위험한 출력이 있는지 확인 |
| OFF 조건 위치 | OFF 또는 RST 조건이 점프 구간 밖에서도 실행되는지 확인 |
| SET/RST 사용 여부 | SET된 비트가 점프 중에도 해제되는지 확인 |
| 최종 출력부 | 안전 인터락이 CJ와 무관하게 항상 실행되는지 확인 |
| 점프 전 초기화 | 필요한 경우 점프 전에 상태를 정리하는지 확인 |
CJ는 로직을 끄는 것이 아니라 읽지 않고 지나가는 것입니다. 그래서 출력 차단 목적이라면 CJ보다 별도 인터락이나 최종 출력 조건을 사용하는 것이 안전합니다.
CJ를 사용하기 전에 출력 구조를 분리한다
CJ를 안정적으로 사용하려면 연산 루틴과 최종 출력 제어를 분리하는 것이 좋습니다.
예를 들어 자동운전 계산, 문자열 비교, 레시피 복사, 조건 판단 같은 연산성 로직은 CJ로 건너뛸 수 있습니다. 그러나 실제 Y 출력, 실린더 구동, 모터 구동, 히터 출력 같은 최종 출력부는 CJ에 의해 건너뛰지 않도록 별도 영역에서 항상 연산되게 구성하는 것이 안전합니다.
구조를 나누면 다음과 같습니다.
| 영역 | CJ 적용 여부 |
|---|---|
| 대량 데이터 처리 | 조건부 CJ 적용 가능 |
| 문자열 비교 | 데이터 수신 시에만 실행 가능 |
| 모델 변경 처리 | 변경 요청 시에만 실행 가능 |
| 상태 플래그 정리 | 상황에 따라 주의 필요 |
| 최종 출력 제어 | CJ로 건너뛰지 않는 것이 안전 |
| 비상정지·안전 인터락 | 항상 연산되는 위치에 배치 |
CJ를 사용해 스캔 타임을 줄이더라도 최종 출력 안전 조건은 매 스캔 확인되도록 설계해야 합니다.
포인터 위치는 추적 가능하게 남긴다
CJ를 많이 사용하면 디버깅이 어려워집니다. 프로그램이 위에서 아래로 순서대로 실행되지 않고 중간 구간을 건너뛰기 때문에, 나중에 유지보수할 때 어느 위치로 점프했는지 찾기 어려울 수 있습니다.
따라서 CJ와 포인터를 사용할 때는 주석과 상태 표시를 남기는 것이 좋습니다.
| 관리 기준 | 설명 |
|---|---|
| 포인터 주석 | 포인터 위치에 용도를 명확히 표시 |
| CJ 주석 | 어떤 조건에서 어디로 점프하는지 기록 |
| 가까운 범위 유지 | CJ와 도착 포인터를 너무 멀리 떨어뜨리지 않음 |
| 상태 변수 활용 | 현재 어떤 루틴을 실행 중인지 D나 M으로 표시 |
| 점프 구조 최소화 | 불필요한 다중 점프를 피함 |
예를 들어 P1 위치가 자동운전 루틴 시작점이라면 포인터 근처에 자동운전 루틴 시작이라는 주석을 남겨야 합니다. 점프 전후로 상태값을 남기면 모니터링 중에도 현재 어느 흐름을 타고 있는지 확인하기 쉽습니다.
CJ를 남발하면 유지보수가 어려워진다
CJ는 스캔 타임 개선에 도움이 될 수 있지만, 너무 많이 사용하면 프로그램 흐름이 끊겨 보입니다. 특히 점프가 여러 단계로 중첩되면 현재 로직이 왜 실행되지 않는지 찾기가 어려워집니다.
CJ를 사용할 때는 다음 기준을 적용하는 것이 좋습니다.
| 기준 | 설명 |
|---|---|
| 필요한 구간에만 사용 | 매 스캔 불필요한 연산에 한정 |
| 안전 로직 제외 | 안전, 정지, 최종 출력부는 점프 대상에서 제외 |
| 구간 단위로 사용 | 작은 조건마다 점프하지 않고 루틴 단위로 정리 |
| 포인터 명확화 | 점프 도착지와 목적을 주석으로 표시 |
| 스캔 타임 확인 | 실제 개선 효과를 SD 스캔 타임 등으로 확인 |
CJ를 넣었다고 항상 스캔 타임이 의미 있게 개선되는 것은 아닙니다. 실제로 어떤 루틴이 스캔 타임을 많이 사용하고 있는지 확인한 뒤 적용하는 것이 좋습니다.
CJ 설계 시 점검할 항목
CJ 명령어를 사용할 때는 다음 항목을 점검해야 합니다.
| 점검 항목 | 확인 내용 |
|---|---|
| 점프 조건 | 의도치 않게 항상 ON 상태가 되지 않는지 확인 |
| 점프 구간 | 중요한 연산이나 안전 로직이 포함되지 않았는지 확인 |
| 출력 상태 | ON된 출력이 점프 중 HOLD되지 않는지 확인 |
| RST 조건 | 필요한 리셋이 점프 구간 밖에서도 실행되는지 확인 |
| 포인터 위치 | CJ와 포인터가 명확하게 연결되는지 확인 |
| 주석 | 점프 목적과 도착 위치를 추적할 수 있는지 확인 |
| 스캔 타임 효과 | 적용 전후 스캔 타임 변화를 확인했는지 확인 |
| 유지보수성 | 다른 작업자가 흐름을 이해할 수 있는지 확인 |
CJ는 잘 쓰면 프로그램 효율을 높일 수 있지만, 잘못 쓰면 로직이 실행되지 않는 이유를 찾기 어렵게 만듭니다.
CJ 활용 기준 정리
CJ는 조건에 따라 불필요한 로직 구간을 건너뛰는 명령어입니다. 매 스캔 실행할 필요가 없는 문자열 비교, 대량 데이터 검사, 모델 변경 루틴, 자동운전 전용 루틴 등에 활용하면 스캔 타임 개선에 도움이 될 수 있습니다.
하지만 CJ는 출력을 끄는 명령이 아닙니다. 점프 구간 안에 출력 OFF 조건이나 RST 조건이 있으면, 점프 중에는 그 조건이 실행되지 않을 수 있습니다. 이 때문에 출력 HOLD나 내부 플래그 잔류 문제가 발생할 수 있습니다.
따라서 CJ를 사용할 때는 연산 루틴과 최종 출력부를 분리하고, 안전 조건과 정지 조건은 항상 스캔되는 위치에 두는 것이 좋습니다. 또한 포인터 위치와 점프 목적을 주석으로 남겨 나중에 흐름을 추적할 수 있게 해야 합니다.
스캔 타임 개선은 단순히 로직을 줄이는 작업이 아니라, 어떤 로직을 매 스캔 실행해야 하고 어떤 로직은 조건부로 실행해도 되는지 구분하는 작업입니다. CJ는 그 구분이 명확할 때 효과적인 명령어입니다.




