Programming Language/Javascript

[JS] RORO 패턴이란?

개발자참치 2024. 7. 1. 20:00

RORO 패턴이란?

RORO는 "Receive an Object, Return an Object"의 약자로, 함수의 매개변수와 반환값을 모두 객체로 사용하는 JavaScript 패턴이다.
이 패턴은 TypeScript와 함께 사용할 때 특히 유용하다고 한다. RORO 패턴의 주요 이점은 다음과 같다:

  1. 매개변수의 순서에 구애받지 않음
  2. 선택적 매개변수를 쉽게 처리
  3. 함수 시그니처의 변경이 용이
  4. 코드의 가독성과 유지보수성 향상
  5. TypeScript와 함께 사용 시 타입 안정성 강화

RORO 패턴 예시

예시1

기존의 함수:

function createUser(name: string, age: number, email: string, isAdmin: boolean = false) {
  // 사용자 생성 로직
}

createUser("John Doe", 30, "john@example.com");

RORO 패턴 적용 함수:

interface CreateUserParams {
  name: string;
  age: number;
  email: string;
  isAdmin?: boolean;
}

interface User {
  id: string;
  name: string;
  age: number;
  email: string;
  isAdmin: boolean;
}

function createUser({ name, age, email, isAdmin = false }: CreateUserParams): User {
  const id = generateUniqueId(); // 고유 ID 생성 함수라고 가정
  return { id, name, age, email, isAdmin };
}

const newUser = createUser({
  name: "John Doe",
  age: 30,
  email: "john@example.com",
  // isAdmin은 선택적이므로 생략 가능
});

적용 컴포넌트:

interface ButtonProps {
  text: string;
  onClick: () => void;
  color?: 'primary' | 'secondary';
  size?: 'small' | 'medium' | 'large';
}

const Button: React.FC<ButtonProps> = ({ text, onClick, color = 'primary', size = 'medium' }) => {
  return (
    <button className={`btn btn-${color} btn-${size}`} onClick={onClick}>
      {text}
    </button>
  );
};

// 사용
<Button text="Click me" onClick={() => console.log('Clicked')} color="secondary" />

예시2

기존의 함수:

function calculateTotalPrice(productPrice: number, quantity: number, discountRate: number, taxRate: number) {
  const discountedPrice = productPrice * (1 - discountRate);
  const priceBeforeTax = discountedPrice * quantity;
  const totalPrice = priceBeforeTax * (1 + taxRate);
  return totalPrice;
}

const total = calculateTotalPrice(100, 2, 0.1, 0.08);

RORO 패턴 적용 함수:

interface PriceCalculationParams {
  productPrice: number;
  quantity: number;
  discountRate: number;
  taxRate: number;
}

interface PriceCalculationResult {
  totalPrice: number;
  priceBeforeTax: number;
  discountAmount: number;
  taxAmount: number;
}

function calculateTotalPrice({
  productPrice,
  quantity,
  discountRate,
  taxRate
}: PriceCalculationParams): PriceCalculationResult {
  const discountAmount = productPrice * discountRate * quantity;
  const priceBeforeTax = (productPrice * quantity) - discountAmount;
  const taxAmount = priceBeforeTax * taxRate;
  const totalPrice = priceBeforeTax + taxAmount;

  return {
    totalPrice,
    priceBeforeTax,
    discountAmount,
    taxAmount
  };
}

const result = calculateTotalPrice({
  productPrice: 100,
  quantity: 2,
  discountRate: 0.1,
  taxRate: 0.08
});

console.log(`Total Price: $${result.totalPrice.toFixed(2)}`);

적용 컴포넌트:

interface ProductCardProps {
  name: string;
  price: number;
  imageUrl: string;
  inStock?: boolean;
  onAddToCart: () => void;
}

const ProductCard: React.FC<ProductCardProps> = ({
  name,
  price,
  imageUrl,
  inStock = true,
  onAddToCart
}) => {
  return (
    <div className="product-card">
      <img src={imageUrl} alt={name} />
      <h3>{name}</h3>
      <p>Price: ${price.toFixed(2)}</p>
      {inStock ? (
        <button onClick={onAddToCart}>Add to Cart</button>
      ) : (
        <p>Out of Stock</p>
      )}
    </div>
  );
};

// 사용
<ProductCard
  name="Wireless Headphones"
  price={79.99}
  imageUrl="/images/headphones.jpg"
  onAddToCart={() => console.log('Added to cart')}
/>

  1. 일관성 유지: 프로젝트 전체에서 RORO 패턴을 일관되게 사용하세요. 이는 코드의 예측 가능성을 높인다.
  2. 기본값 활용: 선택적 매개변수에 대해 기본값을 제공하여 사용의 유연성을 높이는 것이 좋다.
  3. 구조 분해 할당 사용: 함수 내부에서 매개변수 객체를 구조 분해 할당하여 사용하면 코드가 더 깔끔해진다.
  4. 타입 정의 분리: 매개변수와 반환값의 타입을 별도의 인터페이스로 정의하면 재사용성과 유지보수성이 향상된다.
  5. 과도한 사용 주의: 매우 간단한 함수의 경우 RORO 패턴이 오히려 복잡성을 증가시킬 수 있으므로 상황에 맞게 사용하는 것이 좋다.
  6. 문서화: JSDoc 주석을 사용하여 각 매개변수의 목적과 사용법을 문서화하면 더욱 좋다.
  7. 중첩 객체 주의: 매개변수 객체가 너무 깊게 중첩되면 복잡성이 증가할 수 있으므로 적절한 수준으로 유지하는 것이 좋다.