이전 포스팅에서 스프링 부트의 Relaxed Binding에 대해 알아보았다.
https://hsunnystory.tistory.com/259
[Spring Boot] Relaxed Binding란
이전 포스팅에서 5가지 네이밍 컨벤션과 데이터 매핑 전략에 대해 알아보았다.https://hsunnystory.tistory.com/258 [Clean Code] 실무에서 알아야할 5가지 네이밍 컨벤션과 데이터 매핑 전략개발자로 일하다
hsunnystory.tistory.com
이번 포스팅에서는 자주 쓰이는 5가지 네이밍 케이스를 정리하고, 특히 각기 다른 컨벤션을 가진 시스템(DB, JSON API, OS)간의 임피던스 불일치(Impedance Mismatch)를 아키텍처 관점에서 어떻게 해결해야 하는지 알아본다.
개발자로 일하다 보면 프론트엔드 개발자나 인프라 담당자와 협업할 때 이런 상황을 자주 겪는다.
프론트엔드에서 API 로 user_name 이라는 데이터를 보냈는데, 백엔드의 자바 객체(DTO)에서는 userName으로 받고 있어 값이 전부 null로 매핑되는 것이다.
이때 자바 변수명을 user_name으로 바꾸면 해결되겠지라고 생각한다면 큰 오산이다. 프로그래밍에서 네이밍 컨벤션(Nameing Convension)은 단순한 취향 차이가 아니라, 시스템 간의 데이터를 주고받는 규악이자 언어 생태계의 표준이다.
1. 5가지 주요 네이밍 컨벤션
카멜 (Camel, camelCase)
- 첫 단어는 소문자, 이어지는 단어의 첫 글자는 대문자로 표기
- Java, JavaScript의 변수명 및 메서드명, JSON의 표준 키값에 사용
파스칼 (Pascal, PascalCase)
- 카멜 케이스와 같지만, 첫 단어의 첫 글자도 대문자로 표기한다.(Upper Camel Case)
- Java, C# 등의 클래스명, 인터페이스명에 사용
케밥 (Kebab, kebab-case)
- 모든 단어를 소문자로 쓰고, 단어 사이를 하이픈( - )으로 연결
- URL URI 경로, HTML/CSS의 클래스명, application.yml 등의 설정 파일 키값에 사용
스네이크 (Snacke, snake_case)
- 모든 단어를 소문자로 쓰고, 단어 사이를 언더스코어( _ )로 연결
- Python의 변수명, RDB의 테이블 및 컬럼명에 사용
어퍼 스네이크 (Upper Snake, UPPER_SNAKE_CASE)
- 스네이크 케이스와 같지만, 모든 글자를 대문자로 표기
- Java의 static final 상수, OS 환경 변수(Environment Variables)
스네이크와 어퍼 스네이크를 분리하는 이유
형태상으로는 대소문자 차이일 뿐이지만, 실무에서는 이 둘을 완전히 다른 목적으로 취급한다. snake_case는 DB나 API를 통해 흘러 다니는 가변적인 일반 데이터(State)를 의미하고, UPPER_SNAKE_CASE는 코드 내부의 상수나 OS 인프라에서 주입되는 불변의 설정(Constant)을 의미한다. 코드는 의도를 담아야 하므로 두 케이스는 아키텍처 상 분리해서 사고하는 것이 옳다.
2. 문제점 - 컨벤션이 충돌하는 경계
가장 큰 문제는 서로 다른 컨벤션을 사용하는 시스템이 통신할 때 발생한다. 데이터베이스는 주로 스네이크 케이스(user_id)를 사용하고, 자바 백엔드는 카멜 케이스(userId)를 사용하며, 외부 API는 종종 스네이크 케이스 포멧의 JSON을 던져준다.
이 때 데이터를 제대로 받기 위해 자바 코드의 네이밍 규칙을 무너뜨리는 것은 객체지향 설계의 본질을 해치는 최악의 접근이다.
Bad Code: 생태계 표준을 무시한 DTO 설계
public class UserRequestDto {
// 문제 1: Java의 카멜 케이스 표준을 위반했다.
// 문제 2: 외부 시스템의 JSON 키 포맷이 변경되면 자바 코드(필드명, getter/setter)를 전부 뜯어고쳐야 한다.
private String user_name;
private String phone_number;
public String getUser_name() { return user_name; }
public String getPhone_number() { return phone_number; }
}
이러한 코드는 자바의 표준을 깨뜨릴 뿐만 아니라, 외부 통신 규약과 내부 도메인 로직을 강하게 결합시킨다. OCP(개방-폐쇄 원칙)에 위배되는 전형적인 사례다.
3. 해결책 - 어댑터(Adapter) 역할을 하는 프레임워크 기능 활용
설계의 원칙은 명확하다. 내부(Java)는 철저히 자바의 표준(Camel Case)을 따르고, 시스템의 경계(Controller, Repository)에서만 직렬화/역직렬화를 통해 포맷을 변환한다.
Spring Boot 환경에서는 Jackson 라이브러리와 Hibernate가 이 어댑터 역할을 아주 훌륭하게 수행해 준다.
Good Code: Jackson을 활용한 JSON 매핑
개별 필드 매핑 ( @JsonProperty )
특정 필드만 다른 이름으로 매핑해야 할 때 유용하다. 자바 필드명은 userName을 유지하면서, JSON으로 들어오고 나갈 때는 user_name으로 안전하게 변환된다.
public class UserRequestDto {
@JsonProperty("user_name")
private String userName; // Java 표준인 Camel Case 유지
@JsonProperty("phone_number")
private String phoneNumber;
}
클래스 단위 일괄 매핑 ( @JsonNameing )
만약 외부 API가 100% 스네이크 케이스 포맷을 사용한다면, 일일이 @JsonProperty를 붙이는 것은 비효율적이다. 이때는 클래스 레벨에서 Naming Strategy를 지정할 수 있다.
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
// 이 DTO의 모든 필드는 직렬화/역직렬화 시 자동으로 스네이크 케이스와 매핑된다.
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public class UserRequestDto {
private String userName; // JSON: user_name
private String phoneNumber; // JSON: phone_number
private String emailAddress; // JSON: email_address
}
데이터베이스와의 매핑도 마찬가지다. Spring Data JPA를 사용하면 SpringPhysialNamingStrategy가 기본적용되어, 자바 엔티티의 userName 필드를 DB의 user_name 컬럼으로 자동 변환해 준다.
결론
카멜, 파스칼, 케밥, 스네이크, 어퍼 스네이크 케이스는 단순한 텍스트 형태가 아니라 각 기술 생태계가 합의한 언어다.
프레임워크가 제공하는 매핑 전략(Jackson, JPA Naming Strategy 등)을 시스템의 경계에 배치하여 통신을 매끄럽게 번역하자. 네이밍 컨벤션을 지키는 것은 클린 코드와 유연한 아키텍처를 향한 가장 기본적이고 중요한 첫걸음이다.
'Software Engineering' 카테고리의 다른 글
| [Software Enginnering] 에자일(Agile) 이란? (0) | 2026.04.16 |
|---|---|
| [Software Enginnering] 워터폴(Waterfall) 방법론의 명과 암 (0) | 2026.04.13 |
| [Software Engineering] 테스트 주도 개발(TDD)란? (0) | 2026.04.06 |
| [Software Engineering] 트랜잭션 스크립트 패턴(Transaction Script Pattern) (0) | 2026.03.31 |
| [Software Engineering] DDD(도메인 주도 설계)란 (0) | 2026.03.26 |
