---
name: Readability
description: 가독성 원칙. 같이 실행되지 않는 코드 분리, 구현 상세 추상화, 시점 이동 최소화. toss/frontend-fundamentals 기반.
type: coding-standard
category: readability
---

> 출처: 팀 공통 원칙 문서 `principles/` 2026-07-03 발췌. 원칙 개정은 원본(팀 공통 문서) 먼저, 이 사본은 따라간다.

# 가독성 (Readability)

> 읽는 사람이 한 번에 머릿속에서 고려하는 맥락이 적고, 위에서 아래로 자연스럽게 이어지는 코드.

## P-028 같이 실행되지 않는 코드 분리하기

서로 다른 분기에서만 실행되는 코드가 한 컴포넌트에 섞여 있으면 분기별로 컴포넌트를 분리한다.

```tsx
// ❌ viewer/admin 로직이 한 컴포넌트에 교차 — 두 분기를 동시에 읽어야 함
function SubmitButton() {
  const isViewer = useRole() === 'viewer';
  useEffect(() => {
    if (isViewer) return;
    showButtonAnimation();
  }, [isViewer]);
  return isViewer ? (
    <TextButton disabled>Submit</TextButton>
  ) : (
    <Button type="submit">Submit</Button>
  );
}

// ✅ 분기별 분리 — 각 컴포넌트는 하나의 분기만 관리
function SubmitButton() {
  const isViewer = useRole() === 'viewer';
  return isViewer ? <ViewerSubmitButton /> : <AdminSubmitButton />;
}
function ViewerSubmitButton() {
  return <TextButton disabled>Submit</TextButton>;
}
function AdminSubmitButton() {
  useEffect(() => {
    showButtonAnimation();
  }, []);
  return <Button type="submit">Submit</Button>;
}
```

## P-029 구현 상세 추상화하기

컴포넌트가 자신과 관련 없는 맥락(인증 체크, 권한 가드 등)을 직접 처리하지 않는다.
Wrapper 컴포넌트나 HOC로 추상화해 각 컴포넌트가 자신의 역할에만 집중하게 한다.

```tsx
// ❌ LoginStartPage가 로그인 체크 로직까지 직접 처리
function LoginStartPage() {
  const status = useCheckLoginStatus();
  useEffect(() => {
    if (status === 'LOGGED_IN') location.href = '/home';
  }, [status]);
  return status !== 'LOGGED_IN' ? <PageContent /> : null;
}

// ✅ AuthGuard로 추상화 — LoginStartPage는 자신의 역할에만 집중
function App() {
  return (
    <AuthGuard>
      <LoginStartPage />
    </AuthGuard>
  );
}
function AuthGuard({ children }) {
  const status = useCheckLoginStatus();
  useEffect(() => {
    if (status === 'LOGGED_IN') location.href = '/home';
  }, [status]);
  return status !== 'LOGGED_IN' ? children : null;
}
```

## P-030 시점 이동 줄이기

코드를 파악하기 위해 여러 함수/파일을 넘나드는 "시점 이동"을 최소화한다.
조건이 단순하다면 인라인 객체로 한눈에 드러내는 것이 낫다.

```tsx
// ❌ Page → getPolicyByRole → POLICY_SET: 3번 이동해야 파악 가능
function Page() {
  const user = useUser();
  const policy = getPolicyByRole(user.role); // 따라가야 함
  return (
    <div>
      <Button disabled={!policy.canInvite}>Invite</Button>
      <Button disabled={!policy.canView}>View</Button>
    </div>
  );
}

// ✅ 인라인 객체로 한눈에 확인 — 이동 없이 파악 가능
function Page() {
  const user = useUser();
  const policy = {
    admin: { canInvite: true, canView: true },
    viewer: { canInvite: false, canView: true },
  }[user.role];
  return (
    <div>
      <Button disabled={!policy.canInvite}>Invite</Button>
      <Button disabled={!policy.canView}>View</Button>
    </div>
  );
}
```
