diff --git a/apps/commerce-api/src/main/java/com/loopers/application/user/UserFacade.java b/apps/commerce-api/src/main/java/com/loopers/application/user/UserFacade.java
index f74e2154f..883a659f5 100644
--- a/apps/commerce-api/src/main/java/com/loopers/application/user/UserFacade.java
+++ b/apps/commerce-api/src/main/java/com/loopers/application/user/UserFacade.java
@@ -1,13 +1,15 @@
 package com.loopers.application.user;
 
 import com.loopers.domain.user.Gender;
-import com.loopers.domain.user.UserModel;
+import com.loopers.domain.user.User;
 import com.loopers.domain.user.UserService;
 import com.loopers.support.error.CoreException;
 import com.loopers.support.error.ErrorType;
 import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Component;
 
+import java.math.BigDecimal;
+
 @RequiredArgsConstructor
 @Component
 public class UserFacade {
@@ -16,13 +18,13 @@ public class UserFacade {
 
     public UserInfo accountUser( String userId, String email, String birthdate, Gender gender ) {
 
-        UserModel user = userService.accountUser(userId, email, birthdate, gender);
+        User user = userService.accountUser(userId, email, birthdate, gender);
         return UserInfo.from(user);
 
     }
 
     public UserInfo getUserInfo(String userId) {
-        UserModel user = userService.getUserByUserId(userId);
+        User user = userService.getUserByUserId(userId);
 
         if(user == null) {
             throw new CoreException(ErrorType.NOT_FOUND, "해당 ID를 가진 회원이 존재하지 않습니다.");
@@ -31,18 +33,18 @@ public UserInfo getUserInfo(String userId) {
         return UserInfo.from(user);
     }
 
-    public Integer getUserPoint(String userId) {
-        UserModel findUser = userService.getUserPointByUserId(userId);
+    public BigDecimal getUserPoint(String userId) {
+        User findUser = userService.getUserPointByUserId(userId);
 
         if (findUser == null ) {
             throw new CoreException(ErrorType.NOT_FOUND, "해당 ID를 가진 회원이 존재하지 않습니다.");
         }
 
-        return findUser.getPoint();
+        return findUser.getPoint().getAmount();
     }
 
-    public UserInfo chargeUserPoint(String userId, Integer chargePoint) {
-        UserModel findUser = userService.chargePointByUserId(userId, chargePoint);
+    public UserInfo chargeUserPoint(String userId, BigDecimal chargePoint) {
+        User findUser = userService.chargePointByUserId(userId, chargePoint);
 
         return UserInfo.from(findUser);
     }
diff --git a/apps/commerce-api/src/main/java/com/loopers/application/user/UserInfo.java b/apps/commerce-api/src/main/java/com/loopers/application/user/UserInfo.java
index 9fa4966ef..1097aa720 100644
--- a/apps/commerce-api/src/main/java/com/loopers/application/user/UserInfo.java
+++ b/apps/commerce-api/src/main/java/com/loopers/application/user/UserInfo.java
@@ -1,17 +1,19 @@
 package com.loopers.application.user;
 
 import com.loopers.domain.user.Gender;
-import com.loopers.domain.user.UserModel;
+import com.loopers.domain.user.User;
 
-public record UserInfo(Long id, String userId, String email, String birthdate, Gender gender, Integer point) {
-    public static UserInfo from(UserModel userModel) {
+import java.math.BigDecimal;
+
+public record UserInfo(Long id, String userId, String email, String birthdate, Gender gender, BigDecimal point) {
+    public static UserInfo from(User user) {
         return new UserInfo(
-                userModel.getId(),
-                userModel.getUserId(),
-                userModel.getEmail(),
-                userModel.getBirthdate(),
-                userModel.getGender(),
-                userModel.getPoint()
+                user.getId(),
+                user.getUserId(),
+                user.getEmail(),
+                user.getBirthdate(),
+                user.getGender(),
+                user.getPoint().getAmount()
         );
     }
 }
diff --git a/apps/commerce-api/src/main/java/com/loopers/domain/Money.java b/apps/commerce-api/src/main/java/com/loopers/domain/Money.java
new file mode 100644
index 000000000..c39b68178
--- /dev/null
+++ b/apps/commerce-api/src/main/java/com/loopers/domain/Money.java
@@ -0,0 +1,81 @@
+package com.loopers.domain;
+
+import com.loopers.support.error.CoreException;
+import com.loopers.support.error.ErrorType;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import lombok.AccessLevel;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+
+@Embeddable
+@NoArgsConstructor(access = AccessLevel.PROTECTED)
+@Getter
+@EqualsAndHashCode
+public class Money {
+
+    @Column(nullable = false)
+    private BigDecimal amount;
+
+    private Money(BigDecimal amount) {
+        validateAmount(amount);
+        this.amount = amount;
+    }
+
+    public static Money of(BigDecimal amount) {
+        return new Money(amount);
+    }
+
+    public static Money of(long amount) {
+        return new Money(BigDecimal.valueOf(amount));
+    }
+
+    public static Money zero() {
+        return new Money(BigDecimal.ZERO);
+    }
+
+    public Money add(Money other) {
+        return new Money(this.amount.add(other.amount));
+    }
+
+    public Money subtract(Money other) {
+        return new Money(this.amount.subtract(other.amount));
+    }
+
+    public Money multiply(int quantity) {
+        return new Money(this.amount.multiply(BigDecimal.valueOf(quantity)));
+    }
+
+    public Money multiply(long quantity) {
+        return new Money(this.amount.multiply(BigDecimal.valueOf(quantity)));
+    }
+
+    public boolean isGreaterThan(Money other) {
+        return this.amount.compareTo(other.amount) > 0;
+    }
+
+    public boolean isGreaterThanOrEqual(Money other) {
+        return this.amount.compareTo(other.amount) >= 0;
+    }
+
+    public boolean isLessThan(Money other) {
+        return this.amount.compareTo(other.amount) < 0;
+    }
+
+    public boolean isLessThanOrEqual(Money other) {
+        return this.amount.compareTo(other.amount) <= 0;
+    }
+
+    private void validateAmount(BigDecimal amount) {
+        if (amount == null) {
+            throw new CoreException(ErrorType.BAD_REQUEST, "금액은 필수입니다");
+        }
+
+        if (amount.compareTo(BigDecimal.ZERO) < 0) {
+            throw new CoreException(ErrorType.BAD_REQUEST, "금액은 0보다 작을 수 없습니다");
+        }
+    }
+}
diff --git a/apps/commerce-api/src/main/java/com/loopers/domain/brand/Brand.java b/apps/commerce-api/src/main/java/com/loopers/domain/brand/Brand.java
new file mode 100644
index 000000000..12b4d7783
--- /dev/null
+++ b/apps/commerce-api/src/main/java/com/loopers/domain/brand/Brand.java
@@ -0,0 +1,54 @@
+package com.loopers.domain.brand;
+
+import com.loopers.domain.BaseEntity;
+import com.loopers.support.error.CoreException;
+import com.loopers.support.error.ErrorType;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Table;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor
+@Entity
+@Table(name = "brands")
+@Getter
+public class Brand extends BaseEntity {
+
+    @Column(name = "brand_name", nullable = false, unique = true)
+    private String brandName;
+
+    @Column(name = "is_active", nullable = false, columnDefinition = "boolean default true")
+    private boolean isActive = true;
+
+    @Builder
+    protected Brand(String brandName) {
+        validateBrandName(brandName);
+        this.brandName = brandName;
+    }
+
+    public static Brand createBrand(String brandName) {
+        return Brand.builder()
+                .brandName(brandName)
+                .build();
+    }
+
+    private static void validateBrandName(String brandName) {
+        if (brandName == null || brandName.isBlank()) {
+            throw new CoreException(ErrorType.BAD_REQUEST, "브랜드 이름은 필수입니다");
+        }
+    }
+
+    public void activate() {
+        this.isActive = true;
+    }
+
+    public void deactivate() {
+        this.isActive = false;
+    }
+
+    public boolean isAvailable() {
+        return this.isActive && this.getDeletedAt() == null;
+    }
+}
diff --git a/apps/commerce-api/src/main/java/com/loopers/domain/like/ProductLike.java b/apps/commerce-api/src/main/java/com/loopers/domain/like/ProductLike.java
new file mode 100644
index 000000000..3d9e30c4d
--- /dev/null
+++ b/apps/commerce-api/src/main/java/com/loopers/domain/like/ProductLike.java
@@ -0,0 +1,80 @@
+package com.loopers.domain.like;
+
+import com.loopers.domain.product.Product;
+import com.loopers.domain.user.User;
+import com.loopers.support.error.CoreException;
+import com.loopers.support.error.ErrorType;
+import jakarta.persistence.*;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+import java.time.ZonedDateTime;
+
+@NoArgsConstructor
+@Entity
+@Table(
+    name = "product_like",
+    uniqueConstraints = {
+        @UniqueConstraint(
+            name = "uk_product_like_user_product",
+            columnNames = {"user_id", "product_id"}
+        )
+    }
+)
+@Getter
+public class ProductLike {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private final Long id = 0L;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "user_id", referencedColumnName = "id")
+    private User likeUser;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "product_id", referencedColumnName = "id")
+    private Product likeProduct;
+
+    @Column(name = "like_at", nullable = false, updatable = false)
+    private ZonedDateTime likeAt;
+
+    @PrePersist
+    private void prePersist() {
+        this.likeAt = ZonedDateTime.now();
+    }
+
+    @Builder
+    private ProductLike(User likeUser, Product likeProduct) {
+
+        validateUser(likeUser);
+
+        validateProduct(likeProduct);
+
+        this.likeUser = likeUser;
+        this.likeProduct = likeProduct;
+    }
+
+    public static ProductLike addLike(User user, Product product) {
+        return ProductLike.builder()
+                .likeUser(user)
+                .likeProduct(product)
+                .build();
+    }
+
+    public boolean isSameUserAndProduct(User user, Product product) {
+        return this.likeUser.equals(user) && this.likeProduct.equals(product);
+    }
+
+    private static void validateProduct(Product likeProduct) {
+        if( likeProduct == null ) {
+            throw new CoreException(ErrorType.BAD_REQUEST, "좋아요를 누를 상품이 필요합니다");
+        }
+    }
+
+    private static void validateUser(User likeUser) {
+        if( likeUser == null ) {
+            throw new CoreException(ErrorType.BAD_REQUEST, "좋아요를 누를 사용자가 필요합니다");
+        }
+    }
+}
diff --git a/apps/commerce-api/src/main/java/com/loopers/domain/like/ProductLikeRepository.java b/apps/commerce-api/src/main/java/com/loopers/domain/like/ProductLikeRepository.java
new file mode 100644
index 000000000..1a58a24bd
--- /dev/null
+++ b/apps/commerce-api/src/main/java/com/loopers/domain/like/ProductLikeRepository.java
@@ -0,0 +1,16 @@
+package com.loopers.domain.like;
+
+import com.loopers.domain.product.Product;
+import com.loopers.domain.user.User;
+
+import java.util.Optional;
+
+public interface ProductLikeRepository {
+    ProductLike save(ProductLike productLike);
+
+    Optional<ProductLike> findByLikeUserAndLikeProduct(User user, Product product);
+
+    void delete(ProductLike productLike);
+
+    boolean existsByLikeUserAndLikeProduct(User user, Product product);
+}
\ No newline at end of file
diff --git a/apps/commerce-api/src/main/java/com/loopers/domain/like/ProductLikeService.java b/apps/commerce-api/src/main/java/com/loopers/domain/like/ProductLikeService.java
new file mode 100644
index 000000000..e694b8faf
--- /dev/null
+++ b/apps/commerce-api/src/main/java/com/loopers/domain/like/ProductLikeService.java
@@ -0,0 +1,40 @@
+package com.loopers.domain.like;
+
+import com.loopers.domain.product.Product;
+import com.loopers.domain.user.User;
+import com.loopers.support.error.CoreException;
+import com.loopers.support.error.ErrorType;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Component;
+
+@RequiredArgsConstructor
+@Component
+public class ProductLikeService {
+
+    private final ProductLikeRepository productLikeRepository;
+
+    public ProductLike addLike(User user, Product product) {
+        // 멱등성 처리: 이미 좋아요가 존재하면 기존 것을 반환
+        return productLikeRepository.findByLikeUserAndLikeProduct(user, product)
+                .orElseGet(() -> {
+                    // 좋아요가 없는 경우에만 새로 생성
+                    ProductLike like = ProductLike.addLike(user, product);
+                    ProductLike savedLike = productLikeRepository.save(like);
+
+                    // Product의 좋아요 수 증가
+                    product.incrementLikeCount(savedLike);
+
+                    return savedLike;
+                });
+    }
+
+    public void cancelLike(User user, Product product) {
+        ProductLike like = productLikeRepository.findByLikeUserAndLikeProduct(user, product)
+                .orElseThrow(() -> new CoreException(ErrorType.NOT_FOUND, "좋아요가 존재하지 않습니다"));
+
+        // Product의 좋아요 수 감소
+        product.decrementLikeCount(like);
+
+        productLikeRepository.delete(like);
+    }
+}
\ No newline at end of file
diff --git a/apps/commerce-api/src/main/java/com/loopers/domain/order/Order.java b/apps/commerce-api/src/main/java/com/loopers/domain/order/Order.java
new file mode 100644
index 000000000..f9e77350e
--- /dev/null
+++ b/apps/commerce-api/src/main/java/com/loopers/domain/order/Order.java
@@ -0,0 +1,112 @@
+package com.loopers.domain.order;
+
+import com.loopers.domain.BaseEntity;
+import com.loopers.domain.Money;
+import com.loopers.domain.orderproduct.OrderProduct;
+import com.loopers.domain.product.Product;
+import com.loopers.domain.user.User;
+import com.loopers.support.error.CoreException;
+import com.loopers.support.error.ErrorType;
+import jakarta.persistence.*;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+@NoArgsConstructor
+@Entity
+@Table(name = "orders")
+@Getter
+public class Order extends BaseEntity {
+
+    @Column(name = "status", nullable = false)
+    @Enumerated(EnumType.STRING)
+    private OrderStatus status;
+
+    @Embedded
+    @AttributeOverride(name = "amount", column = @Column(name = "total_price", nullable = false))
+    private Money totalPrice;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "user_id", referencedColumnName = "id")
+    private User user;
+
+    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
+    private List<OrderProduct> orderProducts = new ArrayList<>();
+
+    private Order(User user, Map<Product, Integer> productQuantities) {
+        validateUser(user);
+        validateProductQuantities(productQuantities);
+
+        // 총 금액 계산
+        Money calculatedTotal = calculateTotalPrice(productQuantities);
+
+        // 포인트 부족 검증
+        validateUserPoint(user, calculatedTotal);
+
+        // 재고 부족 검증
+        validateProductStock(productQuantities);
+
+        this.user = user;
+        this.status = OrderStatus.INIT;
+        this.totalPrice = Money.zero();
+
+        // OrderProduct 생성 및 총 금액 계산
+        productQuantities.forEach((product, quantity) -> {
+            OrderProduct orderProduct = new OrderProduct(this, product, quantity);
+            this.orderProducts.add(orderProduct);
+            this.totalPrice = this.totalPrice.add(orderProduct.getTotalPrice());
+        });
+    }
+
+    public static Order createOrder(User user, Map<Product, Integer> productQuantities) {
+        return new Order(user, productQuantities);
+    }
+
+    private void validateUser(User user) {
+        if (user == null) {
+            throw new CoreException(ErrorType.BAD_REQUEST, "사용자는 필수입니다");
+        }
+    }
+
+    private void validateProductQuantities(Map<Product, Integer> productQuantities) {
+        if (productQuantities == null || productQuantities.isEmpty()) {
+            throw new CoreException(ErrorType.BAD_REQUEST, "주문 상품은 필수입니다");
+        }
+    }
+
+    private void validateStatusUpdate(OrderStatus status) {
+        if (status == null) {
+            throw new CoreException(ErrorType.BAD_REQUEST, "주문 상태는 필수입니다");
+        }
+    }
+
+    private void validateUserPoint(User user, Money totalPrice) {
+        if (user.getPoint().isLessThan(totalPrice)) {
+            throw new CoreException(ErrorType.BAD_REQUEST,
+                    "포인트가 부족합니다. 현재 포인트: " + user.getPoint().getAmount() + ", 필요 포인트: " + totalPrice.getAmount());
+        }
+    }
+
+    private void validateProductStock(Map<Product, Integer> productQuantities) {
+        productQuantities.forEach((product, quantity) -> {
+            if (!product.getStock().isSufficient(quantity)) {
+                throw new CoreException(ErrorType.BAD_REQUEST,
+                        "재고가 부족합니다. 상품: " + product.getProductName() + ", 현재 재고: " + product.getStockQuantity());
+            }
+        });
+    }
+
+    public void updateStatus(OrderStatus status) {
+        validateStatusUpdate(status);
+        this.status = status;
+    }
+
+    private Money calculateTotalPrice(Map<Product, Integer> productQuantities) {
+        return productQuantities.entrySet().stream()
+                .map(entry -> entry.getKey().getPrice().multiply(entry.getValue()))
+                .reduce(Money.zero(), Money::add);
+    }
+}
diff --git a/apps/commerce-api/src/main/java/com/loopers/domain/order/OrderRepository.java b/apps/commerce-api/src/main/java/com/loopers/domain/order/OrderRepository.java
new file mode 100644
index 000000000..6588fa063
--- /dev/null
+++ b/apps/commerce-api/src/main/java/com/loopers/domain/order/OrderRepository.java
@@ -0,0 +1,5 @@
+package com.loopers.domain.order;
+
+public interface OrderRepository {
+    Order save(Order order);
+}
diff --git a/apps/commerce-api/src/main/java/com/loopers/domain/order/OrderService.java b/apps/commerce-api/src/main/java/com/loopers/domain/order/OrderService.java
new file mode 100644
index 000000000..98507bccd
--- /dev/null
+++ b/apps/commerce-api/src/main/java/com/loopers/domain/order/OrderService.java
@@ -0,0 +1,33 @@
+package com.loopers.domain.order;
+
+import com.loopers.domain.product.Product;
+import com.loopers.domain.user.User;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Map;
+
+@RequiredArgsConstructor
+@Component
+public class OrderService {
+
+    private final OrderRepository orderRepository;
+
+    @Transactional
+    public Order createOrder(User user, Map<Product, Integer> productQuantities) {
+        // Order 생성 (검증 포함)
+        Order order = Order.createOrder(user, productQuantities);
+
+        // 재고 차감
+        productQuantities.forEach((product, quantity) -> {
+            product.decreaseStock(quantity);
+        });
+
+        // 포인트 차감
+        user.usePoint(order.getTotalPrice());
+
+        // Order 저장
+        return orderRepository.save(order);
+    }
+}
diff --git a/apps/commerce-api/src/main/java/com/loopers/domain/order/OrderStatus.java b/apps/commerce-api/src/main/java/com/loopers/domain/order/OrderStatus.java
new file mode 100644
index 000000000..d1c5cf12b
--- /dev/null
+++ b/apps/commerce-api/src/main/java/com/loopers/domain/order/OrderStatus.java
@@ -0,0 +1,17 @@
+package com.loopers.domain.order;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+@Getter
+@RequiredArgsConstructor
+public enum OrderStatus {
+    INIT("주문생성"),
+    CANCELED("주문취소"),
+    PAYMENT_COMPLETE("결제완료"),
+    PAYMENT_FAILED("결제실패"),
+    RECEIVED("주문접수"),
+    COMPLETED("처리완료");
+
+    private final String text;
+}
diff --git a/apps/commerce-api/src/main/java/com/loopers/domain/orderproduct/OrderProduct.java b/apps/commerce-api/src/main/java/com/loopers/domain/orderproduct/OrderProduct.java
new file mode 100644
index 000000000..95db24218
--- /dev/null
+++ b/apps/commerce-api/src/main/java/com/loopers/domain/orderproduct/OrderProduct.java
@@ -0,0 +1,70 @@
+package com.loopers.domain.orderproduct;
+
+import com.loopers.domain.BaseEntity;
+import com.loopers.domain.Money;
+import com.loopers.domain.order.Order;
+import com.loopers.domain.product.Product;
+import com.loopers.support.error.CoreException;
+import com.loopers.support.error.ErrorType;
+import jakarta.persistence.*;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor
+@Entity
+@Table(name = "order_product")
+@Getter
+public class OrderProduct {
+
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    @Column(name = "quantity", nullable = false)
+    private int quantity;
+
+    @Embedded
+    @AttributeOverride(name = "amount", column = @Column(name = "price", nullable = false))
+    private Money price;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "order_id", referencedColumnName = "id")
+    private Order order;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "product_id", referencedColumnName = "id")
+    private Product product;
+
+    public OrderProduct(Order order, Product product, int quantity) {
+        validateOrder(order);
+        validateProduct(product);
+        validateQuantity(quantity);
+
+        this.order = order;
+        this.product = product;
+        this.quantity = quantity;
+        this.price = product.getPrice();
+    }
+
+    private void validateOrder(Order order) {
+        if (order == null) {
+            throw new CoreException(ErrorType.BAD_REQUEST, "주문은 필수입니다");
+        }
+    }
+
+    private void validateProduct(Product product) {
+        if (product == null) {
+            throw new CoreException(ErrorType.BAD_REQUEST, "상품은 필수입니다");
+        }
+    }
+
+    private void validateQuantity(int quantity) {
+        if (quantity <= 0) {
+            throw new CoreException(ErrorType.BAD_REQUEST, "수량은 1개 이상이어야 합니다");
+        }
+    }
+
+    public Money getTotalPrice() {
+        return this.price.multiply(this.quantity);
+    }
+}
diff --git a/apps/commerce-api/src/main/java/com/loopers/domain/product/Product.java b/apps/commerce-api/src/main/java/com/loopers/domain/product/Product.java
new file mode 100644
index 000000000..e78ecd11a
--- /dev/null
+++ b/apps/commerce-api/src/main/java/com/loopers/domain/product/Product.java
@@ -0,0 +1,127 @@
+package com.loopers.domain.product;
+
+import com.loopers.domain.BaseEntity;
+import com.loopers.domain.Money;
+import com.loopers.domain.brand.Brand;
+import com.loopers.domain.like.ProductLike;
+import com.loopers.support.error.CoreException;
+import com.loopers.support.error.ErrorType;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embedded;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.OneToMany;
+import jakarta.persistence.Table;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@NoArgsConstructor
+@Entity
+@Table(name = "products")
+@Getter
+public class Product extends BaseEntity {
+
+    @Column(name = "product_code", nullable = false, unique = true)
+    private String productCode;
+
+    @Column(name = "product_name", nullable = false)
+    private String productName;
+
+    @Embedded
+    private Stock stock;
+
+    @Embedded
+    private Money price;
+
+    @Column(name = "like_count", nullable = false, columnDefinition = "int default 0")
+    private Long likeCount = 0L;
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "brand_id", nullable = false)
+    private Brand brand;
+
+    @OneToMany(mappedBy = "likeProduct")
+    private List<ProductLike> productLikes = new ArrayList<>();
+
+    @Builder
+    protected Product(String productCode, String productName, int stockQuantity, Money price, Brand brand) {
+
+        validationProductCode(productCode);
+
+        validationProductName(productName);
+
+        validationBrand(brand);
+
+        validationPrice(price);
+
+        this.productCode = productCode;
+        this.productName = productName;
+        this.stock = Stock.of(stockQuantity);
+        this.price = price;
+        this.brand = brand;
+    }
+
+    public static Product createProduct(String productCode, String productName, Money price, int stock, Brand brand) {
+        return Product.builder()
+                .productCode(productCode)
+                .productName(productName)
+                .price(price)
+                .stockQuantity(stock)
+                .brand(brand)
+                .build();
+    }
+
+    private static void validationProductCode(String productCode) {
+        if( productCode == null || productCode.trim().isEmpty()) {
+            throw new CoreException(ErrorType.BAD_REQUEST, "상품 코드는 필수값입니다");
+        }
+    }
+
+    private static void validationProductName(String productName) {
+        if( productName == null || productName.trim().isEmpty()) {
+            throw new CoreException(ErrorType.BAD_REQUEST, "상품 이름은 필수값입니다");
+        }
+    }
+
+    private static void validationBrand(Brand brand) {
+        if (brand == null) {
+            throw new CoreException(ErrorType.BAD_REQUEST, "브랜드는 필수입니다");
+        }
+    }
+
+    private static void validationPrice(Money price) {
+        if (price == null) {
+            throw new CoreException(ErrorType.BAD_REQUEST, "상품 가격은 필수입니다");
+        }
+    }
+
+    public void increaseStock(int amount) {
+        this.stock = this.stock.increase(amount);
+    }
+
+    public void decreaseStock(int amount) {
+        this.stock = this.stock.decrease(amount);
+    }
+
+    public int getStockQuantity() {
+        return this.stock.getQuantity();
+    }
+
+    public void incrementLikeCount(ProductLike productLike) {
+        this.productLikes.add(productLike);
+        this.likeCount++;
+    }
+
+    public void decrementLikeCount(ProductLike productLike) {
+        this.productLikes.remove(productLike);
+        if (this.likeCount > 0) {
+            this.likeCount--;
+        }
+    }
+}
diff --git a/apps/commerce-api/src/main/java/com/loopers/domain/product/ProductRepository.java b/apps/commerce-api/src/main/java/com/loopers/domain/product/ProductRepository.java
new file mode 100644
index 000000000..0c3ce0eae
--- /dev/null
+++ b/apps/commerce-api/src/main/java/com/loopers/domain/product/ProductRepository.java
@@ -0,0 +1,14 @@
+package com.loopers.domain.product;
+
+import java.util.List;
+import java.util.Optional;
+
+public interface ProductRepository {
+    Product registerProduct(Product product);
+
+    boolean existsProductCode(String productCode);
+
+    List<Product> findAllBySortType(ProductSortType sortType);
+
+    Optional<Product> findByIdWithBrand(Long productId);
+}
diff --git a/apps/commerce-api/src/main/java/com/loopers/domain/product/ProductService.java b/apps/commerce-api/src/main/java/com/loopers/domain/product/ProductService.java
new file mode 100644
index 000000000..86d5dc977
--- /dev/null
+++ b/apps/commerce-api/src/main/java/com/loopers/domain/product/ProductService.java
@@ -0,0 +1,44 @@
+package com.loopers.domain.product;
+
+import com.loopers.domain.Money;
+import com.loopers.domain.brand.Brand;
+import com.loopers.support.error.CoreException;
+import com.loopers.support.error.ErrorType;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Component;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@RequiredArgsConstructor
+@Component
+public class ProductService {
+
+    private final ProductRepository productRepository;
+
+    public Product registerProduct(String productCode, String productName, BigDecimal price, int stock, Brand brand) {
+        if (productCode == null || productCode.trim().isEmpty()) {
+            throw new CoreException(ErrorType.BAD_REQUEST, "상품 코드는 필수값입니다");
+        }
+        validateProductCodeNotDuplicated(productCode);
+
+        Product product = Product.createProduct(productCode, productName, Money.of(price), stock, brand);
+        return productRepository.registerProduct(product);
+    }
+
+    public List<Product> getProducts(ProductSortType sortType) {
+        ProductSortType appliedSortType = (sortType != null) ? sortType : ProductSortType.LATEST;
+        return productRepository.findAllBySortType(appliedSortType);
+    }
+
+    public Product getProductDetail(Long productId) {
+        return productRepository.findByIdWithBrand(productId)
+                .orElseThrow(() -> new CoreException(ErrorType.NOT_FOUND, "상품을 찾을 수 없습니다"));
+    }
+
+    private void validateProductCodeNotDuplicated(String productCode) {
+        if (productRepository.existsProductCode(productCode)) {
+            throw new CoreException(ErrorType.BAD_REQUEST, "중복된 상품 코드 오류");
+        }
+    }
+}
diff --git a/apps/commerce-api/src/main/java/com/loopers/domain/product/ProductSortType.java b/apps/commerce-api/src/main/java/com/loopers/domain/product/ProductSortType.java
new file mode 100644
index 000000000..db7a9262c
--- /dev/null
+++ b/apps/commerce-api/src/main/java/com/loopers/domain/product/ProductSortType.java
@@ -0,0 +1,17 @@
+package com.loopers.domain.product;
+
+public enum ProductSortType {
+    LATEST("최신순"),
+    PRICE_ASC("가격 낮은 순"),
+    LIKES_DESC("좋아요 많은 순");
+
+    private final String description;
+
+    ProductSortType(String description) {
+        this.description = description;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+}
diff --git a/apps/commerce-api/src/main/java/com/loopers/domain/product/Stock.java b/apps/commerce-api/src/main/java/com/loopers/domain/product/Stock.java
new file mode 100644
index 000000000..5aae7c746
--- /dev/null
+++ b/apps/commerce-api/src/main/java/com/loopers/domain/product/Stock.java
@@ -0,0 +1,58 @@
+package com.loopers.domain.product;
+
+import com.loopers.support.error.CoreException;
+import com.loopers.support.error.ErrorType;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import lombok.AccessLevel;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+@Embeddable
+@NoArgsConstructor(access = AccessLevel.PROTECTED)
+@Getter
+@EqualsAndHashCode
+public class Stock {
+
+    @Column(name = "stock", nullable = false, columnDefinition = "int default 0")
+    private int quantity;
+
+    private Stock(int quantity) {
+        validateQuantity(quantity);
+        this.quantity = quantity;
+    }
+
+    public static Stock of(int quantity) {
+        return new Stock(quantity);
+    }
+
+    public Stock increase(int amount) {
+        if (amount <= 0) {
+            throw new CoreException(ErrorType.BAD_REQUEST, "재고 증가량은 양수여야 합니다");
+        }
+        return new Stock(this.quantity + amount);
+    }
+
+    public Stock decrease(int amount) {
+        if (amount <= 0) {
+            throw new CoreException(ErrorType.BAD_REQUEST, "재고 감소량은 양수여야 합니다");
+        }
+
+        if (!isSufficient(amount)) {
+            throw new CoreException(ErrorType.BAD_REQUEST, "재고가 부족합니다. 현재 재고: " + this.quantity);
+        }
+
+        return new Stock(this.quantity - amount);
+    }
+
+    public boolean isSufficient(int required) {
+        return this.quantity >= required;
+    }
+
+    private void validateQuantity(int quantity) {
+        if (quantity < 0) {
+            throw new CoreException(ErrorType.BAD_REQUEST, "상품 재고는 음수일 수 없습니다");
+        }
+    }
+}
diff --git a/apps/commerce-api/src/main/java/com/loopers/domain/user/User.java b/apps/commerce-api/src/main/java/com/loopers/domain/user/User.java
new file mode 100644
index 000000000..1dc52a7b6
--- /dev/null
+++ b/apps/commerce-api/src/main/java/com/loopers/domain/user/User.java
@@ -0,0 +1,107 @@
+package com.loopers.domain.user;
+
+import com.loopers.domain.BaseEntity;
+import com.loopers.domain.Money;
+import com.loopers.support.error.CoreException;
+import com.loopers.support.error.ErrorType;
+import jakarta.persistence.*;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor
+@Entity
+@Table(name = "users")
+@Getter
+public class User extends BaseEntity {
+
+    @Column(name = "user_id", nullable = false, unique = true, length = 10)
+    private String userId;
+
+    @Column(name = "email", nullable = false, unique = true)
+    private String email;
+
+    @Column(name = "birthdate", nullable = false)
+    private String birthdate;
+
+    @Enumerated(EnumType.STRING)
+    @Column(name = "gender", nullable = false)
+    private Gender gender;
+
+    @Embedded
+    @AttributeOverride(name = "amount", column = @Column(name = "point", nullable = false, columnDefinition = "decimal(15,2) default 0"))
+    private Money point = Money.zero();
+
+    @Builder
+    protected User(String userId, String email, String birthdate, Gender gender) {
+        validateUserId(userId);
+        validateUserEmail(email);
+        validateBirthdate(birthdate);
+        validateGender(gender);
+
+        this.userId = userId;
+        this.email = email;
+        this.birthdate = birthdate;
+        this.gender = gender;
+    }
+
+    public static User createUser(String userId, String email, String birthdate, Gender gender) {
+        return User.builder()
+                .userId(userId)
+                .email(email)
+                .birthdate(birthdate)
+                .gender(gender)
+                .build();
+    }
+
+    private static void validateUserId(String userId) {
+        if (userId == null || userId.isEmpty()) {
+            throw new CoreException(ErrorType.BAD_REQUEST, "유저 ID는 필수값입니다");
+        }
+
+        if (!userId.matches("^[a-zA-Z0-9]{1,10}$")) {
+            throw new CoreException(ErrorType.BAD_REQUEST, "유저 ID는 영문자와 숫자로만 구성된 1-10자여야 합니다");
+        }
+    }
+
+    private static void validateUserEmail(String email) {
+        if (email == null || email.isEmpty()) {
+            throw new CoreException(ErrorType.BAD_REQUEST, "이메일은 필수값입니다");
+        }
+
+        if (!email.matches("^[\\w\\.]+@[\\w\\.]+\\.[a-zA-Z]{2,}$")) {
+            throw new CoreException(ErrorType.BAD_REQUEST, "올바른 이메일 형식이 아닙니다");
+        }
+    }
+
+    private static void validateBirthdate(String birthdate) {
+        if (birthdate == null || birthdate.isEmpty()) {
+            throw new CoreException(ErrorType.BAD_REQUEST, "생년월일은 필수값입니다");
+        }
+
+        if (!birthdate.matches("^\\d{4}-\\d{2}-\\d{2}$")) {
+            throw new CoreException(ErrorType.BAD_REQUEST, "생년월일은 YYYY-MM-DD 형식이어야 합니다");
+        }
+    }
+
+    private static void validateGender(Gender gender) {
+        if (gender == null) {
+            throw new CoreException(ErrorType.BAD_REQUEST, "성별은 필수값입니다");
+        }
+    }
+
+    private void validateAmount(Money amount) {
+        if (this.point.isLessThan(amount)) {
+            throw new CoreException(ErrorType.BAD_REQUEST, "포인트가 부족합니다. 현재 포인트: " + this.point.getAmount());
+        }
+    }
+
+    public void chargePoint(Money amount) {
+        this.point = this.point.add(amount);
+    }
+
+    public void usePoint(Money amount) {
+        validateAmount(amount);
+        this.point = this.point.subtract(amount);
+    }
+}
diff --git a/apps/commerce-api/src/main/java/com/loopers/domain/user/UserModel.java b/apps/commerce-api/src/main/java/com/loopers/domain/user/UserModel.java
deleted file mode 100644
index 3b6811839..000000000
--- a/apps/commerce-api/src/main/java/com/loopers/domain/user/UserModel.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package com.loopers.domain.user;
-
-import com.loopers.domain.BaseEntity;
-import com.loopers.support.error.CoreException;
-import com.loopers.support.error.ErrorType;
-import jakarta.persistence.*;
-import lombok.Builder;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-
-@NoArgsConstructor
-@Entity
-@Table(name = "users")
-@Getter
-public class UserModel extends BaseEntity {
-
-    @Id
-    @GeneratedValue(strategy = GenerationType.IDENTITY)
-    private Long id;
-    private String userId;
-    private String email;
-    private String birthdate;
-
-    @Enumerated( EnumType.STRING )
-    private Gender gender;
-    private Integer point = 0;
-
-    @Builder
-    public UserModel(String userId, String email, String birthdate, Gender gender) {
-
-        validUserInfo(userId, email, birthdate);
-
-        this.userId = userId;
-        this.email = email;
-        this.birthdate = birthdate;
-        this.gender = gender;
-    }
-
-    private static void validUserInfo(String userId, String email, String birthdate) {
-        if( !userId.matches("^[a-zA-Z0-9]{1,10}$") ) {
-            throw new CoreException(ErrorType.BAD_REQUEST, "유저 ID 형식 오류");
-        }
-
-        if (!email.matches("^[\\w\\.]+@[\\w\\.]+\\.[a-zA-Z]{2,}$")) {
-            throw new CoreException(ErrorType.BAD_REQUEST, "이메일 형식 오류");
-        }
-
-        if (!birthdate.matches("^\\d{4}-\\d{2}-\\d{2}$")) {
-            throw new CoreException(ErrorType.BAD_REQUEST, "생년월일 형식 오류");
-        }
-    }
-
-    protected void chargePoint(Integer point) {
-
-        if( point <= 0 ) {
-            throw new CoreException(ErrorType.BAD_REQUEST, "충전할 포인트는 1 이상의 정수여야 합니다.");
-        }
-
-        this.point += point;
-    }
-}
diff --git a/apps/commerce-api/src/main/java/com/loopers/domain/user/UserRepository.java b/apps/commerce-api/src/main/java/com/loopers/domain/user/UserRepository.java
index caf6bc7ec..3f50fef00 100644
--- a/apps/commerce-api/src/main/java/com/loopers/domain/user/UserRepository.java
+++ b/apps/commerce-api/src/main/java/com/loopers/domain/user/UserRepository.java
@@ -6,7 +6,7 @@ public interface UserRepository {
 
     boolean existsByUserId(String userId);
 
-    UserModel save(UserModel userModel);
+    User save(User user);
 
-    Optional<UserModel> findUserByUserId(String userId);
+    Optional<User> findUserByUserId(String userId);
 }
diff --git a/apps/commerce-api/src/main/java/com/loopers/domain/user/UserService.java b/apps/commerce-api/src/main/java/com/loopers/domain/user/UserService.java
index 4f79bda4b..70773ab70 100644
--- a/apps/commerce-api/src/main/java/com/loopers/domain/user/UserService.java
+++ b/apps/commerce-api/src/main/java/com/loopers/domain/user/UserService.java
@@ -1,11 +1,14 @@
 package com.loopers.domain.user;
 
+import com.loopers.domain.Money;
 import com.loopers.support.error.CoreException;
 import com.loopers.support.error.ErrorType;
 import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.math.BigDecimal;
+
 @RequiredArgsConstructor
 @Component
 public class UserService {
@@ -14,43 +17,38 @@ public class UserService {
 
 
     @Transactional
-    public UserModel accountUser(String userId, String email, String birthdate, Gender gender) {
+    public User accountUser(String userId, String email, String birthdate, Gender gender) {
 
         if( userRepository.existsByUserId(userId) ) {
             throw new CoreException(ErrorType.BAD_REQUEST, "이미 존재하는 ID 입니다.");
         }
 
-        UserModel user = UserModel.builder()
-                .userId(userId)
-                .email(email)
-                .birthdate(birthdate)
-                .gender(gender)
-                .build();
+        User user = User.createUser(userId, email, birthdate, gender);
 
         return userRepository.save(user);
     }
 
     @Transactional( readOnly = true )
-    public UserModel getUserByUserId(String userId) {
+    public User getUserByUserId(String userId) {
         return userRepository.findUserByUserId(userId)
                 .orElse(null);
     }
 
     @Transactional( readOnly = true )
-    public UserModel getUserPointByUserId(String userId) {
+    public User getUserPointByUserId(String userId) {
         return userRepository.findUserByUserId(userId)
                 .orElse(null);
     }
 
     @Transactional
-    public UserModel chargePointByUserId(String notExistsUserId, Integer chargePoint) {
+    public User chargePointByUserId(String notExistsUserId, BigDecimal chargePoint) {
 
-        UserModel findUser = userRepository.findUserByUserId(notExistsUserId)
+        User findUser = userRepository.findUserByUserId(notExistsUserId)
                 .orElseThrow(
                         () -> new CoreException(ErrorType.NOT_FOUND, "해당 ID 의 회원이 존재하지 않아 포인트 충전이 실패하였습니다.")
                 );
 
-        findUser.chargePoint(chargePoint);
+        findUser.chargePoint(Money.of(chargePoint));
 
         return findUser;
     }
diff --git a/apps/commerce-api/src/main/java/com/loopers/infrastructure/order/OrderJpaRepository.java b/apps/commerce-api/src/main/java/com/loopers/infrastructure/order/OrderJpaRepository.java
new file mode 100644
index 000000000..fb51c05c6
--- /dev/null
+++ b/apps/commerce-api/src/main/java/com/loopers/infrastructure/order/OrderJpaRepository.java
@@ -0,0 +1,8 @@
+package com.loopers.infrastructure.order;
+
+import com.loopers.domain.order.Order;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface OrderJpaRepository extends JpaRepository<Order, Long> {
+    Order save(Order order);
+}
diff --git a/apps/commerce-api/src/main/java/com/loopers/infrastructure/order/OrderRepositoryImpl.java b/apps/commerce-api/src/main/java/com/loopers/infrastructure/order/OrderRepositoryImpl.java
new file mode 100644
index 000000000..5ea7ca142
--- /dev/null
+++ b/apps/commerce-api/src/main/java/com/loopers/infrastructure/order/OrderRepositoryImpl.java
@@ -0,0 +1,18 @@
+package com.loopers.infrastructure.order;
+
+import com.loopers.domain.order.Order;
+import com.loopers.domain.order.OrderRepository;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Component;
+
+@RequiredArgsConstructor
+@Component
+public class OrderRepositoryImpl implements OrderRepository {
+
+    private final OrderJpaRepository orderJpaRepository;
+
+    @Override
+    public Order save(Order order) {
+        return orderJpaRepository.save(order);
+    }
+}
diff --git a/apps/commerce-api/src/main/java/com/loopers/infrastructure/product/ProductJpaRepository.java b/apps/commerce-api/src/main/java/com/loopers/infrastructure/product/ProductJpaRepository.java
new file mode 100644
index 000000000..3766b0eb3
--- /dev/null
+++ b/apps/commerce-api/src/main/java/com/loopers/infrastructure/product/ProductJpaRepository.java
@@ -0,0 +1,25 @@
+package com.loopers.infrastructure.product;
+
+import com.loopers.domain.product.Product;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+
+import java.util.List;
+import java.util.Optional;
+
+public interface ProductJpaRepository extends JpaRepository<Product, Long> {
+    Product save(Product product);
+
+    boolean existsByProductCode(String productCode);
+
+    @Query("SELECT p FROM Product p WHERE p.deletedAt IS NULL")
+    List<Product> findAllByDeletedAtIsNull(Sort sort);
+
+    @Query("SELECT DISTINCT p FROM Product p " +
+            "LEFT JOIN FETCH p.brand " +
+            "LEFT JOIN FETCH p.productLikes " +
+            "WHERE p.id = :productId AND p.deletedAt IS NULL")
+    Optional<Product> findByIdWithBrand(@Param("productId") Long productId);
+}
diff --git a/apps/commerce-api/src/main/java/com/loopers/infrastructure/product/ProductRepositoryImpl.java b/apps/commerce-api/src/main/java/com/loopers/infrastructure/product/ProductRepositoryImpl.java
new file mode 100644
index 000000000..0a9560bec
--- /dev/null
+++ b/apps/commerce-api/src/main/java/com/loopers/infrastructure/product/ProductRepositoryImpl.java
@@ -0,0 +1,49 @@
+package com.loopers.infrastructure.product;
+
+import com.loopers.domain.product.Product;
+import com.loopers.domain.product.ProductRepository;
+import com.loopers.domain.product.ProductSortType;
+import lombok.RequiredArgsConstructor;
+import org.springframework.data.domain.Sort;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Optional;
+
+@RequiredArgsConstructor
+@Component
+public class ProductRepositoryImpl implements ProductRepository {
+
+    private final ProductJpaRepository productJpaRepository;
+
+    @Override
+    public Product registerProduct(Product product) {
+        return productJpaRepository.save(product);
+    }
+
+    @Override
+    public boolean existsProductCode(String productCode) {
+        return productJpaRepository.existsByProductCode(productCode);
+    }
+
+    @Override
+    public List<Product> findAllBySortType(ProductSortType sortType) {
+        Sort sort = getSortBySortType(sortType);
+
+        // Repository 레벨에서 deletedAt IS NULL 조건으로 필터링
+        return productJpaRepository.findAllByDeletedAtIsNull(sort);
+    }
+
+    @Override
+    public Optional<Product> findByIdWithBrand(Long productId) {
+        return productJpaRepository.findByIdWithBrand(productId);
+    }
+
+    private Sort getSortBySortType(ProductSortType sortType) {
+        return switch (sortType) {
+            case LATEST -> Sort.by(Sort.Direction.DESC, "createdAt");
+            case PRICE_ASC -> Sort.by(Sort.Direction.ASC, "price.amount");  // @Embedded Money 타입의 중첩 경로
+            case LIKES_DESC -> Sort.by(Sort.Direction.DESC, "likeCount");
+        };
+    }
+}
diff --git a/apps/commerce-api/src/main/java/com/loopers/infrastructure/user/UserJpaRepository.java b/apps/commerce-api/src/main/java/com/loopers/infrastructure/user/UserJpaRepository.java
index e01431083..8c68f866f 100644
--- a/apps/commerce-api/src/main/java/com/loopers/infrastructure/user/UserJpaRepository.java
+++ b/apps/commerce-api/src/main/java/com/loopers/infrastructure/user/UserJpaRepository.java
@@ -1,11 +1,11 @@
 package com.loopers.infrastructure.user;
 
-import com.loopers.domain.user.UserModel;
+import com.loopers.domain.user.User;
 import org.springframework.data.jpa.repository.JpaRepository;
 
-public interface UserJpaRepository extends JpaRepository<UserModel, Long> {
+public interface UserJpaRepository extends JpaRepository<User, Long> {
 
     boolean existsByUserId(String userId);
 
-    UserModel findByUserId(String userId);
+    User findByuserId(String userId);
 }
diff --git a/apps/commerce-api/src/main/java/com/loopers/infrastructure/user/UserRepositoryImpl.java b/apps/commerce-api/src/main/java/com/loopers/infrastructure/user/UserRepositoryImpl.java
index 55814687e..9954dccde 100644
--- a/apps/commerce-api/src/main/java/com/loopers/infrastructure/user/UserRepositoryImpl.java
+++ b/apps/commerce-api/src/main/java/com/loopers/infrastructure/user/UserRepositoryImpl.java
@@ -1,6 +1,6 @@
 package com.loopers.infrastructure.user;
 
-import com.loopers.domain.user.UserModel;
+import com.loopers.domain.user.User;
 import com.loopers.domain.user.UserRepository;
 import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Component;
@@ -14,14 +14,14 @@ public class UserRepositoryImpl implements UserRepository {
     private final UserJpaRepository userJpaRepository;
 
     @Override
-    public UserModel save(UserModel userModel) {
+    public User save(User user) {
 
-        return userJpaRepository.save(userModel);
+        return userJpaRepository.save(user);
     }
 
     @Override
-    public Optional<UserModel> findUserByUserId(String userId) {
-        UserModel user = userJpaRepository.findByUserId(userId);
+    public Optional<User> findUserByUserId(String userId) {
+        User user = userJpaRepository.findByuserId(userId);
 
         return Optional.ofNullable(user);
     }
diff --git a/apps/commerce-api/src/main/java/com/loopers/interfaces/api/user/UserV1Controller.java b/apps/commerce-api/src/main/java/com/loopers/interfaces/api/user/UserV1Controller.java
index d7ae8d06d..3f3701784 100644
--- a/apps/commerce-api/src/main/java/com/loopers/interfaces/api/user/UserV1Controller.java
+++ b/apps/commerce-api/src/main/java/com/loopers/interfaces/api/user/UserV1Controller.java
@@ -7,6 +7,8 @@
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import java.math.BigDecimal;
+
 @RequiredArgsConstructor
 @RestController
 @RequestMapping("/api/v1/users")
@@ -45,7 +47,7 @@ public ApiResponse<UserV1DTO.UserPointResponse> getUserPoint(
             @RequestHeader(value = "X-USER-ID") String headerUserId
     ) {
 
-        Integer userPoint = userFacade.getUserPoint(userId);
+        BigDecimal userPoint = userFacade.getUserPoint(userId);
 
         UserV1DTO.UserPointResponse response = UserV1DTO.UserPointResponse.from(userId, userPoint);
 
diff --git a/apps/commerce-api/src/main/java/com/loopers/interfaces/api/user/UserV1DTO.java b/apps/commerce-api/src/main/java/com/loopers/interfaces/api/user/UserV1DTO.java
index fd0d99373..06cc36a34 100644
--- a/apps/commerce-api/src/main/java/com/loopers/interfaces/api/user/UserV1DTO.java
+++ b/apps/commerce-api/src/main/java/com/loopers/interfaces/api/user/UserV1DTO.java
@@ -5,6 +5,8 @@
 import jakarta.validation.constraints.NotBlank;
 import jakarta.validation.constraints.NotNull;
 
+import java.math.BigDecimal;
+
 public class UserV1DTO {
 
     public record UserRequest(
@@ -16,10 +18,10 @@ public record UserRequest(
 
     public record UserPointRequest(
             @NotBlank(message = "사용자 ID는 필수값입니다.") String userId,
-            Integer chargePoint
+            BigDecimal chargePoint
     ) { }
 
-    public record UserResponse(Long id, String userId, String email, String birthdate, Gender gender, Integer point) {
+    public record UserResponse(Long id, String userId, String email, String birthdate, Gender gender, BigDecimal point) {
         public static UserResponse from(UserInfo userInfo) {
             return new UserResponse(
                     userInfo.id(),
@@ -32,8 +34,8 @@ public static UserResponse from(UserInfo userInfo) {
         }
     }
 
-    public record UserPointResponse(String userId, Integer point) {
-        public static UserPointResponse from(String userId, Integer point) {
+    public record UserPointResponse(String userId, BigDecimal point) {
+        public static UserPointResponse from(String userId, BigDecimal point) {
             return new UserPointResponse(
                     userId,
                     point
diff --git a/apps/commerce-api/src/test/java/com/loopers/domain/brand/BrandTest.java b/apps/commerce-api/src/test/java/com/loopers/domain/brand/BrandTest.java
new file mode 100644
index 000000000..74cb73f75
--- /dev/null
+++ b/apps/commerce-api/src/test/java/com/loopers/domain/brand/BrandTest.java
@@ -0,0 +1,65 @@
+package com.loopers.domain.brand;
+
+import com.loopers.support.error.CoreException;
+import com.loopers.support.error.ErrorType;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class BrandTest {
+
+    @DisplayName("브랜드 이름은 필수값이다.")
+    @Test
+    void whenRegisterBrandInvalidName_throwBadRequest() {
+
+        CoreException result = assertThrows(CoreException.class, () -> {
+            Brand.createBrand(null);
+        });
+
+        assertThat(result.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);
+        assertThat(result.getCustomMessage()).isEqualTo("브랜드 이름은 필수입니다");
+    }
+
+    @DisplayName("브랜드 최초 등록시 Active 값은 true 이다.")
+    @Test
+    void whenRegisterBrand_isActiveIsTrue() {
+        // given
+        Brand brand = Brand.createBrand("Nike");
+
+        // when // then
+        assertThat(brand.isActive()).isTrue();
+    }
+
+    @DisplayName("브랜드 미사용 처리시 Active 값은 false 이다.")
+    @Test
+    void whenDeactivateBrand_isActiveIsFalse() {
+        // given
+        Brand brand = Brand.createBrand("Nike");
+
+        // when
+        brand.deactivate();
+
+        // then
+        assertThat(brand.isActive()).isFalse();
+
+    }
+
+    @DisplayName("브랜드 사용 처리시 Active 값은 true 이다.")
+    @Test
+    void whenActivateBrand_isActiveIsTrue() {
+        // given
+        Brand brand = Brand.createBrand("Nike");
+
+        // when // then
+        brand.deactivate();
+
+        assertThat(brand.isActive()).isFalse();
+
+        brand.activate();
+
+        assertThat(brand.isActive()).isTrue();
+
+    }
+}
diff --git a/apps/commerce-api/src/test/java/com/loopers/domain/like/ProductLikeServiceTest.java b/apps/commerce-api/src/test/java/com/loopers/domain/like/ProductLikeServiceTest.java
new file mode 100644
index 000000000..774ec6beb
--- /dev/null
+++ b/apps/commerce-api/src/test/java/com/loopers/domain/like/ProductLikeServiceTest.java
@@ -0,0 +1,171 @@
+package com.loopers.domain.like;
+
+import com.loopers.domain.Money;
+import com.loopers.domain.brand.Brand;
+import com.loopers.domain.product.Product;
+import com.loopers.domain.user.Gender;
+import com.loopers.domain.user.User;
+import com.loopers.support.error.CoreException;
+import com.loopers.support.error.ErrorType;
+import com.loopers.utils.DatabaseCleanUp;
+import jakarta.persistence.EntityManager;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.transaction.annotation.Transactional;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+@ActiveProfiles("test")
+@SpringBootTest
+class ProductLikeServiceTest {
+
+    @Autowired
+    private ProductLikeService productLikeService;
+
+    @Autowired
+    private ProductLikeRepository productLikeRepository;
+
+    @Autowired
+    private EntityManager entityManager;
+
+    @Autowired
+    private DatabaseCleanUp databaseCleanUp;
+
+    @AfterEach
+    void tearDown() {
+        databaseCleanUp.truncateAllTables();
+    }
+
+    @DisplayName("유저와 상품으로 좋아요를 등록할 수 있다")
+    @Test
+    @Transactional
+    void addLike_success() {
+        // given
+        User user = createUser("user123", "user@test.com");
+        Product product = createProduct("P001", "상품1");
+        Long initialLikeCount = product.getLikeCount();
+
+        // when
+        ProductLike like = productLikeService.addLike(user, product);
+
+        // then
+        assertThat(like.getId()).isNotNull();
+        assertThat(like.getLikeUser()).isEqualTo(user);
+        assertThat(like.getLikeProduct()).isEqualTo(product);
+        assertThat(like.getLikeAt()).isNotNull();
+        assertThat(product.getLikeCount()).isEqualTo(initialLikeCount + 1);
+    }
+
+    @DisplayName("같은 유저가 같은 상품에 여러 번 좋아요를 등록해도 성공한다 (멱등성)")
+    @Test
+    @Transactional
+    void addLike_idempotent_success() {
+        // given
+        User user = createUser("user123", "user@test.com");
+        Product product = createProduct("P001", "상품1");
+        Long initialLikeCount = product.getLikeCount();
+
+        // when
+        ProductLike firstLike = productLikeService.addLike(user, product);
+        ProductLike secondLike = productLikeService.addLike(user, product);
+        ProductLike thirdLike = productLikeService.addLike(user, product);
+
+        // then
+        assertThat(firstLike.getId()).isNotNull();
+        assertThat(secondLike.getId()).isEqualTo(firstLike.getId());
+        assertThat(thirdLike.getId()).isEqualTo(firstLike.getId());
+
+        // 좋아요 수는 1번만 증가해야 함
+        assertThat(product.getLikeCount()).isEqualTo(initialLikeCount + 1);
+
+        // DB에는 1개의 좋아요만 존재해야 함
+        boolean exists = productLikeRepository.existsByLikeUserAndLikeProduct(user, product);
+        assertThat(exists).isTrue();
+    }
+
+    @DisplayName("등록된 좋아요를 취소할 수 있다")
+    @Test
+    @Transactional
+    void cancelLike_success() {
+        // given
+        User user = createUser("user123", "user@test.com");
+        Product product = createProduct("P001", "상품1");
+
+        productLikeService.addLike(user, product);
+        Long likeCountAfterAdd = product.getLikeCount();
+
+        // when
+        productLikeService.cancelLike(user, product);
+
+        // then
+        boolean exists = productLikeRepository.existsByLikeUserAndLikeProduct(user, product);
+        assertThat(exists).isFalse();
+        assertThat(product.getLikeCount()).isEqualTo(likeCountAfterAdd - 1);
+    }
+
+    @DisplayName("존재하지 않는 좋아요를 취소하려고 하면 예외가 발생한다")
+    @Test
+    @Transactional
+    void cancelLike_notExists_throwException() {
+        // given
+        User user = createUser("user123", "user@test.com");
+        Product product = createProduct("P001", "상품1");
+
+        // when // then
+        CoreException exception = assertThrows(CoreException.class, () -> {
+            productLikeService.cancelLike(user, product);
+        });
+
+        assertThat(exception.getErrorType()).isEqualTo(ErrorType.NOT_FOUND);
+        assertThat(exception.getCustomMessage()).isEqualTo("좋아요가 존재하지 않습니다");
+    }
+
+    @DisplayName("좋아요를 등록하고 취소한 후 다시 등록할 수 있다")
+    @Test
+    @Transactional
+    void addLike_afterCancel_success() {
+        // given
+        User user = createUser("user123", "user@test.com");
+        Product product = createProduct("P001", "상품1");
+
+        productLikeService.addLike(user, product);
+        productLikeService.cancelLike(user, product);
+
+        entityManager.flush();
+        entityManager.clear();
+
+        // when
+        ProductLike newLike = productLikeService.addLike(user, product);
+
+        // then
+        assertThat(newLike.getId()).isNotNull();
+        assertThat(newLike.getLikeUser().getId()).isEqualTo(user.getId());
+        assertThat(newLike.getLikeProduct().getId()).isEqualTo(product.getId());
+    }
+
+    private User createUser(String userId, String email) {
+        User user = User.createUser(userId, email, "1990-01-01", Gender.MALE);
+        entityManager.persist(user);
+        return user;
+    }
+
+    private Product createProduct(String productCode, String productName) {
+        Brand brand = Brand.createBrand("테스트브랜드");
+        entityManager.persist(brand);
+
+        Product product = Product.createProduct(
+                productCode,
+                productName,
+                Money.of(10000),
+                100,
+                brand
+        );
+        entityManager.persist(product);
+        return product;
+    }
+}
diff --git a/apps/commerce-api/src/test/java/com/loopers/domain/like/ProductLikeTest.java b/apps/commerce-api/src/test/java/com/loopers/domain/like/ProductLikeTest.java
new file mode 100644
index 000000000..e32eaeae9
--- /dev/null
+++ b/apps/commerce-api/src/test/java/com/loopers/domain/like/ProductLikeTest.java
@@ -0,0 +1,91 @@
+package com.loopers.domain.like;
+
+import com.loopers.domain.product.Product;
+import com.loopers.domain.user.User;
+import com.loopers.support.error.CoreException;
+import com.loopers.support.error.ErrorType;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+class ProductLikeTest {
+
+    @DisplayName("좋아요 등록 시 유저 정보는 필수이다.")
+    @Test
+    void whenCreateLikeInvalidUser_throwException() {
+        // given
+        Product mockProduct = mock(Product.class);
+        when(mockProduct.getProductCode()).thenReturn("P001");
+        when(mockProduct.getProductName()).thenReturn("상품1");
+
+        // when // then
+        CoreException result = assertThrows(CoreException.class, () -> {
+            ProductLike like = ProductLike.addLike(null, mockProduct);
+        });
+
+        assertThat(result.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);
+        assertThat(result.getCustomMessage()).isEqualTo("좋아요를 누를 사용자가 필요합니다");
+
+    }
+
+    @DisplayName("좋아요 등록 시 상품 정보는 필수이다.")
+    @Test
+    void whenCreateLikeInvalidProduct_throwException() {
+        // given
+        User mockUser = mock(User.class);
+        when(mockUser.getUserId()).thenReturn("test123");
+        when(mockUser.getEmail()).thenReturn("test123@test.com");
+
+        // when // then
+        CoreException result = assertThrows(CoreException.class, () -> {
+            ProductLike like = ProductLike.addLike(mockUser, null);
+        });
+
+        assertThat(result.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);
+        assertThat(result.getCustomMessage()).isEqualTo("좋아요를 누를 상품이 필요합니다");
+
+    }
+
+    @DisplayName("유저와 상품이 유효하면 좋아요를 등록할 수 있다.")
+    @Test
+    void whenCreateLikeWithValidUserAndProduct_success() {
+        // given
+        User mockUser = mock(User.class);
+        when(mockUser.getUserId()).thenReturn("test123");
+        when(mockUser.getEmail()).thenReturn("test123@test.com");
+
+        Product mockProduct = mock(Product.class);
+        when(mockProduct.getProductCode()).thenReturn("P001");
+        when(mockProduct.getProductName()).thenReturn("상품1");
+
+        // when
+        ProductLike like = ProductLike.addLike(mockUser, mockProduct);
+
+        // then
+        assertThat(like).isNotNull();
+        assertThat(like.getLikeUser()).isEqualTo(mockUser);
+        assertThat(like.getLikeProduct()).isEqualTo(mockProduct);
+        assertThat(like.isSameUserAndProduct(mockUser, mockProduct)).isTrue();
+    }
+
+    @DisplayName("같은 유저가 같은 상품에 중복으로 좋아요를 등록하려고 하면 이미 존재함을 확인할 수 있다.")
+    @Test
+    void whenCheckDuplicateLike_returnTrue() {
+        // given
+        User mockUser = mock(User.class);
+        Product mockProduct = mock(Product.class);
+
+        ProductLike like = ProductLike.addLike(mockUser, mockProduct);
+
+        // when
+        boolean isDuplicate = like.isSameUserAndProduct(mockUser, mockProduct);
+
+        // then
+        assertThat(isDuplicate).isTrue();
+    }
+
+}
diff --git a/apps/commerce-api/src/test/java/com/loopers/domain/order/OrderServiceTest.java b/apps/commerce-api/src/test/java/com/loopers/domain/order/OrderServiceTest.java
new file mode 100644
index 000000000..e09012971
--- /dev/null
+++ b/apps/commerce-api/src/test/java/com/loopers/domain/order/OrderServiceTest.java
@@ -0,0 +1,175 @@
+package com.loopers.domain.order;
+
+import com.loopers.domain.Money;
+import com.loopers.domain.brand.Brand;
+import com.loopers.domain.product.Product;
+import com.loopers.domain.product.Stock;
+import com.loopers.domain.user.Gender;
+import com.loopers.domain.user.User;
+import com.loopers.domain.user.UserRepository;
+import com.loopers.utils.DatabaseCleanUp;
+import jakarta.persistence.EntityManager;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertAll;
+
+@ActiveProfiles("test")
+@SpringBootTest
+class OrderServiceTest {
+
+    @Autowired
+    private OrderService orderService;
+
+    @Autowired
+    private UserRepository userRepository;
+
+    @Autowired
+    private DatabaseCleanUp databaseCleanUp;
+
+    @Autowired
+    private EntityManager entityManager;
+
+    @AfterEach
+    void tearDown() {
+        databaseCleanUp.truncateAllTables();
+    }
+
+    @DisplayName("주문 생성 시 상품의 재고를 차감한다.")
+    @Test
+    @Transactional
+    void createOrder_decreaseStock_success() {
+        // given
+        User user = User.createUser("testUser", "test@test.com", "1990-01-01", Gender.MALE);
+        user.chargePoint(Money.of(100000));
+        entityManager.persist(user);
+
+        Brand brand = Brand.createBrand("테스트브랜드");
+        entityManager.persist(brand);
+
+        Product product = Product.createProduct("P001", "테스트상품", Money.of(25000), 100, brand);
+        entityManager.persist(product);
+
+        Map<Product, Integer> productQuantities = new HashMap<>();
+        productQuantities.put(product, 3);
+
+        // when
+        orderService.createOrder(user, productQuantities);
+
+        entityManager.flush();
+        entityManager.clear();
+
+        // then
+        Product productAfterOrder = entityManager.find(Product.class, product.getId());
+        assertThat(productAfterOrder.getStock()).isEqualTo(Stock.of(97)); // 100 - 3
+    }
+
+    @DisplayName("주문 생성 시 사용자의 포인트를 차감한다.")
+    @Test
+    @Transactional
+    void createOrder_usePoint_success() {
+        // given
+        User user = User.createUser("testUser", "test@test.com", "1990-01-01", Gender.MALE);
+        user.chargePoint(Money.of(100000));
+        entityManager.persist(user);
+
+        Brand brand = Brand.createBrand("테스트브랜드");
+        entityManager.persist(brand);
+
+        Product product = Product.createProduct("P001", "테스트상품", Money.of(25000), 100, brand);
+        entityManager.persist(product);
+
+        Map<Product, Integer> productQuantities = new HashMap<>();
+        productQuantities.put(product, 2); // 25000 * 2 = 50000
+
+        // when
+        orderService.createOrder(user, productQuantities);
+
+        entityManager.flush();
+        entityManager.clear();
+
+        // then
+        User userAfterOrder = entityManager.find(User.class, user.getId());
+        assertThat(userAfterOrder.getPoint().getAmount()).isEqualByComparingTo(BigDecimal.valueOf(50000)); // 100000 - 50000
+    }
+
+    @DisplayName("주문 생성 시 여러 상품의 재고와 포인트를 차감한다.")
+    @Test
+    @Transactional
+    void createOrder_withMultipleProducts_success() {
+        // given
+        User user = User.createUser("testUser", "test@test.com", "1990-01-01", Gender.MALE);
+        user.chargePoint(Money.of(200000));
+        entityManager.persist(user);
+
+        Brand brand = Brand.createBrand("테스트브랜드");
+        entityManager.persist(brand);
+
+        Product product1 = Product.createProduct("P001", "상품1", Money.of(25000), 100, brand);
+        Product product2 = Product.createProduct("P002", "상품2", Money.of(10000), 50, brand);
+        entityManager.persist(product1);
+        entityManager.persist(product2);
+
+        Map<Product, Integer> productQuantities = new HashMap<>();
+        productQuantities.put(product1, 2); // 25000 * 2 = 50000
+        productQuantities.put(product2, 3); // 10000 * 3 = 30000
+        // 총 80000원
+
+        // when
+        orderService.createOrder(user, productQuantities);
+
+        entityManager.flush();
+        entityManager.clear();
+
+        // then
+        User userAfterOrder = entityManager.find(User.class, user.getId());
+        Product product1AfterOrder = entityManager.find(Product.class, product1.getId());
+        Product product2AfterOrder = entityManager.find(Product.class, product2.getId());
+
+        assertAll(
+                () -> assertThat(userAfterOrder.getPoint().getAmount()).isEqualByComparingTo(Money.of(120000).getAmount()), // 200000 - 80000
+                () -> assertThat(product1AfterOrder.getStock()).isEqualTo(Stock.of(98)), // 100 - 2
+                () -> assertThat(product2AfterOrder.getStock()).isEqualTo(Stock.of(47)) // 50 - 3
+        );
+    }
+
+    @DisplayName("주문이 정상적으로 저장된다.")
+    @Test
+    @Transactional
+    void createOrder_saveOrder_success() {
+        // given
+        User user = User.createUser("testUser", "test@test.com", "1990-01-01", Gender.MALE);
+        user.chargePoint(Money.of(100000));
+        entityManager.persist(user);
+
+        Brand brand = Brand.createBrand("테스트브랜드");
+        entityManager.persist(brand);
+
+        Product product = Product.createProduct("P001", "테스트상품", Money.of(25000), 100, brand);
+        entityManager.persist(product);
+
+        Map<Product, Integer> productQuantities = new HashMap<>();
+        productQuantities.put(product, 1);
+
+        // when
+        Order order = orderService.createOrder(user, productQuantities);
+
+        // then
+        assertAll(
+                () -> assertThat(order.getId()).isNotNull(),
+                () -> assertThat(order.getStatus()).isEqualTo(OrderStatus.INIT),
+                () -> assertThat(order.getTotalPrice().getAmount()).isEqualByComparingTo(BigDecimal.valueOf(25000)),
+                () -> assertThat(order.getOrderProducts()).hasSize(1)
+        );
+    }
+}
diff --git a/apps/commerce-api/src/test/java/com/loopers/domain/order/OrderTest.java b/apps/commerce-api/src/test/java/com/loopers/domain/order/OrderTest.java
new file mode 100644
index 000000000..5467be362
--- /dev/null
+++ b/apps/commerce-api/src/test/java/com/loopers/domain/order/OrderTest.java
@@ -0,0 +1,214 @@
+package com.loopers.domain.order;
+
+import com.loopers.domain.Money;
+import com.loopers.domain.product.Product;
+import com.loopers.domain.product.Stock;
+import com.loopers.domain.user.User;
+import com.loopers.support.error.CoreException;
+import com.loopers.support.error.ErrorType;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.*;
+
+class OrderTest {
+
+    @DisplayName("주문 생성 시 주문 상태는 INIT(주문생성) 이다.")
+    @Test
+    void createOrderWithExisistProduct_returnOrder() {
+        // given
+        User mockUser = mock(User.class);
+        when(mockUser.getPoint()).thenReturn(Money.of(100000));
+
+        Product mockProduct = mock(Product.class);
+        when(mockProduct.getPrice()).thenReturn(Money.of(25000));
+        when(mockProduct.getStock()).thenReturn(Stock.of(100));
+
+        Map<Product, Integer> productQuantities = new HashMap<>();
+        productQuantities.put(mockProduct, 1);
+
+        // when
+        Order order = Order.createOrder(mockUser, productQuantities);
+
+        // then
+        assertThat(order.getStatus()).isEqualTo(OrderStatus.INIT);
+    }
+
+    @DisplayName("주문 생성 시 상품 리스트와 수량에서 주문의 총 금액을 계산한다.")
+    @Test
+    void createOrderWithExisistProduct_returnTotalPrice() {
+        // given
+        User mockUser = mock(User.class);
+        when(mockUser.getPoint()).thenReturn(Money.of(100000));
+
+        Product mockProduct1 = mock(Product.class);
+        when(mockProduct1.getPrice()).thenReturn(Money.of(25000));
+        when(mockProduct1.getStock()).thenReturn(Stock.of(100));
+
+        Product mockProduct2 = mock(Product.class);
+        when(mockProduct2.getPrice()).thenReturn(Money.of(10000));
+        when(mockProduct2.getStock()).thenReturn(Stock.of(100));
+
+        Map<Product, Integer> productQuantities = new HashMap<>();
+        productQuantities.put(mockProduct1, 1); // 25000 * 1 = 25000
+        productQuantities.put(mockProduct2, 2); // 10000 * 2 = 20000
+
+        // when
+        Order order = Order.createOrder(mockUser, productQuantities);
+
+        // then
+        assertThat(order.getTotalPrice().getAmount()).isEqualByComparingTo(BigDecimal.valueOf(45000));
+    }
+
+    @DisplayName("생성된 주문의 상태를 변경할 수 있다.")
+    @Test
+    void changeOrderStatus_success() {
+        // given
+        User mockUser = mock(User.class);
+        when(mockUser.getPoint()).thenReturn(Money.of(100000));
+
+        Product mockProduct = mock(Product.class);
+        when(mockProduct.getPrice()).thenReturn(Money.of(25000));
+        when(mockProduct.getStock()).thenReturn(Stock.of(100));
+
+        Map<Product, Integer> productQuantities = new HashMap<>();
+        productQuantities.put(mockProduct, 1);
+
+        Order order = Order.createOrder(mockUser, productQuantities);
+
+        // when
+        order.updateStatus(OrderStatus.COMPLETED);
+
+        // then
+        assertThat(order.getStatus()).isEqualTo(OrderStatus.COMPLETED);
+    }
+
+    @DisplayName("주문 생성 시 사용자는 필수다.")
+    @Test
+    void createOrderWithoutUser_throwException() {
+        // given
+        Product mockProduct = mock(Product.class);
+        when(mockProduct.getPrice()).thenReturn(Money.of(25000));
+
+        Map<Product, Integer> productQuantities = new HashMap<>();
+        productQuantities.put(mockProduct, 1);
+
+        // when // then
+        CoreException exception = assertThrows(CoreException.class, () ->
+            Order.createOrder(null, productQuantities)
+        );
+
+        assertThat(exception.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);
+        assertThat(exception.getCustomMessage()).isEqualTo("사용자는 필수입니다");
+    }
+
+    @DisplayName("주문 생성 시 상품은 필수다.")
+    @Test
+    void createOrderWithoutProducts_throwException() {
+        // given
+        User mockUser = mock(User.class);
+
+        // when // then
+        CoreException exception = assertThrows(CoreException.class, () ->
+            Order.createOrder(mockUser, null)
+        );
+
+        assertThat(exception.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);
+        assertThat(exception.getCustomMessage()).isEqualTo("주문 상품은 필수입니다");
+    }
+
+    @DisplayName("주문 생성 시 상품 목록이 비어있으면 예외가 발생한다.")
+    @Test
+    void createOrderWithEmptyProducts_throwException() {
+        // given
+        User mockUser = mock(User.class);
+        Map<Product, Integer> emptyProducts = new HashMap<>();
+
+        // when // then
+        CoreException exception = assertThrows(CoreException.class, () ->
+            Order.createOrder(mockUser, emptyProducts)
+        );
+
+        assertThat(exception.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);
+        assertThat(exception.getCustomMessage()).isEqualTo("주문 상품은 필수입니다");
+    }
+
+    @DisplayName("주문 상태 변경 시 상태는 필수다.")
+    @Test
+    void updateOrderStatusWithNull_throwException() {
+        // given
+        User mockUser = mock(User.class);
+        when(mockUser.getPoint()).thenReturn(Money.of(100000));
+
+        Product mockProduct = mock(Product.class);
+        when(mockProduct.getPrice()).thenReturn(Money.of(25000));
+        when(mockProduct.getStock()).thenReturn(Stock.of(100));
+
+        Map<Product, Integer> productQuantities = new HashMap<>();
+        productQuantities.put(mockProduct, 1);
+
+        Order order = Order.createOrder(mockUser, productQuantities);
+
+        // when // then
+        CoreException exception = assertThrows(CoreException.class, () ->
+            order.updateStatus(null)
+        );
+
+        assertThat(exception.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);
+        assertThat(exception.getCustomMessage()).isEqualTo("주문 상태는 필수입니다");
+    }
+
+    @DisplayName("주문 생성 시 재고가 부족하면 예외가 발생한다.")
+    @Test
+    void createOrder_withInsufficientStock_throwException() {
+        // given
+        User mockUser = mock(User.class);
+        when(mockUser.getPoint()).thenReturn(Money.of(500000)); // 충분한 포인트
+
+        Product mockProduct = mock(Product.class);
+        when(mockProduct.getPrice()).thenReturn(Money.of(25000));
+        when(mockProduct.getStock()).thenReturn(Stock.of(5)); // 재고 5개
+        when(mockProduct.getProductName()).thenReturn("테스트상품");
+
+        Map<Product, Integer> productQuantities = new HashMap<>();
+        productQuantities.put(mockProduct, 10); // 10개 주문 (250000원)
+
+        // when // then
+        CoreException exception = assertThrows(CoreException.class, () ->
+            Order.createOrder(mockUser, productQuantities)
+        );
+
+        assertThat(exception.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);
+        assertThat(exception.getCustomMessage()).contains("재고가 부족합니다");
+    }
+
+    @DisplayName("주문 생성 시 포인트가 부족하면 예외가 발생한다.")
+    @Test
+    void createOrder_withInsufficientPoint_throwException() {
+        // given
+        User mockUser = mock(User.class);
+        when(mockUser.getPoint()).thenReturn(Money.of(10000)); // 포인트 10000
+
+        Product mockProduct = mock(Product.class);
+        when(mockProduct.getPrice()).thenReturn(Money.of(25000));
+        when(mockProduct.getStock()).thenReturn(Stock.of(100));
+
+        Map<Product, Integer> productQuantities = new HashMap<>();
+        productQuantities.put(mockProduct, 1); // 25000원 필요
+
+        // when // then
+        CoreException exception = assertThrows(CoreException.class, () ->
+            Order.createOrder(mockUser, productQuantities)
+        );
+
+        assertThat(exception.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);
+        assertThat(exception.getCustomMessage()).contains("포인트가 부족합니다");
+    }
+
+}
diff --git a/apps/commerce-api/src/test/java/com/loopers/domain/orderproduct/OrderProductTest.java b/apps/commerce-api/src/test/java/com/loopers/domain/orderproduct/OrderProductTest.java
new file mode 100644
index 000000000..3e7a0da51
--- /dev/null
+++ b/apps/commerce-api/src/test/java/com/loopers/domain/orderproduct/OrderProductTest.java
@@ -0,0 +1,173 @@
+package com.loopers.domain.orderproduct;
+
+import com.loopers.domain.Money;
+import com.loopers.domain.order.Order;
+import com.loopers.domain.product.Product;
+import com.loopers.support.error.CoreException;
+import com.loopers.support.error.ErrorType;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.math.BigDecimal;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+class OrderProductTest {
+
+    @DisplayName("OrderProduct를 정상적으로 생성할 수 있다.")
+    @Test
+    void createOrderProduct_withValidInputs_success() {
+        // given
+        Order mockOrder = mock(Order.class);
+        Product mockProduct = mock(Product.class);
+        when(mockProduct.getPrice()).thenReturn(Money.of(10000));
+        int quantity = 2;
+
+        // when
+        OrderProduct orderProduct = new OrderProduct(mockOrder, mockProduct, quantity);
+
+        // then
+        assertThat(orderProduct.getOrder()).isEqualTo(mockOrder);
+        assertThat(orderProduct.getProduct()).isEqualTo(mockProduct);
+        assertThat(orderProduct.getQuantity()).isEqualTo(2);
+    }
+
+    @DisplayName("OrderProduct 생성 시 상품의 가격이 price에 저장된다.")
+    @Test
+    void createOrderProduct_setPriceFromProduct() {
+        // given
+        Order mockOrder = mock(Order.class);
+        Product mockProduct = mock(Product.class);
+        when(mockProduct.getPrice()).thenReturn(Money.of(15000));
+        int quantity = 1;
+
+        // when
+        OrderProduct orderProduct = new OrderProduct(mockOrder, mockProduct, quantity);
+
+        // then
+        assertThat(orderProduct.getPrice()).isEqualTo(Money.of(15000));
+    }
+
+    @DisplayName("OrderProduct 생성 시 총 금액을 정확히 계산한다.")
+    @Test
+    void createOrderProduct_calculateTotalPrice_correctly() {
+        // given
+        Order mockOrder = mock(Order.class);
+        Product mockProduct = mock(Product.class);
+        when(mockProduct.getPrice()).thenReturn(Money.of(10000));
+        int quantity = 2;
+
+        // when
+        OrderProduct orderProduct = new OrderProduct(mockOrder, mockProduct, quantity);
+
+        // then
+        // 10000 * 2 = 20000
+        assertThat(orderProduct.getTotalPrice()).isEqualTo(Money.of(20000));
+    }
+
+    @DisplayName("OrderProduct 생성 시 여러 개 수량의 총 금액을 정확히 계산한다.")
+    @Test
+    void createOrderProduct_withMultipleQuantity_calculateCorrectly() {
+        // given
+        Order mockOrder = mock(Order.class);
+        Product mockProduct = mock(Product.class);
+        when(mockProduct.getPrice()).thenReturn(Money.of(7500));
+        int quantity = 5;
+
+        // when
+        OrderProduct orderProduct = new OrderProduct(mockOrder, mockProduct, quantity);
+
+        // then
+        // 7500 * 5 = 37500
+        assertThat(orderProduct.getTotalPrice()).isEqualTo(Money.of(37500));
+    }
+
+    @DisplayName("Order가 null이면 예외가 발생한다.")
+    @Test
+    void createOrderProduct_withNullOrder_throwException() {
+        // given
+        Product mockProduct = mock(Product.class);
+        when(mockProduct.getPrice()).thenReturn(Money.of(10000));
+        int quantity = 1;
+
+        // when // then
+        CoreException exception = assertThrows(CoreException.class, () ->
+            new OrderProduct(null, mockProduct, quantity)
+        );
+
+        assertThat(exception.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);
+        assertThat(exception.getCustomMessage()).isEqualTo("주문은 필수입니다");
+    }
+
+    @DisplayName("Product가 null이면 예외가 발생한다.")
+    @Test
+    void createOrderProduct_withNullProduct_throwException() {
+        // given
+        Order mockOrder = mock(Order.class);
+        int quantity = 1;
+
+        // when // then
+        CoreException exception = assertThrows(CoreException.class, () ->
+            new OrderProduct(mockOrder, null, quantity)
+        );
+
+        assertThat(exception.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);
+        assertThat(exception.getCustomMessage()).isEqualTo("상품은 필수입니다");
+    }
+
+    @DisplayName("수량이 0이면 예외가 발생한다.")
+    @Test
+    void createOrderProduct_withZeroQuantity_throwException() {
+        // given
+        Order mockOrder = mock(Order.class);
+        Product mockProduct = mock(Product.class);
+        when(mockProduct.getPrice()).thenReturn(Money.of(10000));
+        int quantity = 0;
+
+        // when // then
+        CoreException exception = assertThrows(CoreException.class, () ->
+            new OrderProduct(mockOrder, mockProduct, quantity)
+        );
+
+        assertThat(exception.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);
+        assertThat(exception.getCustomMessage()).isEqualTo("수량은 1개 이상이어야 합니다");
+    }
+
+    @DisplayName("수량이 음수이면 예외가 발생한다.")
+    @Test
+    void createOrderProduct_withNegativeQuantity_throwException() {
+        // given
+        Order mockOrder = mock(Order.class);
+        Product mockProduct = mock(Product.class);
+        when(mockProduct.getPrice()).thenReturn(Money.of(10000));
+        int quantity = -1;
+
+        // when // then
+        CoreException exception = assertThrows(CoreException.class, () ->
+            new OrderProduct(mockOrder, mockProduct, quantity)
+        );
+
+        assertThat(exception.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);
+        assertThat(exception.getCustomMessage()).isEqualTo("수량은 1개 이상이어야 합니다");
+    }
+
+    @DisplayName("수량이 1일 때 정상적으로 생성된다.")
+    @Test
+    void createOrderProduct_withQuantityOne_success() {
+        // given
+        Order mockOrder = mock(Order.class);
+        Product mockProduct = mock(Product.class);
+        when(mockProduct.getPrice()).thenReturn(Money.of(12000));
+        int quantity = 1;
+
+        // when
+        OrderProduct orderProduct = new OrderProduct(mockOrder, mockProduct, quantity);
+
+        // then
+        assertThat(orderProduct.getQuantity()).isEqualTo(1);
+        assertThat(orderProduct.getTotalPrice()).isEqualTo(Money.of(12000));
+    }
+}
diff --git a/apps/commerce-api/src/test/java/com/loopers/domain/product/ProductServiceTest.java b/apps/commerce-api/src/test/java/com/loopers/domain/product/ProductServiceTest.java
new file mode 100644
index 000000000..38c7f4328
--- /dev/null
+++ b/apps/commerce-api/src/test/java/com/loopers/domain/product/ProductServiceTest.java
@@ -0,0 +1,345 @@
+package com.loopers.domain.product;
+
+import com.loopers.domain.Money;
+import com.loopers.domain.brand.Brand;
+import com.loopers.support.error.CoreException;
+import com.loopers.support.error.ErrorType;
+import com.loopers.utils.DatabaseCleanUp;
+import jakarta.persistence.EntityManager;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+@ActiveProfiles("test")
+@SpringBootTest
+class ProductServiceTest {
+
+    @Autowired
+    private ProductService productService;
+
+    @Autowired
+    private ProductRepository productRepository;
+
+    @Autowired
+    private DatabaseCleanUp databaseCleanUp;
+
+    @Autowired
+    private EntityManager entityManager;
+
+    @AfterEach
+    void tearDown() {
+        databaseCleanUp.truncateAllTables();
+    }
+
+    @DisplayName("상품 코드, 상품명, 가격, 수량, 브랜드를 입력받아, 상품을 등록한다.")
+    @Test
+    @Transactional
+    void whenRegisterProduct_thenSuccess() {
+
+        // given
+        Brand brand = Brand.createBrand("리바이스");
+        entityManager.persist(brand);
+
+        String productCode = "P001";
+        String productName = "청바지";
+        BigDecimal price = Money.of(25000).getAmount();
+        int stock = 200;
+
+        // when
+        Product productResponse = productService.registerProduct(
+                        productCode, productName, price, stock, brand
+                );
+
+        // then
+        assertAll(
+                () -> assertThat(productResponse.getProductCode()).isEqualTo("P001"),
+                () -> assertThat(productResponse.getProductName()).isEqualTo("청바지"),
+                () -> assertThat(productResponse.getPrice().getAmount()).isEqualByComparingTo(Money.of(25000).getAmount()),
+                () -> assertThat(productResponse.getStock()).isEqualTo(Stock.of(200)),
+                () -> assertThat(productResponse.getBrand()).isNotNull(),
+                () -> assertThat(productResponse.getBrand().getBrandName()).isEqualTo("리바이스")
+        );
+    }
+
+    @DisplayName("이미 존재하는 상품 코드는 등록에 실패한다.")
+    @Test
+    @Transactional
+    void whenRegisterProductWithDuplicateCode_thenBadRequest() {
+
+        // given
+        Brand brand = Brand.createBrand("리바이스");
+        entityManager.persist(brand);
+
+        String productCode1 = "P001";
+        String productName1 = "청바지";
+        BigDecimal price1 = Money.of(25000).getAmount();
+        int stock1 = 200;
+
+        String productCode2 = "P001";
+        String productName2 = "청바지";
+        BigDecimal price2 = Money.of(25000).getAmount();
+        int stock2 = 100;
+
+        // when
+        productService.registerProduct(productCode1, productName1, price1, stock1, brand);
+
+        // then
+        CoreException result = assertThrows(CoreException.class, () -> {
+            productService.registerProduct(productCode2, productName2, price2, stock2, brand);
+        });
+
+        assertThat(result.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);
+        assertThat(result.getCustomMessage()).isEqualTo("중복된 상품 코드 오류");
+    }
+
+    @DisplayName("정렬 조건이 null인 경우, 기본값(최신순)으로 상품 목록을 조회한다.")
+    @Test
+    @Transactional
+    void whenGetProductsWithNullSortType_thenReturnLatestOrder() {
+        // given
+        Brand brand = Brand.createBrand("테스트브랜드");
+        entityManager.persist(brand);
+
+        productService.registerProduct("P001", "상품1", Money.of(10000).getAmount(), 10, brand);
+        productService.registerProduct("P002", "상품2", Money.of(20000).getAmount(), 20, brand);
+        productService.registerProduct("P003", "상품3", Money.of(15000).getAmount(), 15, brand);
+
+        // when
+        List<Product> products = productService.getProducts(null);
+
+        // then
+        assertThat(products).isNotEmpty();
+        assertThat(products.size()).isEqualTo(3);
+    }
+
+    @DisplayName("LATEST 정렬 조건으로 상품 목록을 최신순으로 조회한다.")
+    @Test
+    @Transactional
+    void whenGetProductsWithLatest_thenReturnLatestOrder() {
+        // given
+        Brand brand = Brand.createBrand("테스트브랜드");
+        entityManager.persist(brand);
+
+        productService.registerProduct("P001", "상품1", Money.of(10000).getAmount(), 10, brand);
+        productService.registerProduct("P002", "상품2", Money.of(20000).getAmount(), 20, brand);
+        productService.registerProduct("P003", "상품3", Money.of(15000).getAmount(), 15, brand);
+
+        // when
+        List<Product> products = productService.getProducts(ProductSortType.LATEST);
+
+        // then
+        assertThat(products).isNotEmpty();
+        assertThat(products).hasSize(3);
+        // 최신순이므로 P003, P002, P001 순서
+        assertThat(products.get(0).getProductCode()).isEqualTo("P003");
+        assertThat(products.get(1).getProductCode()).isEqualTo("P002");
+        assertThat(products.get(2).getProductCode()).isEqualTo("P001");
+    }
+
+    @DisplayName("PRICE_ASC 정렬 조건으로 상품 목록을 가격 낮은 순으로 조회한다.")
+    @Test
+    @Transactional
+    void whenGetProductsWithPriceAsc_thenReturnPriceAscOrder() {
+        // given
+        Brand brand = Brand.createBrand("테스트브랜드");
+        entityManager.persist(brand);
+
+        productService.registerProduct("P001", "상품1", Money.of(30000).getAmount(), 10, brand);
+        productService.registerProduct("P002", "상품2", Money.of(10000).getAmount(), 20, brand);
+        productService.registerProduct("P003", "상품3", Money.of(20000).getAmount(), 15, brand);
+
+        // when
+        List<Product> products = productService.getProducts(ProductSortType.PRICE_ASC);
+
+        // then
+        assertThat(products).isNotEmpty();
+        assertThat(products.size()).isEqualTo(3);
+        // 가격 낮은 순이므로 P002(10000), P003(20000), P001(30000) 순서
+        assertThat(products.get(0).getProductCode()).isEqualTo("P002");
+        assertThat(products.get(0).getPrice()).isEqualTo(Money.of(10000));
+        assertThat(products.get(1).getProductCode()).isEqualTo("P003");
+        assertThat(products.get(1).getPrice()).isEqualTo(Money.of(20000));
+        assertThat(products.get(2).getProductCode()).isEqualTo("P001");
+        assertThat(products.get(2).getPrice()).isEqualTo(Money.of(30000));
+    }
+
+    @DisplayName("LIKES_DESC 정렬 조건으로 상품 목록을 좋아요 많은 순으로 조회한다.")
+    @Test
+    @Transactional
+    void whenGetProductsWithLikesDesc_thenReturnLikesDescOrder() {
+        // given
+        Brand brand = Brand.createBrand("테스트브랜드");
+        entityManager.persist(brand);
+
+        productService.registerProduct("P001", "상품1", Money.of(10000).getAmount(), 10, brand);
+        productService.registerProduct("P002", "상품2", Money.of(20000).getAmount(), 20, brand);
+        productService.registerProduct("P003", "상품3", Money.of(15000).getAmount(), 15, brand);
+
+        // when
+        List<Product> products = productService.getProducts(ProductSortType.LIKES_DESC);
+
+        // then
+        assertThat(products).isNotEmpty();
+        assertThat(products.size()).isEqualTo(3);
+        // 좋아요 많은 순 (초기 좋아요는 모두 0이므로 조회만 확인)
+    }
+
+    @DisplayName("상품 목록 조회 시 삭제된 상품은 제외된다.")
+    @Test
+    @Transactional
+    void whenGetProducts_thenExcludeDeletedProducts() {
+        // given
+        Brand brand = Brand.createBrand("테스트브랜드");
+        entityManager.persist(brand);
+
+        Product product1 = productService.registerProduct("P001", "상품1", Money.of(10000).getAmount(), 10, brand);
+        productService.registerProduct("P002", "상품2", Money.of(20000).getAmount(), 20, brand);
+        productService.registerProduct("P003", "상품3", Money.of(15000).getAmount(), 15, brand);
+
+        // 상품1 삭제
+        product1.delete();
+
+        // DB에 삭제 상태 반영 및 영속성 컨텍스트 초기화
+        entityManager.flush();
+        entityManager.clear();
+
+        // when
+        List<Product> products = productService.getProducts(ProductSortType.LATEST);
+
+        // then
+        // 삭제되지 않은 상품만 조회되어야 함
+        assertThat(products).isNotEmpty()
+                .hasSize(2)
+                .noneMatch(p -> p.getProductCode().equals("P001"));
+    }
+
+    @DisplayName("상품 ID로 상세 정보를 조회한다 (Brand 정보 포함).")
+    @Test
+    @Transactional
+    void whenGetProductDetailWithBrand_thenSuccess() {
+        // given
+        Brand brand = Brand.createBrand("나이키");
+        entityManager.persist(brand);
+
+        Product product = Product.createProduct(
+                "P001",
+                "에어맥스",
+                Money.of(150000),
+                50,
+                brand
+        );
+        Product savedProduct = productRepository.registerProduct(product);
+
+        entityManager.flush();
+        entityManager.clear();
+
+        // when
+        Product result = productService.getProductDetail(savedProduct.getId());
+
+        // then
+        assertAll(
+                () -> assertThat(result.getId()).isEqualTo(savedProduct.getId()),
+                () -> assertThat(result.getProductCode()).isEqualTo("P001"),
+                () -> assertThat(result.getProductName()).isEqualTo("에어맥스"),
+                () -> assertThat(result.getPrice().getAmount()).isEqualByComparingTo(Money.of(150000).getAmount()),
+                () -> assertThat(result.getStock()).isEqualTo(Stock.of(50)),
+                () -> assertThat(result.getBrand()).isNotNull(),
+                () -> assertThat(result.getBrand().getBrandName()).isEqualTo("나이키")
+        );
+    }
+
+    @DisplayName("상품 ID로 상세 정보를 조회한다 (ProductLike 정보 포함).")
+    @Test
+    @Transactional
+    void whenGetProductDetailWithProductLikes_thenSuccess() {
+        // given
+        Brand brand = Brand.createBrand("아디다스");
+        entityManager.persist(brand);
+
+        Product product = Product.createProduct(
+                "P002",
+                "슈퍼스타",
+                Money.of(120000),
+                100,
+                brand
+        );
+        Product savedProduct = productRepository.registerProduct(product);
+
+        entityManager.flush();
+        entityManager.clear();
+
+        // when
+        Product result = productService.getProductDetail(savedProduct.getId());
+
+        // then
+        assertAll(
+                () -> assertThat(result.getId()).isEqualTo(savedProduct.getId()),
+                () -> assertThat(result.getProductCode()).isEqualTo("P002"),
+                () -> assertThat(result.getProductName()).isEqualTo("슈퍼스타"),
+                () -> assertThat(result.getPrice().getAmount()).isEqualByComparingTo(Money.of(120000).getAmount()),
+                () -> assertThat(result.getStock()).isEqualTo(Stock.of(100)),
+                () -> assertThat(result.getBrand()).isNotNull(),
+                () -> assertThat(result.getBrand().getBrandName()).isEqualTo("아디다스"),
+                () -> assertThat(result.getProductLikes()).isNotNull(),
+                () -> assertThat(result.getProductLikes()).isEmpty()
+        );
+    }
+
+    @DisplayName("존재하지 않는 상품 ID로 조회 시 NOT_FOUND 예외가 발생한다.")
+    @Test
+    void whenGetProductDetailWithInvalidId_thenNotFound() {
+        // given
+        Long invalidProductId = 99999L;
+
+        // when // then
+        CoreException exception = assertThrows(CoreException.class, () -> {
+            productService.getProductDetail(invalidProductId);
+        });
+
+        assertThat(exception.getErrorType()).isEqualTo(ErrorType.NOT_FOUND);
+        assertThat(exception.getCustomMessage()).isEqualTo("상품을 찾을 수 없습니다");
+    }
+
+    @DisplayName("삭제된 상품 조회 시 NOT_FOUND 예외가 발생한다.")
+    @Test
+    @Transactional
+    void whenGetProductDetailWithDeletedProduct_thenNotFound() {
+        // given
+        Brand brand = Brand.createBrand("테스트브랜드");
+        entityManager.persist(brand);
+
+        Product product = Product.createProduct(
+                "P003",
+                "삭제될 상품",
+                Money.of(20000),
+                30,
+                brand
+        );
+        Product savedProduct = productRepository.registerProduct(product);
+
+        // 상품 삭제
+        savedProduct.delete();
+
+        entityManager.flush();
+        entityManager.clear();
+
+        // when // then
+        CoreException exception = assertThrows(CoreException.class, () -> {
+            productService.getProductDetail(savedProduct.getId());
+        });
+
+        assertThat(exception.getErrorType()).isEqualTo(ErrorType.NOT_FOUND);
+        assertThat(exception.getCustomMessage()).isEqualTo("상품을 찾을 수 없습니다");
+    }
+}
diff --git a/apps/commerce-api/src/test/java/com/loopers/domain/product/ProductTest.java b/apps/commerce-api/src/test/java/com/loopers/domain/product/ProductTest.java
new file mode 100644
index 000000000..8b0e074ee
--- /dev/null
+++ b/apps/commerce-api/src/test/java/com/loopers/domain/product/ProductTest.java
@@ -0,0 +1,189 @@
+package com.loopers.domain.product;
+
+import com.loopers.domain.Money;
+import com.loopers.domain.brand.Brand;
+import com.loopers.support.error.CoreException;
+import com.loopers.support.error.ErrorType;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.math.BigDecimal;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class ProductTest {
+
+    @DisplayName("상품 코드는 필수값이다.")
+    @Test
+    void whenRegisterProductInvalidCode_throwBadRequest() {
+
+        Brand brand = Brand.createBrand("테스트브랜드");
+        String productName = "상품1";
+        BigDecimal price = BigDecimal.valueOf(25000);
+        int stock = 100;
+
+        CoreException result = assertThrows(CoreException.class, () -> {
+            Product.createProduct(null, productName, Money.of(price), stock, brand);
+        });
+
+        assertThat(result.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);
+        assertThat(result.getCustomMessage()).isEqualTo("상품 코드는 필수값입니다");
+
+    }
+
+    @DisplayName("상품의 이름은 필수값이다.")
+    @Test
+    void whenRegisterProductInvalidName_throwBadRequest() {
+
+        Brand brand = Brand.createBrand("테스트브랜드");
+        String productCode = "P001";
+        BigDecimal price = BigDecimal.valueOf(25000);
+        int stock = 100;
+
+        CoreException result = assertThrows(CoreException.class, () -> {
+            Product.createProduct(productCode, null, Money.of(price), stock, brand);
+        });
+
+        assertThat(result.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);
+        assertThat(result.getCustomMessage()).isEqualTo("상품 이름은 필수값입니다");
+
+    }
+
+    @DisplayName("상품의 가격은 0보다 큰 정수여야 한다.")
+    @Test
+    void whenRegisterProductInvalidPrice_throwBadRequest() {
+
+        Brand brand = Brand.createBrand("테스트브랜드");
+        String productCode = "P001";
+        String productName = "상품1";
+        BigDecimal price = BigDecimal.valueOf(-1);
+        int stock = 100;
+
+        CoreException result = assertThrows(CoreException.class, () -> {
+            Product.createProduct(productCode, productName, Money.of(price), stock, brand);
+        });
+
+        assertThat(result.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);
+        assertThat(result.getCustomMessage()).isEqualTo("금액은 0보다 작을 수 없습니다");
+
+    }
+
+    @DisplayName("상품 재고는 0 이상의 정수여야 한다.")
+    @Test
+    void whenRegisterProductInvalidStock_throwBadRequest() {
+
+        Brand brand = Brand.createBrand("테스트브랜드");
+        String productCode = "P001";
+        String productName = "상품1";
+        BigDecimal price = BigDecimal.valueOf(25000);
+
+        CoreException result = assertThrows(CoreException.class, () -> {
+            Product.createProduct(productCode, productName, Money.of(price), -1, brand);
+        });
+
+        assertThat(result.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);
+        assertThat(result.getCustomMessage()).isEqualTo("상품 재고는 음수일 수 없습니다");
+
+    }
+
+    @DisplayName("브랜드는 필수값이다.")
+    @Test
+    void whenRegisterProductWithoutBrand_throwBadRequest() {
+
+        String productCode = "P001";
+        String productName = "상품1";
+        BigDecimal price = BigDecimal.valueOf(25000);
+        int stock = 100;
+
+        CoreException result = assertThrows(CoreException.class, () -> {
+            Product.createProduct(productCode, productName, Money.of(price), stock, null);
+        });
+
+        assertThat(result.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);
+        assertThat(result.getCustomMessage()).isEqualTo("브랜드는 필수입니다");
+
+    }
+
+    @Test
+    @DisplayName("재고를 증가시킬 수 있다")
+    void whenIncreaseStock_shouldIncreaseStockAmount() {
+        Brand brand = Brand.createBrand("테스트브랜드");
+        Product product = Product.createProduct("P001", "Shoes",
+                Money.of(10000), 10, brand);
+
+        product.increaseStock(5);
+
+        assertThat(product.getStock()).isEqualTo(Stock.of(15));
+    }
+
+    @Test
+    @DisplayName("재고 증가량이 음수이면 예외가 발생한다")
+    void whenIncreaseStock_withNegativeAmount_shouldThrowException() {
+        Brand brand = Brand.createBrand("테스트브랜드");
+        Product product = Product.createProduct("P001", "Shoes",
+                Money.of(10000), 10, brand);
+
+        CoreException result = assertThrows(CoreException.class, () -> {
+            product.increaseStock(-5);
+        });
+
+        assertThat(result.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);
+        assertThat(result.getCustomMessage()).isEqualTo("재고 증가량은 양수여야 합니다");
+    }
+
+    @Test
+    @DisplayName("재고를 감소시킬 수 있다")
+    void whenDecreaseStock_shouldDecreaseStockAmount() {
+        Brand brand = Brand.createBrand("테스트브랜드");
+        Product product = Product.createProduct("P001", "Shoes",
+                Money.of(10000), 10, brand);
+
+        product.decreaseStock(3);
+
+        assertThat(product.getStock()).isEqualTo(Stock.of(7));
+    }
+
+    @Test
+    @DisplayName("재고가 부족하면 예외가 발생한다")
+    void whenDecreaseStock_withInsufficientStock_shouldThrowException() {
+        Brand brand = Brand.createBrand("테스트브랜드");
+        Product product = Product.createProduct("P001", "Shoes",
+                Money.of(10000), 5, brand);
+
+        CoreException result = assertThrows(CoreException.class, () -> {
+            product.decreaseStock(10);
+        });
+
+        assertThat(result.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);
+        assertThat(result.getCustomMessage()).contains("재고가 부족합니다");
+    }
+
+    @Test
+    @DisplayName("재고 감소량이 음수이면 예외가 발생한다")
+    void whenDecreaseStock_withNegativeAmount_shouldThrowException() {
+        Brand brand = Brand.createBrand("테스트브랜드");
+        Product product = Product.createProduct("P001", "Shoes",
+                Money.of(10000), 10, brand);
+
+        CoreException result = assertThrows(CoreException.class, () -> {
+            product.decreaseStock(-5);
+        });
+
+        assertThat(result.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);
+        assertThat(result.getCustomMessage()).isEqualTo("재고 감소량은 양수여야 합니다");
+    }
+
+    @Test
+    @DisplayName("재고를 0으로 만들 수 있다")
+    void whenDecreaseStock_toZero_shouldWork() {
+        Brand brand = Brand.createBrand("테스트브랜드");
+        Product product = Product.createProduct("P001", "Shoes",
+                Money.of(10000), 10, brand);
+
+        product.decreaseStock(10);
+
+        assertThat(product.getStock()).isEqualTo(Stock.of(0));
+    }
+
+}
diff --git a/apps/commerce-api/src/test/java/com/loopers/domain/user/UserServiceTest.java b/apps/commerce-api/src/test/java/com/loopers/domain/user/UserServiceTest.java
index 5b7bf988e..b009d1da8 100644
--- a/apps/commerce-api/src/test/java/com/loopers/domain/user/UserServiceTest.java
+++ b/apps/commerce-api/src/test/java/com/loopers/domain/user/UserServiceTest.java
@@ -1,5 +1,6 @@
 package com.loopers.domain.user;
 
+import com.loopers.domain.Money;
 import com.loopers.infrastructure.user.UserJpaRepository;
 import com.loopers.support.error.CoreException;
 import com.loopers.support.error.ErrorType;
@@ -12,6 +13,8 @@
 import org.springframework.boot.test.mock.mockito.SpyBean;
 import org.springframework.test.context.ActiveProfiles;
 
+import java.math.BigDecimal;
+
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.jupiter.api.Assertions.assertAll;
 import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -47,7 +50,7 @@ void accountUser() {
         String birthday = "1995-08-25";
 
         // when
-        UserModel userResponse = userService.accountUser(userId, email, birthday, Gender.MALE);
+        User userResponse = userService.accountUser(userId, email, birthday, Gender.MALE);
 
         // 정상적으로 회원가입이 처리되었는지 검증
         assertAll(
@@ -58,7 +61,7 @@ void accountUser() {
         );
 
         // then
-        verify(userJpaRepository, times(1)).save(any(UserModel.class));
+        verify(userJpaRepository, times(1)).save(any(User.class));
 
     }
 
@@ -72,7 +75,7 @@ void accountUserWithDuplicateId_throwsException() {
         String birthday = "1995-08-25";
 
         // when
-        UserModel userResponse = userService.accountUser(userId, email, birthday, Gender.MALE);
+        User userResponse = userService.accountUser(userId, email, birthday, Gender.MALE);
 
         // 정상적으로 회원가입이 처리되었는지 검증
         assertAll(
@@ -100,9 +103,9 @@ void findUserById_existingId_returnsUserInfo() {
         String birthday = "1995-08-25";
 
         // when // then
-        UserModel userResponse = userService.accountUser(userId, email, birthday, Gender.MALE);
+        User userResponse = userService.accountUser(userId, email, birthday, Gender.MALE);
 
-        UserModel findUser = userService.getUserByUserId(userId);
+        User findUser = userService.getUserByUserId(userId);
 
         assertAll(
                 () -> assertThat(findUser.getUserId()).isEqualTo("testUser1"),
@@ -119,7 +122,7 @@ void findUserById_notExistingId_returnsNull() {
         String notExistsUserId = "noUser1";
 
         // when
-        UserModel findUser = userService.getUserByUserId(notExistsUserId);
+        User findUser = userService.getUserByUserId(notExistsUserId);
 
         // then
         assertThat(findUser).isNull();
@@ -134,9 +137,9 @@ void findUserById_existingId_returnPoint() {
         String birthday = "1995-08-25";
 
         // when // then
-        UserModel userResponse = userService.accountUser(userId, email, birthday, Gender.MALE);
+        User userResponse = userService.accountUser(userId, email, birthday, Gender.MALE);
 
-        UserModel findUser = userService.getUserPointByUserId(userId);
+        User findUser = userService.getUserPointByUserId(userId);
 
         assertThat(findUser).isNotNull();
         assertThat(findUser.getPoint()).isNotNull();
@@ -150,7 +153,7 @@ void findUserById_notExistingId_returnPoint() {
         String notExistsUserId = "noUser1";
 
         // when
-        UserModel findUser = userService.getUserPointByUserId(notExistsUserId);
+        User findUser = userService.getUserPointByUserId(notExistsUserId);
 
         // then
         assertThat(findUser).isNull();
@@ -165,15 +168,15 @@ void findUserById_existingUser_chargingPoint() {
         String email = "test@test.com";
         String birthday = "1995-08-25";
 
-        Integer chargePoint = 10000;
+        BigDecimal chargePoint = BigDecimal.valueOf(10000);
 
-        UserModel userResponse = userService.accountUser(userId, email, birthday, Gender.MALE);
+        User userResponse = userService.accountUser(userId, email, birthday, Gender.MALE);
 
         // when
-        UserModel user = userService.chargePointByUserId(userId, chargePoint);
+        User user = userService.chargePointByUserId(userId, chargePoint);
 
         // then
-        assertThat(user.getPoint()).isEqualTo(chargePoint);
+        assertThat(user.getPoint().getAmount()).isEqualByComparingTo(Money.of(chargePoint).getAmount());
 
     }
 
@@ -183,7 +186,7 @@ void findUserById_notExistingUser_throwsException() {
 
         // given
         String notExistsUserId = "noUser1";
-        Integer chargePoint = 10000;
+        BigDecimal chargePoint = BigDecimal.valueOf(10000);
 
         // when // then
         CoreException coreException = assertThrows(CoreException.class, () -> {
diff --git a/apps/commerce-api/src/test/java/com/loopers/domain/user/UserModelTest.java b/apps/commerce-api/src/test/java/com/loopers/domain/user/UserTest.java
similarity index 65%
rename from apps/commerce-api/src/test/java/com/loopers/domain/user/UserModelTest.java
rename to apps/commerce-api/src/test/java/com/loopers/domain/user/UserTest.java
index c5d7c8e85..bcc20cb98 100644
--- a/apps/commerce-api/src/test/java/com/loopers/domain/user/UserModelTest.java
+++ b/apps/commerce-api/src/test/java/com/loopers/domain/user/UserTest.java
@@ -1,26 +1,29 @@
 package com.loopers.domain.user;
 
+import com.loopers.domain.Money;
 import com.loopers.support.error.CoreException;
 import com.loopers.support.error.ErrorType;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Test;
 
+import java.math.BigDecimal;
+
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 
-class UserModelTest {
+class UserTest {
 
     @DisplayName("유저 ID가 영문 및 숫자 10자 이내 형식이어야 한다.")
     @Test
     void createUserWithInvalidId_throwException() {
 
         CoreException result = assertThrows(CoreException.class, () -> {
-            accountUser("tooLongId123", "mail@test.com", "1995-08-25", Gender.MALE);
+            User.createUser("tooLongId123", "mail@test.com", "1995-08-25", Gender.MALE);
         });
 
         assertThat(result.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);
-        assertThat(result.getCustomMessage()).isEqualTo("유저 ID 형식 오류");
+        assertThat(result.getCustomMessage()).isEqualTo("유저 ID는 영문자와 숫자로만 구성된 1-10자여야 합니다");
     }
 
     @DisplayName("이메일은 xx@yy.zz 형식이어야 한다.")
@@ -28,24 +31,24 @@ void createUserWithInvalidId_throwException() {
     void createUserWithInvalidEmail_throwException() {
 
         CoreException result = assertThrows(CoreException.class, () -> {
-            accountUser("validID123", "no-email", "1995-08-25", Gender.MALE);
+            User.createUser("validID123", "no-email", "1995-08-25", Gender.MALE);
         });
 
         assertThat(result.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);
-        assertThat(result.getCustomMessage()).isEqualTo("이메일 형식 오류");
+        assertThat(result.getCustomMessage()).isEqualTo("올바른 이메일 형식이 아닙니다");
 
     }
 
-    @DisplayName("생년월일이 yyyy-mm-dd 형식이어야 한다.")
+    @DisplayName("생년월일이 YYYY-MM-DD 형식이어야 한다.")
     @Test
     void createUserWithInvalidBirthdate_throwException() {
 
         CoreException result = assertThrows(CoreException.class, () -> {
-            accountUser("validID123", "mail@test.com", "1995.08.25", Gender.MALE);
+            User.createUser("validID123", "mail@test.com", "1995.08.25", Gender.MALE);
         });
 
         assertThat(result.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);
-        assertThat(result.getCustomMessage()).isEqualTo("생년월일 형식 오류");
+        assertThat(result.getCustomMessage()).isEqualTo("생년월일은 YYYY-MM-DD 형식이어야 합니다");
 
     }
 
@@ -54,7 +57,7 @@ void createUserWithInvalidBirthdate_throwException() {
     void createUserWithValid() {
 
         assertDoesNotThrow(() -> {
-            accountUser("validID123", "mail@test.com", "1995-08-25", Gender.MALE);
+            User.createUser("validID123", "mail@test.com", "1995-08-25", Gender.MALE);
         });
 
     }
@@ -64,27 +67,18 @@ void createUserWithValid() {
     void whenChargePoint_isSmallThenZero_returnException() {
 
         // given
-        UserModel user = accountUser("validID123", "mail@test.com", "1995-08-25", Gender.MALE);
+        User user = User.createUser("validID123", "mail@test.com", "1995-08-25", Gender.MALE);
 
-        Integer chargePoint = -1;
+        BigDecimal chargePoint = BigDecimal.valueOf(-1);
 
         // when // then
         CoreException coreException = assertThrows(CoreException.class, () -> {
-            user.chargePoint(chargePoint);
+            user.chargePoint(Money.of(chargePoint));
         });
 
         assertThat(coreException.getErrorType()).isEqualTo(ErrorType.BAD_REQUEST);
-        assertThat(coreException.getCustomMessage()).isEqualTo("충전할 포인트는 1 이상의 정수여야 합니다.");
-
-    }
+        assertThat(coreException.getCustomMessage()).isEqualTo("금액은 0보다 작을 수 없습니다");
 
-    private static UserModel accountUser(String userId, String email, String birthdate, Gender gender) {
-        return UserModel.builder()
-                .userId(userId)
-                .email(email)
-                .birthdate(birthdate)
-                .gender(gender)
-                .build();
     }
 
 }
diff --git a/apps/commerce-api/src/test/java/com/loopers/interfaces/api/user/UserV1ControllerE2ETest.java b/apps/commerce-api/src/test/java/com/loopers/interfaces/api/user/UserV1ControllerE2ETest.java
index 12b09ca18..dc255745d 100644
--- a/apps/commerce-api/src/test/java/com/loopers/interfaces/api/user/UserV1ControllerE2ETest.java
+++ b/apps/commerce-api/src/test/java/com/loopers/interfaces/api/user/UserV1ControllerE2ETest.java
@@ -1,7 +1,7 @@
 package com.loopers.interfaces.api.user;
 
 import com.loopers.domain.user.Gender;
-import com.loopers.domain.user.UserModel;
+import com.loopers.domain.user.User;
 import com.loopers.infrastructure.user.UserJpaRepository;
 import com.loopers.interfaces.api.ApiResponse;
 import com.loopers.utils.DatabaseCleanUp;
@@ -15,6 +15,8 @@
 import org.springframework.core.ParameterizedTypeReference;
 import org.springframework.http.*;
 
+import java.math.BigDecimal;
+
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.jupiter.api.Assertions.assertAll;
 import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -118,7 +120,7 @@ void whenFindUserSuccess_returnUserInfo() {
 
             String userId = "test123";
 
-            UserModel user = UserModel.builder()
+            User user = User.builder()
                     .userId(userId)
                     .email("test@test.com")
                     .birthdate("1995-08-25")
@@ -186,7 +188,7 @@ void whenFindUserSuccess_returnUserPoint() {
 
             String userId = "test123";
 
-            UserModel user = UserModel.builder()
+            User user = User.builder()
                     .userId(userId)
                     .email("test@test.com")
                     .birthdate("1995-08-25")
@@ -221,7 +223,7 @@ void whenFindUserSuccess_returnUserPoint() {
         void whenHeaderToX_USER_IDIsNotExist_returnBadRequest () {
             String userId = "test123";
 
-            UserModel user = UserModel.builder()
+            User user = User.builder()
                     .userId(userId)
                     .email("test@test.com")
                     .birthdate("1995-08-25")
@@ -259,19 +261,19 @@ void whenChargePointSuccess_returnUserChargedPoint() {
 
             // 유저 생성
             String userId = "test123";
-            Integer chargePoint = 1000;
+            BigDecimal chargePoint = BigDecimal.valueOf(1000);
 
-            UserModel user = UserModel.builder()
+            User user = User.builder()
                     .userId(userId)
                     .email("test@test.com")
                     .birthdate("1995-08-25")
                     .gender(Gender.MALE)
                     .build();
 
-            UserModel saved = userJpaRepository.save(user);
+            User saved = userJpaRepository.save(user);
 
             // 유저의 기존 포인트
-            Integer originPoint = saved.getPoint();
+            BigDecimal originPoint = saved.getPoint().getAmount();
 
             // 포인트 충전 request
             UserV1DTO.UserPointRequest request = new UserV1DTO.UserPointRequest(userId, chargePoint);
@@ -291,7 +293,7 @@ void whenChargePointSuccess_returnUserChargedPoint() {
                     () -> assertTrue(response.getStatusCode().is2xxSuccessful()),
                     () -> assertThat(response.getBody()).isNotNull(),
                     () -> assertThat(response.getBody().data()).isNotNull(),
-                    () -> assertThat(response.getBody().data().point()).isEqualTo(originPoint + chargePoint)
+                    () -> assertThat(response.getBody().data().point()).isEqualByComparingTo(originPoint.add(chargePoint))
             );
 
         }
diff --git a/docs/week2/03-class-diagram.md b/docs/week2/03-class-diagram.md
index e7ce3c2d1..b9cef39e2 100644
--- a/docs/week2/03-class-diagram.md
+++ b/docs/week2/03-class-diagram.md
@@ -3,52 +3,116 @@
 ```mermaid
 classDiagram
 
+    class Money {
+        - BigDecimal amount
+        + of(BigDecimal amount) Money
+        + of(long amount) Money
+        + zero() Money
+        + add(Money other) Money
+        + subtract(Money other) Money
+        + multiply(int quantity) Money
+        + multiply(long quantity) Money
+        + isGreaterThan(Money other) boolean
+        + isGreaterThanOrEqual(Money other) boolean
+        + isLessThan(Money other) boolean
+        + isLessThanOrEqual(Money other) boolean
+        - validateAmount(BigDecimal amount)
+    }
+
+    class Stock {
+        - int quantity
+        + of(int quantity) Stock
+        + increase(int amount) Stock
+        + decrease(int amount) Stock
+        + isSufficient(int required) boolean
+        - validateQuantity(int quantity)
+    }
+
     class User {
-        +Long userId
-        +String name
-        +String email
-        +Gender gender
-        +int points
-        +String birthdate
-        + validUserInfo()
-        + chargePoint()
+        -Long id
+        -String userId
+        -String name
+        -String email
+        -Gender gender
+        -Money point
+        -String birthdate
+        + createUser()
+        - validationuserId(String userId)
+        - validationUserEmail(String email)
+        - validationUserBirthdate(String birthdate)
+        - validateGender(Gender gender)
+        - validateAmount(Money amount)
+        + chargePoint(Money amount)
+        + usePoint(Money amount)
     }
 
     class Brand {
-        +Long brandId
-        +String name
+        -Long id
+        -String brandName
+        -boolean isActive
+        +createBrand(String brandName)
+        -validationBrandName(String brandName)
+        +activate()
+        +deactivate()
+        +isAvailable()
     }
 
     class Product {
-        +Long productId
-        +Brand brand
-        +String name
-        +int price
-        +int stock
-        +int likeCount
-        +incrementLikeCount()
-        +decrementLikeCount()
-        +increaseStock()
-        +decreaseStock()
+        -Long id
+        -String productCode
+        -String productName
+        -Stock stock
+        -Money price
+        -int likeCount
+        -List<ProductLike> productLikes
+        -Brand brand
+        +createProduct()
+        -validationProductCode(String productCode)
+        -validationProductName(String productName)
+        -validationProductPrice(Money price)
+        -validationProductStock(Stock stock)
+        -validationBrand(Brand brand)
+        +increaseStock(Stock increase)
+        +decreaseStock(Stock decrease)
+        +incrementLikeCount(ProductLike productLike)
+        +decrementLikeCount(ProductLike productLike)
     }
 
     class OrderProduct {
-        +Order order
-        +Product product
-        +int quantity
-        +int price
+        -Long id
+        -Order order
+        -Product product
+        -int quantity
+        -Money price
+        -Money totalPrice
+        -validateOrder(Order order)
+        -validateProduct(Product product)
+        -validateQuantity(int quantity)
     }
-    
+
     class Order {
-        +Long orderId
-        +User user
-        +String status
-        +int totalPrice
+        -Long id
+        -User user
+        -String status
+        -Money totalPrice
+        -createOrder()
+        -validateUser(User user)
+        -validateProductQuantities(Map<Product, Integer> productQuantities)
+        -validateStatusUpdate(OrderStatus status)
+        -validateUserPoint(User user, Money totalPrice)
+        -validateProductStock(Map<Product, Integer> productQuantities)
+        +updateStatus(OrderStatus status)
+        -calculateTotalPrice(Map<Product, Integer> productQuantities)
     }
 
     class ProductLike {
-        +User user
-        +Product product
+        -Long id
+        -User user
+        -Product product
+        +addLike()
+        +isSameUserAndProduct()
+        -validateUser(User user)
+        -validateProduct(Product product)
     }
 
     User "1" -- "0..*" Order : 
@@ -57,6 +121,13 @@ classDiagram
     Product "1" -- "0..*" OrderProduct : 
     Product "1" -- "0..*" ProductLike : 
     Brand "1" -- "0..*" Product : 
+    
+    Product "1" *-- "1" Money : price
+    Product "1" *-- "1" Stock : stock
+    User "1" *-- "1" Money : point
+    OrderProduct "1" *-- "1" Money : price
+    OrderProduct "1" *-- "1" Money : totalPrice
+    Order "1" *-- "1" Money : totalPrice
 
 ```
 
diff --git a/docs/week2/04-erd.md b/docs/week2/04-erd.md
index 9bc33f435..c969af5d1 100644
--- a/docs/week2/04-erd.md
+++ b/docs/week2/04-erd.md
@@ -3,44 +3,48 @@
 ```mermaid
 erDiagram
     USER {
-        bigint user_id PK "사용자 ID"
+        bigint id PK "사용자 고유 ID"
+        String user_id "사용자 로그인 ID"
         varchar name "이름"
         varchar email "이메일"
         varchar gender "성별"
         varchar birthdate "생년월일(yyyy-mm-dd)"
-        int points "보유 포인트"
+        numeric points "보유 포인트"
         datetime created_at "가입 일시"
+        datetime deleted_at "탈퇴 일시"
     }
     ORDERS {
-        bigint order_id PK "주문 ID"
-        bigint user_id FK "사용자 ID"
+        bigint order_id PK "주문 고유 ID"
+        bigint user_id FK "사용자 고유 ID"
         varchar status "주문 상태"
-        int total_price "총 주문 금액"
+        numeric total_price "총 주문 금액"
         datetime created_at "주문 일시"
+        datetime deleted_at "주문 삭제 일시"
     }
     ORDER_PRODUCT {
-        bigint order_id PK, FK "주문 ID"
-        bigint product_id PK, FK "상품 ID"
+        bigint order_id PK, FK "주문 고유 ID"
+        bigint product_id PK, FK "상품 고유 ID"
         int quantity "수량"
-        int price "주문 시점 가격"
+        numeric price "주문 시점 가격"
     }
     PRODUCT {
-        bigint product_id PK "상품 ID"
-        bigint brand_id FK "브랜드 ID"
+        bigint product_id PK "상품 고유 ID"
+        bigint brand_id FK "브랜드 고유 ID"
         varchar name "상품명"
         text description "상품 설명"
-        int price "가격"
+        numeric price "가격"
         int stock "재고"
         int like_count "좋아요 수 (비정규화)"
         datetime created_at "생성 일시"
         datetime deleted_at "삭제 일시"
     }
     PRODUCT_LIKE {
-        bigint user_id PK, FK "사용자 ID"
-        bigint product_id PK, FK "상품 ID"
+        bigint user_id PK, FK "사용자 고유 ID"
+        bigint product_id PK, FK "상품 고유 ID"
+        datetime likeAt "좋아요 일시"
     }
     BRAND {
-        bigint brand_id PK "브랜드 ID"
+        bigint brand_id PK "브랜드 고유 ID"
         varchar name "브랜드명"
         text description "브랜드 설명"
         datetime created_at "생성 일시"
@@ -52,7 +56,7 @@ erDiagram
 
     PRODUCT ||--o{ ORDER_PRODUCT : ""
     PRODUCT ||--o{ PRODUCT_LIKE : ""
-    
+
     ORDERS ||--|{ ORDER_PRODUCT : ""
 
     BRAND ||--|{ PRODUCT : ""
