Files
document-haness/.agents/skills/rewriting-technical-prose-naturally/references/korean-tech-blog-register.md
T

21 KiB

한국 기술 블로그 문장 규범

한국 대기업 기술 블로그가 실제로 쓰는 문장을 모아 정리한 것이다. 인용문은 아래 글에서 가져왔다.

인용문 출처에 관한 한계. 원 사이트가 자동 수집을 막고 있어, 아래 인용문은 페이지를 그대로 내려받지 않고 추출 도구를 거쳐 옮겼다. 문장의 어투·어미·낱말 선택을 보기에는 충분하지만 한 글자까지 원문과 같다고 보장하지 못한다. 이 파일의 인용문을 문서에 직접 인용으로 옮기지 말고, 필요하면 원문 링크에서 직접 확인한 뒤 옮긴다. 이 파일의 쓰임은 문체 관찰이다.

문장 틀을 베끼라는 뜻이 아니다. 같은 표현을 반복해서 쓰면 그것이 또 하나의 기계 문체가 된다. 여기서 가져갈 것은 어떤 자리에 어떤 품사와 어떤 동사를 쓰는가이고, 버릴 것은 문장 자체다.


1. 쓸 말은 쓰기 전에 정의한다

기술 블로그는 처음 쓰는 말을 그 자리에서 한 문장으로 풀고 시작한다. 정의는 그 말이 무엇인지무엇을 하는지를 말하지, 이 글에서 어떤 역할을 맡는지를 말하지 않는다.

"'진입점'은 사용자 요청의 시작점을 의미합니다. 애플리케이션 또는 시스템에서 사용자 요청이 최초 진입되는 지점이 바로 진입점 입니다."

"MDC(Mapped Diagnostic Context)는 자바 로깅 프레임워크(slf4j 등)에서 지원하는, 현재 실행중인 쓰레드 단위에 메타 정보를 넣고 관리하는 공간입니다."

"WMS(Warehouse Management System, 창고 관리 시스템)는 물류센터에서 반복되는 수기 작업을 시스템화하여 안정적으로 운영될 수 있도록 합니다."

"화면에 렌더링되어 사용자에게 노출되는 문자열을 '문구'라고 하겠습니다."

"할당이란? 동일한 상품이 물류 센터 내 여러 로케이션(위치)에 흩어져 있는 경우, 작업자가 출고할 상품을 선점하는 작업이 필요한데 이 작업을 할당이라고 합니다."

"Payload는 특정 term에 추가로 저장할 수 있는 메타데이터를 의미합니다."

"샌드박스는 브라우저에서 바로 연동 흐름을 체험하고, 테스트 연동을 해볼 수 있는 개발자 도구예요."

정의에 쓰는 서술어는 좁다. ~를 의미합니다 · ~입니다 · ~하는 공간입니다 · ~하는 설정입니다 · ~라고 하겠습니다 · ~를 X라고 합니다.

두 가지 습관을 같이 본다.

  • 약어는 처음 나올 때 편다. MDC(Mapped Diagnostic Context), WMS(Warehouse Management System, 창고 관리 시스템), AST(Abstract Syntax Tree).
  • 정의한 뒤 한 번 더 구체적으로 바꿔 말한다. 진입점 예시가 그렇다. 첫 문장은 사전적으로, 두 번째 문장은 이 시스템에서 어디를 가리키는지로 다시 말한다.

정의를 넣는 자리는 그 말을 처음 쓰기 직전이다. 글 끝의 용어집이나 각주가 아니다.


2. 원인과 결과는 한 문장 안에서 잇는다

한국어 기술 문장은 이유를 연결어미로 문장 안에 넣는다. 사실 하나마다 문장을 끊지 않는다.

"행정동은 변경이 잦기 때문에, 실시간으로 반영하지 않으면 내부에서 관리하는 행정동과 실제 행정동이 달라 배달팁이 실제 '동' 기준으로 부과되지 못하는 문제가 발생합니다."

"폴리곤 데이터는 실시간으로 변경되는 데이터가 아니기 때문에 메모리에 올려놓고 사용해도 무방했습니다."

"카테고리ID 필드는 숫자이기 때문에 integer로 색인을 하였는데, 정확하게 일치하는 값을 찾아내는 용도로만 쓰고 있기 때문에 keyword로 타입을 변경했습니다."

"높은 집중력이 요구되는 작업에서 사람은 실수 덩어리이고 LLM은 확률적이다 보니 판단력이 다소 아쉬웠습니다."

"물론 린트가 자동 교정까지 해주면 가장 이상적이겠지만 자연어를 기계적으로 교정하기는 어렵다 보니, 역할을 나눠서 린트가 탐지하고 AI가 교정하는 하이브리드 접근법으로 가겠습니다."

자주 쓰는 이음말: ~기 때문에 · ~다 보니 · ~어서 · ~(으)므로 · ~는데 · ~니 · ~면.

문장 길이는 대체로 40–120자다. 한 문장에 사실 하나만 담으라는 규칙을 기계적으로 적용하면 "A였다. B였다. 그래서 C였다."처럼 끊기는데, 이렇게 쓰는 한국 기술 블로그는 없다. 끊는 기준은 사실의 개수가 아니라 주어가 바뀌는 지점이다. 주어가 같고 이유·조건으로 이어지면 한 문장에 둔다. 주어가 바뀌면 끊는다.


3. 수치는 동사로 말한다

"색인 문서의 양이 약 3배 증가했습니다." "검색 및 리스팅 API 호출 수는 약 1.5배 증가했습니다." "p99.9와 p99.99의 응답 속도가 20% 개선되었습니다." "aggregation 수행 속도가 2배 이상 향상되었습니다." "응답시간 0.7초 이상 슬로우쿼리가 모두 제거되었습니다." "기존에는 약 4시간이 소요되었고, 개선 후에는 약 1분이 소요되었습니다." "성능을 약 150배 향상 할 수 있었습니다." "파일에서 컬럼을 읽어서 저장하기에 INSERT에 비해 약 20배 정도까지 빠를 수 있습니다."

틀은 단순하다. <잰 것>이/가 <수치만큼> <동사>했습니다. 앞뒤 비교는 기존에는 ~, 개선 후에는 ~로 둔다. , 이상, 정도까지로 정밀도를 솔직하게 낮춘다.

증가 관계를 말하는 법

두 값이 같이 늘어난다는 말을 억지로 만들지 않는다. 실제로 쓰는 말은 이렇다.

관계 쓰는 표현
같은 수만큼 아이템이 100개면 쿼리도 100번 나갔습니다 · N과 같은 수로 늘었습니다
비례 N에 비례해 늘었습니다 · N이 커진 만큼 늘었습니다
배수 약 3배 증가했습니다 · 50배까지 벌어졌습니다
안 변함 N을 바꿔도 2개로 그대로였습니다 · 페이지 크기에 고정되었습니다
단위로 증가 배치 크기마다 한 번씩 늘었습니다

~를 따라 늘었다, ~를 따라갔다, ~를 좇았다는 쓰지 않는다. 한국어에서 따라가다의 목적어는 사람·길·기준 같은 것이지 개수가 아니다. 조회 수는 아이템 수 100을 따라갔다는 한국어 문장이 아니다. 무엇이 몇이면 무엇이 몇이었는지를 그대로 적으면 된다.


4. 문맥에 따른 동사 선택

같은 뜻이라도 자리마다 쓰는 동사가 다르다. 아래는 관찰한 글에서 실제로 쓰인 동사다.

무엇을 말할 때 쓰는 동사
쿼리·요청이 실행됨 나갔습니다 · 실행되었습니다 · 호출했습니다
수가 늘어남 늘었습니다 · 증가했습니다 · 벌어졌습니다 · 부풀었습니다
수가 줄어듦 줄었습니다 · 감소했습니다 · 제거되었습니다
빨라짐·좋아짐 개선되었습니다 · 향상되었습니다 · 빨라졌습니다
시간이 걸림 소요되었습니다 · 걸렸습니다
문제가 나타남 발생합니다 · 생겼습니다 · 드러났습니다 · 초래했습니다
문제가 사라짐 해소되었습니다 · 사라졌습니다 · 막았습니다
설정을 바꿈 변경했습니다 · 조정했습니다 · 분기했습니다
기능을 넣음 적용했습니다 · 도입했습니다 · 추가했습니다
재보고 확인함 측정했습니다 · 확인했습니다 · 살펴보겠습니다 · 파보겠습니다
코드가 훑음 순회합니다 · 탐색합니다 · 마주합니다
코드가 찾아냄 찾아냅니다 · 잡습니다 · 탐지합니다
코드가 판정함 판단합니다 · 허용합니다 · 제한합니다 · 위반으로 잡습니다
코드가 저장·전달함 넣고 관리합니다 · 삽입합니다 · 표시합니다 · 전달합니다
원인을 지목함 ~ 때문입니다 · ~에서 비롯되었습니다
판단을 밝힘 ~라고 판단했습니다 · ~해도 무방했습니다 · 도입하기 무리였습니다 · 한계가 있었습니다

코드 동작을 설명하는 문장의 예시다.

"린터의 원리는 AST 노드를 순회하면서 설정된 규칙 기반으로 패턴을 찾아내는 것입니다." "노드에 진입·퇴장하는 이벤트마다 스택에 삽입·회수할 플래그들을 정의합니다." "계속 탐색하다 보면 어느새 말단에서 세 가지 타입의 문자열에 각각 상응하는 노드를 마주합니다." "내부에 JSX 텍스트만 있고 엘리먼트나 컴포넌트가 없는 <Trans> 컴포넌트를 위반으로 잡을 뿐입니다." "이 규칙은 함수 파라미터의 기본값으로 문자열 리터럴이 들어가는 것을 허용하는데, 프로젝트에서는 최종적으로 이런 기본값이 노출될 수도 있으니 제한해야 합니다."

코드는 ~합니다 현재형으로 쓴다. 측정과 겪은 일은 ~했습니다 과거형으로 쓴다. 둘을 섞지 않는다.


5. 조사

자리 조사
잰 대상 이/가 응답 속도가 20% 개선되었습니다
앞뒤 대비 은/는 기존에는 4시간, 개선 후에는 1분
바뀐 결과 상태 (으)로 keyword로 타입을 변경 · 1분이 소요
비교 기준 에 비해 · 보다 INSERT에 비해 약 20배
비례 기준 에 비례해 · 만큼 N에 비례해 · N이 커진 만큼
출처·주체 로부터 · 에서 DC 관리자로부터 문의가 들어왔습니다
용도 한정 용도로만 일치하는 값을 찾는 용도로만 쓰고 있기 때문에
  • ~를 따라를 개수 증가에 붙이지 않는다. (3절)
  • 를 세 번 이상 잇지 않는다. 조회 수의 증가 형태의 비교조회 수가 어떻게 늘었는지로 푼다.
  • 명사를 ~에 대한으로 잇지 말고 동사로 푼다. 쿼리 수에 대한 측정쿼리 수를 측정했습니다.

6. 명사: 역할 이름이 아니라 물건 이름

기술 블로그는 대상을 그 대상의 이름으로 부른다. 논증에서 맡은 역할로 부르지 않는다.

쓰지 않는 말 쓰는 말
기준선 / 비교 대상 처음 만든 loadFeed 구현 · 이 코드를 그대로 두고 잰 값
최소한의 선 / 마지노선 반드시 지켜야 하는 조건은 <조건>입니다
관계 (막연한) FeedItemHighlight@OneToMany 매핑 · user_id 외래 키
위반 어떤 요구를 어떻게 어겼는지
핵심 / 본질 / 실체 실제로 일어난 일
구조적 문제 어떤 코드가 어떤 조건에서 무엇을 하는지
증가 형태 / 비용 쿼리 수 · 조회 행 수 · 응답 시간
~는 비교 대상이 아니다 두 값은 세는 것이 다릅니다. A는 <A가 세는 것>, B는 <B가 세는 것>입니다

관계는 JPA 연관 관계처럼 이름의 일부일 때만 쓴다. 무엇과 무엇이 어떻게 연결되는지를 관계라는 낱말로 덮으면 독자는 어느 매핑인지 알 수 없다.


6.5 라틴 문자는 식별자에만

관찰한 다섯 편은 자리잡은 외래어를 모두 한글로 적는다. 라틴 문자로 남는 것은 실제 식별자와 제품명뿐이다.

한글로 적는다 라틴으로 둔다
쿼리 · 캐시 · 인덱스 · 라이브러리 · 컴포넌트 · 플러그인 · 스레드 · 클래스 · 메서드 · 필드 · 테스트 · 세션 · 토큰 · 커넥션 · 타임아웃 · 어댑터 · 인스턴스 · 클라이언트 CacheAsideExecutor · getLoadCount() · min-replicas-to-write 1 · application.yml · @ManyToOne · GETDEL
자격 증명 · 상한 · 소유자 · 원본 · 응답 · 경고 · 계정 · 묶음 · 갈래 · 상태 · 설정 · 키 Redis · Nginx · Hibernate · Spring · Keycloak · PostgreSQL

실측: 우아한형제들은 문장당 맨몸 영문 낱말이 1.4개, 글자 중 한글이 **58%**다. 같은 자리에서 이 저장소 문서는 **4.4개 / 34%**였다. 영어 낱말을 조사로 이어 붙인 문장이 "AI가 정리한 기술 보고서"처럼 읽히는 가장 큰 이유다.


7. 주어

  • 결정과 행동은 사람이 주어다. 저는 ~하기로 했습니다, 역할을 나눠서 ~로 가겠습니다, 거의 전부 AI에게 맡겼습니다.
  • 결과와 현상은 잰 대상이 주어이고 서술어는 피동이다. 응답 속도가 개선되었습니다, 슬로우쿼리가 모두 제거되었습니다, 약 40시간 이상이 걸릴 것으로 예측이 되었습니다.
  • 코드를 설명할 때는 코드 요소가 주어다. 린터의 원리는 ~, 이 규칙은 ~를 허용하는데, @rollup/browser는 파일 시스템이 아닌 메모리상의 데이터를 다뤄요.
  • 주어를 생략해도 앞 문장에서 분명하면 생략한다. 문단마다 주어를 다시 세우지 않는다.

8. 문제는 사건으로 쓴다

"DC 관리자로부터 취소된 이관요청서에 재고가 할당되어있다는 문의가 들어왔습니다." "동시성 이슈의 원인은 취소 작업에는 분산 락이 걸려 있지 않기 때문입니다." "데이터를 추출하고 보니, 이 배치를 통해 정확한 매핑 데이터를 추출하기에는 한계가 있었습니다." "최초에 해당 배치를 개발하고 성능 측정을 해보았을 때, 운영환경의 데이터 기준 약 40시간 이상이 걸릴 것으로 예측이 되었습니다." "그래서 기존 코드에서 많은 한글 문구들이 탐지되지 않아 번역이 누락되었고, 내부 개발용 코드의 한글 문자열이 잘못 잡히는 문제도 있었습니다."

문제가 있었습니다로 끝내지 않는다. 누가 무엇을 겪었는지, 어떤 조건에서 무엇이 어긋났는지를 적는다. 원인은 원인은 ~ 때문입니다로 한 번에 지목한다.


9. 선택과 권고

"처음에는 이상적인 린트 플러그인을 섭외하여 공수를 절감하려 했지만 눈앞의 생태계는 상당히 척박했습니다." "옵션 조절로도 해결이 어려운 문제가 다수 있어서 도입하기 무리였습니다." "결국 컨벤션들을 충족시키는 커스텀 린트 규칙들과 이들을 포함하는 플러그인을 직접 개발하기로 했습니다." "단일 term일 경우 match_phrase 쿼리가 아니라 match 쿼리로도 요구사항을 만족할 수 있기 때문에 분석된 term에 따라 쿼리를 변경하도록 쿼리를 분기했습니다." "폴리곤 데이터는 실시간으로 변경되는 데이터가 아니기 때문에 메모리에 올려놓고 사용해도 무방했습니다."

순서가 일정하다. 먼저 해보려던 것 → 안 된 이유 → 그래서 고른 것 → 고른 이유. 대안을 대안으로는 A, B가 있다처럼 목록으로 늘어놓지 않고, 실제로 검토했다가 접은 것만 이유와 함께 쓴다.

권고할 때 쓰는 말: ~해야 합니다 · ~하는 편이 낫습니다 · 가급적 ~를 씁니다 · ~해도 무방했습니다 · 도입하기 무리였습니다.


9.5 설명의 순서

용어 하나를 설명하는 대목은 대체로 같은 순서로 흘러간다.

  1. 정의 — 그 말이 무엇이고 무엇을 하는지 (화면에 렌더링되어 사용자에게 노출되는 문자열을 '문구'라고 하겠습니다)
  2. 그래서 무슨 일이 벌어지는가 — 그 말이 실제 코드·운영에서 어떻게 쓰이는지
  3. 거기서 생기는 문제 — 어떤 조건에서 무엇이 어긋나는지 (판단력이 다소 아쉬웠습니다, 미탐과 오탐이 생겨 ~ 하락을 초래했습니다)
  4. 그래서 무엇으로 대신하는가 — 대안과 고른 이유 (역할을 나눠서 린트가 탐지하고 AI가 교정하는 하이브리드 접근법으로 가겠습니다)

읽는 사람은 이 순서대로 알게 된다. 정의를 뒤로 미루면 2번과 3번을 읽는 동안 무슨 말인지 모른 채 따라가야 한다. 문제를 먼저 던지고 정의를 나중에 붙이는 구성은 극적이지만, 기술 문서에서는 독자가 같은 문단을 두 번 읽게 만든다.

TechLog 기록은 서로 링크로 이어지는 관계형 문서라 분량이 짧을 수 있다. 그렇더라도 핵심 주장과, 그 주장을 이해하는 데 필요한 선수 지식은 그 기록 안에 있어야 한다. 다른 기록으로 넘겨도 되는 것은 더 깊은 배경이지, 이 문장을 읽는 데 당장 필요한 정의가 아니다.

4번은 자료에 근거가 있을 때만 쓴다. 대안을 검토한 적이 없으면 3번에서 멈춘다.


10. 소제목

형태
질문형 진입점이 뭐죠? · 근데 왜 진입점 정보가 남아야 해요? · MDC를 아시나요?
행동형 1 단계: 분산 락 추가하기 · 할당과 취소가 동시에 처리되는 것을 막아보자 · 브라우저에서 번들링하기
대상형 공간데이터 및 GeoJSON · @lib/i18n과 세 가지 컨벤션 · 세 가지 린트 규칙과 위반 탐지 과정
한계·상태형 사람과 AI 검수의 한계 · 험난한 컨벤션 준수의 길 · 남은 과제들

셋 다 이 절에서 다루는 대상이나 하려는 일을 이름으로 말한다. 대비를 만들거나 수수께끼를 내지 않는다. 같은 EAGER가 정반대 곡선을 그린다 같은 제목은 이 목록에 없다.


11. 절 첫 문장 — 예고는 되고 되풀이는 안 된다

앞으로 무엇을 어떤 각도에서 볼지 알려 주는 문장은 실제로 쓴다.

"이번에는 그렇게 탄생한 규칙들을 깊게 파보겠습니다." "그러므로 각 규칙이 위반·허용 패턴을 정의하는 방식과, 특정 노드의 진입·퇴장 이벤트에서 패턴을 찾아내고 처리하는 로직을 중심으로 살펴보겠습니다."

이 문장은 읽는 각도라는 새 정보를 준다. 반면 아래 같은 문장은 뒤 문장이 이미 하는 말이라 지운다.

  • 제목이 반복되는 하이라이트 조회 하나의 실행계획인데 첫 문장이 반복되는 하이라이트 조회 하나를 실행계획으로 확인했다
  • 설명을 시작하기 전에 붙이는 이 코드는 반복문이 없는 상황이다 / 여기서는 조회가 여러 번 일어나는 경우를 다룬다
  • 관찰을 적고 나서 붙이는 이 관찰은 두 가지를 보여준다

판별법: 그 문장을 지웠을 때 독자가 잃는 정보가 있는가. 없으면 지운다.


12. 가져오지 않는 것

관찰한 글에는 이런 문장도 많다.

"AI를 향한 무한한 숭배심은 던져버렸습니다." "더 깐깐한 컨벤션 경찰이 필요합니다." "쉬운 길은 없었습니다." "어느정도 개발이 많이 진행된 상태에서 이런 상황이 닥치면 의욕이 상실되기도 하고, 대상 없는 원망이 생기기도 합니다."

이 활력은 필자가 실제로 겪은 일에서 나온다. 자료에 없으면 만들지 않는다. 감정, 실패담, 비유, 1인칭 서술을 문체를 살리려고 지어내면 이 저장소의 작업 규칙을 어긴다.

자료 없이도 가져올 수 있는 것은 따로 있다. 평범한 동사, 구체적인 명사, 문장 안에서 이어지는 이유, 정의를 먼저 두는 순서다. 문장을 사람처럼 만드는 것은 감탄사가 아니라 이 네 가지다.


13. 소리 내어 읽기 검사

고친 문장마다 묻는다. 한국어를 쓰는 개발자가 동료에게 이 말을 이대로 하는가.

  • 조회 수는 아이템 수 100을 따라갔다 → 아무도 이렇게 말하지 않는다. → 아이템이 100개면 조회도 100번 나갔습니다
  • 채워진 목록 수가 반환 아이템 수와 정확히 같았다 → 말하지 않는다. → 아이템 하나당 목록을 한 번씩 채웠습니다
  • 이 값은 비교 대상이 아니다 → 말하지 않는다. → 두 값은 세는 것이 다릅니다
  • 최소한의 선을 지켰다 → 말하지 않는다. → <지킨 조건>은 지켰습니다

정확한데 아무도 그렇게 말하지 않는 문장은 고쳐야 할 문장이다. 정확성은 낱말을 비틀어서가 아니라 조건을 한 문장 더 적어서 지킨다.