7주차 Unit 4.5 — 자동 매핑 규칙

Psj·2026년 6월 1일

F-lab

목록 보기
228/240

Unit 4.5 — 자동 매핑 규칙

F-LAB JAVA · 7주차 · Phase 4 · JPA 엔티티 매핑
🏆 Phase 4 완주 + 🎯 Part A 완주 — 데이터 모델링과 ORM 의 정점


📌 학습 목표

이 Unit을 끝내면 다음을 답할 수 있어야 한다.

  • 자동 매핑 의 정의는?
  • Spring Boot 명명 전략 은?
  • SpringPhysicalNamingStrategy 는?
  • camelCase ↔ snake_case 변환 규칙 은?
  • 명시 vs 자동 의 균형은?
  • 자동 변환 끄기 방법은?
  • Hibernate 기본 vs Spring Boot 차이는?
  • PhysicalNamingStrategy vs ImplicitNamingStrategy 차이는?
  • 명명 전략 커스터마이징 은?

🎯 핵심 한 문장

Spring Boot 의 JPA 통합은 SpringPhysicalNamingStrategy 라는 명명 전략을 자동 적용해 자바 필드의 camelCase (blNo, createdAt) 를 DB 컬럼의 snake_case (bl_no, created_at) 로 자동 변환하므로 @Column(name = ...) 명시 없이도 표준적인 한국 기업 DB 컨벤션에 자연스럽게 매핑되며, 이 자동 변환은 PhysicalNamingStrategy 빈을 교체해 끄거나 커스터마이징할 수 있다.
자동 매핑 은 JPA + Spring Boot 가 — 자바 필드명 → DB 컬럼명, 자바 클래스명 → DB 테이블명 을 어노테이션 없이도 자동으로 변환하는 동작이다.
핵심 메커니즘은 SpringPhysicalNamingStrategy — Spring Boot 가 Hibernate 의 명명 전략을 오버라이드해서 camelCase 를 snake_case 로 강제 변환 한다 (blNobl_no, createdAtcreated_at, Shipmentshipment).
변환 규칙은 — (1) 소문자 + 대문자 경계에 _ 삽입 (blNo → bl_No), (2) 모두 소문자로 (bl_no), (3) 약어 (BL/SQL/HTTP) 도 모두 분리 (BLNumber → b_l_number, 주의!), (4) 클래스명도 같은 규칙으로 (Shipment → shipment, ShipmentItem → shipment_item).
실무는 — 균형이 핵심 — 단순 필드 (blNo → bl_no) 는 자동에 맡기고, 명시적 제약 (length/nullable/unique/precision) 이 필요한 컬럼만 @Column 으로 명시한다.
이 자동 변환을 끄려면 Spring Boot 의 physical-strategy 를 Hibernate 기본 (PhysicalNamingStrategyStandardImpl) 으로 변경 — 그러면 자바 필드명 그대로 (blNo → blNo) 가 되어 옛 시스템 호환성 확보, 하지만 한국 기업 표준은 snake_case 라 거의 변경하지 않는다.

비유 — 한↔영 자동 번역기 (Spring Boot 의 친절)

자동 매핑 = 한↔영 자동 번역기:

상황:
  - 자바 (한국어): camelCase (blNo)
  - DB (영어): snake_case (bl_no)
  - 매번 손으로 번역?

Spring Boot 의 친절:
  - 자동 번역기 (SpringPhysicalNamingStrategy)
  - 자바 → DB 변환 자동
  - 코드 ↓

변환 규칙:
  - 대문자 경계 → "_" 삽입
  - 모두 소문자
  - blNo → bl_no
  - createdAt → created_at
  - Shipment → shipment

장점:
  - @Column(name = ...) 생략
  - 코드 깔끔
  - 한국 기업 표준 DB 명명과 자연 일치

단점:
  - "마법" 느낌
  - 규칙 모르면 헷갈림
  - 약어 처리 미묘 (BLNumber → b_l_number 주의)

균형:
  - 단순 필드: 자동
  - 제약 필요: @Column 명시

자동 변환 끄기:
  - physical-strategy 변경
  - Hibernate 기본 (변환 X)
  - 옛 시스템 / 비표준

명명 전략 두 가지:
  - PhysicalNamingStrategy (물리 이름)
  - ImplicitNamingStrategy (논리 이름)
  - 둘 다 있음

Hibernate 기본 vs Spring Boot:
  - Hibernate: 변환 X (blNo → blNo)
  - Spring Boot: snake_case 변환

ILIC:
  - Spring Boot 자동 활용
  - 일관된 snake_case DB
  - 명시 + 자동 균형

→ 자동 매핑 = camelCase ↔ snake_case 자동, Spring Boot 친절, 균형 활용.


🧭 9개 섹션 로드맵

1. 자동 매핑 개요
2. Spring Boot 명명 전략
3. SpringPhysicalNamingStrategy
4. 변환 규칙
5. 명시 vs 자동 균형
6. 자동 변환 끄기
7. Hibernate 기본 vs Spring Boot
8. PhysicalNamingStrategy vs ImplicitNamingStrategy
9. Phase 4 완주 + Part A 완주

1️⃣ 자동 매핑 개요

1.1 자동 매핑

자동 매핑:

  JPA + Spring Boot 가 자동으로:
    - 자바 필드명 → DB 컬럼명
    - 자바 클래스명 → DB 테이블명
    - 어노테이션 없이도 변환

  핵심:
    camelCase ↔ snake_case

1.2 어노테이션 없이

// 어노테이션 없이도 매핑
@Entity
public class Shipment {
    @Id
    private Long id;
    
    private String blNo;             // → bl_no
    private LocalDateTime createdAt; // → created_at
    private String shipperName;       // → shipper_name
}

// DB:
// CREATE TABLE shipment (
//     id BIGINT,
//     bl_no VARCHAR(255),
//     created_at TIMESTAMP,
//     shipper_name VARCHAR(255)
// );

// → @Column 명시 X
// → 자동 변환

1.3 한국 기업 컨벤션과 일치

한국 기업 컨벤션:

  DB 표준:
    - snake_case (소문자 + 언더스코어)
    - 자바 표준 (camelCase) 와 다름

  Spring Boot:
    - 자동 변환 (camelCase → snake_case)
    - 한국 기업 컨벤션과 일치

→ "자연스럽게 표준"

1.4 자동의 가치

자동의 가치:

  1. 코드 ↓:
     - @Column(name = ...) 생략
     - 깔끔

  2. 일관:
     - 모든 엔티티 같은 규칙
     - 학습 쉬움

  3. 표준 준수:
     - 한국 DB 표준 자연

  4. 변경 안전:
     - 필드명 변경 시 자동

1.5 ILIC 의 맥락

// ILIC 의 자동 매핑 활용
@Entity
@Table(name = "shipments")   // 테이블만 명시
public class Shipment {
    @Id
    @GeneratedValue
    private Long id;
    
    private String blNo;              // bl_no (자동)
    private String status;             // status
    private BigDecimal weight;         // weight
    private LocalDateTime createdAt;   // created_at (자동)
    private LocalDateTime updatedAt;   // updated_at (자동)
    private String shipperName;        // shipper_name (자동)
}

// 102 테이블 모두 비슷:
// - 자바: camelCase
// - DB: snake_case (자동)
// - 한국 표준 일관

// @Column 은 제약 필요 시만

1.6 자기 점검 답변

자동 매핑의 정의는?

:
1. 자동 매핑:

  • 자바 ↔ DB 자동 변환
  1. 변환:

    • camelCase ↔ snake_case
  2. 어노테이션 없이:

    • 가능
  3. 표준:

    • 한국 DB 컨벤션

2️⃣ Spring Boot 명명 전략

2.1 Spring Boot 의 자동 설정

Spring Boot 의 자동 설정:

  spring-boot-starter-data-jpa:
    - PhysicalNamingStrategy 빈 자동
    - = SpringPhysicalNamingStrategy
    - 자동 변환 활성화

2.2 자동 등록 빈

자동 등록 빈:

  @Bean SpringPhysicalNamingStrategy:
    - 클래스명 / 필드명을
    - snake_case 로 변환

  Hibernate 가:
    - 이 빈을 사용
    - 자동 매핑

2.3 동작 시점

동작 시점:

  애플리케이션 시작:
    1. Spring Boot 자동 설정
    2. SpringPhysicalNamingStrategy 빈 등록
    3. EntityManagerFactory 생성 시
       - 이 빈 주입
    4. Hibernate 가 명명 전략 사용
    5. 엔티티 → 테이블/컬럼 매핑

→ 자동으로 동작

2.4 명시적 확인

# application.yml (Spring Boot 자동, 명시 X)
# Spring Boot 가 자동 등록 (아래 코드 불필요)

spring:
  jpa:
    hibernate:
      naming:
        physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
        # ↑ Spring Boot 자동 (명시 불필요)

2.5 두 가지 명명 전략

두 가지 명명 전략:

  1. PhysicalNamingStrategy (물리):
     - 실제 DB 이름 결정
     - SpringPhysicalNamingStrategy (Spring Boot)
     - snake_case 변환

  2. ImplicitNamingStrategy (논리):
     - 어노테이션 없을 때 기본 이름 결정
     - SpringImplicitNamingStrategy (Spring Boot)
     - JPA 표준 따르며 일부 다름

→ 두 단계
→ 다음 섹션 8 에서 상세

2.6 ILIC 의 맥락

ILIC = Spring Boot 자동 활용

ILIC application.yml:
  spring:
    jpa:
      hibernate:
        ddl-auto: validate
        # naming 설정 X (Spring Boot 기본)

  → SpringPhysicalNamingStrategy 자동
  → snake_case 자동 변환
  → 한국 기업 컨벤션

  Hibernate 기본을 사용하려면 설정 필요
  (보통 안 함)

2.7 자기 점검 답변

Spring Boot 명명 전략은?

:
1. Spring Boot:

  • 자동 설정
  1. :

    • SpringPhysicalNamingStrategy
  2. 동작:

    • EntityManagerFactory 시
  3. 두 가지:

    • Physical / Implicit

3️⃣ SpringPhysicalNamingStrategy

3.1 SpringPhysicalNamingStrategy

SpringPhysicalNamingStrategy:

  Spring Boot 의 핵심 클래스:
    - PhysicalNamingStrategy 구현
    - camelCase → snake_case 변환
    - Spring Boot 기본 (자동 등록)

  패키지:
    org.springframework.boot.orm.jpa.hibernate

3.2 동작 (내부)

// SpringPhysicalNamingStrategy (Spring Boot 코드, 간략)
public class SpringPhysicalNamingStrategy 
    implements PhysicalNamingStrategy {
    
    @Override
    public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment env) {
        return apply(name);
    }
    
    @Override
    public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment env) {
        return apply(name);
    }
    
    private Identifier apply(Identifier name) {
        if (name == null) return null;
        
        StringBuilder builder = new StringBuilder(name.getText().replace('.', '_'));
        
        // camelCase → snake_case 변환 로직
        for (int i = 1; i < builder.length() - 1; i++) {
            if (isUnderscoreRequired(builder.charAt(i - 1),
                                      builder.charAt(i),
                                      builder.charAt(i + 1))) {
                builder.insert(i++, '_');
            }
        }
        return getIdentifier(builder.toString(), name.isQuoted(), env);
    }
    
    private boolean isUnderscoreRequired(char prev, char cur, char next) {
        return Character.isLowerCase(prev) 
            && Character.isUpperCase(cur) 
            && Character.isLowerCase(next);
    }
}
class Identifier {
    String getText() { return null; }
    boolean isQuoted() { return false; }
}
interface PhysicalNamingStrategy {
    Identifier toPhysicalTableName(Identifier name, JdbcEnvironment env);
    Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment env);
}
class JdbcEnvironment {}
class StringBuilder {
    StringBuilder(String s) {}
    char charAt(int i) { return ' '; }
    int length() { return 0; }
    void insert(int i, char c) {}
    String toString() { return null; }
}
Identifier getIdentifier(String s, boolean q, JdbcEnvironment env) { return null; }

3.3 변환 단계

변환 단계:

  입력: "blNo"
  
  1. 각 문자 순회:
     b, l, N, o
  
  2. 대문자 경계 확인:
     - "lNo" 의 N (이전 소문자 + 대문자 + 다음 소문자)
     - "_" 삽입 위치

  3. 결과:
     "bl_No"

  4. 소문자화:
     "bl_no"

→ 출력

3.4 변환 예시

입력 (자바)출력 (DB)
blNobl_no
createdAtcreated_at
shipperNameshipper_name
isActiveis_active
Shipmentshipment
ShipmentItemshipment_item
OrderHistoryorder_history

3.5 약어 주의

약어 주의:

  연속 대문자 → 각각 분리:
    - URL → u_r_l (의도와 다름!)
    - HTTPRequest → h_t_t_p_request
    - BLNumber → b_l_number (의도와 다름!)

  해결:
    - 자바 필드명 변경 (urlPath → urlPath)
    - 또는 @Column(name = "bl_number") 명시

→ 약어 사용 시 주의

3.6 ILIC 의 맥락

// ILIC 의 변환 예시
@Entity
@Table(name = "shipments")
public class Shipment {
    private String blNo;              // → bl_no ✓
    private String shipperName;        // → shipper_name ✓
    private LocalDateTime createdAt;   // → created_at ✓
    private LocalDateTime updatedAt;   // → updated_at ✓
    private BigDecimal totalAmount;    // → total_amount ✓
    private String portOfLoading;      // → port_of_loading ✓
    
    // 주의 (약어):
    // private String URL;  // → u_r_l (X)
    // → 해결: url 또는 @Column 명시
}

// 한국 표준 일관 ✓

3.7 자기 점검 답변

SpringPhysicalNamingStrategy 는?

:
1. SpringPhysicalNamingStrategy:

  • Spring Boot 의 명명 전략
  1. 변환:

    • camelCase → snake_case
  2. 로직:

    • 대문자 경계 → "_"
  3. 주의:

    • 연속 대문자 (약어)

4️⃣ 변환 규칙

4.1 규칙 1 — 대문자 경계

규칙 1 — 대문자 경계:

  소문자 + 대문자 + 소문자 → "_" 삽입:
    - "blN" → "bl_N"

  ↓ 모두 소문자
    - "bl_n"

4.2 규칙 2 — 모두 소문자

규칙 2 — 모두 소문자:

  변환 후 모두 소문자:
    - bl_No → bl_no
    - Created_At → created_at
    - Shipment → shipment

4.3 규칙 3 — 연속 대문자

규칙 3 — 연속 대문자:

  대문자 여러 개 연속 → 각각 분리 (주의!):
    - URL → u_r_l
    - HTTPRequest → h_t_t_p_request

  → 의도와 다름
  → 해결: 자바에서 url, httpRequest 권장

4.4 규칙 4 — 숫자

규칙 4 — 숫자:

  숫자 처리:
    - shipment2 → shipment2 (그대로)
    - bl2No → bl2_no (대문자 경계만)

  → 숫자는 영향 X

4.5 클래스명 → 테이블명

클래스명 → 테이블명:

  @Entity 의 @Table 생략 시:
    - 클래스명에 같은 규칙 적용
    - PascalCase → snake_case

  예:
    - Shipment → shipment (단수, 그대로 소문자)
    - ShipmentItem → shipment_item
    - OrderHistory → order_history

  주의:
    - 한국 표준은 "복수" 자주 사용 (shipments)
    - 명시 권장 (@Table(name = "shipments"))

4.6 종합 예시

@Entity
// @Table 생략 → shipment (단수)
// 보통 @Table(name = "shipments") 명시
public class Shipment {
    private Long id;                           // id
    private String blNo;                       // bl_no
    private String customerName;                // customer_name
    private LocalDateTime createdAt;            // created_at
    private boolean isActive;                   // is_active
    private BigDecimal totalAmount;             // total_amount
    private String portOfLoading;               // port_of_loading
    private LocalDate estimatedArrivalDate;     // estimated_arrival_date
}

// 모두 자동 변환

4.7 ILIC 의 맥락

// ILIC 의 종합 변환
@Entity
@Table(name = "shipments")   // 복수 명시
public class Shipment {
    @Id
    @GeneratedValue
    private Long id;
    
    private String blNo;                    // bl_no
    private String containerNo;              // container_no
    private String vesselName;                // vessel_name
    private String voyageNo;                  // voyage_no
    private String portOfLoading;             // port_of_loading
    private String portOfDischarge;           // port_of_discharge
    private LocalDate etd;                    // etd
    private LocalDate eta;                    // eta
    private BigDecimal grossWeight;           // gross_weight
    private BigDecimal netWeight;             // net_weight
    private LocalDateTime createdAt;          // created_at
    private LocalDateTime updatedAt;          // updated_at
    
    // 약어 주의:
    // private String ETD;  // e_t_d (X)
    // → 해결: etd 또는 @Column
}

// → 한국 기업 DB 표준 일관
// → @Column 거의 불필요

4.8 자기 점검 답변

camelCase ↔ snake_case 변환 규칙은?

:
1. 규칙 1:

  • 대문자 경계 → "_"
  1. 규칙 2:

    • 모두 소문자
  2. 규칙 3:

    • 약어 분리 (주의)
  3. 클래스:

    • 같은 규칙

5️⃣ 명시 vs 자동 균형

5.1 균형의 원칙

균형의 원칙:

  자동 활용:
    - 단순 매핑 (이름)
    - 표준 컨벤션 따름

  명시 권장:
    - 제약 (length/nullable/unique)
    - 정밀도 (precision/scale)
    - 다른 이름 (이름 X 일치)
    - updatable = false

5.2 명시가 좋은 케이스

// 명시 권장
@Entity
@Table(name = "shipments")
public class Shipment {
    @Id @GeneratedValue
    private Long id;
    
    // 1. UNIQUE + NOT NULL
    @Column(name = "bl_no", length = 50, unique = true, nullable = false)
    private String blNo;
    
    // 2. NOT NULL
    @Column(length = 20, nullable = false)
    @Enumerated(EnumType.STRING)
    private ShipmentStatus status;
    
    // 3. 정밀도 (BigDecimal)
    @Column(precision = 10, scale = 2)
    private BigDecimal weight;
    
    // 4. updatable = false (불변)
    @Column(name = "created_at", nullable = false, updatable = false)
    private LocalDateTime createdAt;
    
    // 5. TEXT
    @Column(columnDefinition = "TEXT")
    private String memo;
}
enum ShipmentStatus {}

5.3 자동이 좋은 케이스

// 자동 (생략)
@Entity
@Table(name = "shipments")
public class Shipment {
    @Id @GeneratedValue
    private Long id;
    
    // 자동 변환 OK
    private String shipperName;       // shipper_name
    private LocalDateTime updatedAt;   // updated_at
    private Boolean isActive;          // is_active
    
    // 명시 권장 (제약)
    @Column(name = "bl_no", length = 50, unique = true)
    private String blNo;
}

5.4 ILIC 의 표준

ILIC 의 표준:

  명시 패턴:
    - 식별 필드 (bl_no, email): 명시
    - 제약 (length, unique): 명시
    - 정밀도 (precision/scale): 명시
    - updatable = false: 명시

  자동 패턴:
    - 일반 필드 (memo, status): 자동 가능
    - 타임스탬프 (created_at, updated_at): 자동 가능

  보수적:
    - "명시 + 자동" 혼합
    - 의도 명확

5.5 코드 리뷰

코드 리뷰:

  명시 권장:
    - "이 필드 의도가 무엇인가?"
    - 코드 리뷰 친화

  자동 사용:
    - "표준 규칙 따름"
    - 명시 불필요 시

→ 팀 컨벤션

5.6 ILIC 의 맥락

// ILIC 의 균형 패턴
@Entity
@Table(name = "shipments")
public class Shipment {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    // 명시 (제약)
    @Column(name = "bl_no", length = 50, unique = true, nullable = false)
    private String blNo;
    
    // 명시 (NOT NULL + ENUM)
    @Enumerated(EnumType.STRING)
    @Column(length = 20, nullable = false)
    private ShipmentStatus status;
    
    // 명시 (정밀도)
    @Column(precision = 10, scale = 2)
    private BigDecimal weight;
    
    // 자동 (일반)
    private String shipperName;        // shipper_name
    private String consigneeName;       // consignee_name
    
    // 명시 (updatable = false)
    @Column(name = "created_at", nullable = false, updatable = false)
    private LocalDateTime createdAt;
    
    private LocalDateTime updatedAt;    // updated_at (자동)
    
    // 연관관계 (자동 + 명시)
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "customer_id", nullable = false)
    private Customer customer;
}
enum ShipmentStatus {}
class Customer {}

5.7 자기 점검 답변

명시 vs 자동의 균형은?

:
1. 명시 권장:

  • 제약 / 정밀도
  1. 자동 활용:

    • 단순 이름
  2. 균형:

    • 의도 명확 + 깔끔
  3. 팀 컨벤션:

    • 따름

6️⃣ 자동 변환 끄기

6.1 끄기 시기

끄기 시기 (드묾):

  - 옛 시스템 (camelCase DB)
  - 비표준 DB
  - 외부 시스템 호환
  - 학습 목적

  실무 한국:
    - 거의 안 끔
    - 자동 변환 표준

6.2 application.yml 설정

# 자동 변환 끄기 (Hibernate 기본)
spring:
  jpa:
    hibernate:
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
        # ↑ Hibernate 기본 (변환 X)

# 결과:
# - 자바 blNo → DB blNo (변환 X)
# - 자바 createdAt → DB createdAt

6.3 Hibernate 기본의 동작

Hibernate 기본:

  PhysicalNamingStrategyStandardImpl:
    - 자바 이름 그대로 사용
    - 변환 X
    - 옛 JPA 표준 동작

  결과:
    - blNo → blNo (대소문자 그대로)
    - 또는 DB 가 대소문자 무시 (MySQL 등)

6.4 효과

// Hibernate 기본 사용 시
@Entity
public class Shipment {
    private String blNo;   // 자바
}

// DB:
// CREATE TABLE shipment (
//     blNo VARCHAR(255)   // 자바명 그대로!
// );

// 한국 표준 (snake_case) 과 다름
// → @Column(name = "bl_no") 매번 명시 필요

6.5 옛 시스템 호환

옛 시스템 호환:

  레거시 DB:
    - 옛 컬럼명 camelCase
    - 또는 PascalCase
    - 변경 불가

  → 자동 변환 끄기
  → 또는 @Column 모두 명시

  실무는 보통:
    - @Column 명시 (특정 컬럼만)
    - 전체 끄기 X

6.6 ILIC 의 맥락

ILIC 의 정책

ILIC = 자동 변환 ON (기본):
  - 신규 시스템
  - 한국 표준 snake_case DB
  - 깔끔 코드

  자동 변환 끄기 안 함:
    - 표준 따름
    - 일관

  특수 케이스만 @Column 명시:
    - 약어 (URL 등)
    - 레거시 컬럼명
    - 의도 명확화

→ "자동 + 명시 균형"

6.7 자기 점검 답변

자동 변환 끄기 방법은?

:
1. physical-strategy:

  • 변경
  1. Hibernate 기본:

    • PhysicalNamingStrategyStandardImpl
  2. 결과:

    • 변환 X
  3. 시기:

    • 옛 시스템 (드묾)

7️⃣ Hibernate 기본 vs Spring Boot

7.1 비교 표

항목Hibernate 기본Spring Boot 기본
클래스PhysicalNamingStrategyStandardImplSpringPhysicalNamingStrategy
동작그대로 (변환 X)snake_case 변환
자바 blNoDB blNoDB bl_no
한국 표준안 맞음일치
자동 적용아님 (직접 설정)O (Spring Boot 자동)

7.2 Hibernate 기본의 의미

Hibernate 기본:

  PhysicalNamingStrategyStandardImpl:
    - JPA 표준 (변환 X)
    - 자바 이름 그대로
    - DB 별 따라 (대소문자)

  MySQL:
    - 대소문자 무시 (보통)
    - blNo 와 blno 같게

  PostgreSQL:
    - 대소문자 구분
    - 따옴표 필요할 수

7.3 Spring Boot 의 친절

Spring Boot 의 친절:

  SpringPhysicalNamingStrategy:
    - Hibernate 기본 오버라이드
    - snake_case 강제
    - 한국 / 글로벌 DB 표준

  자동 적용:
    - 의존성만 추가
    - 설정 X
    - 즉시 동작

7.4 변경 방법

# 1. Spring Boot 기본 사용 (생략)
# 변환 자동 (snake_case)

# 2. Hibernate 기본 사용 (변환 X)
spring:
  jpa:
    hibernate:
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

# 3. 커스텀
spring:
  jpa:
    hibernate:
      naming:
        physical-strategy: com.ilic.MyCustomNamingStrategy

7.5 어떤 걸 사용?

어떤 걸 사용?:

  Spring Boot 기본 (snake_case):
    - 99% 신규 프로젝트
    - 한국 표준
    - 깔끔

  Hibernate 기본:
    - 옛 시스템
    - 특수 호환성
    - 거의 X

→ Spring Boot 기본 압도적

7.6 ILIC 의 맥락

ILIC 의 선택

ILIC = Spring Boot 기본 (변환 자동):
  - 신규 시스템 (2024+)
  - 한국 DB 표준 (snake_case)
  - 깔끔 자바 (camelCase)
  - 102 테이블 일관

  Hibernate 기본 X:
    - 표준 안 맞음
    - 매번 @Column 명시 부담
    - 일관성 ↓

→ Spring Boot 표준 사용
→ 균형 패턴 (자동 + 명시)

7.7 자기 점검 답변

Hibernate 기본 vs Spring Boot 차이는?

:
1. Hibernate 기본:

  • 변환 X
  1. Spring Boot:

    • snake_case
  2. 자동:

    • Spring Boot 만
  3. 선택:

    • Spring Boot 압도적

8️⃣ PhysicalNamingStrategy vs ImplicitNamingStrategy

8.1 두 가지 전략

두 가지 명명 전략:

  1. ImplicitNamingStrategy:
     - 어노테이션 없을 때 "논리적" 이름
     - JPA 표준 기본
     - 예: 클래스명 → 테이블명

  2. PhysicalNamingStrategy:
     - 논리 이름 → "물리적" DB 이름
     - 변환 단계
     - 예: snake_case 변환

→ 두 단계 (Implicit → Physical)

8.2 단계별 동작

단계별 동작:

  @Entity
  public class ShipmentItem {
      private String itemName;
  }

  1. ImplicitNamingStrategy:
     - 클래스명 → 논리 테이블명
     - "ShipmentItem" → "ShipmentItem" (그대로)
     - 또는 JPA 표준에 따른 변환

  2. PhysicalNamingStrategy:
     - 논리 → 물리 (DB 실제)
     - "ShipmentItem" → "shipment_item"
     - snake_case 변환

  최종 DB: shipment_item

8.3 Spring Boot 의 둘 다 오버라이드

Spring Boot 의 오버라이드:

  ImplicitNamingStrategy:
    → SpringImplicitNamingStrategy
    - JPA 표준 따르며 일부 다름

  PhysicalNamingStrategy:
    → SpringPhysicalNamingStrategy
    - snake_case 변환 (핵심)

→ Spring Boot 가 둘 다 자동

8.4 보통 PhysicalNamingStrategy 만 관심

보통 PhysicalNamingStrategy 만:

  - snake_case 변환 = 핵심
  - ImplicitNamingStrategy 는 거의 안 건드림

  명명 전략 = 보통 Physical

8.5 커스텀 (드물게)

// 커스텀 PhysicalNamingStrategy (예)
public class CustomNamingStrategy 
    implements PhysicalNamingStrategy {
    
    @Override
    public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment env) {
        // 예: 모든 테이블에 "tbl_" 접두사
        return Identifier.toIdentifier("tbl_" + name.getText().toLowerCase());
    }
    
    @Override
    public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment env) {
        // snake_case + 일부 규칙
        // ...
    return null;
    }
    
    // 다른 메서드들...
}

// 설정
spring:
  jpa:
    hibernate:
      naming:
        physical-strategy: com.ilic.CustomNamingStrategy

interface PhysicalNamingStrategy {
    Identifier toPhysicalTableName(Identifier name, JdbcEnvironment env);
    Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment env);
}
class Identifier {
    static Identifier toIdentifier(String s) { return null; }
    String getText() { return null; }
}
class JdbcEnvironment {}

8.6 ILIC 의 맥락

ILIC = Spring Boot 기본 활용

ILIC 의 정책:
  - SpringImplicitNamingStrategy (자동)
  - SpringPhysicalNamingStrategy (자동)
  - 커스텀 X

  단순 + 표준 + 일관

  커스텀 케이스 (가정):
    - 멀티테넌트 (테넌트별 prefix)
    - 레거시 호환 (특별 매핑)
    - 거의 안 함

8.7 자기 점검 답변

PhysicalNamingStrategy vs ImplicitNamingStrategy 차이는?

:
1. Implicit:

  • 논리 이름
  1. Physical:

    • 물리 이름 (DB 실제)
  2. 변환:

    • Implicit → Physical
  3. Spring Boot:

    • 둘 다 오버라이드

9️⃣ Phase 4 완주 + Part A 완주

9.1 Phase 4 학습 종합

🏷️ Phase 4 — JPA 엔티티 매핑

Unit 4.1 — @Entity 와 엔티티 개념
  - JPA 관리 객체 선언
  - 3가지 조건 (어노테이션 / 기본 생성자 / final X)
  - DTO vs Entity

Unit 4.2 — @Id 와 PK 매핑
  - PK 필수
  - 영속성 컨텍스트 키
  - 자연 키 vs 대리 키

Unit 4.3 — @GeneratedValue 전략 ★
  - 4가지 (IDENTITY / SEQUENCE / TABLE / AUTO)
  - IDENTITY 단점 (배치 X)
  - SEQUENCE 우위 (allocationSize)

Unit 4.4 — @Column 과 컬럼 매핑
  - 6가지 옵션
  - 명시 vs 자동

Unit 4.5 — 자동 매핑 규칙 ← 여기
  - SpringPhysicalNamingStrategy
  - camelCase ↔ snake_case
  - Phase 4 완주 + Part A 완주

9.2 Part A 학습 종합 (16 Unit)

🗂️ Part A — 데이터 모델링과 ORM

📚 Phase 1 — SQL JOIN (5):
  - JOIN 의 필요성 / INNER / LEFT-RIGHT / FULL OUTER
  - 선택 가이드 ★

🔄 Phase 2 — ORM 패러다임 (2):
  - 객체-관계 미스매치 5가지
  - ORM 의 정의와 효과

🌱 Phase 3 — JPA 입문 (4):
  - SQL Mapper 한계
  - JPA 등장 ★
  - JPA 동작 위치
  - Spring Data JPA + Querydsl ★

🏷️ Phase 4 — JPA 엔티티 매핑 (5):
  - @Entity / @Id / @GeneratedValue ★ / @Column / 자동 매핑

→ "SQL 부터 객체 매핑까지"
→ ORM 의 본질 완전 정복

9.3 핵심 메시지

Part A 핵심 메시지:

  "관계형 DB 의 SQL 부터 객체-관계 미스매치 그리고
   JPA 의 객체 매핑까지 - 자바 백엔드의 데이터 계층 정수.
   6주차 JdbcTemplate (SQL Mapper) 의 한계를 넘어
   JPA 가 객체-관계 미스매치 5가지를 자동으로 메우는
   추상화의 정점이다."

9.4 6주차 ↔ 7주차 Part A 연계

6주차 ↔ 7주차 Part A:

6주차 (DB 접근 인프라):
  - JDBC / DataSource / HikariCP / ACID
  - JdbcTemplate (SQL Mapper)

7주차 Part A (ORM 추상화):
  - SQL JOIN 마스터 (Phase 1)
  - 객체-관계 미스매치 인식 (Phase 2)
  - JPA 등장 + Spring Data JPA + Querydsl (Phase 3)
  - 엔티티 매핑 어노테이션 (Phase 4)

→ 6주차 인프라 위에 JPA 가 얹힘
→ 그 위에 Spring Data JPA / Querydsl
→ 자바 백엔드의 표준 스택

9.5 Part B 예고

🔄 Part B — 트랜잭션 추상화의 진화 (8 Unit)

🔧 Phase 5 — 수동 트랜잭션의 한계 (2):
  - 5.1 트랜잭션이 비즈니스 로직과 결합
  - 5.2 수동 트랜잭션 3가지 함정

🎯 Phase 6 — PlatformTransactionManager (3):
  - 6.1 인터페이스 추상화
  - 6.2 3가지 구현체 (DataSource/Hibernate/JPA)
  - 6.3 사용 전후 비교

✨ Phase 7 — @Transactional (3, 모두 ★깊이):
  - 7.1 프록시 패턴 ★
  - 7.2 @Transactional 동작 원리 ★★★
  - 7.3 @Transactional 5가지 함정 ★

→ "트랜잭션의 자동화"
→ 6주차 ACID 의 추상화
→ 자바 백엔드의 또 다른 정점

9.6 면접 단골 질문 매핑

Q핵심 답변
자동 매핑?snake_case 변환
SpringPhysicalNamingStrategy?Spring Boot 명명
변환 규칙?대문자 경계 + 소문자
약어 주의?URL → u_r_l
끄기?physical-strategy 변경
Hibernate 기본?변환 X
@Column 생략?자동 매핑 시
ImplicitNamingStrategy?논리 이름
PhysicalNamingStrategy?물리 이름
균형?자동 + 명시

9.7 자기 점검 체크리스트

자동 매핑

  • 개요

Spring Boot 전략

  • 자동 설정

SpringPhysicalNamingStrategy

  • 동작

변환 규칙

  • 4가지

명시 vs 자동

  • 균형

끄기

  • 방법

Hibernate vs Spring Boot

  • 차이

Physical vs Implicit

  • 단계

Part A 완주

  • 종합

9.8 추가 심화 질문

Q1: SpringPhysicalNamingStrategy 의 소스 코드 위치?

답:

  • org.springframework.boot.orm.jpa.hibernate
  • spring-boot-autoconfigure
  • 오픈소스 (GitHub)

Q2: 약어 처리 우회?

답:

  • 자바 필드명을 약어 X 로 (url, sql)
  • 또는 @Column(name = "...") 명시
  • 또는 커스텀 NamingStrategy

Q3: Hibernate 6 의 변화?

답:

  • 명명 전략 일부 변경
  • 호환성 모드
  • 대부분 동일

Q4: 다중 DB 환경의 명명?

답:

  • DB 별 다른 컨벤션 가능
  • 보통 같은 전략
  • 마이그레이션 시 주의

Q5: 어노테이션 우선순위?

답:

  • @Column(name = "...") 최우선
  • 그다음 NamingStrategy
  • 명시 > 자동

🎯 핵심 요약 — 3줄 정리

1. 자동 매핑 = SpringPhysicalNamingStrategy

  • Spring Boot 가 자동 적용 (의존성만)
  • camelCase → snake_case 자동 변환 (blNo → bl_no)
  • 한국 / 글로벌 DB 표준과 자연 일치

2. 변환 규칙

  • (1) 소문자 + 대문자 + 소문자 경계 → "_" 삽입
  • (2) 모두 소문자로
  • (3) 약어 (URL) 는 연속 분리 (u_r_l) → 자바 필드명 주의
  • (4) 클래스명도 같은 규칙 (Shipment → shipment)

3. 명시 vs 자동 균형

  • 자동 활용: 단순 이름 매핑 (코드 ↓)
  • 명시 권장: 제약 (length/nullable/unique) / 정밀도 / updatable=false
  • 자동 변환 끄기: physical-strategy 변경 (드묾)

🏆 Phase 4 완주 — JPA 엔티티 매핑

🏷️ Phase 4 — JPA 엔티티 매핑
  ✅ Unit 4.1 @Entity 와 엔티티 개념
  ✅ Unit 4.2 @Id 와 PK 매핑
  ✅ Unit 4.3 @GeneratedValue 전략 ★깊이
  ✅ Unit 4.4 @Column 과 컬럼 매핑
  ✅ Unit 4.5 자동 매핑 규칙 ← 여기, Phase 4 완주

→ JPA 엔티티 매핑 완전 정복
→ 객체 → DB 매핑 모든 방법

🎯 Part A 완주 — 데이터 모델링과 ORM

🗂️ Part A — 데이터 모델링과 ORM (16/16)
  ✅ Phase 1 — SQL JOIN (5)
  ✅ Phase 2 — ORM 패러다임 (2)
  ✅ Phase 3 — JPA 입문 (4)
  ✅ Phase 4 — JPA 엔티티 매핑 (5) ← 완주

→ SQL 부터 JPA 까지 데이터 계층의 완전한 그림
→ 6주차 (인프라) + 7주차 Part A (추상화)
→ 자바 백엔드의 데이터 정점

📚 다음으로...

Part B — 트랜잭션 추상화의 진화

🔄 Part B — 트랜잭션 추상화의 진화 (8 Unit)

🔧 Phase 5 — 수동 트랜잭션의 한계 (2)
🎯 Phase 6 — PlatformTransactionManager (3)
✨ Phase 7 — @Transactional (3, 모두 ★깊이)

Part B 의 가치:

  • 6주차 ACID 의 자동화 추상화
  • 5주차 DI / 디자인 패턴의 결정체
  • @Transactional 1줄로 트랜잭션 처리
  • 면접 단골 (프록시 패턴, AOP, 5가지 함정)

Unit 5.1 — 트랜잭션이 비즈니스 로직과 결합

다음 Unit 은 Phase 5 의 시작 — 수동 트랜잭션의 결합 문제.

  • 수동 트랜잭션 코드:
    • tx.begin(), tx.commit(), tx.rollback() 매번 작성
  • 비즈니스 로직과 인프라 코드의 결합 (SoC 위반)
  • 5주차 DI / 디자인 패턴 정신 위반
  • "트랜잭션을 자동화할 수는 없을까?"

7주차 누적 진행

🗂️ Part A — 데이터 모델링과 ORM
  ✅ Phase 1 (5)
  ✅ Phase 2 (2)
  ✅ Phase 3 (4)
  ✅ Phase 4 (5) ← Phase 4 완주, Part A 완주!

🔄 Part B — 트랜잭션 추상화의 진화
  ⏭ Phase 5 (2)
  ⏭ Phase 6 (3)
  ⏭ Phase 7 (3) — 7.1/7.2/7.3 모두 ★깊이

총: 16/24 Unit (67%, Part A 완주!)

🏆 Phase 4 완주 + 🎯 Part A 완주 — 데이터 모델링과 ORM 의 정점

profile
Software Developer

0개의 댓글