요즘IT
위시켓
AIDP - AX
Rise ERP
콘텐츠프로덕트 밸리
요즘 작가들컬렉션물어봐
놀이터
콘텐츠
프로덕트 밸리
요즘 작가들
컬렉션
물어봐
놀이터
새로 나온
인기
개발
AI
IT서비스
기획
디자인
비즈니스
프로덕트
커리어
트렌드
스타트업
서비스 전체보기
위시켓요즘ITAIDP - AXRise ERP
고객 문의
02-6925-4867
10:00-18:00주말·공휴일 제외
yozm_help@wishket.com
요즘IT
요즘IT 소개작가 지원
기타 문의
콘텐츠 제안하기광고 상품 보기
요즘IT 슬랙봇크롬 확장 프로그램
이용약관
개인정보 처리방침
청소년보호정책
㈜위시켓
대표이사 : 박우범
서울특별시 강남구 테헤란로 211 3층 ㈜위시켓
사업자등록번호 : 209-81-57303
통신판매업신고 : 제2018-서울강남-02337 호
직업정보제공사업 신고번호 : J1200020180019
제호 : 요즘IT
발행인 : 박우범
편집인 : 노희선
청소년보호책임자 : 박우범
인터넷신문등록번호 : 서울,아54129
등록일 : 2022년 01월 23일
발행일 : 2021년 01월 10일
© 2013 Wishket Corp.
로그인
요즘IT 소개
콘텐츠 제안하기
광고 상품 보기
프로덕트

깃허브 스타 42만 개 REA로 노션형 블록 에디터 구현해봤다

효빈
10분
1시간 전
152
에디터가 직접 고른 실무 인사이트 매주 목요일에 만나요.
newsletter_profile0명 뉴스레터 구독 중

우리가 쓰는 앱은 대부분 소스 코드를 공개하지 않은 채 배포됩니다. 웹 앱도 마찬가지입니다. 브라우저로 자바스크립트 파일이 내려오기는 하지만, 그 파일은 압축과 번들링을 거쳐 사람이 읽기 어려운 모양이 됩니다. 이렇게 완성된 결과물에서 거꾸로 동작 원리를 알아내는 일을 리버스 엔지니어링(Reverse Engineering)이라고 부릅니다.

 

2026년 10월에는 이 리버스 엔지니어링을 AI 코딩 에이전트에 맡기는 오픈소스 도구 REA(Reverse Engineer Anything)가 깃허브(GitHub)에서 빠르게 주목받았습니다. 제가 확인한 2026년 11월 3일 기준으로 REA 저장소의 별(Star)이 424,297개입니다.

 

미국 IT 매체 404 Media의 제이슨 쾨블러(Jason Koebler) 기자는 2026년 10월 20일 기사 “‘Reverse-Engineer Anything’ Is the New Wild West of AI”에서 REA 열풍을 “AI의 새로운 무법지대”라고 부르며, AI로 만든 복제품의 품질과 보안 문제를 함께 짚었습니다.

 

그렇다면 REA를 설치하면 정말 남의 앱 기능을 알아내고 따라 만들 수 있을까요? 그래서 저는 노션과 비슷한 오픈소스 앱 AFFiNE의 대표 기능 두 가지를 REA로 분석하고, 원본 소스와 맞춰 채점한 뒤 직접 다시 만들어 봤습니다.

 

미리 요점만 콕 집어보면?

  • REA는 압축된 자바스크립트 번들을 분석해 기능과 관련된 함수의 위치를 찾아주지만, 분석 결과의 정확성과 완전성을 보장하지는 않습니다.
  • 오픈소스 앱 AFFiNE의 슬래시 메뉴와 블록 이동 기능을 분석한 결과 정리한 동작 규칙 18개 중 16개가 원본 소스와 일치했습니다.
  • REA를 활용한 기능 복제에는 AI의 해석 오류를 검증하는 과정이 필요하며, 코드 압축은 보안 장치가 아니므로 배포 전 번들에 남은 키와 주소를 점검해야 합니다.

 

 

REA란?

실험 이야기에 앞서 REA가 어떤 도구이고, 공식 문서에서 어떤 한계를 밝히고 있는지부터 살펴봅시다.

 

1) 대상에 따라 달라지는 분석 방식

REA는 깃허브에 MIT 라이선스로 공개된 프로젝트로, 터미널 명령(CLI)과 에이전트용 MCP 서버 두 가지 방식으로 쓸 수 있습니다.

 

분석 방식은 대상에 따라 다릅니다. 기계어로 된 네이티브 프로그램은 Hopper·Ghidra·IDA 같은 기존 분석 도구를 연결해 분석하고, 웹사이트는 크롬 계열 브라우저를 띄워 화면과 네트워크를 관찰합니다. 이번 실험처럼 자바스크립트나 일렉트론 앱은 별도 분석 도구 없이 REA에 들어 있는 분석기가 파일을 실행하지 않고 읽어서 모듈과 함수 관계를 정리합니다. Claude Code나 Codex 같은 에이전트는 이 기능들을 불러 쓰면서, 결과를 근거로 기능의 동작을 설명합니다.

 

2) REA가 스스로 밝힌 한계

REA의 면책 문서(DISCLAIMER.md)는 분석 결과가 불완전하거나 틀릴 수 있고, 정확성과 완전성을 보장하지 않는다고 밝힙니다. 소스 코드처럼 보이는 결과를 얻었다고 해서 그 코드에 대한 권리가 생기는 것도 아니라고 적어 두었습니다.

 

README는 REA를 합법적인 연구·교육·호환성 확보·소프트웨어 보존, 그리고 본인이 소유하거나 분석 권한을 받은 소프트웨어의 분석에 쓰라고 안내합니다. 저는 이 안내를 다시 읽고 실험 대상을 바꾸게 됐습니다.

 

 

노션 대신 AFFiNE를 고른 이유

AFFiNE는 노션처럼 문서를 블록 단위로 쓰면서, 같은 내용을 화이트보드처럼 넓은 캔버스에 펼쳐 정리할 수도 있는 오픈소스 작업 도구입니다. 싱가포르 회사 TOEVERYTHING이 만들고 있고, 데이터를 먼저 내 기기에 저장하는 로컬 우선(Local-first) 방식이라 웹(app.affine.pro)에서 로그인 없이 바로 써 볼 수 있습니다.

 

AFFiNE 웹 앱 초기 화면, 'What can I help you with?' 입력창과 좌측에 All docs·Journals·Intelligence 메뉴가 보인다
<출처: AFFiNE, 캡처>

 

사실 처음 실험 대상은 노션이었습니다. 슬래시(/) 메뉴와 블록 끌어 옮기기처럼 많은 사람이 써 본 기능이 있어서, 독자가 결과를 바로 비교할 수 있다고 생각했습니다. 그런데 아래 이유로 AFFiNE로 대상을 바꿨습니다.

 

1) 노션 이용약관에서 확인한 금지 조항

노션 웹 앱 번들(2026-10-21 배포본)을 받아 분석을 시작한 뒤, 이용약관을 다시 확인했습니다. 노션의 개인 이용약관(Personal Use Terms of Service)에는 서비스를 디컴파일하거나 리버스 엔지니어링하는 행위를 금지하고, 그 대상에 “서비스의 바탕이 되는 아이디어나 알고리즘”까지 포함한다고 적혀 있습니다.

 

기능의 동작 규칙을 알아내 글로 공개하는 이 실험은 그 조항에 저촉될 수 있다고 판단했습니다. 그래서 노션 분석 결과는 원고에 쓰지 않기로 하고 대상을 바꿨습니다.

 

REA를 써 보려는 분들도 분석하기 전에 대상 앱의 이용약관과 라이선스부터 확인하시길 권합니다.

 

2) MIT 라이선스로 공개된 AFFiNE

AFFiNE는 README에서 스스로를 노션과 미로(Miro)의 대안이라고 소개합니다. 저장소(toeverything/AFFiNE)의 별은 73,883개(2026-10-27 기준)이고, 서버 등 일부 폴더를 뺀 대부분의 코드가 MIT 라이선스입니다. MIT 라이선스가 적용된 범위에서는 코드를 보고 분석하고 고치는 일이 허용됩니다. 이번에 다룬 편집기 화면 코드도 그 범위에 속하고, 따라 만든 결과물은 공개하거나 배포하지 않았습니다.

 

 

REA로 AFFiNE 기능 따라 만들기

실험 환경은 macOS 26.6.2, Node.js 24.13.1, REA(npm 패키지 rea-agents) 6.7.0이고, 따라 만든 기능은 크롬과 같은 크로뮴 엔진을 쓰는 브라우저에서 테스트했습니다. 분석과 구현은 Claude Code에 맡겼고, 저는 과정을 지켜보며 막힌 곳과 결과를 확인했습니다. 전체 흐름은 아래와 같습니다.

 

REA로 AFFiNE 기능 하나를 따라 만들기까지 6단계 흐름도: 번들 받기, 정적 분석, 위치 짚기, 코드 읽기, 원본 소스로 채점, 다시 만들기
<출처: 작가, Claude로 생성>

 

1) 메모리 부족으로 멈춘 첫 분석

AFFiNE 웹 앱 HTML에서 자바스크립트 파일 11개(14MB)를 받는 데는 4초면 충분했습니다. 코드 대부분은 index.js 한 파일(8.6MB)에 들어 있었습니다.

 

REA 설치는 간단했습니다. 다만 REA가 유명해지면서 이름이 비슷한 가짜 저장소가 생겨, 공식 설명서에도 “정해진 세 곳(GitHub 저장소, rea.tools, npm 패키지 rea-agents)에서만 받으라”는 경고가 있습니다. 그래서 설치 전에 패키지를 만든 사람과 저장소 주소가 공식과 같은지 먼저 확인했습니다.

 

막힌 곳은 분석 단계였습니다. REA는 코드를 분석할 때 함수, 변수, 조건문 같은 작은 조각으로 코드를 쪼개 메모리에 펼쳐 놓고 살펴봅니다. 그리고 따로 설정하지 않으면 이 작업에 메모리를 1GB까지만 쓰도록 정해져 있습니다.

 

보통 크기의 파일은 이걸로 충분하지만, AFFiNE 코드 대부분이 몰려 있는 index.js(8.6MB)는 쪼개 보니 조각이 약 196만 개나 돼서 1GB 안에 다 담기지 않았습니다. 그래서 파일 11개 분석이 84초 만에 끝났다고 나왔는데도, 정작 가장 중요한 index.js는 제대로 분석되지 않았습니다. 설정을 잘못한 것이 아니라, 기본값으로는 감당하기 어려운 크기였던 것입니다.

 

REA에는 이 한도를 바꾸는 옵션(--max-heap-mb)이 있어서 6GB까지 쓰도록 늘린 뒤 index.js만 다시 분석했고, 이번에는 110초 만에 끝났습니다.

 

두 번째 분석은 성공했지만 결과가 입력보다 몇 배 큰 54MB였습니다. 그래서 에이전트가 전부 읽게 하는 대신, 결과 안의 함수 정보를 줄 번호로 걸러 보게 했습니다.

 

2) 함수 이름으로 찾은 기능의 위치

REA는 분석을 마치면 코드 안의 함수들이 몇 번째 줄에 있는지 정리해 줍니다. 함수는 “메뉴를 연다”, “블록을 놓을 위치를 정한다”처럼 기능 하나씩을 맡은 코드 묶음입니다. 압축된 코드는 보통 함수 이름이 a, b처럼 알아볼 수 없게 바뀌는데, AFFiNE는 이름이 그대로 남아 있었습니다. 그래서 REA가 정리한 목록에서 SlashMenu(슬래시 메뉴), _getDropResult(놓을 위치 계산) 같은 이름을 찾아, 4만 줄이 넘는 코드 중 어디를 읽으면 되는지 바로 알 수 있었습니다.

 

다만 REA가 한 파일에서 정리하는 정보에는 상한이 있어서, 이 목록은 파일 앞쪽 약 2만 7천 줄까지만 만들어졌습니다. 다행히 두 기능 모두 그 안에 있었습니다.

 

3) 슬래시 메뉴에서 읽어 낸 규칙

AFFiNE 문서에서 /를 입력하면 아래와 같은 메뉴가 뜹니다.

 

AFFiNE 문서에서 슬래시를 입력하면 뜨는 메뉴, Ask AI와 Text·Heading 1·Heading 2·Heading 3·Other Headings·Code Block·Quote 항목이 나열된다
<출처: AFFiNE(app.affine.pro), 작가 캡처>

 

코드를 읽어 보니 검색 규칙이 생각보다 세심했습니다. 항목마다 이름 외에 검색용 별칭(searchAlias)이 있어서, 메뉴에 보이는 이름이 아니어도 별칭으로 찾을 수 있습니다. 검색은 첫 단계 메뉴와 “Other Headings” 같은 하위 메뉴를 처음부터 함께 훑고, 두 단계 모두에서 결과가 없을 때만 더 깊은 단계로 내려갑니다. 그다음 검색어와 연속으로 겹치는 글자가 많은 항목을 위로 올립니다.

 

이동은 화살표뿐 아니라 Tab과 Shift+Tab, Ctrl+N과 Ctrl+P(맥에서는 Cmd)로도 할 수 있고, 끝에서 다시 처음으로 돌아갑니다. 메뉴 높이는 메뉴를 띄울 수 있는 공간과 390px 중 작은 값으로 정해집니다.

 

4) 블록 끌어 옮기기에서 읽어 낸 규칙

블록을 놓는 위치는 _getDropResult 함수가 정합니다. 다른 블록의 위쪽 가장자리에 놓으면 그 앞에, 그 밖에는 뒤에 들어갑니다. 예외는 문서 전체를 감싸는 Note 블록 위에 Note 블록을 끌어 놓을 때로, 이때는 안쪽에 넣습니다.

 

노션과 다른 점은 오른쪽 가장자리입니다. 노션은 블록을 옆에 놓으면 열을 나누지만, AFFiNE는 목록 블록의 오른쪽에 놓았을 때 끄는 블록이 모두 목록이면 그 목록의 하위 항목으로 들여 넣습니다. 이때 놓일 자리를 알려 주는 파란 선도 24px 안쪽에서 시작합니다. 끄는 블록 중 목록이 아닌 것이 섞여 있으면 들여 넣지 않고, 대상 목록을 감싸고 있는 가장 바깥 블록을 찾아 그 뒤에 넣고, 그런 블록을 찾지 못하면 놓을 자리를 표시하지 않습니다.

 

5) 원본 소스와 맞춰 본 결과

REA는 원래 소스 코드가 공개되지 않은 앱을 분석할 때 쓰는 도구입니다. 그래서 보통은 맞춰 볼 정답이 없고, 다시 만든 결과가 원본과 똑같이 동작하는지 비교해 보는 방식으로 확인합니다.

 

하지만 이 글에서는 REA로 알아낸 내용이 실제로 얼마나 맞는지를 숫자로 보여 드리고 싶었습니다. 그래서 일부러 소스가 공개된 AFFiNE를 골랐습니다. 분석과 구현은 소스가 없는 앱을 다룰 때와 똑같이 브라우저로 내려오는 번들만 보고 진행했고, 원본 소스는 모든 작업을 마친 뒤 채점할 때만 꺼냈습니다. AFFiNE는 웹 앱 안에 빌드 버전을 적어 두기 때문에, 지금 배포된 앱과 같은 시점의 소스를 깃허브에서 찾아 맞춰 볼 수 있었습니다.

 

채점 대상은 제가 정리한 규칙 18개(슬래시 메뉴 13개, 블록 이동 5개)입니다. 원본 소스에서 같은 조건과 값이 확인되면 맞은 것으로 판정했고, 그 결과 18개 중 16개가 맞았습니다.

 

틀린 2개는 모두 압축된 조건식을 읽는 단계에서 나왔습니다. 첫 번째로 에이전트는 “검색 결과가 없을 때 글자를 더 치면 메뉴가 닫힌다”고 정리했습니다. 그런데 원본 소스에는 isTextInputKey라는 함수와 함께 “검색어를 바꾸는 입력은 막지 않는다”는 주석이 있었습니다. 실제 동작은 반대로, 결과가 없어도 글자는 계속 받고 공백, 화살표나 Enter처럼 글자가 아닌 키, 단축키, 한글을 조합 중인 키에서 닫힙니다. Backspace는 예외라서 검색어를 지운 뒤 다시 찾습니다. 압축 과정에서 함수가 조건식 하나로 풀려 들어가면서 참과 거짓을 거꾸로 읽은 것입니다.

 

두 번째는 하위 메뉴 검색입니다. 에이전트는 “첫 단계에서 결과가 없을 때만 하위 메뉴를 찾는다”고 정리했지만, 원본에는 “첫 번째와 두 번째 단계를 검색한다”는 주석과 함께 두 단계를 항상 함께 훑는 반복문이 있었습니다. 이 오류는 원고를 다른 AI(Codex)에 원본 소스와 다시 대조하게 하는 과정에서 발견했습니다. REA 분석 결과에는 관련 코드의 위치가 정확히 나왔지만, 그 코드를 해석하는 단계에서 실수가 생긴 것입니다.

 

6) 직접 다시 만든 결과

원본 소스로 바로잡은 규칙을 따라 HTML 파일 하나(약 330줄)로 두 기능을 근사하게 다시 만들었습니다. 아래는 따라 만든 슬래시 메뉴에서 list로 검색한 모습입니다.

 

직접 만든 편집기에서 슬래시 입력 후 list로 검색해 글머리 목록과 할 일 목록이 뜬 모습
<출처: 작가>

 

블록 끌어 옮기기도 같은 방식으로 만들었습니다. 목록 항목 B를 A의 오른쪽 끝으로 끌면 24px 안쪽에서 시작하는 파란 선이 나타나고, 놓으면 A의 하위 항목이 됩니다.

 

직접 만든 편집기에서 목록 항목 B를 끌어 목록 항목 A의 하위 항목으로 옮기는 드래그 동작, 파란 안내선이 표시된다
<출처: 작가>

 

브라우저에서 메뉴 열기, 별칭 검색, Tab으로 이동해 선택하기, 결과가 없을 때 공백으로 닫기, 하위 메뉴 열고 닫기, /를 지워 닫기, 블록 위아래 이동, 목록 들여 넣기까지 확인했고, 모두 제가 구현한 규칙대로 동작했습니다.

 

테스트 중에 버그도 하나 있었습니다. /를 치고 바로 이어서 입력하면 메뉴가 한 박자 늦게 열려 앞 글자를 놓쳤는데, 메뉴를 여는 시점을 입력 이벤트 직후로 옮겨 고쳤습니다.

 

다만 이번에 따라 만든 것은 AFFiNE의 두 기능을 그대로 옮긴 것이 아니라, 읽어 낸 동작 규칙을 비슷하게 구현한 것입니다. 검색 일치와 점수를 계산하는 세부 함수는 다른 패키지에 있어서 비슷하게 직접 짰고, 오른쪽 가장자리로 판단하는 폭이나 손잡이 모양도 제가 정했습니다. 키 조합 처리도 단순하게 줄였고, Note 블록 예외와 여러 블록을 한꺼번에 끄는 경우는 구현하지 않았습니다. 문서 저장, 여러 사람이 동시에 고치는 동기화, 화이트보드 모드 같은 AFFiNE의 나머지는 다루지 않았습니다.

 

 

개발을 마친 뒤 점검할 2가지

이번 실험에서 번들에 남은 이름이 분석 범위를 좁히는 데 얼마나 쓸모 있는지 실감했습니다. 누구나 AI로 번들을 읽을 수 있다는 전제라면, 기능을 하나 만들 때마다 따로 챙기기보다 개발을 모두 마친 다음 배포 전에 아래 항목을 한꺼번에 점검하는 편이 빠뜨리지 않기 좋습니다. 저도 제 프로젝트에 먼저 이 순서대로 적용해 봤습니다.

 

1) 보호 장치가 아닌 코드 압축

코드 압축(Minify)은 파일 크기를 줄이려는 최적화이지, 코드를 숨기는 장치가 아닙니다. 변수 이름이 줄어들어도 로직과 문자열은 남고, AFFiNE처럼 클래스 이름이 보존되는 설정이라면 구조까지 그대로 드러납니다. 예전에는 사람이 읽기 귀찮아서 어느 정도 가려지는 효과가 있었지만, 지금은 에이전트가 그 수고를 대신합니다. 따라서 “압축했으니 안 보이겠지”라는 전제로 둔 로직이 있다면 다시 볼 필요가 있습니다.

 

2) 번들에 남은 키와 주소

Vite에서는 VITE_로 시작하는 환경 변수가 빌드할 때 번들 안에 문자열로 그대로 들어갑니다.

 

<코드>// .envVITE_API_KEY=sk-test-1234// src/api.jsconst key = import.meta.env.VITE_API_KEY;// 빌드 결과const key = “sk-test-1234”; // 누구나 볼 수 있는 문자열로 남습니다<코드>

 

.env 파일을 Git에 올리지 않았더라도, 번들에 들어간 값은 배포와 동시에 공개됩니다.

 

실험을 마친 뒤 제가 만든 원고 편집기의 번들(177KB)도 같은 눈으로 살펴봤습니다. 다행히 API 키나 토큰처럼 보이는 문자열은 없었고 소스맵도 배포되지 않았지만, 서버 API 주소 14개가 번들 안에 그대로 보였습니다. 제 컴퓨터에서만 쓰는 도구라 문제는 없지만, 공개 서비스였다면 이 목록만으로 서버에 어떤 기능이 있는지 짐작할 수 있습니다.

 

 

마치며

REA는 소스 코드가 없는 앱의 기능을 알아내, 내 프로젝트에 비슷하게 만들 수 있도록 돕는 도구입니다. 직접 써 보니 그 과정을 REA가 혼자 끝까지 해 주지는 않았습니다. REA가 맡은 일은 압축된 코드를 분석해 기능과 관련된 함수가 어디에 있는지 정리해 주는 데까지였고, 그 코드를 읽고 동작을 이해해 다시 만드는 일은 에이전트가, 제대로 만들었는지 확인하는 일은 사람이 맡아야 했습니다.

 

설치는 쉬웠지만 큰 파일은 메모리 한도를 늘려야 했고, 결과가 입력보다 몇 배 커서 무엇을 골라 읽을지도 직접 판단해야 했습니다. 해석 단계에서는 실제로 틀린 결론도 나왔고, 원본 소스가 없었다면 그 실수를 알아채지 못했을 것입니다.

 

그래서 저는 번들 구조를 어느 정도 읽을 줄 아는 프론트엔드 개발자에게는 REA를 권하고, 결과를 검증할 방법이 없는 상태에서 상용 서비스를 따라 만들려는 용도로는 권하지 않습니다. 기술적으로 가능한 것과 약관이 허용하는 것이 다르다는 점도 이번에 직접 확인했습니다. 분석해 보고 싶은 기능이 있다면 오픈소스 프로젝트에서 시작해, 원본과 맞춰 보며 감을 익히는 순서를 추천합니다.

 

이 글은 AI의 도움을 받아 작성했습니다.

 

ⓒ요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.