skills/allra-fintech/allra-database-schema/SKILL.md
Allra 데이터베이스 설계 및 QueryDSL 사용 규칙. Use when creating JPA entities, writing QueryDSL queries, or adding @Transactional annotations.
npx skillsauth add aiskillstore/marketplace allra-database-schemaInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Allra 백엔드 팀의 데이터베이스 설계, JPA, QueryDSL, 트랜잭션 관리 표준을 정의합니다.
이 가이드는 다음 환경을 기준으로 작성되었습니다:
참고: 프로젝트별로 사용하는 데이터베이스(MariaDB, PostgreSQL, MySQL 등)와 라이브러리가 다를 수 있습니다.
JPA Repository와 Support 인터페이스를 함께 사용:
// JPA Repository 인터페이스
public interface UserRepository extends JpaRepository<User, Long>, UserRepositorySupport {
}
// QueryDSL Support 인터페이스
public interface UserRepositorySupport {
List<UserSummaryDto> findUserSummaries(UserSearchCondition condition);
}
// QueryDSL Support 구현체
@Repository
public class UserRepositoryImpl implements UserRepositorySupport {
private final JPAQueryFactory queryFactory;
@Override
public List<UserSummaryDto> findUserSummaries(UserSearchCondition condition) {
return queryFactory
.select(new QUserSummaryDto(
user.id,
user.email,
user.name
))
.from(user)
.where(
emailContains(condition.email()),
nameContains(condition.name())
)
.fetch();
}
private BooleanExpression emailContains(String email) {
return email != null ? user.email.contains(email) : null;
}
}
참고: Support 패턴은 선택 사항입니다. 프로젝트에 따라 @Query 어노테이션이나 다른 방식을 사용할 수 있습니다.
Record와 @QueryProjection 사용:
public record UserSummaryDto(
Long id,
String email,
String name
) {
@QueryProjection
public UserSummaryDto {}
}
빌드 설정:
Gradle:
annotationProcessor "com.querydsl:querydsl-apt:${queryDslVersion}:jakarta"
Maven:
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/generated-sources/java</outputDirectory>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>
From절에 해당하는 Repository에 정의하는 것을 권장:
// ❌ 피하기: Order에서 User를 조회
public interface OrderRepositorySupport {
List<UserDto> findUsersByOrderDate(LocalDate date); // From user
}
// ✅ 권장: User에서 Order를 조인
public interface UserRepositorySupport {
List<UserOrderDto> findUsersWithOrders(LocalDate date); // From user
}
QueryDSL 작성 시 사용 중인 데이터베이스의 특성을 고려:
// 일반적인 쿼리
queryFactory
.selectFrom(user)
.where(user.createdAt.between(startDate, endDate))
.fetch();
// LIMIT/OFFSET
queryFactory
.selectFrom(user)
.limit(10)
.offset(0)
.fetch();
참고: 윈도우 함수나 특정 DB 함수는 데이터베이스 버전에 따라 지원 여부가 다를 수 있습니다.
반드시 JPA Repository 인터페이스를 통해 사용:
// ❌ 잘못된 예
@Service
public class UserService {
private final UserRepositoryImpl userRepositoryImpl; // 구현체 직접 주입
}
// ✅ 올바른 예
@Service
public class UserService {
private final UserRepository userRepository; // 인터페이스 주입
}
각 서비스 메서드에 명시적으로 선언:
@Transactional(readOnly = true)@Transactional@Service
public class UserService {
private final UserRepository userRepository;
// 읽기 전용 트랜잭션
@Transactional(readOnly = true)
public List<User> findAllUsers() {
return userRepository.findAll();
}
// 쓰기 트랜잭션
@Transactional
public User createUser(SignUpRequest request) {
User user = User.create(request.email(), request.password());
return userRepository.save(user);
}
// 조회 + 변경
@Transactional
public User activateUser(Long id) {
User user = userRepository.findById(id)
.orElseThrow(() -> new UserNotFoundException(id));
user.activate(); // 변경
return user;
}
}
참고: 트랜잭션 전파(Propagation)는 기본값(REQUIRED)을 사용하며, 특수한 경우에만 명시합니다.
@Entity
@Table(name = "users")
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, unique = true, length = 100)
private String email;
@Column(nullable = false, length = 100)
private String name;
@Enumerated(EnumType.STRING)
@Column(nullable = false, length = 20)
private UserStatus status;
@CreatedDate
@Column(nullable = false, updatable = false)
private LocalDateTime createdAt;
@LastModifiedDate
@Column(nullable = false)
private LocalDateTime updatedAt;
// 정적 팩토리 메서드
public static User create(String email, String password, String name) {
User user = new User();
user.email = email;
user.password = password;
user.name = name;
user.status = UserStatus.ACTIVE;
return user;
}
// 비즈니스 메서드
public void activate() {
this.status = UserStatus.ACTIVE;
}
}
@Entity
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// ManyToOne - 지연 로딩 권장
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
private User user;
// OneToMany - 지연 로딩, Cascade 설정
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
private List<OrderItem> items = new ArrayList<>();
// 연관관계 편의 메서드
public void addItem(OrderItem item) {
items.add(item);
item.setOrder(this);
}
}
참고: 연관관계는 지연 로딩(LAZY)을 기본으로 사용하는 것을 권장합니다.
이 skill은 다음 상황에서 자동으로 적용됩니다:
데이터베이스 관련 코드 작성 시 확인사항:
development
Apple Human Interface Guidelines for content display components. Use this skill when the user asks about charts component, collection view, image view, web view, color well, image well, activity view, lockup, data visualization, content display, displaying images, rendering web content, color pickers, or presenting collections of items in Apple apps. Also use when the user says how should I display charts, what's the best way to show images, should I use a web view, how do I build a grid of items, what component shows media, or how do I present a share sheet. Cross-references: hig-foundations for color/typography/accessibility, hig-patterns for data visualization patterns, hig-components-layout for structural containers, hig-platforms for platform-specific component behavior.
tools
Automate HelpDesk tasks via Rube MCP (Composio): list tickets, manage views, use canned responses, and configure custom fields. Always search tools first for current schemas.
testing
Expert Haskell engineer specializing in advanced type systems, pure functional design, and high-reliability software. Use PROACTIVELY for type-level programming, concurrency, and architecture guidance.
tools
GraphQL gives clients exactly the data they need - no more, no less. One endpoint, typed schema, introspection. But the flexibility that makes it powerful also makes it dangerous. Without proper controls, clients can craft queries that bring down your server. This skill covers schema design, resolvers, DataLoader for N+1 prevention, federation for microservices, and client integration with Apollo/urql. Key insight: GraphQL is a contract. The schema is the API documentation. Design it carefully.