기술 블로그를 쓰다 보면 어느 순간 글이 설명문보다 코드 덩어리의 집합처럼 보일 때가 있습니다. 작성자 입장에서는 필요한 예제를 빠짐없이 넣었다고 느끼기 쉬운데, 읽는 사람 입장에서는 어디부터 읽어야 하는지 감이 안 잡히는 경우가 많습니다. 특히 모바일에서 긴 코드 블록이 연달아 나오면 본문 흐름이 자주 끊기고, 독자는 “이 코드가 왜 여기 들어가 있는지”를 놓치기 쉽습니다.

저는 코드가 많은 글의 가독성은 문장 실력보다 편집 규칙에 더 크게 좌우된다고 생각합니다. 같은 코드라도 어떤 단위로 끊고, 어떤 제목 아래 배치하고, 코드 앞뒤에 무엇을 설명하느냐에 따라 읽히는 난이도가 크게 달라집니다. 그래서 코드 블록은 예쁘게 보이게 만드는 것보다, 독자가 “지금 이 블록에서 봐야 할 것”을 빠르게 이해하게 만드는 편이 중요합니다.

CommonMark와 GitHub Flavored Markdown 문서도 fenced code block을 명확한 구획으로 다루고, HTML의 <pre><code> 요소 역시 “사전 서식화된 텍스트”와 “코드 조각”이라는 역할을 분리해 설명합니다. 즉 코드 블록은 단순 장식이 아니라, 문서 구조 안에서 다른 문단과 구분되는 정보 단위입니다. 이 점을 기준으로 잡으면 긴 기술 글도 훨씬 정리하기 쉬워집니다.

이 글에서는 1인 개발 블로그 기준으로, 코드 블록이 많은 글을 읽기 쉽게 만드는 실제 서식 규칙을 정리해보겠습니다. 이미 앞선 글에서 기술 튜토리얼 스크린샷 규칙을 다뤘다면, 이번 글은 텍스트와 코드 중심 튜토리얼의 흐름을 정리하는 편이라고 생각하면 됩니다.

경험/운영가독성

코드 블록이 많은 글을 읽기 쉽게 만드는 서식 규칙

코드가 많은 기술 글도 끝까지 읽히게 만드는 편집 규칙을 정리합니다. 블록 분리, 파일명 표기, 설명의 위치, 긴 코드 축약법, 모바일 가독성까지 실제 발행 기준으로 설명합니다.

핵심 1

먼저 결론: 코드 블록은 “자료 첨부”가 아니라 “한 단계의 결정”처럼 배치하는 편이 좋다

핵심 2

한 블록에 한 역할만 남기고, 큰 파일은 단계별로 쪼갠다

핵심 3

코드보다 먼저 “왜 이 블록이 필요한지”를 한두 문장으로 적는다

가독성경험/운영code block reading rhythm
긴 코드 덩어리를 그대로 보여주는 나쁜 예와 짧은 설명과 분리된 코드 블록으로 읽기 쉽게 정리한 좋은 예

먼저 결론: 코드 블록은 “자료 첨부”가 아니라 “한 단계의 결정”처럼 배치하는 편이 좋다

코드가 많은 글일수록 제일 먼저 잡아야 하는 기준은 단순합니다. 한 코드 블록은 한 가지 의도를 가져야 합니다.

  • 이 블록은 설치 명령을 보여주는 블록
  • 이 블록은 파일 생성 위치를 보여주는 블록
  • 이 블록은 핵심 옵션 두세 개를 설명하는 블록
  • 이 블록은 수정 전과 수정 후의 차이를 보여주는 블록

이 기준이 없으면 글이 자꾸 이렇게 흐릅니다. “일단 전체 파일을 붙여 넣고, 아래에서 중요한 부분을 설명하자.” 그런데 이 방식은 독자가 이미 너무 많은 정보를 본 뒤에야 무엇이 중요한지 알게 만듭니다. 반대로 좋은 글은 먼저 맥락을 짧게 알려주고, 코드 블록은 그 맥락을 확인하는 증거처럼 배치합니다.

1. 한 블록에 한 역할만 남기고, 큰 파일은 단계별로 쪼갠다

코드 블록이 많은 글이 읽기 어려운 가장 흔한 이유는 파일 하나를 통째로 보여주기 때문입니다. 물론 완성본 전체가 필요할 때도 있습니다. 하지만 대부분의 튜토리얼 단계에서는 전체 파일보다 “이번 단계에서 바뀐 부분”만 보여주는 편이 훨씬 낫습니다.

예를 들어 API 라우트에 입력 검증과 메일 전송을 한 번에 붙여넣는 대신, 아래처럼 나누는 편이 읽기 쉽습니다.

1-1. 먼저 입력값 검증만 추가한다

src/app/api/contact/route.ts

import { NextResponse } from "next/server";

export async function POST(request: Request) {
  const body = await request.json();

  if (!body.email || !body.message) {
    return NextResponse.json(
      { message: "필수 항목이 비어 있습니다." },
      { status: 400 },
    );
  }

  return NextResponse.json({ ok: true });
}

이 블록에서 독자가 봐야 하는 핵심은 “필수 입력 누락 시 400 응답을 반환한다”는 점입니다. 여기서는 메일 전송 로직까지 같이 보여줄 필요가 없습니다.

1-2. 그 다음 메일 전송 로직을 별도 단계로 붙인다

src/app/api/contact/route.ts

import { sendContactMail } from "@/lib/send-contact-mail";

export async function POST(request: Request) {
  const body = await request.json();

  if (!body.email || !body.message) {
    return Response.json({ message: "필수 항목이 비어 있습니다." }, { status: 400 });
  }

  await sendContactMail({
    email: body.email,
    message: body.message,
  });

  return Response.json({ ok: true });
}

이렇게 분리하면 글을 읽는 사람은 “지금은 검증”, “다음은 전송”처럼 단계를 따라가며 이해할 수 있습니다. 큰 파일을 그대로 한 번에 보여주는 것보다 훨씬 덜 지칩니다.

2. 코드보다 먼저 “왜 이 블록이 필요한지”를 한두 문장으로 적는다

좋은 기술 글은 코드를 먼저 던지지 않습니다. 블록 앞에 짧은 설명이 먼저 옵니다. 이 설명은 길 필요가 없고, 오히려 짧을수록 좋습니다. 중요한 건 독자가 코드 안으로 들어가기 전에 관찰 포인트를 알고 들어가게 만드는 것입니다.

제가 자주 쓰는 패턴은 아래와 같습니다.

  1. 이번 단계의 목적을 한 문장으로 요약
  2. 코드에서 봐야 하는 포인트를 한 줄로 지정
  3. 그 다음 코드 블록 배치

예를 들면 이런 식입니다.

여기서는 캐시 정책 전체를 설명하려는 것이 아니라, 이미지 응답에 Cache-Control 헤더를 붙이는 위치만 확인하면 됩니다.

src/app/api/og/route.ts

return new ImageResponse(element, {
  headers: {
    "Cache-Control": "public, max-age=0, s-maxage=86400",
  },
});

이런 문장 하나가 있으면 독자는 블록 전체를 세세히 해독하려고 애쓰지 않고, “아, 여기서는 헤더 위치만 보면 되는구나”라고 바로 이해합니다.

3. 파일명, 경로, 실행 위치는 코드 블록 안이 아니라 바깥에서 알려주는 편이 낫다

기술 글에서 자주 보는 실수 중 하나는 파일명이나 셸 프롬프트 맥락을 코드 블록 안에 억지로 섞는 것입니다. 예를 들어 // app/layout.tsx 같은 주석을 파일 맨 위에 계속 넣거나, 셸 명령어 앞에 긴 사용자 경로를 그대로 붙여 넣으면 코드보다 잡음이 더 커집니다.

그래서 저는 코드 블록 위에 짧은 라벨을 두는 방식을 선호합니다.

  • 파일을 보여줄 때: `src/app/layout.tsx`
  • 명령어를 보여줄 때: 프로젝트 루트에서 실행
  • 설정값을 보여줄 때: `.env.local`

이 방식이 좋은 이유는 세 가지입니다.

  • 코드 자체가 더 짧고 읽기 쉬워집니다.
  • 복사해 실행할 때 불필요한 문자열이 섞이지 않습니다.
  • 모바일에서도 코드 첫 줄이 덜 복잡하게 보입니다.

예를 들어 환경 변수는 아래처럼 정리하는 편이 훨씬 깔끔합니다.

.env.local

RESEND_API_KEY=re_xxxxxxxxxxxx
[email protected]

그리고 명령어는 이렇게 분리하는 편이 좋습니다.

프로젝트 루트에서 실행

npm install @supabase/supabase-js

코드 블록의 첫 줄은 독자가 복사할 가능성이 높은 곳입니다. 그러니 가능한 한 실제로 복사해도 되는 내용만 남겨두는 편이 좋습니다.

4. 셸, 코드, 출력 결과, diff는 서로 다른 종류의 블록으로 분리한다

코드가 많은 글이 지저분해 보이는 또 다른 이유는 서로 다른 성격의 내용을 같은 모양으로 쌓아두기 때문입니다. 설치 명령, 애플리케이션 코드, 콘솔 출력, 변경점 비교는 모두 읽는 방식이 다릅니다. 그런데 전부 같은 코드 블록처럼 붙어 있으면 독자는 매번 “이건 실행해야 하는 건가, 그냥 읽기만 하면 되는 건가”를 다시 판단해야 합니다.

그래서 아래처럼 역할을 분리하는 편이 좋습니다.

  • 실행 명령은 bash
  • 설정 파일은 json, yaml, env
  • 애플리케이션 코드는 ts, tsx, js
  • 변경 사항 비교는 diff
  • 출력 결과는 필요한 부분만 따로 짧게

예를 들면 수정 전후를 설명할 때는 완성본 두 개를 나란히 보여주기보다 diff가 더 읽기 쉽습니다.

- export const dynamic = "auto";
+ export const dynamic = "force-static";

이 한 줄 차이를 설명하려고 40줄짜리 파일을 다시 보여주는 건 너무 비싼 선택입니다. 독자가 알아야 할 변화가 작다면, 표시도 작게 하는 편이 맞습니다.

5. 긴 코드가 꼭 필요할 때는 “전체 코드”보다 “핵심 부분 + 생략 기준”을 함께 제시한다

실전 글을 쓰다 보면 정말로 긴 코드가 필요한 순간도 있습니다. 예를 들어 메타데이터 생성 함수나 Prisma 스키마처럼 문맥상 전체를 보는 편이 나은 경우가 있습니다. 이런 때도 그냥 길게 붙여넣는 것보다, 먼저 핵심 조각을 보여주고 나중에 확장본을 보여주는 편이 좋습니다.

예를 들어 메타데이터 생성 규칙을 설명한다면 먼저 핵심 함수만 짧게 보여줄 수 있습니다.

export async function generateMetadata({ params }: PageProps): Promise<Metadata> {
  const article = await getArticle(params.slug);

  return {
    title: article.seoTitle,
    description: article.seoDescription,
  };
}

그리고 그 아래에서 “Open Graph, canonical, alternates까지 모두 포함한 확장본은 아래와 같습니다”라고 안내한 뒤 더 긴 예제를 보여주는 식입니다. 이렇게 하면 독자는 먼저 뼈대를 이해한 뒤 자세한 구현을 읽게 됩니다.

긴 코드를 그대로 보여줘야 한다면 적어도 아래 기준은 지키는 편이 좋습니다.

  • 이번 글의 핵심과 관계없는 부분은 제거하거나 생략 표시를 둔다
  • 줄 간격과 빈 줄을 유지해 구조가 보이게 한다
  • 함수, 객체, 조건문 경계가 한눈에 보이게 포맷한다
  • 긴 상수 문자열과 긴 URL은 의미 단위로 나눈다

6. 코드 블록 사이에는 “해석 문장”이 있어야 한다

코드 블록이 많은 글에서 가장 중요한 건 사실 코드 자체보다 블록 사이 문장입니다. 이 문장이 없으면 글이 아니라 코드 모음이 됩니다.

제가 중요하게 보는 해석 문장은 크게 세 가지입니다.

  • 방금 본 코드가 무엇을 해결했는지
  • 다음 블록이 왜 이어서 필요한지
  • 독자가 흔히 놓치는 포인트가 무엇인지

예를 들면 아래처럼 짧게 끊어줄 수 있습니다.

여기까지 하면 API는 성공 응답을 반환하지만, 클라이언트 폼에서는 아직 에러 메시지를 읽지 못합니다. 다음 블록에서는 응답 상태에 따라 화면 문구를 바꾸겠습니다.

이런 문장이 있으면 독자는 블록을 “개별 부품”이 아니라 “하나의 흐름”으로 읽게 됩니다. 코드가 많은 글일수록 이 연결 문장이 더 중요합니다.

7. 코드 안의 주석은 설명을 대신하는 용도로 남발하지 않는다

가독성을 높이겠다고 코드 안에 주석을 지나치게 많이 넣는 경우도 자주 봅니다. 하지만 주석이 많아질수록 코드 블록은 더 길어지고, 실제 로직보다 설명이 먼저 눈에 들어오기 쉽습니다. 설명은 되도록 본문이 맡고, 코드 안 주석은 코드만 봐도 바로 이해하기 어려운 의도에만 쓰는 편이 좋습니다.

예를 들어 아래 정도는 괜찮습니다.

const siteUrl = getSiteUrl();

// 정적 export와 운영 환경에서 같은 기준 URL을 쓰기 위해 분리한다.
const canonicalUrl = new URL(`/blog/${article.slug}`, siteUrl).toString();

반대로 모든 줄마다 “여기서 변수 선언”, “여기서 함수 호출” 같은 주석을 붙이는 건 도움이 되지 않습니다. 설명이 길어질수록 코드 블록은 오히려 더 천천히 읽히기 때문입니다.

8. 가로 스크롤이 자주 생기면 예제를 다시 쪼개야 한다

데스크톱에서는 괜찮아 보여도 모바일에서는 코드 블록이 훨씬 더 답답하게 느껴집니다. 긴 import 줄, 긴 클래스 문자열, 긴 URL, 긴 SQL, 긴 객체 리터럴은 대부분 모바일에서 가로 스크롤을 유발합니다. 어느 정도 스크롤은 피할 수 없지만, 너무 자주 발생하면 독자는 글 흐름을 금방 잃습니다.

그래서 저는 아래 기준으로 다시 손봅니다.

  • import가 너무 길면 줄을 나눈다
  • 큰 객체는 속성별로 세로 정렬한다
  • className 문자열은 의미 단위로 정리한다
  • URL은 변수로 분리하거나 설명용 예시 도메인을 짧게 쓴다

예를 들어 아래 두 코드는 같은 의미지만 읽는 피로도는 다릅니다.

나쁜 예:

const metadata = { title: article.title, description: article.summary, alternates: { canonical: `${siteUrl}/blog/${article.slug}` }, openGraph: { title: article.title, description: article.summary, url: `${siteUrl}/blog/${article.slug}` } };

좋은 예:

const canonicalUrl = `${siteUrl}/blog/${article.slug}`;

const metadata = {
  title: article.title,
  description: article.summary,
  alternates: {
    canonical: canonicalUrl,
  },
  openGraph: {
    title: article.title,
    description: article.summary,
    url: canonicalUrl,
  },
};

둘 다 같은 코드지만, 두 번째 예시는 구조를 훨씬 빠르게 파악할 수 있습니다.

9. 코드 블록의 개수보다 “본문과 코드의 비율”을 본다

글 하나에 코드 블록이 10개 있다고 해서 무조건 나쁜 건 아닙니다. 오히려 각 블록이 짧고 설명이 좋으면 긴 글도 충분히 잘 읽힙니다. 문제는 문단 없이 코드만 연달아 붙는 패턴입니다.

저는 대체로 아래 리듬을 선호합니다.

  • 짧은 문제 정의
  • 첫 번째 코드 블록
  • 해석 문장
  • 두 번째 코드 블록
  • 왜 이렇게 나눴는지 설명
  • 체크리스트 또는 주의점

즉 독자가 한 번에 읽는 단위가 문단 -> 코드 -> 문단 -> 코드처럼 교차하는 편이 좋습니다. 코드 블록 사이에 문장이 거의 없다면, 그 글은 설명서가 아니라 소스 덤프처럼 느껴질 가능성이 큽니다.

10. 마지막엔 “복붙용 코드”와 “이해용 코드”를 구분해 주는 편이 좋다

독자는 항상 같은 목적으로 글을 읽지 않습니다. 어떤 사람은 개념을 이해하려고 읽고, 어떤 사람은 당장 복사해 붙여 넣으려고 읽습니다. 그래서 글 마지막에 어떤 블록이 복붙용이고, 어떤 블록이 구조 이해용인지 한 번 정리해 주면 만족도가 높습니다.

예를 들면 아래처럼 마무리할 수 있습니다.

  • 바로 적용할 사람: .env.local, 설치 명령, 핵심 함수 블록부터 확인
  • 구조를 이해할 사람: 단계별 분리 예제와 diff 블록부터 확인
  • 디버깅 중인 사람: 출력 결과와 에러 처리 블록을 먼저 확인

이런 정리는 사소해 보이지만, 긴 글을 끝까지 읽은 뒤 독자가 “그래서 나는 무엇부터 가져가면 되지?”라는 질문에 답해줍니다.

실무에서 바로 쓰는 체크리스트

  • 코드 블록 하나에 한 가지 역할만 담았는가
  • 코드 앞에 이 블록의 목적을 한두 문장으로 설명했는가
  • 파일명과 실행 위치를 코드 블록 바깥에서 알려주고 있는가
  • 셸, 코드, diff, 출력 결과를 같은 모양으로 섞어 쓰지 않았는가
  • 긴 완성본보다 핵심 부분과 변경점부터 보여주고 있는가
  • 코드 블록 사이에 해석 문장이 충분히 있는가
  • 모바일에서 가로 스크롤이 과도하게 생기지 않는가
  • 복사할 코드에 불필요한 프롬프트, 주석, 개인 경로가 섞여 있지 않은가

마무리

코드 블록이 많은 글의 완성도는 문장을 얼마나 멋지게 쓰느냐보다, 코드를 어디서 끊고 어떤 순서로 보여주느냐에 더 크게 좌우됩니다. 기술 글은 결국 독자가 따라 하거나 비교하거나 디버깅하려고 읽는 문서이기 때문에, 코드 블록은 많을 수 있어도 무질서하면 안 됩니다.

한 블록에 한 역할만 남기고, 블록 앞에 맥락을 짧게 두고, 긴 코드는 핵심부터 보여주고, 블록 사이 문장으로 흐름을 이어주면 글 전체 리듬이 훨씬 안정됩니다. 스크린샷이 필요한 장면과 코드가 필요한 장면을 구분하고 싶다면 앞서 정리한 튜토리얼 스크린샷 배치 규칙 글도 함께 보면 좋습니다.

참고 자료: