본문으로 건너뛰기

기본 개념

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());
}
}

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