알리바바, AI 코드 리뷰 도구 OpenCodeReview 오픈소스로 공개
알리바바가 오픈소스로 공개한 OpenCodeReview에 SQL 인젝션 등 5개 결함을 심은 diff를 넣자 45초 만에 6개 지적을 모두 잡아냈다고 작성자가 밝혔다.
중국어 원문을 AI로 번역했습니다. 고유명사와 수치는 원문 표기를 우선하며, 중요한 판단에는 아래 출처 원문을 함께 확인하세요.
오늘 오전 GitHub Trending을 훑어봤는데, 1위가 알리바바가 오픈소스로 공개한 open-code-review였고 하루 만에 별이 3천 개 넘게 늘었다. 별 수가 핵심은 아니고, 핵심은 이 도구가 내 최근의 진짜 고민을 정확히 찔렀다는 점이다. AI가 코딩의 문턱을 낮춰놨는데 리뷰는 여전히 제자리걸음이라는 것 — Cursor, Claude Code가 생성하는 코드는 점점 늘어나는데, 누가 심사할 것인가? diff를 그대로 범용 AI 채팅창에 던져 리뷰를 시켜본 적이 여러 번 있는데, 결과는 기본적으로 세 가지였다. 파일 30개를 고쳐도 한 군데만 물고 늘어짐, 알려준 문제의 행 번호가 안 맞음, 그리고 '주석 추가를 권장합니다' 식의 뻔한 소리 한 무더기. 토큰만 불태우는 건 아주 시원했다.
OpenCodeReview(설치 후 커맨드라인 이름은 ocr)의 발상은 좀 다르다. 애초에 모델이 자유분방하게 놀도록 내버려둘 생각이 없다. 공식 문서에 따르면 전체 리뷰는 세 단계로 쪼개진다. 규칙으로 유도되는 작업 분배, 컨텍스트 제약을 동반한 파일 리뷰, 그리고 마지막에 독립적인 반성 필터링 한 겹. 파일 선별, 규칙 매칭, 코멘트 위치 특정 같은 결정론적 작업은 전통적인 코드 로직이 담당하고, LLM 서브에이전트는 변경을 이해하고 문제가 지적할 만한 가치가 있는지 판단하는 일만 맡으며, 게다가 이것이 받는 도구 집합은 제약된 코드 도구이지 unrestricted shell이 아니다. 이 설계가 꽤 마음에 든다. 코드 리뷰는 고도로 반복적인 엔지니어링 작업이라, 모델에 최대한의 자유도를 주는 것은 오히려 매번 결과가 예측 불가능해진다는 뜻이다 — 비즈니스 코드를 작성할 때는 하늘을 나는 상상도 괜찮지만, '이 한 줄에 코멘트를 달아야 하는가' 같은 판단에서는 족쇄가 곧 생산성이다.
설치하면 바로 돌아가고, DeepSeek는 프리셋 항목
설치는 npm 한 줄이다.
npm install -g @alibaba-group/open-code-review
내 쪽은 2초 만에 설치가 끝났고 ocr version도 정상이었다.
open-code-review v1.12.5 (189be5b024) linux/amd64 built at: 2026-09-17T13:19:46Z https://github.com/alibaba/open-code-review
작은 에피소드가 하나 있다. 공식 요구 사항은 Git 2.41 이상인데, 내 낡은 장비는 2.34.1이라 실행할 때마다 git 2.34.1 is older than the minimum supported version 2.41.0 경고가 한 번씩 뜬다. 실측으로는 어떤 기능도 막지 않았고 diff 파싱도 전부 정상이었지만, 보기에는 확실히 좀 거슬려서 나중에 올릴 생각이다. 모델 연결은 내 예상보다 간편했다. 나는 커스텀 provider 방식의 절차를 거쳐야 하는 줄 알았는데, DeepSeek는 그냥 프리셋 항목이었다.
ocr config set providers.deepseek.api_key sk-당신의key ocr llm test
테스트가 통과할 때 모델이 자기소개 한 단락을 돌려줬는데, 꽤 볼만했다.
Source: provider:deepseek URL: https://api.deepseek.com Model: deepseek-flash I am open-code-review (ocr), a code review assistant developed by Alibaba that runs in your command-line environment... ✓ Connection test successful
deepseek-flash가 알리바바 리뷰 도우미의 탈을 쓰고 일하는 셈인데, 오픈소스 도구가 중국산 모델 연동을 이 정도 수준으로 해냈으니 국내 사용자들은 사실상 문턱이 없다. DeepSeek 사용자가 아니어도 된다. OpenAI 호환과 Anthropic 호환 커스텀 endpoint를 모두 지원하니, 팀에 자체 게이트웨이가 있으면 그쪽으로 지정하면 된다.
함정을 심어 실측: 45초, 6건 전부 적중
데모만 봐서는 안 믿긴다. 그래서 실제 시나리오를 하나 만들었다. 작은 사용자 서비스용 Python 프로젝트로, 먼저 깨끗한 코드 한 버전을 커밋하고, 그다음 작업 공간에 사용자 검색 인터페이스를 추가했다 — 그러면서 슬쩍 함정 5개를 심었다.
- SQL 문자열 결합 주입 (키워드를 문자열 연결로 그대로 LIKE 쿼리에 삽입)
- 푸시 게이트웨이의 프로덕션 key 하드코딩
- 페이지네이션 상한 로직 반대로 작성 (page_size > 100일 때 1000으로 설정)
- 사용자를 찾지 못했을 때 바로 인덱스 접근 (None 크래시)
- open()을 with로 관리하지 않음
커밋하지 않고 작업 공간 diff 상태를 유지한 다음 ocr review를 실행했다. 기본 workspace 모드는 스테이징된 변경, 스테이징되지 않은 변경, 추적되지 않은 변경을 모두 포괄해서 커밋 전 자체 점검에 딱 맞는다. 먼저 --preview로 범위를 확인했고 문제없어서 바로 심사를 시작했다.
─── user_service.py:20-21 ─── [security · critical] SQL injection: `keyword` is concatenated directly into the query. A value like `' ; DROP TABLE users; --` (or a UNION-based payload) would be executed by the database. Use a parameterized query. - sql = "SELECT id, name, email FROM users WHERE name LIKE '%" + keyword + "%'" + sql = "SELECT id, name, email FROM users WHERE name LIKE ?" + rows = conn.execute(sql, (f "%{keyword}%",)).fetchall()
매개변수화 쿼리로 고치는 방식이 맞았고, LIKE 와일드카드를 바인딩 매개변수 안에 넣어야 한다는 세부 사항까지 놓치지 않았다. 하드코딩 key 건도 critical로 보고했고, 이 key가 이미 작업 공간에 들어갔으니 교체(rotate)하라고 한마디 더 덧붙였다. 페이지네이션 로직 버그는 한눈에 꿰뚫어서, 내가 page_size > 100일 때 1000으로 바꿔버린 조작을 bug · high로 바로 표시했다. 함정 5개 전부 적중했고, 각 항목마다 행 단위 위치 특정과 수정 diff가 붙었다. 뜻밖의 수확은 6번째 항목이었다. requests.post의 반환값이 무시되어 내보내기 실패가 조용히 성공으로 처리된다는 것 — 이 함정은 내가 심지 않았는데 도구가 스스로 찾아냈다. 전 과정 45초, 코멘트 6건, 오탐 0건.
깨끗한 코드로 다시 시도: 아첨하지 않지만, 지적하는 건 모두 진짜 문제
전부 적중에 오탐 0건이라는 건 함정 탐지 능력이 좋다는 것만 보여준다. 나는 또 다른 문제가 신경 쓰였다. 쓸모 있어 보이려고 정상 코드에도 억지로 발견 사항을 끼워 맞추지는 않을까? 이런 종류의 도구에서 가장 호감을 깎는 게 바로 아첨형 심사다. 문제가 없는 곳에서도 꽃을 피워내는 것. 그래서 나는 꽤 규칙적인 재시도 데코레이터를 하나 더 작성했다 — 적어도 내가 직접 쓸 때는 꽤 규칙적이라고 생각했다.
def retry(times=3, backoff=2.0): def decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): delay = 1.0 last_exc = None for attempt in range(times): try: return func(*args, **kwargs) except requests.RequestException as exc: last_exc = exc time.sleep(delay) delay *= backoff raise last_exc return wrapper return decorator
결과적으로 2건을 보고했고 둘 다 low 등급이었지만, 둘 다 성립했다. times에 0이나 음수를 넘기면 루프 본문이 실행되지 않아 last_exc가 여전히 None이고, 마지막 줄의 raise last_exc가 TypeError: exceptions must derive from BaseException이 된다 — 나는 작성할 때 이 부분을 정말 생각 못 했다. 다른 하나는 마지막 실패 이후에도 예외를 던지기 전에 sleep을 먼저 한다는 것으로, 기본 매개변수에서는 4초를 더 헛되이 기다린다. 안전 문제를 억지로 끼워 맞춘 항목은 하나도 없었고, 두 곳 모두 구체적인 수정 방법을 제시했다.
이번 한 바퀴를 돌고 내린 판단은 이렇다. 함정 탐지 능력은 정상 궤도이고, 아첨하지 않으며, 등급 판정도 절제되어 있다(진짜 보안 문제라야 critical로 올리고, 경계선상의 흠은 순순히 low에 머문다). 위에서 테스트한 것은 사실 review 명령 하나뿐이다. help를 전체 훑어봤는데, help를 뒤져서야 발견한 것들도 몇 개 더 있었고 아직 실측하지 않았으니 더 파고들지는 않겠다. scan은 diff와 무관하게 전체 파일을 바로 심사할 수 있어서, 언젠가 유산 코드 디렉터리를 넘겨받을 때 쓸모가 있을 것 같다. 출력은 JSON과 SARIF를 지원하는데, 품질 게이트에 연결하는 건 나도 정말 해보고 싶다. 리뷰 세션은 디스크에 저장돼서 중단되어도 resume할 수 있다. 팀 규칙은 프로젝트 안의 .opencodereview/rule.json에 넣어 리포지토리를 따라다니게 할 수 있어, 규범을 매번 입으로 설명할 필요가 없다. CI 쪽은 GitHub Actions, GitLab CI 템플릿이 모두 준비되어 있다. delegation mode도 꽤 흥미로운데, Claude Code, Cursor 같은 호스트 agent 안에서 실행될 때 ocr은 결정론적인 파일 선별과 규칙 매칭만 하고, 추론은 호스트 agent의 모델을 그대로 사용하며 API key조차 따로 설정할 필요가 없다.
몇 가지 안 하고 넘어갈 수 없는 아쉬운 점
아쉬운 점도 있다. 출력이 현재 전부 영어라 내가 읽는 데는 지장이 없지만, 팀에서 영어가 그다지 능숙하지 않은 동료가 critical 심사 의견을 보면 힘들어할 테니 이후에 현지화 옵션이 있었으면 한다. 이번에 내가 테스트한 것은 단일 파일 +23/-6의 작은 diff라, 크다고 주장하는 대형 PR 그룹화·동시 처리 능력은 내가 검증할 여건이 안 되어 이건 결론을 내리지 않겠다. 또 효과는 결국 모델에 달려 있는데, deepseek-flash는 이런 단일 파일 시나리오를 돌리기에 차고 넘쳤고, 파일 간 복잡한 추론이 되는지는 진짜 프로젝트로 시험해본 뒤에나 말할 수 있다.
적용 시나리오에 대한 내 판단은 명확하다. 커밋 전 자체 점검과 CI 자동 차단, 이 두 자리는 지금 바로 대체 투입이 가능하다. 사람의 리뷰를 대체하는 것까지는 — 이 도구가 잡는 건 기계적인 문제이고, 비즈니스 로직이 합리적인지 같은 일은 아직 이 녀석이 나설 차례가 아니다.
리포지토리 주소: github.com/alibaba/ope…
여기까지 쓰고, 큰 프로젝트로 한 바퀴 압박해본 뒤에 이후 경험을 다시 얘기하겠다.