Google의 TypeScript Style Guide > Naming

FeelsBotMan·2024년 12월 6일
0

GTS

목록 보기
8/8
post-thumbnail

5 Naming

5.1 Identifiers

식별자는 변수, 함수, 클래스, 인터페이스, 타입, 속성 등의 이름을 나타낸다.

식별자에서 허용되는 문자:
영문 대소문자 (A-Z, a-z): 일반적인 알파벳 문자.
숫자 (0-9): 알파벳과 함께 사용 가능. 단, 숫자로 시작할 수는 없다.

특정 상황에서만 밑줄 사용:
상수: ALL_CAPS 스타일의 상수 이름에 밑줄을 사용.
예: MAX_LENGTH, DEFAULT_VALUE.
구조화된 테스트 메서드 이름: 테스트 메서드에서 논리적 구조를 나타내기 위해 밑줄 사용 가능.
예: test_addition_of_two_numbers

달러 기호($):
JavaScript 및 TypeScript에서 $는 변수 이름에 허용되지만, 일반적으로 특별한 목적으로만 사용한다.
예: AngularJS에서 $scope, jQuery에서 $ 같은 경우.

허용되지 않는 문자:
비ASCII 문자(예: 한글, 특수 기호 등)는 식별자로 사용하지 않는다.
예: 이름, #value, @count 등은 허용되지 않음.


5.1.1 Naming style

  • 프로퍼티나 메서드의 맨 앞이나 맨 뒤에 밑줄('_')사용하지 않기
  • 선택적 매개변수 앞에 opt_ 접두사를 사용하지 않기
  • 인터페이스를 특별히 표시하지 않기
    - 'I'또는 'Interface' 같은 접두사/접미사는 불필요하며, 코드의 명확성과 가독성을 해친다. 인터페이스를 도입할 때는 이름을 통해 그 인터페이스가 왜 존재하는지, 어떤 역할을 수행하는지 설명해야 한다.
  • Observable 변수 구분을 위한 $ 접미사의 사용 여부는 팀의 판단에 따름

Before

interface ITodoItem {
  title: string;
  completed: boolean;
}

interface TodoItemInterface {
  title: string;
  completed: boolean;
}
  • IInterface와 같은 특별한 표시는 코드에 의미를 더하지 않는다.
  • 이름만으로는 이 인터페이스가 어떤 용도인지 알기 어렵다.

After

interface TodoItemStorage {
  title: string;
  completed: boolean;
}
  • 의미 있는 이름: TodoItemStorage는 저장소 형식을 표현하기 위한 인터페이스임을 명확히 나타낸다.
  • 클래스(TodoItem)와 역할을 구분하면서도 관계가 명확하다.

5.1.2 Descriptive names

이름은 설명적이고 명확해야 한다. 모호하거나 익숙하지 않은 약어를 사용하지 말고, 단어 내에서 문자를 삭제하여 약어의 사용을 지양하자.

예외: 10줄 이하 범위에 속하는 변수, 즉 내보내는 API에 속하지 않는 인수는 짧은(예: 문자 하나) 변수 이름을 사용할 수 있다.

명확하고 서술적인 이름 사용:
변수나 식별자는 코드만 봐도 무슨 역할을 하는지 쉽게 이해할 수 있는 이름을 사용해야 한다.
외부인이나 새로운 독자가 봐도 직관적으로 의미를 알 수 있도록 이름을 정해야 한다.

모호하거나 생소한 약어 지양:
특정 프로젝트 내부에서만 통용되는 약어나 생소한 약어는 사용하지 말 것.
약어를 쓸 때는 일반적으로 알려진 약어만 사용한다.
예: URL, DNS, Id 등.

단어 내 글자를 생략하지 말 것:
단어의 중간 글자를 삭제하거나 축약하여 의미를 모호하게 만들지 말 것.
예: cstmrIdcustomerId로 작성.

짧은 범위에서는 간결한 이름 허용:
범위가 10줄 이하인 코드(로컬 변수, 함수 인자 등)에서는 단일 문자 또는 간결한 이름이 허용된다.
예: i, n, x 등.

헝가리안 표기법 지양:
변수 이름에 타입 정보를 접두사로 붙이는 헝가리안 표기법은 사용하지 않는다.
예: kSecondsPerDay (잘못된 헝가리안 표기법).

올바른 CamelCase:
CamelCase 표기법을 사용할 때, 약어는 일관되게 소문자로 처리.
예: customerId (올바름), customerID (잘못된 CamelCase).

Before

const n = 5; // 의미 불명확
const nErr = 0; // 애매한 약어
const cstmrId = "12345"; // 축약으로 가독성 저하
const wgcConnections = []; // 팀 내부에만 알려진 약어
const customerID = "12345"; // 잘못된 CamelCase

After

const itemCount = 5; // 명확한 이름
const errorCount = 0; // 가독성이 좋은 이름
const customerId = "12345"; // 축약하지 않은 명확한 이름
const connections = []; // 약어를 제거하여 직관적으로 수정

5.1.3 Camel case

약어는 단어처럼 취급:
약어(Acronym)가 포함된 식별자 이름은 단어처럼 혼합 대소문자로 작성해야 한다.
BAD: loadHTTPURL (약자를 전체 대문자로 작성하면 읽기 어렵다.)
GOOD: loadHttpUrl (Http는 단어처럼 취급되어 첫 글자만 대문자로 표기)

플랫폼 이름이 특별한 경우는 예외:
특정 플랫폼이나 API 이름이 약자를 대문자로 사용하는 경우, 해당 관례를 따라야 한다.
(XMLHttpRequest는 JavaScript의 API 이름에서 사용되는 표준.)


5.1.4 Dollar sign

$는 일반적인 경우 식별자 이름에 사용하지 않는 것이 좋다.
다만, 서드파티 프레임워크의 명명 규칙에 따라 사용하거나, Observable 값을 구분하기 위해 명확한 목적으로 사용할 수 있다.
$를 사용할 경우, 프로젝트 내에서 일관성을 유지하는 것이 중요하다.


5.2 Rules by identifier type

식별자의 종류에 따라 일관된 네이밍 스타일을 사용해야 한다:

스타일대상 카테고리설명
PascalCase클래스, 인터페이스, 타입, 열거형(enum), 데코레이터, 타입 매개변수, TSX/JSX 요소 타입 매개변수첫 단어와 이후 모든 단어의 첫 글자가 대문자. 주로 구조적이고 정의적인 객체에 사용됨.
camelCase변수, 매개변수, 함수, 메서드, 속성, 모듈 별칭첫 단어는 소문자, 이후 단어는 첫 글자만 대문자. 일반적으로 작은 스코프의 요소 또는 동작과 관련된 것들에 사용됨.
CONSTANT_CASE전역 상수 값, 열거형(enum) 값모든 문자가 대문자이며, 단어는 밑줄(_)로 구분. 불변 값을 명확히 구분하기 위해 사용됨.
#identprivate 식별자TypeScript에서는 지원하지 않음. # 접두사는 JavaScript의 private class 필드에 사용되며 TypeScript에서는 일반적으로 private 키워드를 사용.

5.2.1 Type parameters

타입 매개변수는 제네릭(generic)을 사용할 때 선언되며, 함수, 클래스, 인터페이스, 타입 별칭 등에 유연한 타입 지정을 제공한다. 단일 대문자 또는 PascalCase를 사용할 수 있다.

function getKey<K, V>(key: K, value: V): K {
  return key;
}
class ApiResponse<DataType> {
  constructor(public data: DataType, public success: boolean) {}
}
const userResponse = new ApiResponse<{ id: number; name: string }>({
  id: 1,
  name: "Alice",
}, true);

5.2.2 Test names

테스트의 목적과 동작을 명확하게 나타내고, 테스트가 어떤 상황에서 어떤 결과를 예상하는지를 쉽게 이해할 수 있도록 _ (밑줄) 구분자를 사용하여 테스트 메서드를 설명적이고 읽기 쉽게 작성한다.

  • 구조는 일반적으로 testX_whenY_doesZ() 형태를 따른다.
    • X: 테스트하려는 기능 또는 행동.
    • Y: 조건이나 상황.
    • Z: 예상되는 결과 또는 행동
function testLogin_whenCredentialsAreValid_doesRedirectToDashboard() {
  // 로그인 기능 테스트
}
  • testLogin: 로그인 기능을 테스트.
  • whenCredentialsAreValid: 사용자 자격 증명이 유효한 경우에 대해 테스트.
  • doesRedirectToDashboard: 유효한 자격 증명으로 로그인할 때 대시보드로 리디렉션되는지 확인.
function testCalculateTotalPrice_whenItemIsAdded_doesIncreaseTotalPrice() {
  // 상품 추가 시 총 가격이 증가하는지 테스트
}
  • testCalculateTotalPrice: 총 가격 계산 기능을 테스트.
  • whenItemIsAdded: 아이템이 장바구니에 추가될 때.
  • doesIncreaseTotalPrice: 아이템을 추가하면 총 가격이 증가하는지 확인.

구체적이고 설명적이어야 한다. 지나치게 짧거나 모호한 이름을 피하고, 테스트가 무엇을, 언제, 어떻게 확인하는지 명확하게 나타내야 한다.
너무 긴 이름은 가독성을 떨어뜨릴 수 있으므로 적당히 사용한다.


5.2.3 _ prefix/suffix

밑줄을 접두사나 접미사로 사용하지 않기:
식별자는 가능하면 의미가 명확해야 하며, 밑줄을 접두사나 접미사로 사용할 경우 어떤 의미가 있는지 또는 그 식별자가 특별한 목적을 가지고 있는지 명확히 전달되지 않는다.

단독으로 밑줄 사용 금지:
식별자가 의미를 가지지 않게 된다. 변수나 매개변수는 그 목적이 분명해야 한다.
(파이썬에서는 매개변수가 사용되지 않음을 나타내는 경우 단독으로 밑줄을 사용함)

구조 분해 할당을 사용할 때, 배열이나 튜플에서 불필요한 요소를 무시하려면 단순히 중간에 ,를 삽입하여 해당 요소를 무시할 수 있다.

const [a, , b] = [1, 5, 10];  // a <- 1, b <- 10, 중간 요소 5는 무시

5.2.4 Imports

모듈 네임스페이스 (camelCase):
모듈을 네임스페이스로 가져올 때는 camelCase를 사용한다.

import * as fooBar from './foo_bar';  // 올바른 네임스페이스 네이밍

파일 이름 (snake_case):
파일 이름은 snake_case를 사용해야 하며, 이는 소문자와 밑줄(_)로 단어를 구분하는 스타일이다. 예를 들어 foo_bar.ts와 같이 작성된다.

(작성자 첨언) 그러나 모듈과 파일 이름은 camelCase나 kebab-case를 사용하기도 한다.


5.2.5 Constants

CONSTANT_CASE의 사용:
상수(Constant) 값에 CONSTANT_CASE를 사용하여 변하지 않아야 하는 값들을 명확하게 표시하고, 이를 통해 코드에서 해당 값을 수정하지 않도록 유도한다.

static readonly와 CONSTANT_CASE:
클래스에서 static readonly 속성도 상수로 다루어질 수 있다. readonly 키워드를 사용하면 해당 속성의 값을 변경할 수 없다는 점에서 불변성을 보장할 수 있다.

class Foo {
  private static readonly MY_SPECIAL_NUMBER = 5;

  bar() {
    return 2 * Foo.MY_SPECIAL_NUMBER;
  }
}

Global Scope와 CONSTANT_CASE:
CONSTANT_CASE는 모듈 수준에서만 사용된다. 모듈의 최상위에서 정의된 상수값에 대해서만 CONSTANT_CASE를 사용하는 것이 권장된다. 지역 변수나 함수 내부에서 선언된 값은 camelCase를 사용해야 한다.


5.2.6 Aliases

로컬 별칭은 기존 심볼의 네이밍 규칙과 형식을 따르며, 그 목적에 맞는 적절한 선언 방법을 사용해야 한다.

기존 심볼의 네이밍 규칙을 따르기:
로컬에서 기존의 변수를 별칭으로 사용할 때, 별칭의 이름은 기존 심볼의 형식과 규칙을 따라야 한다. 예를 들어, 상수는 대문자 및 밑줄을 사용한 CONSTANT_CASE 형식을 따르고, 변수나 객체는 camelCase 형식을 사용해야 한다. 이렇게 하면 일관된 네이밍 규칙을 유지할 수 있다.

const { BrewStateEnum } = SomeType;  // 기존 심볼
const CAPACITY = 5;  // 기존 상수
  • BrewStateEnumSomeType에서 추출된 객체의 속성이다. 이 값을 사용할 때 로컬에서 새로운 이름을 지정할 수 있다.
  • CAPACITY는 값 5를 나타내는 상수이다. 이 값을 사용하려면 로컬에서 CAPACITY라는 이름을 그대로 사용해야 한다.

로컬 별칭 생성 방법:
로컬에서 별칭을 생성할 때, 변수와 클래스 필드에 대해 서로 다른 방식으로 선언해야 한다.

  • 변수의 로컬 별칭은 const를 사용하여 선언해야 한다.
  • 클래스 필드의 로컬 별칭은 readonly 속성을 사용하여 선언해야 한다.
class Teapot {
  readonly BrewStateEnum = BrewStateEnum;  // 클래스 필드에서 BrewStateEnum을 읽기 전용으로 설정
  readonly CAPACITY = CAPACITY;  // 클래스 필드에서 CAPACITY를 읽기 전용으로 설정
}
  • BrewStateEnumCAPACITY는 각각 기존 값의 별칭이다. 클래스 필드에 대해 readonly를 사용하면 불변 값임을 명확하게 나타낼 수 있다.
  • 이 별칭들은 클래스의 속성으로 사용되며, 외부에서 해당 값을 변경할 수 없도록 보장한다.

템플릿에서의 별칭:
프레임워크나 템플릿을 사용할 때, 별칭을 생성하여 템플릿에 노출하려는 경우에도 이 규칙이 적용된다. 별칭을 만들 때 접근 제어자(예: public, private)를 올바르게 지정하는 것이 중요하다. 프레임워크에서는 특정 데이터나 속성을 템플릿에서 직접 사용할 수 있도록 노출해야 할 때가 많은데, 이때도 접근 제어자를 적절히 설정하여 외부에서 접근할 수 있는지, 또는 내부에서만 접근할 수 있는지를 정의해야 한다.

class Teapot {
  public readonly BrewStateEnum = BrewStateEnum;  // 템플릿에서 사용될 수 있도록 공개
  private readonly CAPACITY = CAPACITY;  // 내부에서만 사용될 수 있도록 제한
}
  • public 접근 제어자는 템플릿에서 이 값을 사용할 수 있도록 함.
  • private 접근 제어자는 템플릿에서 사용되지 않도록 하여, 외부 접근을 제한.

참고자료

Google TypeScript Style Guide

GitHub - google/gts: ☂️ TypeScript style guide, formatter, and linter.

Typescript Google Code Style Part 1
Typescript Google Code Style Part 2
Typescript Google Code Style Part 3

ts.dev - TypeScript style guide

profile
안드로이드 페페

0개의 댓글