top of page

SQLite parse_number(): 파서 재작성 후 C가 Rust를 앞서다

18분 전
9분 분량

Simon Willison의 SQLite parse_number() 실험에서는 처음에 Rust가 C보다 앞섰지만, 표적화된 파서 재작성으로 성능 순위가 뒤집혔다. 2026년 11월 8일 공개된 이 조사에서는 서식이 있는 숫자를 정리하기 위한 데이터베이스 함수를 추가하는 컴파일 확장 기능을 비교했다. 그 결과 C 구현은 더 작은 컴파일 파일을 유지하면서도 테스트한 모든 데이터셋에서 선두를 기록한 것으로 전해진다.

작업은 간단해 보인다. 통화 기호, 쉼표 또는 백분율 기호가 포함된 텍스트를 숫자 정렬과 덧셈에 적합한 값으로 바꾸는 일이다. 그러나 이 비교는 서로 다른 엔지니어링 질문에 서로 다른 답을 드러냈다. Rust는 첫 번째 소수 파서에서 더 빨랐고, 최적화된 C는 결국 가장 빠르게 측정된 구현을 제공했다.

AI가 생성한 코드를 평가하는 개발자에게 핵심 부담은 검토 과정에 있다. 그럴듯한 구현과 익숙한 언어만으로는 실행 시간이 어디에 쓰이는지 알 수 없다. Willison의 조사는 측정을 통해 특정 변환 루틴을 식별하고 더 좁은 실험을 진행하면서 유용해졌다.

SQLite parse_number()는 두 번째 시도 후 결과를 바꾼다

구현이 바뀌자 보고된 승자도 바뀌었으며, 이는 파서 설계가 비교의 핵심임을 보여준다.

Willison은 계정에서 Opus 5.5로 식별된 Claude에게 C와 Rust에서 이 함수를 탐색해 달라고 요청하며 시작했다. 그가 요청한 비교는 실행 속도, 코드 복잡도, 그리고 결과 라이브러리의 크기를 다뤘다. 그는 이 조사를 자신의 SQLite 파싱 실험에서 설명한다.

첫 결과는 파일 크기와 속도를 분리해 보여줬다. Willison은 약 14 KB의 C 확장 기능을 보고했으며, rusqlite 사용 시에는 321 KB, sqlite-loadable-rs 사용 시에는 298 KB였다. 이 Rust 라이브러리들은 Rust 코드를 SQLite에 연결한다. 더 작은 파일 크기에도 불구하고 초기 C 구현은 혼합 및 소수 입력에서 뒤처졌다.

설명의 중심에는 텍스트를 부동소수점 수, 즉 근사적인 수치 표현으로 변환하는 C 라이브러리 함수 strtod()가 있었다. Willison은 Rust가 초기에 소수 처리에서 우위를 보인 이유를 더 빠른 변환 루틴으로 설명했다. 이후 그는 Claude에게 Rust 구현과 동등하거나 이를 뛰어넘는 C 파서를 작성해 달라고 요청했다.

수정된 C 버전은 보고된 비교에서 선두를 차지했다. 혼합 데이터에서 초기 C의 행당 67나노초였던 반올림 순 비용은 수정 C에서 19나노초로 줄었다. Rust 버전은 각각 46과 41을 기록했다. 소수 전용 입력에서는 C 내부의 변화가 더 컸으며, 행당 106나노초에서 18나노초로 감소했다.

이 순서가 이 이야기의 의미를 만든다. 첫 번째 비교에서 멈췄다면 측정된 소수 워크로드에는 Rust를 선택한다는 결론을 뒷받침했을 것이다. 그러나 표적화된 수정을 계속한 결과, 요청된 데이터베이스 함수를 바꾸지 않고도 다른 후보가 나왔다.

이 실험은 대안을 생성하는 일과 대안을 평가하는 일도 구분한다. Claude가 구현을 제공했지만, 그 상대적 가치는 주변의 측정을 통해 드러났다. 초기 답변은 확정된 엔지니어링 결정이 아니라 출발점을 제공했다.

이를 프로그래밍 언어의 보편적 순위로 취급할 근거는 없다. 이것들은 작은 함수의 구체적인 구현들이다. 변환 루틴, 임시 저장소, 통합 코드 등의 차이가 있으며, 이는 넓은 C 대 Rust라는 헤드라인 아래에 놓여 있다.

실질적 변화는 더 구체적이다. 개발자들은 느린 초기 C 초안이 가장 빠르게 측정된 후보가 된 공개 사례를 얻었다. 따라서 이 사례는 구현 선택을 검토하는 데 유용하지만, 더 광범위한 언어 관련 주장을 뒷받침하지는 않는다.

이 벤치마크는 SQLite 내부의 반복 파싱을 측정한다

이 워크로드에서는 반복 변환이 중심 역할을 하므로, 결과는 그 맥락과 함께 해석해야 한다.

공개된 벤치마크 하니스는 200만 행을 담은 인메모리 데이터베이스를 만든다. 각 값을 파싱하고 결과를 합산하는 쿼리를 평가한다. Python이 쿼리를 시작하지만, 반복되는 데이터베이스 작업은 SQLite가 수행한다.

이 구성은 개별 변환마다 Python 루프를 두는 방식을 피하기 때문에 중요하다. 따라서 이 실험은 데이터베이스 함수 호출과 파싱 경로를 결합한 작업을 더 직접적으로 겨냥한다. Python 애플리케이션이 네이티브 코드로 반복 진입하는 상황을 주로 측정하는 것은 아니다.

하니스는 15회 실행에 걸쳐 후보들을 교대로 실행한다. 최소 및 중앙 경과 시간을 기록한 뒤, 최소값에서 광고된 순 수치를 계산한다. 결과가 행당 나노초가 되기 전에는 문자열 길이를 합산하는 기준 스캔을 빼준다.

이 차감은 추가 작업을 분리하는 데 도움이 되지만, 해당 수치는 여전히 비교를 위한 추정치다. 이는 가져오기 전체 시간, 대시보드 새로고침 또는 다른 작업을 포함하는 쿼리의 전체 지속 시간이 아니다. 이를 사용자 관점의 응답 시간으로 해석하면 측정 설계를 넘어선다.

데이터셋도 결과를 형성한다. 별도 실행은 정수 텍스트, 소수 텍스트, 혼합 서식 값들을 다룬다. 혼합 생성기는 통화 기호가 붙은 값, 백분율, 일반 숫자 문자열, 잘못된 항목을 포함한다. 이러한 변형은 소수 변환 문제와 일반적인 파싱 문제를 구분할 수 있게 한다.

가져온 재무 보고서를 반복적으로 정렬하는 애플리케이션을 생각해 보자. 모든 쿼리에서 파싱이 발생한다면 변환 작업은 각 보고서 요청의 일부가 된다. 반면 애플리케이션이 가져오는 과정에서 값을 정규화한다면, 같은 파서는 다른 단계에 영향을 미치며 다른 성능 요구사항을 마주한다.

어느 아키텍처도 이 측정만으로 자동으로 결정되지는 않는다. 이 실험은 파싱 구성 요소에 대한 증거를 제공하는 반면, 애플리케이션이 그 구성 요소의 실행 빈도를 결정한다. 더 빠른 독립 함수는 실제 워크로드에서 의미 있는 비중을 차지할 때 가장 중요하다.

벤치마크의 순수 SQL 대안은 중첩된 replace() 호출, 즉 반복적인 문자열 치환 뒤에 숫자 변환을 사용한다. 이는 개발자에게 친숙한 비교 지점을 제공한다. 하지만 문자를 교체하는 일과 완전한 입력 정책을 적용하는 일은 서로 다르므로, 동등한 동작 여부는 별도로 검토해야 한다.

따라서 짧은 벤치마크 요약을 구현 선택의 근거로 사용하는 개발자에게 부담이 돌아간다. 보고된 순위를 채택하기 전에, 자신의 애플리케이션에서 파싱이 어디에서 발생하는지 식별해야 한다. 또한 자신의 입력이 생성된 데이터셋과 유사한지도 확인해야 한다.

SQLite parse_number()의 경우 하니스는 이러한 질문을 검토할 수 있게 한다. 독자는 승리 수치에만 의존하지 않고, 시간 측정 쿼리와 데이터 생성기를 모두 살펴볼 수 있다.

C는 검증과 변환을 결합해 속도를 얻는다

최적화된 C 구현은 중간 작업을 줄이면서도 지름길의 한계를 벗어나는 입력에 대비한 폴백을 유지한다.

최적화된 소수 파서는 숫자 정보를 누적하면서 문자를 검사한다. 이 스캔 동안 유효 자릿수를 추적하고 소수점 뒤의 자릿수를 센다. 이에 따라 적합한 입력은 정리된 문자열로 재구성하는 과정을 피할 수 있다.

이 지름길은 중간값이 정확한 표현 요건을 충족할 때 적용되는 소수 변환 기법인 Clinger의 빠른 경로를 사용한다. 구현은 명시적인 수치 조건을 사용해 이 경로를 제한한다. 이 조건을 벗어나는 값은 더 느린 변환 경로로 계속 진행된다.

이 구분은 필수적이다. 단순히 반올림 오류를 허용하는 지름길은 다른 엔지니어링 질문에 답하게 된다. 여기서 코드는 의도한 수치 결과를 유지하면서 제한된 입력 집합의 처리를 가속하려 한다.

구현은 최대 19개의 유효 자릿수를 수집한다. 소수 지름길에는 추가로 누적값이 2^53 이하이고 소수 자릿수가 22개를 넘지 않아야 한다는 조건이 있다. 이 경계가 직접 계산의 적용 가능 여부를 결정한다.

더 넓은 설계는 왜 수정이 비교 결과를 바꿨는지 설명한다. 검증 과정에서는 이미 입력 문자를 검사해야 한다. 그 검사 중에 유용한 숫자 정보를 누적하면, 별도 변환 단계가 그렇지 않으면 반복했을 일부 작업을 피할 수 있다.

정수 처리도 같은 접근 방식의 이점을 얻는다. 값이 맞는 경우 함수는 누적한 정수를 직접 반환할 수 있다. 문자열을 다시 변환하기 전에 임시 정리 문자열을 만들 필요가 없다.

폴백 역시 상당한 엔지니어링 작업이다. 검증된 숫자 텍스트를 재구성하고, 가능한 경우 로컬 버퍼를 사용하며, 필요할 때는 추가 저장소를 할당한다. 여기서 할당은 작업을 위해 임시 메모리를 요청하는 것을 뜻하며, 산술 자체를 넘어선 처리를 도입한다.

이 코드는 지름길을 활성화하기 전에 컴파일러의 부동소수점 평가 동작도 확인한다. 이 보호 장치는 중간 계산이 다른 정밀도를 사용할 가능성을 다룬다. 이 세부 사항은 작은 산술 최적화가 겉으로 보이는 코드 줄 수 이상으로 추가 의무를 갖게 될 수 있음을 보여준다.

Rust 후보들은 다른 작업 구성 방식을 사용하므로 여전히 의미 있는 비교 대상이다. 이 조사는 똑같이 특화된 Rust 재작성이 같은 성능을 유지할 것이라고 확립하지 않는다. 최적화된 C를 이 Rust 버전들과 비교한 결과는 해당 후보들에 대한 결과를 확립한다.

합리적인 해석은 이 특화가 테스트된 워크로드에서 효과를 냈다는 것이다. C 재작성은 이전에 분리되어 있던 작업들을 결합하고, 적용 가능한 값에 대해서는 일반 변환 루틴을 피한다. 이러한 해석은 구현에서 확인할 수 있는 메커니즘을 따른다.

또한 이는 언어에 대한 평판이 불완전한 예측을 제공하는 이유를 설명한다. 범용 루틴은 넓은 입력 공간 전반의 동작을 제공하는 반면, 특화 코드는 더 좁은 계약을 겨냥할 수 있다. 성능은 실제로 들어오는 입력에 대해 선택한 경로가 얼마나 많은 작업을 수행하는지에 부분적으로 좌우된다.

유지보수 문제도 바로 이어진다. 더 빠른 구현을 소유하는 사람은 그 적용 조건, 폴백 동작, 수치적 가정도 함께 책임진다. 측정된 이점은 팀이 이후 변경 과정에서도 이러한 속성을 유지할 수 있을 때만 유용하다.

확장 기능 크기와 코드 소유권은 서로 다른 방향으로 작용한다

더 작은 컴파일 산출물과 더 단순한 유지보수 경로는 별개의 기준이며, 어느 것도 다른 하나를 대체하지 않는다.

프로젝트의 구현 비교는 스트립 처리된 C 라이브러리의 크기를 14,408바이트로 보고한다. 해당 Rust 산출물은 rusqlite에서 320,864바이트, sqlite-loadable에서 298,464바이트다. 스트리핑은 컴파일 파일에서 특정 빌드 정보를 제거한다.

같은 보고서는 단순한 C에서 빈 줄과 주석을 제외한 코드 줄 수를 75줄, 최적화된 C에서는 104줄로 집계한다. Rust는 통합 코드 36줄 또는 30줄에 공유 파서 41줄을 더한다. rusqlite 버전은 의존성 20개, sqlite-loadable은 62개를 보고한다.

이 측정들은 서로 다른 형태의 복잡성을 설명한다. 소스 길이는 눈에 보이는 구현 규모를 포착하고, 의존성 수는 빌드 그래프의 일부를 포착한다. 어느 쪽도 미래의 버그를 진단하기가 얼마나 어려운지 직접 측정하지는 않는다.

짧은 함수는 라이브러리 전반에 분산된 동작에 의존할 수 있다. 더 긴 자체 완결형 함수는 애플리케이션 팀이 검토해야 하는 책임을 코드 안에 집중할 수 있다. 둘 중 무엇을 선택할지는 팀이 그 책임을 어디에 두고 싶은지 묻는 일에서 시작된다.

C 구현은 여러 책임을 눈에 보이게 만든다. 버퍼 처리, 정수 범위 검사, 소수점 빠른 경로가 프로젝트 자체 소스에 드러난다. 검토자는 이를 직접 살펴볼 수 있지만, 가시성이 전문성의 필요를 없애지는 않는다.

Rust의 언어 기능과 파싱 라이브러리는 일부 수작업 처리를 줄일 수 있다. 이미 Rust로 작업하는 팀에는 가독성 향상으로 이어질 수 있다. 다만 간결한 통합 계층도 입력 정책, 데이터베이스 동작, 오류 처리 측면에서 검토가 필요하다.

컴파일된 크기는 또 다른 질문을 만든다. 추가 라이브러리는 엄격하게 제한된 배포 환경에서와 이미 상당한 자산을 포함한 애플리케이션에서 서로 다른 의미를 갖는다. 보고된 차이는 측정 가능하지만, 실질적 중요성은 배포 환경에 달려 있다.

파일 크기는 런타임 메모리 소비를 대변할 수도 없다. 디스크에 있는 라이브러리의 바이트 수는 데이터 처리 중 발생하는 모든 할당을 설명하지 못한다. 가장 작은 파일을 가장 적은 메모리를 사용하는 구현으로 간주하려면, 이 비교가 제공하지 않는 측정이 필요하다.

의존성 수에도 같은 주의가 적용된다. 의존성이 많으면 빌드 및 업데이트와 관련한 고려 사항이 늘어날 수 있지만, 단순히 수를 세는 것만으로 결함률이 정해지지는 않는다. 반대로 의존성이 적다고 해서 애플리케이션 소유 코드가 더 유지보수하기 쉽다는 뜻도 아니다.

기존 C 애플리케이션이라면 간결한 C 확장이 확립된 컴파일 및 검토 관행에 잘 맞을 수 있다. 기존 Rust 애플리케이션이라면 별도의 C 구성 요소를 도입하는 일이 추가적인 소유 관리 작업을 만들 수 있다. 이는 벤치마크로 확정된 결과가 아니라 배포에 관한 판단이다.

따라서 SQLite parse_number()는 여러 독립적인 차원을 지닌 선택지를 제시한다. 보고된 최적화 C 후보는 측정된 파싱 성능과 컴파일된 크기에서 앞선다. 그러나 팀은 특화된 변환 경로를 유지하는 일이 자신의 역량과 릴리스 프로세스에 맞는지 여전히 결정해야 한다.

유용한 비교는 이러한 차원을 계속 드러낸다. 이를 단일 승자로 축소하면, 서로 다른 팀이 합리적으로 서로 다른 선택을 할 수 있는 이유를 가리게 된다.

테스트 통과만으로 데이터 계약이 확정되지는 않는다

정확성에는 구현체가 수치 답에 동의하는지를 넘어, 형식화된 텍스트에 부여된 의미도 포함된다.

비교 보고서는 모든 버전이 명시적 사례 40건과 무작위 비교 800만 건을 통과했다고 말한다. 흔히 퍼징이라고 하는 무작위 테스트는 예상치 못한 동작을 찾기 위해 입력을 생성한다. 보고된 결과는 근거를 제공하지만, 이 글을 위해 독립적으로 재현되지는 않았다.

특히 산술 로직을 다시 작성한 뒤에는 구현체 간 일치가 가치 있다. 이는 테스트된 입력 공간 안에서 명백한 불일치가 발생할 가능성을 낮춘다. 그러나 구현체들이 함께 일치한다고 해서 선택한 동작이 특정 애플리케이션의 비즈니스 규칙과 맞는지는 판단할 수 없다.

백분율은 그 차이를 잘 보여준다. 퍼센트 기호를 제거하면 표시된 숫자는 유지되지만, 백분율을 비율로 해석하면 규모가 바뀐다. 애플리케이션은 어느 의미가 필요한지 결정한 뒤에야 둘 중 하나를 올바른 동작으로 볼 수 있다.

통화 표기도 관련된 문제를 제기한다. 기호를 제거하면 텍스트를 수치로 처리하기 쉬워지지만, 값들이 같은 단위를 공유한다는 사실까지 확립되지는 않는다. 서로 다른 통화의 금액을 합치려면 단순한 문자 제거만으로는 제공할 수 없는 정보가 필요하다.

형식 규칙도 주의할 만하다. 쉼표는 한 규칙에서는 자릿수 구분을 뜻하고 다른 규칙에서는 소수점 경계를 뜻할 수 있다. 고정된 규칙을 전제로 설계된 파서는 그 기대 조건이 수신하는 데이터에 함께 명시되어야 한다.

이는 Willison의 구현에서 확인된 결함이 아니라, 도입 과정에서 가정해 볼 수 있는 우려다. 파서가 설계된 대로 정확히 동작하더라도 익숙하지 않은 데이터셋에는 부적절할 수 있는 이유를 설명한다. 정확성은 선택된 계약에서 시작된다.

수치 정밀도는 또 다른 경계를 더한다. SQLite의 부동소수점 문서는 REAL 값이 binary-64 표현을 사용하며 근사값임을 설명한다. 변환을 수행하는 언어와 무관하게, 많은 십진 분수는 이 형식에서 정확히 표현될 수 없다.

올바르게 반올림하는 파서는 표현 가능한 적절한 값을 선택한다. 그렇다고 이후의 모든 산술 연산이 정확해지는 것은 아니다. 정확한 십진 계산이 필요한 애플리케이션은 표현 방식과 산술 요구 사항을 별도로 평가해야 한다.

실패 처리도 같은 수준의 주의를 받을 만하다. 존재하지 않거나 알 수 없는 값을 나타내는 SQLite의 표시인 NULL을 반환하면 텍스트가 유효하지 않아도 처리를 계속할 수 있다. 그렇더라도 애플리케이션은 거부된 데이터를 유효한 수치 입력과 구별할 방법을 보존해야 한다.

그렇지 않으면 깔끔해 보이는 결과가 데이터 품질 문제를 감출 수 있다. 합계를 확인하는 사용자는 예상된 모든 레코드가 의미 있게 반영되었는지 알아야 한다. 파서가 자신의 계약을 따르더라도 이 문제는 주변 애플리케이션에 속한다.

벤치마크 자체도 별도의 불확실성을 도입한다. 기준선 차감 후의 최소 시간은 유리하게 측정된 실행을 설명한다. 이는 프로덕션 경합, 다양한 데이터셋, 또는 다른 컴퓨팅 환경에서의 일반적인 성능을 확립하지는 않는다.

공유된 테스트 결과만으로 보편적인 성능 주장이 나오는 것도 아니다. 비정상적으로 긴 입력이 더 많은 워크로드는 폴백 경로를 더 자주 실행할 수 있다. 그러면 테스트된 일반적인 형식의 값과 비교했을 때 작업의 균형이 달라진다.

따라서 SQLite parse_number()를 회의적으로 읽는 방식은 건설적이다. 결과는 특정 구현을 검토하고 그 동작을 재현할 근거가 된다. 하지만 허용 형식을 정의하고, 거부된 레코드를 보존하며, 의도한 호스트 애플리케이션에서 결과를 검증할 필요를 없애지는 않는다.

재현, Rust 개정, 폴백 동작을 지켜보라

다음으로 유용한 근거는 동작과 측정 방법을 명시적으로 유지하면서 비교 범위를 넓히는 것이다.

가장 먼저 지켜볼 신호는 독립적인 재현이다. 다른 시스템에서 실행하면 보고된 순위가 하드웨어와 빌드 환경의 변화에도 얼마나 유지되는지 검증할 수 있다. 전체 쿼리 시간과 산출된 파싱 비용을 모두 보고하면 그 근거를 더 쉽게 해석할 수 있다.

결과가 일치한다면 최적화 C의 이점이 원래 설정을 넘어선다는 신뢰가 강해진다. 순위가 달라진다면 결론의 범위가 좁아지고, 추가로 조사할 가치가 있는 요인이 드러난다. 환경과 입력 분포가 문서화된다면 어느 결과든 비교를 개선할 수 있다.

재현은 수치 결과와 타이밍의 구분도 보존해야 한다. 허용되는 입력을 바꾸는 빠른 후보는 더 이상 같은 질문에 답하지 않는다. 정확성 결과를 성능과 함께 공개하면 이 경계를 계속 드러낼 수 있다.

두 번째 신호는 비교에서 드러난 구체적 작업을 다루는 개정된 Rust 구현이다. 스캔 및 변환 전략이 더 가까워지면 구현 구조와 언어 선택을 분리하는 데 도움이 된다. 핵심 질문은 비슷한 수준의 특화가 측정된 격차를 줄이는지다.

개정된 Rust가 통합 이점을 유지하면서 차이를 좁힌다면, 초기 결과는 언어를 선택하기 전에 알고리즘을 검토해야 한다는 더 강한 근거가 된다. 최적화 C가 선두를 유지한다면 개발자는 이 특정 구성 요소에 대해 더 확실한 근거를 얻게 된다.

이는 제안된 비교일 뿐, 발표된 릴리스나 약속된 결과가 아니다. 업데이트된 버전이 정해진 일정에 맞춰 나올 것이라고 가정할 이유는 없다. 그 가치는 경쟁 구현체를 더 직접적으로 비교 가능하게 만드는 데서 나온다.

세 번째 신호는 폴백 동작에 관한 근거다. 최적화된 C 빠른 경로는 적격 입력을 신속하게 처리하지만, 더 넓은 입력 분포는 느린 경로가 실행되는 빈도를 바꿀 수 있다. 그러한 사례를 테스트하면 구현의 실제 동작 범위를 더 잘 알 수 있다.

그 작업은 속도만큼 정확성도 면밀히 살펴봐야 한다. 긴 수치 문자열, 형식이 잘못된 레코드, 서로 다른 호스트 설정은 일반적인 형식의 값에서는 드러나지 않는 가정을 노출할 수 있다. 문서화된 결과는 또 하나의 고립된 헤드라인 타이밍보다 신뢰를 더 높일 것이다.

엔지니어링 팀에게는 소스만큼이나 주변 근거를 보존하는 일이 중요하다. 빌드 설정, 입력 예시, 배제된 대안은 특정 구현이 선택된 이유를 설명한다. 이를 검색 가능한 지식 기반에 보관하면 미래의 검토자가 그 결정을 다시 살펴볼 수 있다.

이 조사의 즉각적인 가치는 이미 분명하다. 측정된 병목이 구체적인 개정과 변화된 결과로 이어졌다. 아직 열려 있는 문제는 그 결과가 얼마나 넓게 적용되는가다. 후속 비교는 집중된 실험을 보편적인 언어 우열 판정으로 바꾸지 않으면서 근거를 확장해야 한다.

SQLite parse_number()를 도입하기 전에 애플리케이션이 실제로 마주한 결정이 무엇인지 파악하라. 대표적인 입력을 보존하고, 백분율과 유효하지 않은 레코드가 어떻게 처리되어야 하는지 정의하며, 이를 실행할 호스트 내부에서 후보를 비교하라. 유리한 구성 요소 결과가 사용자 경험과 계속 연결되도록, 전체 쿼리 시간을 산출된 파싱 수치와 함께 보관하라. 특화된 수치 경로는 폴백과 같은 수준의 주의로 검토하고, 둘 모두를 재현하는 데 필요한 빌드 세부 정보도 보존하라. 다음으로 유용한 단계는 이 구현의 장점이 여러분의 요구 사항에서도 유지되는지 시험하는 것이다. 여러분의 애플리케이션에서 선택을 좌우하는 제약은 무엇인가? 반복 변환 시간, 배포 크기, 아니면 파서 유지보수에 필요한 노력인가?

 
 

무료로 시작하세요

개인 지식 관리 기능을 갖춘 로컬 우선 AI 어시스턴트

더 나은 AI 경험을 위해

현재 remio는 Windows 10+ (x64) 및 M-Chip Macs만 지원합니다.

업무를 위한 AI 파트너
remio와 더 많은 일을 해내세요

계획하고, 만들고, 완성하세요
모든 일을 한곳에서

bottom of page