← 블로그 · · ConvertCaseHQ 팀 · 5분 분량

camelCase와 PascalCase 차이: 카멜 케이스와 파스칼 케이스는 언제 쓸까

camelCase(카멜 케이스)와 PascalCase(파스칼 케이스)의 차이는 첫 글자 하나뿐입니다. camelCase는 소문자로 시작하고 두 번째 단어부터 첫 글자를 대문자로 씁니다(userName, parseResponse). PascalCase는 첫 단어를 포함해 모든 단어의 첫 글자를 대문자로 씁니다(UserName, ResponseParser). 관례상 PascalCase는 타입(클래스, 인터페이스, 열거형, React 컴포넌트)을, camelCase는 값과 동작(변수, 함수, 메서드, 속성)을 나타냅니다.

이 대문자 하나는 보기보다 많은 정보를 담고 있습니다. 아래에서는 이 대문자가 무엇을 알려 주는지, 단순한 관례를 넘어 규칙으로 강제되는 언어는 어디인지, 그리고 누구도 합의하지 못한 부분인 약어 처리를 살펴봅니다.

camelCase와 PascalCase 한눈에 비교

camelCasePascalCase
첫 글자소문자대문자
다른 이름lowerCamelCase, mixedCase(PEP 8), camelCasing(Microsoft)UpperCamelCase, CapWords(PEP 8), StudlyCaps(PHP의 PSR-1), PascalCasing(Microsoft)
주로 붙이는 이름변수, 함수, 메서드, 속성, 매개변수클래스, 인터페이스, 타입 별칭, 열거형, 컴포넌트
예orderCount, sendInvoice()OrderService, InvoiceStatus

스타일 가이드를 읽을 때는 용어에 주의하세요. 두 스타일을 모두 “camel case”라고 부르는 사람이 많고, PEP 8은 CamelCase를 CapWords(PEP 8에서 PascalCase를 가리키는 용어)의 다른 이름으로 소개하기까지 합니다. 가이드가 어느 쪽을 뜻하는지 분명하지 않다면 예시를 보세요.

첫 글자가 중요한 이유: 타입과 값

이 관례 덕분에 아무것도 찾아보지 않고도 코드를 읽을 수 있습니다. const invoice = new Invoice(order)에서 Invoice는 생성하는 대상이고 invoice는 그 결과로 받은 값이라는 것을 한눈에 알 수 있습니다. TypeScript 시그니처도 마찬가지입니다. function total(order: Order): Money에서 소문자 이름은 값이고, 대문자로 시작하는 이름은 타입입니다.

또 한 단어로 타입과 값의 이름을 모두 지어도 충돌하지 않습니다. 이런 경우는 아주 흔합니다. user: User, config: Config, request: Request처럼요. 대소문자를 구분하는 언어에서는 이들이 서로 다른 식별자이고, 대문자가 읽는 사람에게 어느 쪽이 무엇인지 알려 줍니다.

언어가 규칙으로 강제하는 경우

JavaScript, Java, C#, Python에서 클래스 이름의 대소문자는 관례일 뿐입니다. class invoice라고 써도 막는 것은 없습니다. JavaScript에서는 ESLint의 new-cap 규칙으로 이 관례를 검사할 수 있습니다. 이 규칙은 기본적으로 new invoice()를 지적하고, Invoice()처럼 대문자로 시작하는 함수를 new 없이 호출하는 경우도 지적합니다. 후자는 대개 버그입니다. 몇몇 언어와 프레임워크는 한 걸음 더 나아가 이 규칙을 아예 내장하고 있습니다.

Go: 첫 글자가 곧 공개 범위 규칙

Go에는 public이나 private 키워드가 없습니다. 패키지 수준의 이름, 구조체 필드, 메서드는 첫 글자가 대문자이면 외부로 공개(export)되고, 소문자이면 해당 패키지 안에서만 쓸 수 있습니다. PascalCase와 camelCase 중 무엇을 쓰느냐가 곧 그 선택입니다.

package shapes

import "math"

// Circle is exported, so other packages can use it.
type Circle struct {
	Radius float64 // exported field
	label  string  // unexported field
}

// Area is exported.
func Area(c Circle) float64 { return math.Pi * square(c.Radius) }

// square is unexported: only code inside package shapes can call it.
func square(x float64) float64 { return x * x }
c := shapes.Circle{Radius: 2}
fmt.Println(shapes.Area(c))   // fine
fmt.Println(shapes.square(2)) // compile error: square is not exported

Effective Go가 공개되지 않은 필드 owner의 getter 이름을 GetOwner가 아니라 Owner로 지으라고 하는 이유도 여기에 있습니다. 대문자만으로 이미 외부에서 접근하는 공개 통로라는 것을 알 수 있기 때문입니다.

React: 컴포넌트는 대문자로 시작해야 합니다

React 문서는 이 점을 단호하게 말합니다. 컴포넌트 이름은 대문자로 시작해야 하며, 그렇지 않으면 작동하지 않습니다. JSX는 <section> 같은 소문자 태그를 HTML 요소로, <OrderSummary />처럼 대문자로 시작하는 태그를 여러분이 만든 컴포넌트로 취급합니다.

Ruby: 클래스 이름은 상수입니다

Ruby에서는 대문자로 시작하는 이름이 모두 상수이고, 클래스 이름은 반드시 상수여야 합니다. class Invoice는 작동하지만 class invoice는 구문 오류(“class/module name must be CONSTANT”)가 납니다.

언어별로 무엇을 쓸까

  • JavaScript와 TypeScript: 변수, 함수, 메서드, 속성은 camelCase, 클래스, 인터페이스, 타입 별칭, 열거형, 컴포넌트는 PascalCase를 씁니다.
  • Java와 Kotlin: 같은 방식에 더해, 진짜 상수에는 밑줄로 연결한 대문자를 씁니다(MAX_RETRIES).
  • C#: 다른 언어보다 PascalCase를 훨씬 많이 씁니다. 메서드, 속성, 이벤트, public 필드, 네임스페이스, 심지어 상수까지 PascalCase입니다. camelCase는 매개변수와 지역 변수에 쓰고, private 필드에는 _camelCase를 씁니다. 전형적인 시그니처는 public decimal CalculateTotal(decimal taxRate) 같은 모습입니다.
  • Swift: 타입과 프로토콜은 PascalCase, 나머지는 모두 camelCase입니다.
  • Go: 원하는 공개 범위에 맞는 쪽을 씁니다.
  • Python: PascalCase는 클래스에만 씁니다. 함수와 변수는 snake_case이고, PEP 8은 이미 camelCase가 주로 쓰이는 오래된 코드에서만 camelCase를 허용합니다.
  • PHP(PSR-1): 클래스는 PascalCase, 메서드는 camelCase입니다.

상수, 파일 등 나머지는 개발자용 명명 스타일 치트시트를 참고하세요.

어려운 부분: 약어와 두문자어

userId일까요, userID일까요? HttpClient일까요, HTTPClient일까요? 주요 스타일 가이드의 답은 서로 다릅니다.

가이드규칙예
Google(JavaScript, TypeScript, Java)약어를 일반 단어처럼 취급xmlHttpRequest, customerId, loadHttpUrl
Microsoft .NET두 글자 약어는 두 글자 모두 대문자, 더 긴 약어는 첫 글자만 대문자IOStream, ioStream, HtmlTag
Go약어 하나 안에서는 대소문자를 통일ServeHTTP, appID, xmlHTTPRequest
Swift보통 대문자로 쓰는 약어는 전부 대문자 또는 전부 소문자로utf8Bytes, userSMTPServer
Rust약어를 한 단어로 취급Uuid, Stdin
Python(PEP 8)CapWords에서는 약어 전체를 대문자로HTTPServerError
Airbnb JavaScript전부 대문자 또는 전부 소문자SMSContainer, httpRequests

저희 의견은 이렇습니다. 쓰는 언어의 가이드에 규칙이 있다면 그 규칙을 따르세요. 표준 라이브러리와 동료들이 기대하는 방식이기 때문입니다. 규칙이 없다면 약어를 단어처럼 취급하세요(HttpClient, userId). 그러면 약어 두 개가 붙어도 단어 경계가 보이고(XMLHTTPRequest와 XmlHttpRequest를 비교해 보세요), 대소문자 스타일 사이를 자동으로 변환해도 이름이 망가지지 않습니다. 브라우저에 내장된 XMLHttpRequest조차 한 이름 안에 두 방식을 섞어 쓰고 있습니다.

더 알고 싶다면 Microsoft의 대문자 표기 규칙(capitalization conventions)을 보세요. 완전한 규칙 체계를 한 페이지에 정리해 둔 좋은 예입니다.

camelCase와 PascalCase 서로 변환하기

단순한 이름이라면 변환은 한 글자로 끝납니다. 첫 글자의 대소문자만 바꾸면 됩니다.

const toPascal = (s) => s.charAt(0).toUpperCase() + s.slice(1);
const toCamel = (s) => s.charAt(0).toLowerCase() + s.slice(1);

toPascal("orderTotal"); // "OrderTotal"
toCamel("OrderTotal");  // "orderTotal"
toCamel("HTMLParser");  // "hTMLParser" (acronyms need a smarter split)

마지막 줄 같은 결과 때문에 도구들은 먼저 이름을 단어로 나눕니다. ConvertCaseHQ의 대소문자 변환기가 까다로운 입력을 어떻게 바꾸는지 보세요.

입력camelCasePascalCase
user iduserIdUserId
XMLHttpRequestxmlHttpRequestXmlHttpRequest
getUserIDgetUserIdGetUserId
IOErrorioErrorIoError
iPhoneiPhoneIPhone

이 변환기는 기존 대문자 위치에서 단어를 나누고 약어를 일반 단어처럼 쓰므로, Google의 규칙과 맞습니다. 프로젝트가 Go, .NET, PEP 8의 약어 규칙을 따른다면 변환한 뒤 해당 이름을 직접 고치세요(Go에서는 getUserId가 getUserID가 됩니다). 브랜드 이름도 함정입니다. IPhone이 어색하다는 것을 아는 알고리즘은 없습니다.

흔히 하는 실수 두 가지

첫째는 인스턴스를 대문자로 시작하는 것입니다. const Cart = new ShoppingCart()라고 쓰면 Cart가 또 하나의 클래스처럼 보여서, 다음에 코드를 읽는 사람이 그 정의를 찾아 헤매게 됩니다. 둘째는 JavaScript에서 function FormatPrice() 같은 PascalCase 헬퍼 함수를 만드는 것입니다. 생성자나 React 컴포넌트가 아니라면 읽는 사람은 new나 JSX가 필요하다고 생각할 테고, 둘 다 없이 호출하면 new-cap 규칙이 경고를 냅니다.

간단한 기준

타입이거나 new로 생성하는 것이라면 PascalCase를 쓰세요. 값이나 동작이라면 camelCase를 쓰세요. 약어는 언어의 가이드에 맡기고, 나머지는 린터가 기억하게 하세요. 상수와 private 필드를 포함한 JavaScript의 세부 사항은 JavaScript 명명 가이드를 참고하세요.

© 2026 ConvertCaseHQ. All rights reserved.