본문으로 건너뛰기

기본 개념

ElastiCORE의 핵심 개념과 작동 방식을 이해하여 프레임워크를 효과적으로 활용하세요.

ElastiCORE 아키텍처

핵심 구성 요소

1. DSL (Domain Specific Language)

직관적인 YAML 기반 문법으로 도메인 모델을 정의합니다.

entity:
User:
meta: entity @expose(20) @audited
fields:
id: string(36)! @id @genid
username: string(50)! @search(like)
email: string(100)! @search(eq) @unique
isActive: boolean @default(true)

2. 어노테이션 프로세서

컴파일 시점에 @EnableElastiCore 어노테이션을 감지하고 자동 코드 생성을 시작합니다.

@EnableElastiCore  // 이 어노테이션이 마법을 시작합니다
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

3. 코드 생성 엔진

블루프린트 정의를 분석하고 Spring Boot 표준 패턴에 따라 Java 코드를 자동 생성합니다.

핵심 개념

1. 블루프린트(Blueprint)

프로젝트의 도메인 모델을 정의하는 YAML 파일의 체계적인 모음입니다.

src/main/resources/blueprint/
├── user/ # 사용자 도메인
│ ├── env.yml # 환경 설정
│ ├── entity.yml # 엔티티 정의
│ └── dto.yml # DTO 정의
├── product/ # 상품 도메인
│ ├── env.yml
│ └── model.yml
└── order/ # 주문 도메인
└── models.yml

2. 도메인(Domain)

관련된 엔티티와 비즈니스 로직을 그룹화하는 논리적 단위입니다.

user/env.yml
elasticore:
enable: true
config:
domainName: user
framework: springboot
mode: jpa
j2ee: jakarta

namespace:
entity: com.example.user.entity
dto: com.example.user.dto
repository: com.example.user.repository
service: com.example.user.service
control: com.example.user.controller

3. 엔티티(Entity)

데이터베이스 테이블에 매핑되는 JPA 엔티티를 정의합니다.

entity:
User:
meta: entity @expose(20) @audited @table(app_users)
fields:
id: string(36)! @id @genid
username: string(50)! @search(like) @unique
email: string(100)! @search(eq) @unique
password: string(255)! @updatable(false)
profile: UserProfile @OneToOne @cascade(ALL)
roles: List<Role> @ManyToMany @cascade(PERSIST)
createdDate: datetime @jpa:org.springframework.data.annotation.CreatedDate
lastModifiedDate: datetime @jpa:org.springframework.data.annotation.LastModifiedDate

4. 검색 DTO(Search DTO)

@expose 또는 @searchable 어노테이션 사용 시 자동 생성되는 동적 검색 전용 DTO입니다.

// 자동 생성되는 SearchDTO:
public class UserSearchDTO implements PageableObject {
private String username; // @search(like) → 부분 일치
private String email; // @search(eq) → 정확한 일치
private int pageNumber = 0; // 페이지네이션
private int pageSize = 20;
private String sortCode;
}

5. 엔티티 관계

entity:
Post:
meta: entity @expose(10)
fields:
id: long @id @sequence
title: string(200)! @search(like)
content: text
author: User @ManyToOne @fetchjoin # 자동 N+1 문제 해결
comments: List<Comment> @OneToMany(mappedBy="post") @dtype(List<CommentDTO>)
tags: List<Tag> @ManyToMany @cascade(PERSIST)

Comment:
meta: entity @service(20) # Service만 생성, Controller 없음
fields:
id: long @id @sequence
content: text!
post: Post @ManyToOne
author: User @ManyToOne @fetchjoin
createdDate: datetime @jpa:org.springframework.data.annotation.CreatedDate

어노테이션 시스템

메타 어노테이션 (엔티티/DTO 레벨)

어노테이션설명생성 코드
@expose(n)REST API + 검색 DTO 자동 생성Controller + Service + SearchDTO
@service(n)Service만 생성 (API 없음)Service + SearchDTO만 생성
@auditedJPA Envers 감사 추적@Audited
@abstract추상 엔티티 (상속용)abstract class
@extend(Parent)엔티티 상속extends ParentEntity
@table(name)테이블명 지정@Table(name = "custom_name")
@pageable(n)기본 페이지 크기Pageable 파라미터 추가

필드 어노테이션

어노테이션설명생성 코드
@id기본키 필드@Id
@sequence자동 증가 ID@GeneratedValue(IDENTITY)
@genid커스텀 ID 생성기env.yml 설정 기반
@search(type)검색 조건SearchDTO 필드 생성
@default(value)기본값생성자에서 기본값 설정
@unique유니크 제약 조건@Column(unique = true)
@updatable(false)수정 불가 필드@Column(updatable = false)
@fetchjoinJOIN FETCH 최적화자동 N+1 문제 해결

검색 어노테이션

entity:
Product:
meta: entity @expose(20)
fields:
name: string(100) @search(like) # 부분 일치 (LIKE %name%)
sku: string(20) @search(eq) # 정확한 일치 (= sku)
price: bigdecimal(10,2) @search(between) # 범위 검색 (BETWEEN)
category: CategoryEnum @search(in) # 다중 선택 (IN)
rating: int @search(gte) # 이상 (>=)
deletedDate: datetime @search(null) # IS NULL 검사

코드 생성 프로세스

생성되는 파일 구조

하나의 엔티티 정의로 완전한 Spring Boot 스택이 생성됩니다:

// 1. JPA 엔티티
@Entity @Table(name = "users")
public class User { /* 모든 JPA 어노테이션과 필드 */ }

// 2. DTO
public class UserDTO { /* 엔티티 필드를 DTO로 변환 */ }

// 3. 검색 DTO (@expose 사용 시에만)
public class UserSearchDTO implements PageableObject { /* 검색 필드 */ }

// 4. Repository
@Repository
public interface UserRepository extends JpaRepository<User, String>,
JpaSpecificationExecutor<User> { }

// 5. Service
@Service @Transactional
public class UserService {
public Page<UserDTO> findBySearch(UserSearchDTO searchDTO, Pageable pageable);
public UserDTO create(UserDTO userDTO);
public UserDTO update(String id, UserDTO userDTO);
// ...
}

// 6. Controller (@expose 사용 시에만)
@RestController @RequestMapping("/api/users")
public class UserController { /* OpenAPI 3.0 문서화된 REST API */ }

// 7. 테스트 코드 (자동 생성)
@SpringBootTest
class UserServiceTest { /* JUnit 5 테스트 케이스 */ }

모범 사례

1. 엔티티 설계 패턴

entity:
# 기본 엔티티 (모든 엔티티가 이 엔티티를 상속)
BaseEntity:
meta: entity @abstract
fields:
createdDate: datetime @jpa:org.springframework.data.annotation.CreatedDate
createdBy: string(50) @jpa:org.springframework.data.annotation.CreatedBy
lastModifiedDate: datetime @jpa:org.springframework.data.annotation.LastModifiedDate
lastModifiedBy: string(50) @jpa:org.springframework.data.annotation.LastModifiedBy

# 감사 추적 엔티티
AuditableEntity:
meta: entity @abstract @extend(BaseEntity) @audited
fields:
version: long @Version

# 구체적인 비즈니스 엔티티
User:
meta: entity @expose(20) @extend(AuditableEntity)
fields:
id: string(36)! @id @genid
username: string(50)! @search(like) @unique
email: string(100)! @search(eq) @unique

2. 검색 필드 전략

entity:
Product:
meta: entity @expose(20)
fields:
# 자주 검색되는 필드
name: string(100)! @search(like)
sku: string(50)! @search(eq) @unique

# 필터 필드
category: CategoryEnum @search(in)
isActive: boolean @search(eq) @default(true)

# 범위 검색 필드
price: bigdecimal(10,2) @search(between)
createdDate: datetime @search(between)

# 검색 불가 필드 (@search 없음)
description: text
internalNotes: text

FAQ

Q1: 생성된 코드를 직접 수정할 수 있나요?

A: 생성된 코드는 다음 빌드 시 덮어쓰여집니다. 대신 확장 패턴을 사용하세요:

@Service
@Primary
public class CustomUserService extends UserService {
@Override
public UserDTO create(UserDTO dto) {
validateUserCreation(dto);
return super.create(dto);
}
}

Q2: 복잡한 비즈니스 로직은 어디에 구현해야 하나요?

A: 생성된 Service를 상속하거나 별도의 비즈니스 서비스를 생성하세요:

@Service
@Transactional
public class OrderBusinessService {
@Autowired private OrderService orderService; // 생성된 서비스
@Autowired private ProductService productService;

public OrderDTO processOrderWithDiscount(OrderCreateRequest request) {
validateProductStock(request.getItems());
BigDecimal discount = calculateDiscount(request);
return orderService.create(request.toOrderDTO());
}
}

더 자세한 가이드를 이어서 학습하세요: