728x90

데이터베이스가 성장하면서 단일 테이블로는 더 이상 효율적인 데이터 관리가 어려워지는 시점이 옵니다. 특히 대용량 데이터를 다룰 때 성능 병목이 발생하게 되는데, 이를 해결하기 위한 대표적인 방법이 파티셔닝(Partitioning)샤딩(Sharding)입니다.

이번 글에서는 Spring Boot와 MySQL을 사용하여 Product 테이블을 예제로 두 방법의 차이점과 장단점을 살펴보겠습니다.

예제 시나리오

우리가 다룰 Product는 다음과 같은 구조를 가집니다:

@Entity
@Table(name = "product")
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
    private String type; // "상의", "하의", "모자", "신발"
    private BigDecimal price;
    private Integer stock;
    private LocalDateTime createdAt;

    // 생성자, getter, setter 생략
}

파티셔닝 (Partitioning)

파티셔닝이란?

파티셔닝은 하나의 데이터베이스 내에서 테이블을 논리적으로 분할하는 기법입니다. 물리적으로는 여전히 같은 데이터베이스에 존재하지만, 데이터를 여러 파티션으로 나누어 관리합니다.

파티셔닝 구조도

┌─────────────────────────────────────────┐
│              MySQL Database             │
├─────────────────────────────────────────┤
│  Product Table (Partitioned by type)    │
├─────────────────────────────────────────┤
│  ┌─────────────┐  ┌─────────────┐      │
│  │ Partition 1 │  │ Partition 2 │      │
│  │   (상의)     │  │   (하의)     │      │
│  └─────────────┘  └─────────────┘      │
│  ┌─────────────┐  ┌─────────────┐      │
│  │ Partition 3 │  │ Partition 4 │      │
│  │   (모자)     │  │   (신발)     │      │
│  └─────────────┘  └─────────────┘      │
└─────────────────────────────────────────┘

MySQL 파티셔닝 구현

-- 파티션 테이블 생성
CREATE TABLE product (
    id BIGINT AUTO_INCREMENT,
    name VARCHAR(255) NOT NULL,
    type VARCHAR(50) NOT NULL,
    price DECIMAL(10,2) NOT NULL,
    stock INT NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id, type)
) 
PARTITION BY LIST COLUMNS(type) (
    PARTITION p_top VALUES IN ('상의'),
    PARTITION p_bottom VALUES IN ('하의'),
    PARTITION p_hat VALUES IN ('모자'),
    PARTITION p_shoes VALUES IN ('신발')
);

Spring Boot에서 파티셔닝 활용

@Repository
public class ProductRepository {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    // 특정 타입의 상품 조회 (파티션 프루닝 활용)
    public List<Product> findByType(String type) {
        String sql = "SELECT * FROM product WHERE type = ?";
        return jdbcTemplate.query(sql, new Object[]{type}, 
            (rs, rowNum) -> mapRowToProduct(rs));
    }

    // 전체 상품 조회 (모든 파티션 스캔)
    public List<Product> findAll() {
        String sql = "SELECT * FROM product";
        return jdbcTemplate.query(sql, (rs, rowNum) -> mapRowToProduct(rs));
    }

    private Product mapRowToProduct(ResultSet rs) throws SQLException {
        Product product = new Product();
        product.setId(rs.getLong("id"));
        product.setName(rs.getString("name"));
        product.setType(rs.getString("type"));
        product.setPrice(rs.getBigDecimal("price"));
        product.setStock(rs.getInt("stock"));
        product.setCreatedAt(rs.getTimestamp("created_at").toLocalDateTime());
        return product;
    }
}

파티셔닝의 장점

  1. 쿼리 성능 향상: 파티션 프루닝을 통해 필요한 파티션만 스캔
  2. 인덱스 효율성: 각 파티션마다 별도의 인덱스 관리
  3. 유지보수 용이성: 파티션별 백업, 복구 가능

파티셔닝의 한계

  1. 메모리 제약: 여전히 단일 데이터베이스의 메모리 한계
  2. QPS 제한: 하나의 DB 서버가 처리할 수 있는 요청 수의 한계
  3. 스케일링 제약: 수직 확장(Scale-up)에만 의존

샤딩 (Sharding)

샤딩이란?

샤딩은 동일한 스키마를 가진 데이터를 여러 데이터베이스에 수평적으로 분산하는 기법입니다. 각 샤드는 독립적인 데이터베이스 서버에서 실행됩니다.

샤딩 구조도

┌─────────────────┐  ┌─────────────────┐
│   MySQL DB 1    │  │   MySQL DB 2    │
│   (상의 샤드)     │  │   (하의 샤드)      │
├─────────────────┤  ├─────────────────┤
│ Product Table   │  │ Product Table   │
│ - 상의 데이터      │  │ - 하의 데이터      │
└─────────────────┘  └─────────────────┘

┌─────────────────┐  ┌─────────────────┐
│   MySQL DB 3    │  │   MySQL DB 4    │
│   (모자 샤드)     │  │   (신발 샤드)     │
├─────────────────┤  ├─────────────────┤
│ Product Table   │  │ Product Table   │
│ - 모자 데이터      │  │ - 신발 데이터     │
└─────────────────┘  └─────────────────┘

Spring Boot에서 샤딩 구현

1. 다중 데이터소스 설정

@Configuration
public class ShardingConfig {

    @Bean
    @Primary
    public DataSource topDataSource() {
        return DataSourceBuilder.create()
            .url("jdbc:mysql://localhost:3306/product_top")
            .username("user")
            .password("password")
            .build();
    }

    @Bean
    public DataSource bottomDataSource() {
        return DataSourceBuilder.create()
            .url("jdbc:mysql://localhost:3307/product_bottom")
            .username("user")
            .password("password")
            .build();
    }

    @Bean
    public DataSource hatDataSource() {
        return DataSourceBuilder.create()
            .url("jdbc:mysql://localhost:3308/product_hat")
            .username("user")
            .password("password")
            .build();
    }

    @Bean
    public DataSource shoesDataSource() {
        return DataSourceBuilder.create()
            .url("jdbc:mysql://localhost:3309/product_shoes")
            .username("user")
            .password("password")
            .build();
    }
}

2. 샤드 라우팅 서비스

@Service
public class ShardingService {

    private final Map<String, JdbcTemplate> shardMap;

    public ShardingService(
            @Qualifier("topDataSource") DataSource topDs,
            @Qualifier("bottomDataSource") DataSource bottomDs,
            @Qualifier("hatDataSource") DataSource hatDs,
            @Qualifier("shoesDataSource") DataSource shoesDs) {

        this.shardMap = Map.of(
            "상의", new JdbcTemplate(topDs),
            "하의", new JdbcTemplate(bottomDs),
            "모자", new JdbcTemplate(hatDs),
            "신발", new JdbcTemplate(shoesDs)
        );
    }

    public JdbcTemplate getShardByType(String type) {
        JdbcTemplate shard = shardMap.get(type);
        if (shard == null) {
            throw new IllegalArgumentException("Unknown product type: " + type);
        }
        return shard;
    }

    public Collection<JdbcTemplate> getAllShards() {
        return shardMap.values();
    }
}

3. 샤딩 Repository 구현

@Repository
public class ShardedProductRepository {

    @Autowired
    private ShardingService shardingService;

    // 특정 타입의 상품 조회 (단일 샤드 접근)
    public List<Product> findByType(String type) {
        JdbcTemplate shard = shardingService.getShardByType(type);
        String sql = "SELECT * FROM product WHERE type = ?";
        return shard.query(sql, new Object[]{type}, this::mapRowToProduct);
    }

    // 상품 저장 (적절한 샤드로 라우팅)
    public void save(Product product) {
        JdbcTemplate shard = shardingService.getShardByType(product.getType());
        String sql = "INSERT INTO product (name, type, price, stock) VALUES (?, ?, ?, ?)";
        shard.update(sql, product.getName(), product.getType(), 
                    product.getPrice(), product.getStock());
    }

    // 전체 상품 조회 (모든 샤드 접근 - 성능 주의!)
    public List<Product> findAll() {
        List<Product> allProducts = new ArrayList<>();

        // 병렬 처리로 성능 개선
        List<CompletableFuture<List<Product>>> futures = 
            shardingService.getAllShards().stream()
                .map(shard -> CompletableFuture.supplyAsync(() -> 
                    shard.query("SELECT * FROM product", this::mapRowToProduct)))
                .collect(Collectors.toList());

        futures.forEach(future -> {
            try {
                allProducts.addAll(future.get());
            } catch (Exception e) {
                throw new RuntimeException("Failed to fetch from shard", e);
            }
        });

        return allProducts;
    }

    // 범위 검색 (가격 기준 - 모든 샤드 접근 필요)
    public List<Product> findByPriceRange(BigDecimal minPrice, BigDecimal maxPrice) {
        List<Product> results = new ArrayList<>();
        String sql = "SELECT * FROM product WHERE price BETWEEN ? AND ?";

        for (JdbcTemplate shard : shardingService.getAllShards()) {
            List<Product> shardResults = shard.query(sql, 
                new Object[]{minPrice, maxPrice}, this::mapRowToProduct);
            results.addAll(shardResults);
        }

        return results.stream()
                .sorted(Comparator.comparing(Product::getPrice))
                .collect(Collectors.toList());
    }

    private Product mapRowToProduct(ResultSet rs, int rowNum) throws SQLException {
        Product product = new Product();
        product.setId(rs.getLong("id"));
        product.setName(rs.getString("name"));
        product.setType(rs.getString("type"));
        product.setPrice(rs.getBigDecimal("price"));
        product.setStock(rs.getInt("stock"));
        product.setCreatedAt(rs.getTimestamp("created_at").toLocalDateTime());
        return product;
    }
}

샤딩의 장점

  1. 수평 확장성: 새로운 서버 추가로 용량과 성능 확장 가능
  2. 메모리 분산: 각 샤드가 독립적인 메모리 공간 사용
  3. QPS 향상: 여러 서버가 동시에 요청 처리
  4. 장애 격리: 한 샤드의 장애가 다른 샤드에 영향 없음

샤딩의 어려움

1. 범위 검색의 복잡성

// 문제점: 모든 샤드를 조회해야 하므로 성능 저하
public List<Product> findExpensiveProducts(BigDecimal threshold) {
    List<Product> results = new ArrayList<>();

    // 모든 샤드에서 데이터 수집
    for (JdbcTemplate shard : shardingService.getAllShards()) {
        String sql = "SELECT * FROM product WHERE price > ?";
        results.addAll(shard.query(sql, new Object[]{threshold}, 
                      this::mapRowToProduct));
    }

    return results.stream()
            .sorted(Comparator.comparing(Product::getPrice).reversed())
            .collect(Collectors.toList());
}

2. 트랜잭션 관리의 복잡성

// 문제점: 여러 샤드에 걸친 트랜잭션 처리
@Transactional
public void transferStock(Long fromProductId, String fromType, 
                         Long toProductId, String toType, Integer quantity) {

    if (!fromType.equals(toType)) {
        // 서로 다른 샤드 간의 트랜잭션 - 복잡한 2PC 필요
        throw new UnsupportedOperationException(
            "Cross-shard transactions not supported");
    }

    JdbcTemplate shard = shardingService.getShardByType(fromType);
    // 같은 샤드 내에서만 트랜잭션 보장 가능
    shard.update("UPDATE product SET stock = stock - ? WHERE id = ?", 
                quantity, fromProductId);
    shard.update("UPDATE product SET stock = stock + ? WHERE id = ?", 
                quantity, toProductId);
}

3. 조인 쿼리의 제약

// 문제점: 서로 다른 샤드의 데이터를 조인할 수 없음
public class OrderService {

    // 주문과 상품이 다른 샤드에 있을 경우 애플리케이션 레벨에서 조인
    public OrderDetailDTO getOrderWithProducts(Long orderId) {
        Order order = orderRepository.findById(orderId);

        List<Product> products = new ArrayList<>();
        for (OrderItem item : order.getItems()) {
            // 각 상품을 개별적으로 조회 (N+1 문제 발생 가능)
            Product product = shardedProductRepository
                .findByType(item.getProductType())
                .stream()
                .filter(p -> p.getId().equals(item.getProductId()))
                .findFirst()
                .orElse(null);
            if (product != null) {
                products.add(product);
            }
        }

        return new OrderDetailDTO(order, products);
    }
}

파티셔닝 vs 샤딩 비교

항목 파티셔닝 샤딩
확장성 수직 확장만 가능 수평 확장 가능
메모리 단일 DB 메모리 한계 각 샤드별 독립적 메모리
QPS 단일 DB 서버 한계 여러 서버로 분산 처리
트랜잭션 ACID 보장 크로스 샤드 트랜잭션 복잡
조인 일반적인 조인 가능 크로스 샤드 조인 불가
범위 검색 효율적 모든 샤드 접근 필요
복잡성 상대적으로 단순 애플리케이션 레벨 복잡성 증가
장애 격리 전체 DB 영향 샤드별 독립적

실제 사용 시나리오

파티셔닝이 적합한 경우

@Service
public class AnalyticsService {

    // 특정 타입의 상품 분석 - 파티션 프루닝 활용
    public ProductAnalytics analyzeByType(String type) {
        List<Product> products = productRepository.findByType(type);

        return ProductAnalytics.builder()
            .totalCount(products.size())
            .averagePrice(calculateAveragePrice(products))
            .topSellingProducts(findTopSelling(products))
            .build();
    }
}

샤딩이 적합한 경우

@Service
public class ProductService {

    // 대용량 데이터 처리 - 각 샤드에서 병렬 처리
    public void updatePricesForType(String type, BigDecimal multiplier) {
        JdbcTemplate shard = shardingService.getShardByType(type);

        String sql = "UPDATE product SET price = price * ? WHERE type = ?";
        int updatedRows = shard.update(sql, multiplier, type);

        log.info("Updated {} products in {} shard", updatedRows, type);
    }

    // 높은 QPS 처리 - 각 샤드가 독립적으로 처리
    @Async
    public CompletableFuture<List<Product>> findTopProductsByType(String type) {
        JdbcTemplate shard = shardingService.getShardByType(type);

        String sql = "SELECT * FROM product WHERE type = ? ORDER BY price DESC LIMIT 10";
        List<Product> products = shard.query(sql, new Object[]{type}, 
                                           this::mapRowToProduct);

        return CompletableFuture.completedFuture(products);
    }
}

결론

파티셔닝과 샤딩은 각각 다른 상황에서 유용한 데이터베이스 확장 기법입니다.

파티셔닝은 비교적 단순한 구현으로 쿼리 성능을 향상시킬 수 있지만, 근본적인 확장성 문제는 해결하지 못합니다. 중간 규모의 데이터에서 성능 개선이 필요한 경우 적합합니다.

샤딩은 더 복잡한 구현이 필요하지만, 진정한 수평 확장을 통해 대용량 데이터와 높은 QPS를 처리할 수 있습니다. 다만 크로스 샤드 쿼리, 트랜잭션 관리 등의 복잡성을 감수해야 합니다.

실제 서비스에서는 데이터의 성격, 트래픽 패턴, 확장 계획을 종합적으로 고려하여 적절한 전략을 선택하는 것이 중요합니다. 때로는 두 방법을 조합하여 사용하는 것도 좋은 선택이 될 수 있습니다.

728x90
728x90

서론: 자본주의의 꽃과 디지털 혁명, 두 자산 시장의 이해

 

본 보고서는 전통적 자본 시장의 핵심인 '주식'과 새로운 디지털 경제의 상징인 '암호화폐'에 대한 포괄적이고 심층적인 분석을 제공하는 것을 목표로 합니다. 현대 투자 환경은 이 두 자산 클래스의 공존과 상호작용으로 인해 그 어느 때보다 복잡하고 역동적으로 변화하고 있습니다. 따라서 투자자가 각 시장의 본질적인 특성, 역사적 배경, 작동 메커니즘, 그리고 가치 평가의 근본적인 차이를 이해하는 것은 성공적인 자산 배분을 위한 필수 전제 조건이 되었습니다.

본 보고서는 다음과 같은 핵심 질문에 대한 명확하고 체계적인 답변을 제시할 것입니다: 주식과 암호화폐는 근본적으로 무엇이 다른가? 각 시장의 가치는 어디에서 비롯되는가? 두 시장은 어떻게 운영되며 어떤 규제를 받는가? 투자자가 활용할 수 있는 핵심 용어, 분석 도구, 그리고 투자 전략에는 무엇이 있는가? 마지막으로, 이 두 시장의 미래는 어떻게 전개될 것인가?

이 보고서를 통해 투자자들은 단편적인 정보를 넘어 두 자산 시장을 관통하는 거시적인 흐름을 파악하고, 정보에 입각한 합리적인 투자 의사결정을 내리는 데 필요한 지적 토대를 구축할 수 있을 것입니다. 기초 개념부터 역사, 작동 원리, 투자 전략, 그리고 미래 전망에 이르기까지 모든 것을 망라하여 현명한 투자자의 길을 안내하고자 합니다.


Part 1: 자본주의의 꽃, 주식 시장의 이해

 

주식 시장은 흔히 '자본주의의 꽃'이라 불립니다.1 이는 기업이 성장에 필요한 자금을 조달하고, 투자자는 그 성장의 과실을 공유하는 현대 자본주의 경제의 가장 핵심적인 메커니즘이기 때문입니다. 이 장에서는 주식의 근본적인 개념과 역사적 배경을 살펴보고, 주식 시장이 어떻게 작동하는지를 심도 있게 분석합니다.

 

1.1. 주식의 본질: 개념과 역사



주식의 정의

 

주식이란 주식회사의 자본을 구성하는 최소 단위를 의미하며, 동시에 해당 회사의 소유권 일부를 나타내는 증서입니다.2 주식을 매수한다는 것은 단순히 특정 가격에 자산을 사는 행위를 넘어, 그 기업의 일부를 소유하는 '주주(株主)'가 되는 것을 의미합니다.6 이 지위는 기업에 돈을 빌려주고 이자를 받는 채권자와는 근본적으로 구별됩니다. 대한민국 상법에서는 주주로서의 권리를 나타내는 이 지위를 '주식'으로, 그리고 그 지위를 증권 형태로 만든 것을 '주권(株券)'으로 명확히 구분하여 표현하고 있습니다.7

 

주식의 탄생: 네덜란드 동인도 회사(VOC)

 

주식이라는 혁신적인 개념은 17세기 초, 대항해시대의 상업적 필요성에서 탄생했습니다. 세계 최초의 주식회사로 인정받는 기업은 1602년 네덜란드에서 설립된 동인도 회사(Vereenigde Oost-Indische Compagnie, VOC)입니다.1 당시 유럽과 아시아를 잇는 향신료 무역은 막대한 이익을 가져다주었지만, 동시에 긴 항해 기간과 예측 불가능한 위험(해적, 난파 등)으로 인해 엄청난 자본과 위험 감수를 요구했습니다.9

이러한 거대한 규모의 사업을 소수의 부유한 상인이나 귀족의 자본만으로는 감당하기 어려웠습니다. 네덜란드 동인도 회사는 이 문제를 해결하기 위해 사업의 소유권을 잘게 쪼개어 '주식'이라는 형태로 만들고, 이를 일반 대중에게 판매하여 자금을 조달하는 방식을 고안했습니다.6 이는 특정 계층에 국한되지 않고 하인, 상인, 인부 등 다양한 사람들이 투자에 참여할 수 있는 길을 열었으며 11, 고위험-고수익 사업의 리스크를 다수의 투자자에게 분산시키고 거대한 자본을 효율적으로 집적하는 최초의 금융 혁신이었습니다. 이처럼 주식의 기원은 '자본 조달'이라는 명확한 상업적 목적에 있으며, 이는 '중앙화된 시스템에 대한 이념적 반발'에서 태동한 암호화폐와 근본적인 차이를 보입니다. 이 본질적인 탄생 배경의 차이가 두 자산의 가치 평가 방식, 규제 체계, 시장 참여자의 행동 양식 등 모든 면에서 뚜렷한 차이를 만들어내는 근원이라 할 수 있습니다.

 

핵심 혁신: 유한책임제도

 

주식의 확산에 결정적인 기여를 한 또 다른 혁신은 '유한책임(Limited Liability)' 제도의 도입입니다.1 유한책임이란 투자자가 자신이 투자한 금액, 즉 보유한 주식의 가치를 한도로만 책임을 지는 것을 의미합니다.12 만약 회사가 파산하더라도 주주는 투자 원금을 잃을 뿐, 회사의 채무를 개인적으로 변제할 의무가 없습니다.5

이전의 '무한책임' 구조에서는 사업 실패가 곧 개인의 파산으로 이어졌기 때문에 투자는 매우 위험한 행위였습니다. 유한책임 제도는 이러한 투자의 심리적, 재정적 장벽을 극적으로 낮추었고, 더 많은 사람들이 안심하고 기업에 자본을 공급할 수 있도록 만들었습니다. 이는 자본의 축적과 재투자를 촉진하여 현대 자본주의 경제가 발전하는 견고한 토대가 되었습니다.5

 

주주의 권리와 책임

 

주주는 회사의 주인으로서 다음과 같은 권리와 책임을 가집니다.

  • 자익권 (Economic Rights): 주주가 자신의 경제적 이익을 위해 회사에 요구할 수 있는 권리입니다.
  • 배당청구권: 회사가 영업활동을 통해 이익을 창출했을 경우, 그 이익의 일부를 현금이나 주식의 형태로 분배받을 권리입니다.5
  • 잔여재산분배청구권: 회사가 해산 또는 청산될 경우, 모든 부채를 변제하고 남은 자산(잔여재산)에 대해 자신의 지분율만큼 분배를 요구할 수 있는 권리입니다. 단, 채권자와 우선주주 다음 순위입니다.2
  • 공익권 (Management Rights): 회사 전체의 이익을 위해 경영에 참여하고 감독할 수 있는 권리입니다.
  • 의결권: 가장 대표적인 공익권으로, 주주총회에 참석하여 보유 주식 1주당 1표의 원칙에 따라 회사의 이사 선임, 정관 변경, 합병 등 중요한 의사결정에 투표로 참여할 수 있는 권리입니다.5
  • 책임: 주주의 책임은 앞서 언급한 유한책임의 원칙에 따라, 자신이 출자한 금액을 한도로 합니다. 회사가 성공하면 주가 상승과 배당을 통해 무한한 이익을 얻을 수 있지만, 최악의 경우(파산)에는 투자 원금 전액을 잃는 것으로 책임이 마무리됩니다.5

 

1.2. 주식 시장의 작동 원리

 

주식 시장은 크게 주식이 처음 만들어져 투자자에게 판매되는 '발행시장'과, 이미 발행된 주식이 투자자들 사이에서 거래되는 '유통시장'으로 나뉩니다.6

 

발행시장(Primary Market)과 유통시장(Secondary Market)

 

  • 발행시장: 기업이 자본 조달을 목적으로 주식을 최초로 발행하여 투자자들에게 판매하는 시장입니다.6 이 시장에서 기업은 사업 확장, 연구 개발, 부채 상환 등에 필요한 실질적인 자금을 직접적으로 확보하게 됩니다. 발행시장의 가장 대표적인 형태는 **기업공개(IPO, Initial Public Offering)**입니다.3 IPO는 비상장기업이 정해진 절차와 요건을 충족하여 처음으로 증권거래소에 주식을 상장하고, 불특정 다수의 투자자에게 주식을 공개적으로 판매하는 것을 말합니다.14
  • 유통시장: 발행시장을 통해 공급된 주식이 투자자들 간에 자유롭게 매매되는 시장을 의미합니다.6 우리가 흔히 '주식 거래'라고 말할 때 언급하는 한국거래소(KRX)의 코스피(KOSPI), 코스닥(KOSDAQ) 시장이 바로 유통시장에 해당합니다.6 이 시장에서 주식의 가격, 즉 '주가'는 매수자와 매도자의 수요와 공급 원리에 따라 끊임없이 변동하며 형성됩니다.3 유통시장은 투자자에게는 투자 자금을 회수할 수 있는 유동성을 제공하고, 시장 전체에는 자원의 효율적 배분이라는 중요한 기능을 수행합니다.

 

기업의 자금 조달 방식

 

상장 기업은 IPO 이후에도 다양한 방법을 통해 유통시장에서 추가적인 자금을 조달할 수 있습니다.

  • 유상증자 (Paid-in Capital Increase): 이미 상장된 기업이 운영 자금이나 투자 자금이 추가로 필요할 때, 새로운 주식(신주)을 발행하여 기존 주주나 새로운 투자자에게 돈을 받고 판매하는 방식입니다.6 이는 기업의 자본금을 직접적으로 늘리는 효과가 있지만, 총 발행 주식 수가 늘어나기 때문에 기존 주주 입장에서는 1주당 가치가 희석될 수 있다는 단점이 있습니다.15
  • 주식 연계 채권 (Equity-linked Securities): 채권의 안정성과 주식의 수익성을 결합한 하이브리드 형태의 자금 조달 방식입니다.
  • 전환사채(CB, Convertible Bond): 발행 시에는 채권이지만, 일정 기간이 지난 후 투자자의 선택에 따라 미리 정해진 가격으로 해당 회사의 주식으로 전환할 수 있는 권리가 붙은 사채입니다.6
  • 신주인수권부사채(BW, Bond with Warrant): 채권으로서의 성격은 그대로 유지하면서, 발행 이후 일정 기간 내에 미리 약정된 가격으로 해당 기업의 신주를 인수할 수 있는 권리(Warrant)가 별도로 부여된 사채입니다.6

 

주가 결정 요인

 

주가는 수많은 요인이 복합적으로 작용하여 결정됩니다. 이를 크게 기업의 내재적 요인과 시장의 외부적 요인으로 나눌 수 있습니다.

  • 내재가치 (Intrinsic Value): 기업의 재무 상태(자산, 부채), 수익성(매출, 이익), 성장성, 기술력, 경영 능력 등 기업 본연의 펀더멘털(Fundamental) 요소를 의미합니다.3 장기적으로 주가는 기업의 내재가치, 특히 이익 창출 능력에 수렴하는 경향이 있습니다.2
  • 외부 요인 (External Factors): 거시 경제 지표(금리, 환율, 경제성장률), 산업 동향 및 경쟁 구도, 정부 정책 및 규제, 그리고 투자자들의 심리(투심)와 수급 관계 등이 주가에 큰 영향을 미칩니다.3 특히 단기적으로는 시장 참여자들의 기대감, 공포감과 같은 심리적 요인이 주가를 크게 좌우하기도 합니다.3

 

1.3. 주식의 종류와 분류

 

주식은 부여된 권리의 내용이나 투자 전략의 관점에 따라 다양하게 분류될 수 있습니다.

 

권리에 따른 분류

 

  • 보통주 (Common Stock): 주식의 가장 표준적인 형태로, 주주총회에서 의결권을 행사하여 경영에 참여할 권리와 이익 발생 시 배당을 받을 권리를 모두 가집니다.7 우리가 일반적으로 거래하는 대부분의 주식이 보통주입니다.
  • 우선주 (Preferred Stock): 이름에서 알 수 있듯이 특정 권리에서 보통주보다 우선적인 지위를 갖는 주식입니다. 일반적으로 의결권이 제한되거나 없는 대신, 이익 배당이나 회사 청산 시 잔여재산 분배에 있어 보통주보다 먼저 권리를 행사할 수 있습니다.2 보통 약정된 고정 배당률을 지급받기 때문에 안정적인 현금흐름을 선호하는 투자자들에게 적합합니다.18

 

투자 전략에 따른 분류

 

투자자들은 자신의 투자 목표와 위험 감수 수준에 따라 다양한 성격의 주식에 투자합니다.

  • 성장주 (Growth Stock): 현재의 재무 상태나 이익 규모보다는 미래의 폭발적인 성장 가능성에 더 높은 가치를 부여받는 주식입니다.14 주로 혁신 기술을 보유한 IT 기업이나 바이오, 신재생에너지 등 신흥 산업에 속한 기업들이 여기에 해당합니다. 높은 주가 상승률을 기대할 수 있지만, 그만큼 주가 변동성이 크고 경기 하강 시 큰 폭으로 하락할 위험도 있습니다.19
  • 가치주 (Value Stock): 기업이 보유한 자산이나 현재 벌어들이는 이익 등 내재가치에 비해 주가가 시장에서 저평가되어 있는 주식입니다.14 투자자들은 시장이 언젠가 이 기업의 진정한 가치를 알아보고 주가가 제자리를 찾아갈 것이라는 기대를 가지고 투자합니다. 일반적으로 성숙 산업에 속한 기업이 많으며, 성장주에 비해 주가 변동이 적고 안정적인 경향이 있습니다.14
  • 방어주 (Defensive Stock): 경기 순환이나 경제 위기 상황에 상대적으로 영향을 덜 받는 기업의 주식을 말합니다.14 음식료, 통신, 전력, 가스 등 필수 소비재나 서비스를 제공하는 기업들이 대표적입니다. 시장 전체가 불안정한 시기에 포트폴리오의 안정성을 높이는 역할을 하며, 꾸준한 배당을 지급하는 경우가 많습니다.14

Part 2: 디지털 자산 혁명, 암호화폐 시장의 이해

 

21세기에 들어 금융 시장은 새로운 차원의 혁명을 맞이했습니다. 바로 암호화폐의 등장입니다. 중앙 기관의 통제 없이 개인 간의 가치 전송을 가능하게 한 이 디지털 자산은 기존 금융 시스템에 대한 근본적인 질문을 던지며 새로운 투자 지평을 열었습니다. 이 장에서는 암호화폐의 개념과 역사, 그리고 그 기반 기술인 블록체인과 시장의 작동 원리를 탐구합니다.

 

2.1. 암호화폐의 탄생: 개념과 역사



암호화폐의 정의

 

암호화폐(Cryptocurrency)는 '암호(Crypto)'와 '통화(Currency)'의 합성어로, 분산원장 기술인 **블록체인(Blockchain)**을 기반으로 하여 암호화 기술을 통해 보안이 유지되는 디지털 자산 또는 가상 자산을 의미합니다.20 가장 핵심적인 특징은 정부, 중앙은행, 금융 회사와 같은 중앙화된 중개 기관 없이 개인과 개인이 직접(P2P, Peer-to-Peer) 가치를 주고받을 수 있는 탈중앙화된 시스템이라는 점입니다.21 거래 기록은 네트워크에 참여하는 다수의 컴퓨터에 분산되어 저장되므로, 위·변조가 사실상 불가능에 가깝습니다.22

 

비트코인(Bitcoin)의 탄생

 

암호화폐의 역사는 2008년 10월, '사토시 나카모토(Satoshi Nakamoto)'라는 가명을 쓰는 정체불명의 개인 혹은 집단이 "비트코인: 개인 간 전자화폐 시스템(Bitcoin: A Peer-to-Peer Electronic Cash System)"이라는 제목의 논문을 온라인에 공개하면서 시작되었습니다.22 이 논문은 은행과 같은 신뢰할 수 있는 제3자 없이도 이중 지불 문제를 해결하며 안전하게 온라인 결제를 할 수 있는 방법을 제시했습니다. 그리고 2009년 1월 3일, 첫 번째 블록인 '제네시스 블록'이 생성되면서 최초의 탈중앙화 암호화폐, 비트코인이 세상에 등장했습니다.20

비트코인의 탄생은 2008년 글로벌 금융위기 이후 기존 중앙집권적 금융 시스템에 대한 깊은 불신과 회의감 속에서 이루어졌습니다. 이는 단순히 새로운 기술의 등장을 넘어, 중개자를 배제하고 개인에게 금융 주권을 돌려주려는 철학적, 이념적 목표를 가진 사회적 운동의 성격을 띠었습니다.23 이러한 '반-체제적' DNA는 암호화폐가 상업적 필요에 의해 탄생한 주식과 근본적으로 다른 길을 걷게 만든 원동력입니다. 이 차이를 이해하는 것은 암호화폐 커뮤니티의 독특한 문화, 규제에 대한 강한 저항, 그리고 시장의 극단적인 변동성을 이해하는 핵심 열쇠가 됩니다.

 

알트코인(Altcoin)의 등장

 

비트코인의 성공 이후, 비트코인의 기술을 개선하거나 다른 목적을 가진 수많은 새로운 암호화폐가 등장하기 시작했습니다. 이들을 비트코인의 '대안(Alternative)'이라는 의미에서 **알트코인(Altcoin)**이라고 통칭합니다.20 초창기 알트코인으로는 비트코인보다 빠른 거래 속도를 목표로 한 라이트코인(Litecoin), 작업증명과 지분증명을 혼합한 피어코인(Peercoin) 등이 있었습니다.20 현재는 수만 종류가 넘는 알트코인이 각자의 목표와 기술을 가지고 경쟁하고 있으며, 이 중에는 혁신적인 기술을 가진 프로젝트도 있지만, 투자자를 현혹하기 위한 스캠(사기) 코인도 다수 존재하여 투자자의 각별한 주의가 요구됩니다.26

 

이더리움(Ethereum)과 스마트 컨트랙트의 혁신

 

알트코인 중 가장 중요한 혁신을 이룬 것은 비탈릭 부테린이 개발한 이더리움(Ethereum)입니다. 비트코인이 'P2P 전자화폐' 즉, 가치 저장과 전송 기능에 집중했다면, 이더리움은 **스마트 컨트랙트(Smart Contract)**라는 개념을 블록체인에 구현하여 그 활용 가능성을 무한히 확장시켰습니다.22

스마트 컨트랙트란 특정 계약 조건이 충족되었을 때, 사전에 프로그래밍된 내용이 제3자의 개입 없이 자동으로 실행되도록 하는 컴퓨터 프로토콜입니다.28 예를 들어, 'A가 B에게 10 이더(ETH)를 보내면, B가 소유한 부동산 등기 정보가 A에게 자동으로 이전된다'와 같은 계약을 코드로 구현할 수 있습니다. 이는 변호사나 등기소 같은 전통적인 중개 기관 없이도 신뢰 기반의 복잡한 계약을 체결할 수 있게 만들었으며, 오늘날

탈중앙화 금융(DeFi), 대체 불가능 토큰(NFT), 탈중앙화 자율 조직(DAO) 등 수많은 블록체인 혁신의 기술적 토대가 되었습니다.27

 

2.2. 암호화폐 시장의 작동 원리

 

암호화폐 시장은 전통 금융 시장과는 다른 독특한 기술과 원리에 의해 움직입니다.

 

핵심 기술: 블록체인과 합의 알고리즘

 

  • 블록체인 (Blockchain): 블록체인은 암호화폐의 모든 거래 기록을 담고 있는 공공 거래 장부입니다. 거래 데이터는 일정 시간 단위로 '블록(Block)'에 담기고, 이 블록들은 암호학적으로 이전 블록과 연결되어 '체인(Chain)' 형태를 이룹니다.29 이 체인은 네트워크에 참여하는 수많은 컴퓨터(노드)에 동일하게 복제 및 분산 저장(Distributed Ledger)되기 때문에, 특정 주체가 데이터를 임의로 위조하거나 변조하는 것이 극히 어렵습니다.20 이러한 특성 덕분에 중앙 관리 기관 없이도 데이터의 무결성과 투명성을 확보할 수 있습니다.
  • 합의 알고리즘 (Consensus Algorithm): 탈중앙화된 네트워크에서 누가 거래 기록(블록)을 장부에 추가할 권한을 가질지, 그리고 그 기록이 진짜임을 모든 참여자가 어떻게 합의할지를 정하는 규칙입니다.
  • 작업증명 (PoW, Proof-of-Work): 비트코인이 채택한 최초의 합의 알고리즘입니다. '채굴자(Miner)'라고 불리는 참여자들이 고성능 컴퓨터를 이용해 매우 복잡한 수학 문제를 푸는 경쟁을 벌이고, 가장 먼저 정답을 찾은 채굴자가 새로운 블록을 생성하고 그 보상으로 암호화폐를 받게 됩니다. 막대한 양의 컴퓨팅 파워와 전력을 소모해야 하므로 공격 비용이 매우 높아 네트워크 보안성이 뛰어나지만, 에너지 효율이 낮다는 비판을 받습니다.30
  • 지분증명 (PoS, Proof-of-Stake): 이더리움 등이 채택한 방식으로, 더 많은 암호화폐를 보유하고 예치(Staking)한 참여자에게 블록을 생성하고 검증할 확률을 더 높게 부여하는 방식입니다.31 PoW에 비해 에너지 소모가 거의 없어 친환경적이며, 네트워크에 자신의 자산을 담보로 걸기 때문에 악의적인 행동을 할 유인이 적다는 장점이 있습니다.

 

거래소: 중앙화(CEX) vs 탈중앙화(DEX)

 

암호화폐는 주로 거래소를 통해 매매됩니다. 거래소는 운영 주체에 따라 크게 두 종류로 나뉩니다.

  • 중앙화 거래소 (CEX, Centralized Exchange): 업비트, 빗썸, 바이낸스와 같이 특정 기업이 운영 주체가 되어 거래 시스템을 제공하고 사용자의 자산을 관리하는 플랫폼입니다.29 주식 거래소와 유사한 방식으로 주문서를 기반으로 거래를 중개하며, 사용이 간편하고 거래 속도가 빠르다는 장점이 있습니다. 하지만 사용자는 자신의 자산을 거래소에 맡겨야 하므로, 거래소가 해킹을 당하거나 파산할 경우 자산을 잃을 위험이 존재합니다.23
  • 탈중앙화 거래소 (DEX, Decentralized Exchange): 특정 운영 주체 없이 스마트 컨트랙트에 의해 자동화된 프로토콜로 운영되는 P2P 거래 플랫폼입니다.29 사용자는 개인 암호화폐 지갑을 직접 연결하여 거래하므로, 자산에 대한 통제권을 본인이 계속 유지할 수 있습니다. 이는 CEX의 수탁 위험(Custodial Risk)을 제거하여 보안성이 높지만, 사용법이 상대적으로 복잡하고 거래 속도가 느릴 수 있다는 단점이 있습니다.

 

가격 결정 요인

 

암호화폐의 가격 역시 기본적으로는 수요와 공급의 원리에 따라 결정되지만, 그 가격에 영향을 미치는 동인은 주식과 매우 다릅니다.32

  • 기술적 요인: 해당 암호화폐의 기반이 되는 블록체인 프로토콜의 업데이트, 확장성 문제 해결(예: 거래 처리 속도 개선), 새로운 기능 도입 등 기술적 진보가 가격에 직접적인 영향을 미칩니다.
  • 네트워크 효과: 암호화폐의 가치는 그 네트워크의 크기와 활성도에 크게 좌우됩니다. 사용자 수, 개발자 커뮤니티의 규모, 해당 블록체인 위에서 운영되는 탈중앙화 애플리케이션(dApp)의 수와 인기가 많을수록 네트워크의 가치는 상승합니다.
  • 시장 심리 및 뉴스: 암호화폐 시장은 아직 성숙 초기 단계에 있어, 시장 참여자들의 심리에 매우 민감하게 반응합니다. 유명인이나 인플루언서의 긍정적 또는 부정적 발언, 주요 국가의 규제 관련 뉴스, 대형 기관 투자자의 시장 진입 소식 등이 가격에 즉각적이고 폭발적인 영향을 미치는 경우가 많습니다.32
  • 희소성 (Scarcity): 비트코인처럼 총 발행량이 2,100만 개로 영원히 고정되어 있는 경우 24, 이 희소성은 인플레이션에 대한 방어 수단(Hedge)으로서의 가치를 부여하며 가격을 지지하는 중요한 요인으로 작용합니다.34

Part 3: 심층 비교 분석: 주식 vs 암호화폐

 

주식과 암호화폐는 모두 '투자 자산'이라는 공통점을 갖지만, 그 본질과 특성은 근본적으로 다릅니다. 성공적인 투자를 위해서는 두 자산 클래스 간의 핵심적인 차이점을 명확히 인지하는 것이 중요합니다. 이 장에서는 내재가치, 시장 운영 방식, 규제 환경 등 다양한 측면에서 두 시장을 심층적으로 비교 분석합니다.

 

3.1. 내재가치의 근본적 차이

 

자산의 가격을 결정하는 가장 근본적인 요소는 내재가치(Intrinsic Value)입니다. 주식과 암호화폐는 이 내재가치의 원천에서부터 극명한 차이를 보입니다.

  • 주식의 가치 근원: 기업의 이익 창출 능력
    주식의 가치는 본질적으로 그 주식을 발행한 기업의 미래 현금흐름 창출 능력에 기반합니다.35 기업은 자산과 노동력을 활용해 재화나 서비스를 생산 및 판매하고, 이를 통해 이익을 창출합니다. 주주는 그 기업의 소유주로서, 미래에 기업이 벌어들일 이익과 보유한 순자산에 대한 청구권을 갖습니다.34
    따라서 투자자들은 손익계산서, 재무상태표, 현금흐름표와 같은 명확한 재무제표를 통해 기업의 수익성, 안정성, 성장성을 분석할 수 있습니다.3 주가수익비율(PER), 주가순자산비율(PBR)과 같은 정량화된 가치 평가 지표들은 '내가 지불하는 가격 대비 얼마나 많은 이익이나 자산을 소유하게 되는가'를 측정하는 도구입니다.16 이처럼 주식 투자는 '소유'의 개념에 기반하며, 그 가치는 비교적 명확하고 합리적인 분석의 대상이 됩니다.
  • 암호화폐의 가치 근원: 네트워크의 효용과 믿음
    반면, 대부분의 암호화폐는 발행 주체의 실질적인 자산이나 이익 창출 능력에 기반하지 않습니다. 그 가치는 본질적으로 네트워크 자체의 가치에서 비롯되며, 이는 명확한 평가 모델이 정립되지 않아 매우 복합적이고 때로는 투기적인 성격을 띱니다.34 암호화폐의 가치를 구성하는 요소는 다음과 같이 다양합니다.
  • 유틸리티 가치 (Utility Value): 해당 블록체인 네트워크 상에서 특정 기능을 수행하기 위해 필요한 '사용권'으로서의 가치입니다. 예를 들어, 이더리움 네트워크에서 스마트 컨트랙트를 실행하거나 탈중앙화 애플리케이션(dApp)을 이용하기 위해서는 수수료(가스비)를 ETH로 지불해야 합니다.
  • 네트워크 효과 (Network Effect): '메칼프의 법칙(Metcalfe's Law)'으로 설명되기도 하며, 네트워크 참여자 수가 증가할수록 그 네트워크의 가치는 기하급수적으로 증가한다는 이론입니다. 더 많은 사람, 개발자, 기업이 특정 블록체인 생태계에 참여할수록 그 암호화폐의 가치는 높아집니다.
  • 희소성 및 '디지털 금' (Scarcity & 'Digital Gold'): 비트코인처럼 총 발행량이 코드로 고정되어 있는 경우, 중앙은행이 무한정 찍어낼 수 있는 법정화폐와 달리 그 희소성이 부각됩니다. 이로 인해 인플레이션 위험을 회피(Hedge)하기 위한 가치 저장 수단, 즉 '디지털 금'으로서의 역할을 기대받습니다.25
  • 거버넌스 권한 (Governance Rights): 일부 암호화폐(거버넌스 토큰)는 보유자에게 해당 블록체인 프로토콜의 향후 개발 방향이나 운영 정책에 대한 투표권을 부여합니다. 이는 주식의 의결권과 유사한 개념이지만, 기업이 아닌 프로토콜에 대한 참여 권한이라는 점에서 차이가 있습니다.

이처럼 주식의 가치 평가가 '소유'의 패러다임에 기반한다면, 암호화폐의 가치 평가는 '참여'의 패러다임에 가깝습니다. "가상자산 보유가 발행 기업의 지분 소유를 의미하지는 않는다"는 점은 36, 전통적인 가치 평가 모델이 암호화폐에 그대로 적용될 수 없음을 명확히 보여줍니다.34 투자자는 주식을 매수할 때 '이 회사는 미래에 돈을 얼마나 잘 벌 것인가?'를 질문하지만, 암호화폐를 매수할 때는 '이 네트워크는 미래에 얼마나 많은 사람에게, 얼마나 유용하게 사용될 것인가?'를 질문해야 합니다. 이 패러다임의 전환을 이해하는 것이 두 자산을 올바르게 평가하는 첫걸음입니다.

 

3.2. 시장 운영 및 규제의 차이

 

두 시장은 거래가 이루어지는 방식과 이를 감독하는 규제 체계에서도 현격한 차이를 보입니다.

  • 거래 시간:
  • 주식 시장: 각 국가의 증권거래소가 정한 정규 시간에만 거래가 가능합니다. 예를 들어 한국 주식 시장은 보통 평일 오전 9시부터 오후 3시 30분까지 운영되며, 주말과 공휴일에는 휴장합니다.34
  • 암호화폐 시장: 국경과 시간의 제약 없이 365일 24시간 내내 전 세계의 거래소에서 중단 없이 거래가 이루어집니다.29 이는 투자자에게 높은 접근성을 제공하지만, 잠자는 동안에도 급격한 가격 변동이 발생할 수 있는 위험을 내포합니다.
  • 가격 제한폭:
  • 주식 시장: 시장의 과도한 과열이나 충격을 방지하기 위해 일일 가격 변동폭에 제한(상한가/하한가, 현재 ±30%)을 둡니다.42 또한 주가 지수가 급락할 경우 시장 전체의 거래를 일시적으로 중단시키는 서킷브레이커(Circuit Breakers)나 프로그램 매매 호가의 효력을 정지시키는 사이드카(Sidecar)와 같은 시장 안정화 장치가 마련되어 있습니다.34
  • 암호화폐 시장: 이러한 가격 제한폭이나 시장 안정화 장치가 전혀 없습니다.34 따라서 이론적으로 가격의 상하한선이 없으며, 하루에도 수백 퍼센트의 등락이 발생하는 극단적인 변동성을 보일 수 있습니다.
  • 자산 보관 (Custody):
  • 주식: 투자자가 매수한 주식은 증권사를 통해 한국예탁결제원(KSD)과 같은 중앙화된 예탁 기관에 전자 등록 형태로 안전하게 보관됩니다. 투자자 본인이 직접 실물 주권을 관리할 필요가 없으며, 분실이나 도난의 위험이 거의 없습니다.
  • 암호화폐: 보관 방식이 이원화되어 있습니다. 하나는 거래소의 지갑에 보관하는 수탁형(Custodial) 방식이고, 다른 하나는 개인이 직접 관리하는 비수탁형(Non-custodial) 지갑(예: 하드웨어 월렛, 소프트웨어 월렛)에 보관하는 방식입니다. 거래소 보관은 편리하지만 해킹이나 파산 시 자산을 잃을 위험이 있고, 개인 지갑은 자산에 대한 완전한 통제권을 제공하는 대신 개인키(비밀번호) 분실이나 해킹에 대한 모든 책임을 본인이 져야 합니다.41
  • 규제 환경:
  • 주식 시장: 수십 년에서 수백 년에 걸쳐 발전해 온 자본시장법과 같은 강력하고 성숙한 법적, 제도적 규제 체계를 갖추고 있습니다. 미공개정보 이용, 시세조종 등 불공정거래를 엄격히 금지하고, 공시 제도를 통해 기업 정보의 투명성을 확보하며, 예금자보호법과는 별개로 투자자 보호를 위한 다양한 장치를 마련하고 있습니다.40
  • 암호화폐 시장: 역사가 짧아 전 세계적으로 규제 초기 단계에 있으며, 국가별로 접근 방식이 매우 다르고 법적 불확실성이 큰 상태입니다.20 한국은 2020년 특정금융정보법(특금법) 개정을 통해 거래소에 자금세탁방지(AML) 의무를 부과하고, 2024년 7월부터는 가상자산이용자보호법을 시행하여 이용자 자산 보호와 불공정거래 행위 금지에 대한 법적 근거를 마련하는 등 점진적으로 규제 틀을 구축하고 있습니다.48

 

3.3. SWOT 분석: 전략적 비교

 

두 시장의 복잡한 특성을 강점(Strength), 약점(Weakness), 기회(Opportunity), 위협(Threat)이라는 네 가지 기준으로 정리하면, 투자자가 각 시장의 전략적 환경을 한눈에 파악하고 정보에 입각한 의사결정을 내리는 데 도움이 됩니다. 다음 표는 관련 연구 자료들을 종합하여 두 시장을 SWOT 관점에서 분석한 결과입니다.40

Table 1: SWOT 분석: 주식 시장 vs. 암호화폐 시장

구분 (Category) 강점 (Strength) 약점 (Weakness) 기회 (Opportunity) 위협 (Threat)
주식 시장 (Stock Market) - 기업 실적 기반의 명확한 가치 평가 3
- 강력한 규제 및 투자자 보호 체계 40

- 배당 등 안정적 현금흐름 창출 가능 6

- 경제 성장과 함께 장기적 우상향 기대 17
- 제한된 거래 시간 및 낮은 유동성 40
- 상대적으로 낮은 변동성 및 수익률 기대치 40

- 정보 비대칭성 및 전문 지식 요구 3

- 거시 경제 변수(금리, 인플레이션)에 취약 40
- 기업 밸류업 프로그램 등 주주환원 정책 강화 17
- AI, 바이오 등 고부가가치 신산업 기업의 상장 17

- 글로벌 경제 성장에 따른 동반 성장
- 경기 침체 시 전반적인 시장 하락 위험 40
- 지정학적 리스크 및 무역 분쟁
- 급격한 금리 인상 및 통화 긴축
암호화폐 시장 (Crypto Market) - 365일 24시간 글로벌 거래 가능 41
- 높은 변동성으로 인한 초고수익 잠재력 40

- 탈중앙화 및 검열 저항성 21

- 기술 혁신에 따른 높은 성장 잠재력 40
- 극심한 가격 변동성 및 높은 위험 20
- 불분명한 가치 평가 기준 및 투기적 성격 34

- 규제 미비 및 투자자 보호 장치 부족 33

- 해킹, 사기, 시장 조작 등 보안 위험 노출 44
- 기관 투자자 참여 증가 및 제도권 편입 40
- DeFi, NFT, RWA 등 생태계 확장 30

- 기술 발전을 통한 새로운 금융 시스템으로의 전환 가능성 56
- 각국 정부의 예측 불가능한 강력한 규제 도입 33
- 시장 조작 및 시세 조종의 용이성 44

- 중앙은행 디지털화폐(CBDC) 도입에 따른 경쟁 및 대체 가능성 25

Part 4: 투자자의 무기, 용어와 분석 도구 대사전

 

성공적인 투자는 시장을 정확히 이해하고 분석하는 능력에서 비롯됩니다. 이를 위해서는 시장에서 통용되는 언어, 즉 핵심 용어와 데이터를 해석하는 도구인 분석 지표에 대한 깊이 있는 이해가 필수적입니다. 이 장에서는 주식과 암호화폐 시장에서 반드시 알아야 할 핵심 용어와 기술적 분석 도구들을 총정리하여 투자자의 무기고를 채워드립니다.

 

4.1. 주식 시장 핵심 용어

 

  • 시장 지수 (Market Index):
  • 코스피 (KOSPI - Korea Composite Stock Price Index): 대한민국 유가증권시장(제1시장)에 상장된 전체 기업의 주가 움직임을 종합하여 산출한 대표 주가지수입니다. 삼성전자, 현대차와 같은 대형주들이 포함되어 있어 한국 경제의 전반적인 흐름을 나타내는 지표로 활용됩니다.42
  • 코스닥 (KOSDAQ - Korean Securities Dealers Automated Quotations): 주로 정보기술(IT), 바이오기술(BT), 문화콘텐츠(CT) 관련 중소·벤처기업들이 상장된 시장의 주가지수입니다. 코스피에 비해 기업 규모는 작지만 성장 잠재력이 높은 기업들이 많아, 코스피보다 주가 변동성이 큰 경향을 보입니다.42
  • 가치 평가 지표 (Valuation Metrics):
  • PER (Price Earnings Ratio, 주가수익비율): 현재 주가를 1주당 순이익(EPS, Earnings Per Share)으로 나눈 값입니다. "시가총액 ÷ 당기순이익"으로도 계산됩니다. 이 지표는 기업이 벌어들이는 이익 1원당 주가가 몇 배로 평가받고 있는지를 나타냅니다. PER이 낮을수록 기업의 이익에 비해 주가가 상대적으로 저평가되어 있다고 해석할 수 있습니다.16
  • PBR (Price Book-value Ratio, 주가순자산비율): 현재 주가를 1주당 순자산(BPS, Book-value Per Share)으로 나눈 값입니다. "시가총액 ÷ 순자산(자본총계)"으로 계산됩니다. 이 지표는 기업의 장부상 자산가치 대비 주가가 어느 수준인지를 보여줍니다. 만약 PBR이 1보다 낮다면, 이는 회사가 당장 청산하더라도 주주가 돌려받는 돈이 현재 주가보다 많다는 의미로, 극심한 저평가 상태로 볼 수 있습니다.38
  • 거래 관련 용어:
  • 공매도 (Short Selling): 특정 주식의 가격 하락을 예상할 때 사용하는 투자 기법입니다. 실제로 주식을 보유하지 않은 상태에서 다른 투자자(주로 기관)로부터 주식을 빌려서 먼저 매도하고, 이후 주가가 실제로 하락하면 더 낮은 가격에 해당 주식을 다시 사들여 빌린 주식을 갚음으로써 그 차익을 얻는 방식입니다.47
  • 예수금, 증거금, 미수금, 반대매매:
  • 예수금: 주식 거래를 위해 증권 계좌에 입금해 둔 현금으로, 아직 주식 매수에 사용되지 않은 대기 자금을 말합니다.
  • 증거금: 주식을 외상으로 매수할 때 필요한 최소한의 보증금입니다.
  • 미수금: 증거금만 내고 주식을 매수한 뒤, 정해진 결제일(보통 T+2일)까지 납입하지 않은 외상 대금을 의미합니다.
  • 반대매매: 투자자가 미수금을 기한 내에 갚지 못할 경우, 증권사가 투자자의 의사와 상관없이 보유 주식을 강제로 매도하여 채권을 회수하는 절차입니다.61
  • 시가총액 (Market Capitalization): 특정 기업의 규모와 가치를 평가하는 대표적인 지표로, '현재 주가 × 총 발행 주식 수'로 계산됩니다. 시가총액이 클수록 시장에서 높은 가치를 인정받는 대기업으로 볼 수 있습니다.61

 

4.2. 암호화폐 시장 핵심 용어

 

암호화폐 시장은 기술과 문화가 결합된 독특한 생태계를 가지고 있어, 고유한 용어들이 많이 사용됩니다.

  • 생태계 관련 용어:
  • 디파이 (DeFi, Decentralized Finance): 은행, 증권사 등 전통적인 금융 중개기관 없이, 블록체인 위의 스마트 컨트랙트를 통해 예금, 대출, 파생상품 거래 등 다양한 금융 서비스를 제공하는 탈중앙화 금융 시스템을 총칭합니다.30
  • NFT (Non-Fungible Token, 대체 불가능 토큰): 블록체인 기술을 활용하여 디지털 파일에 고유한 인식 값을 부여한, 세상에 단 하나뿐인 디지털 자산입니다. 각 토큰이 고유하여 서로 대체할 수 없기 때문에, 디지털 아트, 음악, 게임 아이템, 멤버십 등의 소유권을 증명하고 거래하는 데 널리 사용됩니다.28
  • ICO (Initial Coin Offering): 새로운 블록체인 프로젝트나 암호화폐가 개발 및 운영 자금을 조달하기 위해, 프로젝트 초기에 투자자들에게 코인(토큰)을 판매하는 행위입니다. 주식 시장의 IPO와 개념적으로 유사하지만, 규제가 미비하고 사기 프로젝트가 많아 위험성이 매우 높습니다. 현재 대한민국에서는 ICO가 금지되어 있습니다.28
  • 투자 및 시장 현상 관련 용어:
  • 스테이킹 (Staking): 지분증명(PoS) 방식의 블록체인 네트워크에 참여하고 보안을 유지하는 데 기여하기 위해, 자신이 보유한 암호화폐를 특정 기간 동안 예치(락업)하는 행위입니다. 그 대가로 은행 예금 이자와 유사한 형태의 보상(추가 코인)을 받을 수 있습니다.66
  • 이자 농사 (Yield Farming): DeFi 프로토콜에 자신의 암호화폐를 예치하여 유동성을 공급하거나 담보로 대출해주고, 그 대가로 높은 이자 수익이나 해당 프로토콜의 거버넌스 토큰을 보상으로 받는 매우 적극적인 투자 전략입니다. 높은 수익률을 기대할 수 있지만, 스마트 컨트랙트의 버그, 프로토콜 해킹, 자산 가격 급락 등 고위험을 동반합니다.69
  • 김치 프리미엄 (Kimchi Premium): 동일한 암호화폐(예: 비트코인)가 해외 거래소보다 한국 내 거래소에서 더 높은 가격에 거래되는 현상을 말합니다. 한국 시장의 높은 투자 수요와 외환 규제로 인한 자금 이동의 제약 등이 원인으로 꼽힙니다.72 반대의 경우는 '역프리미엄(역프)'이라고 합니다.
  • HODL: 영어 단어 'HOLD(보유하다)'의 오타에서 유래한 인터넷 밈(meme)으로, 암호화폐의 단기적인 가격 변동에 일희일비하지 않고 장기적인 가치 상승을 믿으며 꿋꿋하게 보유하는 투자 전략을 의미합니다. 한국의 '존버(존나게 버티기)'와 유사한 맥락입니다.72
  • 가즈아 (Gazua), 투더문 (To the Moon): 자신이 투자한 암호화폐의 가격이 달까지 갈 정도로 폭등하기를 기원하는 투자자들의 희망과 열망이 담긴 구호이자 밈입니다.72

 

4.3. 기술적 분석 지표 및 패턴 가이드

 

기술적 분석은 과거의 가격 움직임과 거래량 데이터를 분석하여 미래의 가격 방향을 예측하려는 시도입니다.73 이는 주식과 암호화폐 시장 모두에서 널리 사용되는 분석 방법입니다.

  • 캔들스틱 차트 (Candlestick Chart): 기술적 분석의 가장 기본이 되는 도구로, 정해진 기간(분, 시간, 일, 주 등) 동안의 시가(Open), 종가(Close), 고가(High), 저가(Low)를 하나의 '봉(Candle)' 형태로 시각화한 차트입니다.74 봉의 색깔(양봉/음봉)과 몸통 및 꼬리의 길이를 통해 해당 기간 동안 매수 세력과 매도 세력 간의 힘겨루기 결과와 시장 참여자들의 심리를 직관적으로 파악할 수 있습니다.76
  • 양봉 (Bullish Candle): 종가가 시가보다 높게 마감한 경우로, 보통 붉은색으로 표시됩니다. 매수세가 매도세보다 강했음을 의미합니다.76
  • 음봉 (Bearish Candle): 종가가 시가보다 낮게 마감한 경우로, 보통 파란색으로 표시됩니다. 매도세가 매수세보다 강했음을 의미합니다.76
  • 주요 패턴: 캔들 한두 개의 모양이나 여러 캔들의 조합을 통해 추세의 지속 또는 반전을 예측할 수 있습니다. 대표적으로 망치형/교수형(추세 반전 가능성), 도지(시장 방향성의 불확실성 및 전환 가능성), 장악형(기존 추세를 압도하는 강력한 반전 신호) 등 수많은 패턴이 존재합니다.75
  • 차트 패턴 (Chart Patterns): 일정 기간 동안 주가나 코인 가격의 움직임이 만들어내는 특정 기하학적 모양으로, 이를 통해 향후 가격 추세를 예측하는 데 활용됩니다.
  • 반전형 패턴 (Reversal Patterns): 기존 추세가 마무리되고 새로운 반대 방향의 추세가 시작될 것을 암시하는 패턴입니다. 대표적으로 헤드앤숄더(Head and Shoulders), 쌍바닥(Double Bottom)/쌍천장(Double Top) 등이 있습니다.73
  • 지속형 패턴 (Continuation Patterns): 현재 진행 중인 추세가 잠시 쉬어간 뒤 다시 같은 방향으로 이어질 것임을 암시하는 패턴입니다. 대표적으로 삼각형(Triangle), 깃발형(Flag), 페넌트형(Pennant) 등이 있습니다.73
  • 주요 기술적 지표:
    가격 데이터를 수학적으로 가공하여 만든 보조 지표들은 투자자가 보다 객관적으로 시장 상황을 판단하고 매매 시점을 포착하는 데 도움을 줍니다. 다음 표는 업비트 이용자들이 가장 많이 사용하는 지표들을 포함하여 78, 주식과 암호화폐 시장에서 공통적으로 널리 쓰이는 핵심 기술적 지표들의 활용법을 정리한 것입니다.
    Table 2: 주요 기술적 분석 지표 활용법
지표명 (Indicator) 주요 목적 (Primary Purpose) 핵심 해석 및 활용법 (Key Interpretation & Application) 관련 자료 (Source)
이동평균선 (Moving Average, MA) 추세의 방향성 확인 및 지지/저항선 파악 - 정배열/역배열: 단기 이평선이 장기 이평선 위에 있으면 상승 추세(정배열), 아래에 있으면 하락 추세(역배열)로 판단합니다.
- 골든크로스/데드크로스: 단기 이평선이 장기 이평선을 위로 뚫고 올라가는 '골든크로스'는 강력한 매수 신호로, 반대로 아래로 뚫고 내려가는 '데드크로스'는 강력한 매도 신호로 해석됩니다.
72
볼린저 밴드 (Bollinger Bands) 가격의 변동성 및 상대적 과매수/과매도 구간 파악 - 밴드 폭: 밴드의 폭이 좁아지는 '수축(Squeeze)' 구간은 에너지가 응축되는 시기로, 이후 큰 가격 변동이 나타날 것을 예고합니다. 폭이 넓어지는 '확장'은 변동성이 크다는 의미입니다.
- 매매 전략: 가격이 상단 밴드에 닿거나 넘어서면 과매수(매도 고려), 하단 밴드에 닿거나 이탈하면 과매도(매수 고려) 상태로 해석하는 역추세 전략에 주로 활용됩니다.
78
상대강도지수 (RSI, Relative Strength Index) 가격 상승 압력과 하락 압력 간의 상대적 강도를 측정하여 과매수/과매도 수준을 판단하는 모멘텀 지표 - 기준선: 일반적으로 RSI 값이 70을 넘으면 과매수 구간으로, 향후 가격 하락 가능성을 시사합니다. 반대로 30 미만이면 과매도 구간으로, 가격 반등 가능성을 시사합니다.
- 다이버전스(Divergence): 가격은 신고점을 경신하는데 RSI의 고점은 낮아지는 '하락 다이버전스'는 추세 약화 및 하락 반전의 강력한 신호입니다.
72
이동평균수렴확산 (MACD) 두 이동평균선 간의 관계를 통해 추세의 방향, 강도, 그리고 전환 시점을 종합적으로 파악 - MACD선과 시그널선 교차: MACD선이 시그널선을 상향 돌파(골든크로스)하면 매수 신호, 하향 돌파(데드크로스)하면 매도 신호로 해석합니다.
- 오실레이터(히스토그램): 막대그래프가 0선을 기준으로 위에 있으면 상승 모멘텀이 강함을, 아래에 있으면 하락 모멘텀이 강함을 의미합니다.
78
일목균형표 (Ichimoku Cloud) 추세, 지지/저항, 모멘텀, 매매 신호를 하나의 차트에서 종합적으로 보여주는 선행성 지표 - 구름대(Cloud): 가격이 구름대 위에 위치하면 상승 추세, 아래에 위치하면 하락 추세로 판단합니다. 구름대는 그 자체로 강력한 지지선 또는 저항선 역할을 합니다.
- 전환선/기준선 교차: 단기 추세선인 전환선이 중기 추세선인 기준선을 상향 돌파하면 매수 신호(호전), 하향 돌파하면 매도 신호(역전)로 봅니다.
78

Part 5: 견고한 투자 전략 구축

 

시장에 대한 이해와 분석 도구를 갖추었다면, 다음 단계는 이를 바탕으로 자신만의 견고한 투자 전략을 수립하는 것입니다. 어떤 자산에, 어떤 방식으로, 어떤 원칙을 가지고 투자할 것인지를 정하는 것은 장기적인 성공의 핵심입니다. 이 장에서는 수십 년간 검증된 주식 투자 전략과 새롭게 부상하는 암호화폐 투자 전략, 그리고 모든 투자의 기본이 되는 포트폴리오 구성 및 위험 관리 방안을 제시합니다.

 

5.1. 검증된 주식 투자 전략

 

주식 시장의 오랜 역사만큼이나 다양한 투자 전략이 존재하지만, 크게 세 가지 접근법으로 분류할 수 있습니다.

  • 가치 투자 (Value Investing): '투자의 현인' 워렌 버핏으로 대표되는 가장 고전적이면서도 강력한 투자 철학입니다. 가치 투자의 핵심은 기업의 본질적인 가치, 즉 내재가치(Intrinsic Value)를 계산하고, 현재 시장 가격이 그 내재가치보다 현저히 낮게 거래될 때 주식을 매수하는 것입니다.19 이렇게 확보된 '내재가치와 시장 가격의 차이'를 **안전마진(Margin of Safety)**이라고 부르며, 이는 잠재적 손실을 방어하는 완충재 역할을 합니다. 가치 투자자는 시장의 단기적인 변동이나 심리에 휘둘리지 않고, 기업의 장기적인 펀더멘털에 집중하며, 시장이 결국 기업의 진정한 가치를 알아보는 날까지 인내심을 갖고 주식을 장기 보유하는 전략을 취합니다.12
  • 성장주 투자 (Growth Investing): 현재의 이익이나 자산가치보다는 미래의 높은 성장 잠재력에 초점을 맞추는 전략입니다.19 성장주 투자자는 매출과 이익이 시장 평균보다 훨씬 빠르게 성장하고 있는 기업, 혁신적인 기술이나 비즈니스 모델로 새로운 시장을 창출하는 기업을 발굴하여 투자합니다. 이러한 기업들은 높은 PER이나 PBR을 기록하는 경우가 많아 전통적인 가치 투자 관점에서는 고평가된 것처럼 보일 수 있습니다. 성장주 투자는 성공할 경우 폭발적인 자본 차익을 얻을 수 있지만, 성장이 둔화되거나 시장의 기대에 미치지 못할 경우 주가 하락폭도 매우 클 수 있는 고위험-고수익 전략입니다.
  • 인덱스 펀드 및 ETF를 통한 패시브 투자 (Passive Investing via Index Funds & ETFs): 특정 시장 지수(예: 코스피 200, S&P 500)의 움직임을 그대로 따라가도록 설계된 금융상품에 투자하여, 시장 전체의 평균적인 수익률을 추구하는 전략입니다.19 개별 기업을 분석하고 선택하는 '액티브(Active)' 투자와 달리, 시장 자체를 사는 '패시브(Passive)' 접근법입니다. 인덱스 펀드나 상장지수펀드(ETF)에 투자하면, 소액으로도 수십, 수백 개의 우량 기업에 자동으로 분산 투자하는 효과를 누릴 수 있습니다.19 이는 개별 종목 선택의 어려움과 위험을 피하고, 낮은 운용 비용으로 장기적인 자산 증식을 목표로 하는 투자자들에게 매우 효과적인 방법으로 입증되었습니다.19

 

5.2. 새로운 암호화폐 투자 전략

 

암호화폐 시장은 역사가 짧고 변동성이 극심하여 아직 정형화된 투자 전략이 많지는 않지만, 시장의 특성을 반영한 몇 가지 대표적인 전략들이 존재합니다.

  • HODL (장기 보유): 암호화폐 커뮤니티에서 가장 널리 알려진 기본적인 전략으로, 특정 암호화폐(주로 비트코인)의 장기적인 가치 상승과 기술적 잠재력을 믿고, 단기적인 가격 폭등이나 폭락에 흔들리지 않고 묵묵히 보유하는 것을 의미합니다.72 이는 해당 자산이 결국 주류로 편입되고 가치가 크게 상승할 것이라는 강한 신념에 기반합니다.
  • 스테이킹 (Staking): 단순히 보유하는 것을 넘어, 보유한 암호화폐를 활용해 추가 수익을 창출하는 전략입니다. 지분증명(PoS) 방식의 블록체인 네트워크에 자신이 보유한 코인을 일정 기간 예치(락업)하면, 네트워크의 보안과 운영에 기여한 대가로 추가적인 코인을 이자처럼 보상받을 수 있습니다.66 이는 장기 보유(HODL) 전략과 결합하여 복리 효과를 누릴 수 있는 방법으로, 은행 예금과 유사한 개념으로 이해할 수 있습니다.67
  • 이자 농사 (Yield Farming) 및 유동성 공급: DeFi 생태계에서 사용되는 가장 적극적이고 복잡한 고수익·고위험 전략입니다.69 투자자들은 탈중앙화 거래소(DEX)나 대출 프로토콜과 같은 DeFi 서비스에 자신의 암호화폐 쌍(예: ETH/USDT)을 예치하여 '유동성 공급자(Liquidity Provider)'가 됩니다. 프로토콜은 이 유동성을 활용하여 거래나 대출 서비스를 원활하게 만들고, 그 대가로 유동성 공급자에게 거래 수수료의 일부나 해당 프로토콜의 거버넌스 토큰을 보상으로 지급합니다.70 연이율(APY)이 수백, 수천 퍼센트에 달하는 경우도 있지만, 스마트 컨트랙트의 취약점(해킹), 비영구적 손실(Impermanent Loss), 토큰 가격 폭락 등 매우 높은 위험을 감수해야 합니다.

여기서 중요한 점은 암호화폐에서 얻는 '이자'나 '수익'이 주식의 '배당'과는 그 원천이 근본적으로 다르다는 것입니다. 주식의 배당은 기업이 실제 영업 활동을 통해 창출한 '이익'을 소유주인 주주에게 분배하는, 경제적 가치 창출의 결과물입니다.6 반면, 스테이킹 보상은 네트워크 보안 유지라는 '서비스 제공'에 대한 대가로, 그 재원은 주로 새로 발행되는 토큰(즉, 인플레이션)이나 네트워크 사용자들이 지불하는 거래 수수료에서 나옵니다.67 이는 이익 분배라기보다는 네트워크 운영 비용 지급에 가깝습니다. 이자 농사의 보상 역시 유동성 공급이라는 '위험 감수'에 대한 인센티브로, 주로 해당 프로토콜의 거버넌스 토큰으로 지급됩니다.70 이는 현재의 이익 분배가 아닌, '프로토콜의 미래 가치에 대한 약속'에 가깝습니다. 따라서 투자자는 암호화폐의 '고수익률'이라는 용어 이면에 있는 수익의 원천이 무엇인지 명확히 파악해야 하며, 이는 수익의 질과 지속 가능성, 그리고 내재된 위험을 평가하는 데 결정적인 차이를 만듭니다.

 

5.3. 포트폴리오 구성과 위험 관리

 

어떤 투자 전략을 선택하든, 모든 투자의 성공은 결국 위험 관리에 달려있습니다. 각 자산 클래스가 가진 고유한 위험을 이해하고 이를 관리하기 위한 체계적인 계획을 세워야 합니다.

  • 주식 투자의 주요 위험 및 관리 방안:
  • 시장 위험 (Systematic Risk): 금리 인상, 경기 침체, 전쟁 등 시장 전체에 영향을 미치는 거시적 요인으로 인해 개별 기업의 펀더멘털과 무관하게 주가가 하락하는 위험입니다. 이는 분산투자로도 완전히 피할 수 없는 위험입니다.50
  • 개별 기업 위험 (Unsystematic Risk): 특정 기업의 경영 악화, 신제품 실패, 경쟁 심화, 회계 부정, 경영진의 도덕적 해이 등 해당 기업에만 국한된 요인으로 인해 주가가 하락하는 위험입니다.37
  • 유동성 위험 (Liquidity Risk): 거래량이 적은 소형주나 비인기 종목의 경우, 원하는 시점에 원하는 가격으로 주식을 매수하거나 매도하기 어려운 위험입니다. 급하게 매도해야 할 경우 큰 손실을 보고 팔아야 할 수도 있습니다.50
  • 관리 방안:
  1. 분산 투자: '모든 계란을 한 바구니에 담지 말라'는 격언처럼, 다양한 산업, 국가, 자산 크기(대형주/소형주)에 걸쳐 포트폴리오를 구성하여 개별 기업 위험을 효과적으로 줄일 수 있습니다.82
  2. 손절매 (Stop-loss) 원칙 수립: 주가가 특정 수준 이하로 하락하면 기계적으로 매도하여 더 큰 손실을 방지하는 원칙을 미리 세우고 지키는 것이 중요합니다.
  3. 지속적인 펀더멘털 분석: 투자한 기업의 재무 상태, 실적, 경쟁 환경 등을 정기적으로 점검하여 위험 요인을 사전에 파악하고 대응해야 합니다.
  • 암호화폐 투자의 주요 위험 및 관리 방안:
  • 극심한 변동성 위험 (Volatility Risk): 명확한 내재가치 평가 모델의 부재, 규제 불확실성, 투기적 수요 집중 등으로 인해 자산 가격이 단기간에 수십 퍼센트씩 급등락하는 위험입니다. 이는 암호화폐 투자의 가장 큰 특징이자 가장 큰 위험입니다.20
  • 보안 위험 (Security Risk): 중앙화된 관리 주체가 없기 때문에 보안에 대한 책임이 전적으로 개인에게 있습니다. 거래소 해킹, 개인키 분실 및 도난, 피싱 사기, 그리고 처음부터 투자금 편취를 목적으로 만들어진 스캠(Scam) 프로젝트의 위험이 상존합니다.44
  • 규제 위험 (Regulatory Risk): 각국 정부의 갑작스러운 규제 발표나 정책 방향의 변경이 시장 전체에 엄청난 충격을 줄 수 있는 위험입니다. 거래소 폐쇄, 특정 코인 거래 금지, 과세 강화 등의 조치는 가격 폭락의 직접적인 원인이 될 수 있습니다.33
  • 관리 방안:
  1. 감당 가능한 소액 투자: 전 재산을 투자하는 것은 절대 금물이며, 잃어도 일상생활에 지장이 없는 소액의 여유 자금으로만 투자해야 합니다.
  2. 개인 지갑 사용: 특히 장기 보유할 목적의 자산은 해킹 위험이 있는 거래소보다는 보안성이 높은 개인 지갑, 그중에서도 오프라인으로 개인키를 보관하는 하드웨어 월렛(Hardware Wallet)에 보관하는 것이 안전합니다.
  3. 철저한 자체 조사 (DYOR, Do Your Own Research): 특정 프로젝트에 투자하기 전에 백서(Whitepaper)를 읽고, 개발팀의 이력과 로드맵을 확인하며, 커뮤니티의 활동을 살펴보는 등 스스로 철저히 조사하고 판단하는 습관이 필수적입니다.

Part 6: 시장의 미래와 규제의 지평선

 

투자 시장은 정체되어 있지 않고 끊임없이 진화합니다. 특히 기술 발전과 규제 환경의 변화는 주식과 암호화폐 시장의 미래를 결정짓는 가장 중요한 변수입니다. 이 장에서는 두 시장을 둘러싼 규제의 현재와 미래를 살펴보고, 기관 투자자의 진입, 중앙은행 디지털화폐(CBDC)의 등장 등 미래 시장의 판도를 바꿀 핵심 트렌드를 전망합니다.

 

6.1. 진화하는 규제 환경

 

규제는 투자자를 보호하고 시장의 건전성을 유지하는 필수적인 장치입니다. 주식 시장은 성숙한 규제 체계를 갖춘 반면, 암호화폐 시장은 이제 막 규제의 틀이 만들어지는 과정에 있습니다.

  • 한국 주식 시장 규제: 한국의 주식 시장은 **자본시장과 금융투자업에 관한 법률(자본시장법)**을 근간으로 하는 정교하고 성숙한 규제 시스템을 갖추고 있습니다. 이 시스템의 주요 목표는 시장의 공정성과 투명성을 확보하고 투자자를 보호하는 것입니다.
  • 불공정거래 방지: 미공개 중요 정보를 이용한 내부자 거래, 주가를 인위적으로 조작하는 시세조종 행위, 허위 사실 유포 등을 엄격히 금지하고 위반 시 강력한 법적 처벌을 가합니다.85
  • 공매도 규제: 무차입 공매도를 원칙적으로 금지하고, 공매도 잔고 보고 및 공시 의무를 부과하며, 시장 과열 시 특정 종목의 공매도를 제한하는 등 개인 투자자와 기관 투자자 간의 '기울어진 운동장' 문제를 해소하기 위한 규제를 지속적으로 강화하고 있습니다.47
  • 상장 및 상장폐지 관리: 투자자 보호를 위해 증권거래소에 상장하려는 기업에 대해 엄격한 재무 및 비재무적 요건을 심사하고, 일정 기준에 미달하는 부실 기업은 관리종목으로 지정하거나 시장에서 퇴출(상장폐지)시키는 제도를 운영합니다.46
  • 주주가치 제고 유도: 최근에는 '코리아 디스카운트' 현상을 해소하고 기업의 주주가치 제고 노력을 촉진하기 위해 '기업 밸류업 프로그램'과 같은 정책을 도입하며 시장 체질 개선을 유도하고 있습니다.51
  • 한국 암호화폐 규제 동향: 초기의 완전한 무규제 상태에서 투기 과열, 자금 세탁, 해킹 등 각종 부작용이 속출하자, 한국 정부는 투자자 보호와 시장 투명성 확보를 목표로 점진적으로 규제 체계를 마련해왔습니다.48
  • 특정금융정보법 (특금법): 2021년 시행된 특금법은 암호화폐 거래소에 자금세탁방지(AML) 및 테러자금조달방지(CFT) 의무를 부과하고, 은행으로부터 실명확인 입출금 계정을 발급받도록 의무화했습니다. 이를 통해 음성적인 거래를 양성화하고 거래소의 책임성을 강화하는 기반을 마련했습니다.48
  • 가상자산이용자보호법: 2024년 7월 19일부터 시행된 이 법은 한국 최초의 본격적인 암호화폐 업권법입니다. 주요 내용은 ① 이용자의 예치금을 안전하게 분리 보관하고, ② 해킹 등에 대비한 보험 가입을 의무화하며, ③ 미공개 중요정보 이용, 시세조종 등 불공정거래 행위를 금지하고 처벌하는 것입니다. 이는 투자자 보호를 제도적으로 강화하는 중요한 첫걸음으로 평가됩니다.48
  • 향후 과제: 현재 규제 체계는 아직 초기 단계입니다. 향후 가상자산 소득에 대한 과세 문제를 어떻게 해결할 것인지, 주식과 유사한 성격을 가진 **증권형 토큰(STO, Security Token Offering)**을 자본시장법 체계 내에서 어떻게 포용하고 유통시킬 것인지 등 여전히 해결해야 할 중요한 규제적 과제들이 남아있습니다.36

 

6.2. 투자 시장의 미래 전망

 

기술 발전과 새로운 참여자들의 등장은 두 시장의 미래를 더욱 예측하기 어렵게, 그러나 한편으로는 더욱 흥미롭게 만들고 있습니다.

  • 기관 투자자의 진입과 시장의 성숙:
    과거 암호화폐 시장은 주로 개인 투자자들이 주도하는 변방의 시장으로 여겨졌습니다. 그러나 최근 몇 년 사이 연기금, 자산운용사, 헤지펀드 등 막대한 자금을 운용하는 기관 투자자들이 본격적으로 시장에 진입하고 있습니다.39
    특히 2024년 초 미국 증권거래위원회(SEC)가 비트코인 현물 ETF를 승인한 것은 시장의 판도를 바꾼 결정적인 사건이었습니다.53 이는 기관 투자자들이 규제 안에서 합법적으로, 그리고 대규모로 비트코인에 투자할 수 있는 길을 열어주었습니다. 기관 자금의 유입은 시장에 막대한 유동성을 공급하고, 극심했던 변동성을 점차 완화시키며, 암호화폐를 주류 투자 자산군(Asset Class)으로 편입시키는 촉매제 역할을 할 것으로 기대됩니다.
    이러한 제도권 편입은 암호화폐의 초기 정신이었던 탈중앙화와 반-체제적 성격을 희석시킬 수 있다는 점에서 '야성을 길들이는 양날의 검'이 될 수 있습니다. 시장은 안정성과 대중성을 얻는 대신, 전통 금융 시장의 논리와 거시 경제 변수에 더욱 깊이 종속될 것입니다.87 앞으로 암호화폐의 미래는 '사이퍼펑크의 이상'과 '월스트리트의 자본' 사이의 타협점을 찾아가는 과정이 될 것이며, 투자자들은 이 과정에서 암호화폐가 얻는 것과 잃는 것을 모두 이해해야 합니다.
  • 중앙은행 디지털화폐(CBDC)의 영향:
    전 세계 대부분의 중앙은행들은 법정화폐의 디지털 버전인 **중앙은행 디지털화폐(CBDC, Central Bank Digital Currency)**에 대한 연구 및 개발을 활발히 진행하고 있습니다.57 CBDC는 중앙은행이 직접 발행하고 지급을 보증하므로 가치 변동의 위험이 없고, 국가의 통제 하에 있어 안정적이라는 장점을 가집니다.25
    CBDC가 상용화될 경우, 이는 민간 암호화폐 시장에 중대한 영향을 미칠 수 있습니다. 특히 달러와 같은 법정화폐에 가치를 연동하는 민간 스테이블코인이나, 단순히 결제 및 송금 기능에 초점을 맞춘 일부 암호화폐는 CBDC와의 직접적인 경쟁에 직면하며 그 입지가 크게 위축될 수 있습니다.57
    하지만 모든 암호화폐가 CBDC에 의해 대체될 가능성은 낮습니다. 총 발행량이 제한된 비트코인의 '디지털 금'으로서의 자산적 가치나, 탈중앙화된 애플리케이션 플랫폼으로서 이더리움이 가진 '스마트 컨트랙트' 기능은 중앙은행이 통제하는 CBDC가 제공하기 어려운 고유의 영역입니다.25 따라서 미래에는 CBDC가 일상적인 결제를 담당하고, 특정 암호화폐들은 각자의 고유한 기능(가치 저장, DeFi 플랫폼 등)을 수행하며 서로 다른 영역에서 공존할 가능성이 높습니다.25
  • 기술 발전과 시장의 융합:
    블록체인 기술의 발전은 금융 시장의 경계를 허물고 새로운 형태의 투자를 가능하게 할 것입니다. 인공지능(AI)을 활용한 알고리즘 트레이딩과 시장 예측 기술은 더욱 정교해질 것이며 90, 이는 인간의 감정적 판단을 배제한 데이터 기반의 투자를 확산시킬 것입니다.
    가장 주목할 만한 트렌드는 주식, 채권, 부동산과 같은 전통적인 실물 자산(Real-World Asset)을 블록체인 위에서 토큰화하여 거래하는 **실물자산 토큰(RWA, Real-World Asset tokenization)**입니다.55 RWA는 유동성이 낮았던 고가의 자산을 잘게 쪼개어 소액으로도 투자할 수 있게 하고, 24시간 글로벌 거래를 가능하게 하며, 거래 비용을 절감하는 등 전통 금융과 디지털 자산 시장의 장점을 결합한 혁신을 가져올 것입니다. 이는 미래 투자 시장이 어느 한쪽에 치우치는 것이 아니라, 두 시장이 기술적으로 융합하며 함께 발전해 나갈 것임을 시사합니다.

결론: 현명한 투자자를 위한 최종 제언

 

본 보고서는 주식과 암호화폐라는 두 거대한 자산 시장의 기초부터 미래 전망까지를 포괄적으로 분석했습니다. 두 시장은 표면적으로는 유사해 보이지만, 그 탄생 배경, 내재가치의 원천, 작동 방식, 그리고 위험의 종류에 있어 근본적인 차이를 지니고 있습니다. 이 모든 분석을 종합하여, 현명한 투자자가 되기 위한 최종적인 제언을 다음과 같이 제시합니다.

  • 투자 철학의 정립: 모든 투자의 성공은 '자신을 아는 것'에서 시작합니다. 이 보고서에서 다룬 바와 같이, 주식 투자는 '기업의 성장을 공유'하는 행위이며, 암호화폐 투자는 '기술 네트워크의 미래 가치에 베팅'하는 행위에 가깝습니다. 자신은 안정적인 현금흐름과 예측 가능한 성장을 선호하는지, 아니면 높은 위험을 감수하더라도 혁신 기술의 폭발적인 성장에 참여하고 싶은지를 명확히 해야 합니다. 자신만의 투자 철학을 정립하는 것이 수많은 정보와 시장의 소음 속에서 길을 잃지 않는 첫걸음입니다.
  • 위험에 대한 이해와 분산 투자: 고수익에는 항상 고위험이 따릅니다. 주식 시장은 거시 경제와 기업 실적의 위험을, 암호화폐 시장은 극심한 변동성과 규제, 기술적 위험을 내포하고 있습니다. 자신의 위험 감수 능력을 객관적으로 평가하고 82, 감당할 수 있는 범위 내에서 투자하는 것이 무엇보다 중요합니다. 또한, 특정 자산이나 종목에 모든 자산을 집중하는 '올인' 투자는 매우 위험합니다. 주식, 암호화폐, 그리고 채권, 부동산 등 다른 자산군에 걸쳐 적절히 자산을 배분하는 분산 투자는 변동성을 관리하고 장기적으로 안정적인 성과를 내는 가장 현명하고 검증된 방법입니다.
  • 끊임없는 학습의 중요성: 주식 시장은 수백 년의 역사를 통해 축적된 지혜를 담고 있으며, 암호화폐 시장은 불과 10여 년 만에 세상을 바꾸는 혁신을 거듭하고 있습니다. 두 시장 모두 정체되어 있지 않고 끊임없이 진화합니다. 어제의 성공 공식이 내일의 실패 요인이 될 수 있습니다. 진정으로 성공하는 투자자는 한두 번의 성공에 안주하는 사람이 아니라, 시장의 변화를 겸허히 받아들이고 과거의 데이터와 현재의 트렌드, 그리고 미래의 가능성을 끊임없이 학습하며 자신의 지식과 전략을 지속적으로 업데이트하는 사람입니다.

이 보고서가 독자 여러분의 성공적인 투자 여정에 든든하고 신뢰할 수 있는 초석이 되기를 바랍니다.

참고 자료

  1. 주식은 누가, 왜, 어떻게 처음 만들게 된 것일까? : 네이버 블로그, 6월 14, 2025에 액세스, https://blog.naver.com/nhinvest_official/222137402896?viewType=pc
  2. 알고 싶어요 주식시장, 6월 14, 2025에 액세스, https://main.krxverse.co.kr/_contents/ACA/02/02010201/02.pdf
  3. 주식 투자의 기본개념, 6월 14, 2025에 액세스, https://brunch.co.kr/@a1cba2e3ded9427/4
  4. ko.wikipedia.org, 6월 14, 2025에 액세스, https://ko.wikipedia.org/wiki/%EC%A3%BC%EC%8B%9D#:~:text=%EC%A3%BC%EC%8B%9D(%E6%A0%AA%E5%BC%8F%2C%20%EC%98%81%EC%96%B4%3A%20share,%EC%9D%B4%EB%A5%BC%20%EB%82%98%ED%83%80%EB%82%B4%EB%8A%94%20%EC%A6%9D%EA%B6%8C%EC%9D%84%20%EB%A7%90%ED%95%9C%EB%8B%A4.
  5. 주식 - 나무위키, 6월 14, 2025에 액세스, https://namu.wiki/w/%EC%A3%BC%EC%8B%9D
  6. 주식의 기본 개념에 대해 알고가자!, 6월 14, 2025에 액세스, https://brunch.co.kr/@00b68069c88e4c0/46
  7. 주식 - 위키백과, 우리 모두의 백과사전, 6월 14, 2025에 액세스, https://ko.wikipedia.org/wiki/%EC%A3%BC%EC%8B%9D
  8. 네덜란드 동인도 회사 - 나무위키, 6월 14, 2025에 액세스, https://namu.wiki/w/%EB%84%A4%EB%8D%9C%EB%9E%80%EB%93%9C%20%EB%8F%99%EC%9D%B8%EB%8F%84%20%ED%9A%8C%EC%82%AC
  9. 주식 시장의 역사와 발전 과정, 6월 14, 2025에 액세스, https://www.ebc.com/kr/forex/6918.html
  10. 세계 최초의 주식회사 네덜란드 동인도회사의 역사 : 네이버 블로그, 6월 14, 2025에 액세스, https://blog.naver.com/wildhistory/223645303326
  11. 주식투자의 기원 네덜란드 해상무역 선단에서 시작 - 생글생글, 6월 14, 2025에 액세스, https://sgsg.hankyung.com/article/2021010809191
  12. [전자책] 주린이를 위한 친절한 주식공부 - 예스24, 6월 14, 2025에 액세스, https://m.yes24.com/Goods/Detail/105176461
  13. 주식시장, 어떻게 움직이나? | click 경제교육, 6월 14, 2025에 액세스, https://eiec.kdi.re.kr/material/clickView.do?click_yymm=200908&cidx=1054
  14. 주식은 무엇을 의미하며 어떻게 작동하나요?, 6월 14, 2025에 액세스, https://b2broker.com/ko/news/what-do-equities-stand-for-and-how-do-they-work/
  15. 초보도 쉽게 배우는 주식시장 비밀! - YouTube, 6월 14, 2025에 액세스, https://www.youtube.com/watch?v=FOt6bMDi6vw
  16. 주식시장 -증시 밸류에이션 평가 - 5가지 주요 측정방법 - Schroders, 6월 14, 2025에 액세스, https://www.schroders.com/ko-kr/kr/intermediary/insights/how-to-value-stockmarkets/
  17. 주식시장의 역사를 통해 보는 주식의 본질 : 네이버 블로그, 6월 14, 2025에 액세스, https://blog.naver.com/newsystock/223751008266
  18. 증권시장의 이해, 6월 14, 2025에 액세스, http://main.krxverse.co.kr/_contents/ACA/02/02010200/file/220104_beginner.pdf
  19. 펀드 유형 상세 Ⅱ | 펀드 설명서 | 삼성자산운용, 6월 14, 2025에 액세스, https://www.samsungfund.com/fund/insight/guide/view04.do
  20. 암호화폐의 역사, 6월 14, 2025에 액세스, https://rue.ee/kr/blog/cryptocurrency-history/
  21. 그렇다면 암호화폐란 정확히 무엇일까요? - Ledger, 6월 14, 2025에 액세스, https://www.ledger.com/ko/academy/%EA%B7%B8%EB%A0%87%EB%8B%A4%EB%A9%B4-%EC%95%94%ED%98%B8%ED%99%94%ED%8F%90%EB%9E%80-%EC%A0%95%ED%99%95%ED%9E%88-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C%EC%9A%94
  22. 암호화폐 - 나무위키, 6월 14, 2025에 액세스, https://namu.wiki/w/%EC%95%94%ED%98%B8%ED%99%94%ED%8F%90
  23. 초등학생도 이해하는 비트코인 원리 - YouTube, 6월 14, 2025에 액세스, https://m.youtube.com/watch?v=5dkaMkcTgNA&pp=ygUHI-ykgO2ZlA%3D%3D
  24. 비트코인이란 무엇인가? 그 역사, 특징, 장단점 등, 6월 14, 2025에 액세스, https://kr.cointelegraph.com/learn/articles/what-is-bitcoin
  25. CBDC는 화폐, 코인은 자산 성격 강해 | 나라경제 | KDI 경제교육·정보 ..., 6월 14, 2025에 액세스, https://eiec.kdi.re.kr/publish/naraView.do?fcode=00002000040000100021&cidx=13488&sel_year=2021&sel_month=09
  26. 알트코인 - 나무위키, 6월 14, 2025에 액세스, https://namu.wiki/w/%EC%95%8C%ED%8A%B8%EC%BD%94%EC%9D%B8
  27. 암호화폐 - 위키백과, 우리 모두의 백과사전, 6월 14, 2025에 액세스, https://ko.wikipedia.org/wiki/%EC%95%94%ED%98%B8%ED%99%94%ED%8F%90
  28. 알면 도움이 되는가상화폐 용어 4탄 : 네이버 블로그, 6월 14, 2025에 액세스, https://blog.naver.com/pobain/223594162204?fromRss=true&trackingCode=rss
  29. 암호화폐 거래 방법: 초보자를 위한 거래 가이드 - LiteFinance, 6월 14, 2025에 액세스, https://www.litefinance.org/ko/blog/for-beginners/amhohwapye-geolae-bangbeob/
  30. 암호화폐의 역사와 기술, 그리고 분산금융, 6월 14, 2025에 액세스, https://researcher.hf.go.kr/researcher/sub04/sub04.do?mode=download&articleNo=308119&attachNo=57583
  31. [분석]암호화폐는 수익구조와 기능이 다양하다 - 미래한국, 6월 14, 2025에 액세스, https://www.futurekorea.co.kr/news/articleView.html?idxno=146020
  32. 코인이 오르는 원리가 뭐야 | 물어봐 AI - 요즘IT, 6월 14, 2025에 액세스, https://yozm.wishket.com/magazine/questions/share/I0EA8wUoTuZb93Ww/
  33. 10분 만에 살펴보는 비트코인 투자 기술: 재테크 가이드 - Naver Blog, 6월 14, 2025에 액세스, https://blog.naver.com/police1965/223400181003
  34. [코린이 설명서①] 본질적으로 다르다…코인과 주식의 차이점 8가지 - 경제 | 기사 - 더팩트, 6월 14, 2025에 액세스, https://news.tf.co.kr/read/economy/1857582.htm
  35. 암호화폐의 본질과 그 평가기준에 관한 소고(小考), 6월 14, 2025에 액세스, https://www.klri.re.kr/cmm/fms/FileDown.do?atchFileId=FILE_000000000012883uYEWw&fileSn=0&stat=journal¶m_gubun=Z&data_no=59
  36. 가상자산 사도 될까? 주식 거래와 다른 점 5가지 - 쟁글, 6월 14, 2025에 액세스, https://xangle.io/research/detail/1048
  37. [투자] 주식 초보자를 위한 위험 종목 피하는 법 (feat. 관리종목 ..., 6월 14, 2025에 액세스, https://blog.naver.com/dream_asset/223402009589
  38. 코리아 디스카운트 뜻과 PER PBR 등 주식용어 살펴보기 - 블로그, 6월 14, 2025에 액세스, https://blog.naver.com/kfcc_no1/223529392115
  39. 비트코인 얼마까지 치솟을까? `기관투자자들 시장 진입에 상승 여력 충분` - 매일신문, 6월 14, 2025에 액세스, https://www.imaeil.com/page/view/2021010511081959952
  40. 주식 시장 vs 암호화폐 시장 심층 분석, 6월 14, 2025에 액세스, https://brunch.co.kr/@mentats1/682
  41. 주식과 암호화폐, 어느 게 더 잘 벌까? with 기욤 패트리 - YouTube, 6월 14, 2025에 액세스, https://www.youtube.com/watch?v=xvjjytxnkVA
  42. 코스피 - 나무위키, 6월 14, 2025에 액세스, https://namu.wiki/w/%EC%BD%94%EC%8A%A4%ED%94%BC
  43. 가격제한폭 - 나무위키, 6월 14, 2025에 액세스, https://namu.wiki/w/%EA%B0%80%EA%B2%A9%EC%A0%9C%ED%95%9C%ED%8F%AD
  44. 암호화폐/평가 - 나무위키, 6월 14, 2025에 액세스, https://namu.wiki/w/%EC%95%94%ED%98%B8%ED%99%94%ED%8F%90/%ED%8F%89%EA%B0%80
  45. 비트코인의 투자, 6월 14, 2025에 액세스, https://brunch.co.kr/@thebcstory/193
  46. [보도자료] 주식시장의 질적수준 제고를 위한 「IPO 및 상장폐지 제도개선 방안」 발표, 6월 14, 2025에 액세스, https://www.fsc.go.kr/no010101/83895?srchCtgry=&curPage=&srchKey=&srchText=&srchBeginDt=&srchEndDt=
  47. 채권상장폐지 - 통계 - KRX | 정보데이터시스템, 6월 14, 2025에 액세스, http://data.krx.co.kr/contents/MDC/MDI/mdiLoader/index.cmd?menuId=MDC02030603
  48. 대한민국의 암호화폐 규제 논란 - 나무위키, 6월 14, 2025에 액세스, https://namu.wiki/w/%EB%8C%80%ED%95%9C%EB%AF%BC%EA%B5%AD%EC%9D%98%20%EC%95%94%ED%98%B8%ED%99%94%ED%8F%90%20%EA%B7%9C%EC%A0%9C%20%EB%85%BC%EB%9E%80
  49. KIPA규제동향 - 한국행정연구원, 6월 14, 2025에 액세스, https://www.kipa.re.kr/site/kipa/ex/board/View.do?cbIdx=317&bcIdx=9329
  50. 분산 투자의 기술: 위험을 관리하는 방법, 6월 14, 2025에 액세스, https://files-scs.pstatic.net/2024/03/19/6HW84yBGta/%EB%B6%84%EC%82%B0%20%ED%88%AC%EC%9E%90%EC%9D%98%20%EA%B8%B0%EC%88%A0%20%EC%9C%84%ED%97%98%EC%9D%84%20%EA%B4%80%EB%A6%AC%ED%95%98%EB%8A%94%20%EB%B0%A9%EB%B2%95.pdf%EC%9D%98%20%EC%82%AC%EB%B3%B8.pdf
  51. '23, 6월 14, 2025에 액세스, https://www.fsc.go.kr/comm/getFile?srvcId=BBSTY1&upperNo=81668&fileTy=ATTACH&fileNo=5
  52. 가상화폐 구매, 투자 또는 거래의 위험, 6월 14, 2025에 액세스, https://dfi.wa.gov/sites/default/files/cryptocurrency_guidance_KOR.pdf
  53. 비트코인 ETF 승인: 환호하는 암호화폐 시장… 그 이유와 의미는 ..., 6월 14, 2025에 액세스, https://www.bbc.com/korean/articles/c2vy2zdn99vo
  54. 디파이, 은행 안 거치고 송금·대출…NFT, 대체 불가능한 디지털 원본 ..., 6월 14, 2025에 액세스, https://www.hankyung.com/article/202103149786i
  55. 비트코인 21만 달러 간다?! 2025년 폭등 전망 나왔다|김수현의 '블록체인' 뉴스 - YouTube, 6월 14, 2025에 액세스, https://www.youtube.com/watch?v=CP_go1UlqaU
  56. cryptocurrency 시장 규모, 공유 및 동향 분석 보고서, 2032, 6월 14, 2025에 액세스, https://www.fortunebusinessinsights.com/ko/industry-reports/cryptocurrency-market-100149
  57. 디지털 화폐 총력전 펼치는 중앙은행들…코인 사라질 것 vs 공존 - 한국경제, 6월 14, 2025에 액세스, https://www.hankyung.com/article/2021080371161
  58. KRX | 정보데이터시스템, 6월 14, 2025에 액세스, http://data.krx.co.kr/contents/MDC/MAIN/main/index.cmd
  59. 관세·S공포·공매도…"코스피 2400선 분할매수를" [영상] - 한국경제, 6월 14, 2025에 액세스, https://www.hankyung.com/article/2025033110791
  60. 기록으로 만나는 대한민국 > 경제·산업 > 주식시장, 6월 14, 2025에 액세스, https://theme.archives.go.kr/next/koreaOfRecord/stockMarket.do
  61. [돈터치] 주식용어를 알아야 돈이 보인다! /주식용어/주가/공매도/미수 ..., 6월 14, 2025에 액세스, https://www.youtube.com/watch?v=rPIGS4029wY
  62. 분류:주식 - 나무위키, 6월 14, 2025에 액세스, https://namu.wiki/w/%EB%B6%84%EB%A5%98:%EC%A3%BC%EC%8B%9D
  63. 가상자산, 금융 생태계의 새로운 패러다임 - KPMG International, 6월 14, 2025에 액세스, https://assets.kpmg.com/content/dam/kpmg/kr/pdf/2022/business-focus/kr-bf-cryptoassets-20220809.pdf
  64. 쉽고 빠르게 풀어주는 코인 용어 | NFT - YouTube, 6월 14, 2025에 액세스, https://www.youtube.com/watch?v=BQRXh8t0phU
  65. 주식 VS 가상화폐(코인), 공통점과 차이점 비교 - 네이버 블로그, 6월 14, 2025에 액세스, https://m.blog.naver.com/sexysbkang/222288041316
  66. [코린이탈출] 똑같은 예치? 스테이킹과 고파이·이자농사 뭐가 다를까 - 조선일보, 6월 14, 2025에 액세스, https://www.chosun.com/economy/money/2025/01/19/BXBVUR3SZFYG6MCMP5ZYXRAMKQ/
  67. 암호화폐 스테이킹이란 무엇이며 어떻게 작동하나요? | Ledger, 6월 14, 2025에 액세스, https://www.ledger.com/ko/academy/%EC%95%94%ED%98%B8%ED%99%94%ED%8F%90-%EC%8A%A4%ED%85%8C%EC%9D%B4%ED%82%B9
  68. [코린이탈출] 은행 예금 이자와 같은 가상자산 '스테이킹 이자' - 조선일보, 6월 14, 2025에 액세스, https://www.chosun.com/economy/money/2025/01/11/MYQK7UR426QDMHYX5OIO6VV6RE/
  69. 탈중앙 금융(DeFi)에서 이자 농사란 무엇일까요? - 고팍스 아카데미, 6월 14, 2025에 액세스, https://academy.gopax.co.kr/taljungang-geumyung-defi-eseo-ija-nongsaran-mueosilggayo/
  70. 멈출 줄 모르는 디파이 이자농사…'거품' 주의보 - 디지털데일리, 6월 14, 2025에 액세스, https://m.ddaily.co.kr/page/view/2020090111532998798
  71. 디파이 이자 농사에 대한 설명 - Chainlink Blog, 6월 14, 2025에 액세스, https://blog.chain.link/defi-yield-farming-explained-korean/
  72. 기술적 차트 분석 이론 또는 방법 - 네이버, 6월 14, 2025에 액세스, https://files-scs.pstatic.net/2023/08/07/0sylvy5QMa/temp_1691328851302.298637731.pdf
  73. 코인값 예측하는 '차트 분석', 믿어야 할까 말아야 할까 [한경 코알라], 6월 14, 2025에 액세스, https://www.hankyung.com/article/202201059054i
  74. 기술적 분석 - 위키백과, 우리 모두의 백과사전, 6월 14, 2025에 액세스, https://ko.wikipedia.org/wiki/%EA%B8%B0%EC%88%A0%EC%A0%81_%EB%B6%84%EC%84%9D
  75. 캔들스틱 패턴 - 위키백과, 우리 모두의 백과사전, 6월 14, 2025에 액세스, https://ko.wikipedia.org/wiki/%EC%BA%94%EB%93%A4%EC%8A%A4%ED%8B%B1_%ED%8C%A8%ED%84%B4
  76. 캔들차트 - 나무위키, 6월 14, 2025에 액세스, https://namu.wiki/w/%EC%BA%94%EB%93%A4%EC%B0%A8%ED%8A%B8
  77. 트레이딩 차트 패턴 4가지 유형 | 패턴이 중요한 이유는? - ATFX, 6월 14, 2025에 액세스, https://www.atfx.com/ko/analysis/trading-strategies/4-trading-chart-patterns-why-important
  78. [뉴스] 업비트, 이용자 인기 보조지표 Top 5 공개 - 두나무, 6월 14, 2025에 액세스, https://www.dunamu.com/news/127
  79. 운용 및 전략 I (주식투자운용 및 투자전략) 추가 ① - 와우패스, 6월 14, 2025에 액세스, https://www.wowpass.com/upload/board/%ED%8E%80%EB%93%9C%EB%A7%A4%EB%8B%88%EC%A0%B8(%EC%B6%94%EA%B0%80%EC%9E%90%EB%A3%8C080225).pdf
  80. ETF 란? - 한국투자증권, 6월 14, 2025에 액세스, https://www.truefriend.com/main/customer/tradetransfer/_static/TF04da070000.shtm
  81. 투자위험요소 기재요령 안내서, 6월 14, 2025에 액세스, https://www.shinkim.com/newsletter/2024/GA/2024_vol220/links/2024_vol220_603.pdf
  82. 투자위험 관리 방법 : 네이버 블로그, 6월 14, 2025에 액세스, https://blog.naver.com/jaeminjake/222022360465
  83. 주식 투자 수익 및 위험성은 어느 정도인가요? - EBC Financial Group, 6월 14, 2025에 액세스, https://www.ebc.com/kr/forex/35315.html
  84. 코인베이스 투자 분석: 암호화폐 경제의 개척자, 기회와 도전을 논하다 - Naver Blog, 6월 14, 2025에 액세스, https://blog.naver.com/simula/223865103696?fromRss=true&trackingCode=rss
  85. 주식시장의 불공정거래행위 현황 및 시사점, 6월 14, 2025에 액세스, http://www.kif.re.kr/KMFileDir/128548503619595992_17-18-f2.pdf
  86. [노기자의 잠든사이에 일어난 일]그레이스케일로 보는 기관투자자가 암호화폐 시장에 미치는 영향 - 디센터, 6월 14, 2025에 액세스, https://decenter.kr/NewsView/22H4ZAP5EL/GZ07
  87. 비트코인과 주요 투자 자산 간의 장기 균형관계 추정*, 6월 14, 2025에 액세스, https://riie.jbnu.ac.kr/sites/riie/down/paper/2020123102.pdf
  88. 암호화폐 vs. CBDC part2 - 시스템작업알림, 6월 14, 2025에 액세스, https://invest.kiwoom.com/inv/28060
  89. 중앙은행 디지털화폐 - 나무위키, 6월 14, 2025에 액세스, https://namu.wiki/w/%EC%A4%91%EC%95%99%EC%9D%80%ED%96%89%20%EB%94%94%EC%A7%80%ED%84%B8%ED%99%94%ED%8F%90
  90. 인공지능이 암호화폐 시장에 어떤 영향을 미칠까? - B2Broker, 6월 14, 2025에 액세스, https://b2broker.com/ko/news/how-ai-will-affect-cryptocurrency-market/
  91. 지지와 저항 - CME Group, 6월 14, 2025에 액세스, https://www.cmegroup.com/ko/education/learn-about-trading/courses/technical-analysis/support-and-resistance.html
  92. 기술적지표 #8. 이동평균선 원리, 설정, 계산법, 매매전략까지 한번에! - 알파스퀘어, 6월 14, 2025에 액세스, https://alphasquare.co.kr/home/insight/posts/14c05212-a378-4ba0-b9df-5ae039996c3b
  93. 기술적지표 #1. 볼린저밴드 원리, 설정, 계산법, 매매전략까지 한번에!, 6월 14, 2025에 액세스, https://alphasquare.co.kr/home/insight/posts/2abbd8ab-cc12-448e-9b5e-2db04a939b1b
  94. 볼린저밴드 지표를 활용한 매매방법 7가지!! - 트레이딩뷰, 6월 14, 2025에 액세스, https://kr.tradingview.com/chart/BTCUSDT/zdPfPbXk/
  95. 보조지표 응용 꿀조합을 찾아라 2탄! - RSI과매도+MACD매수신호 편 - YouTube, 6월 14, 2025에 액세스, https://www.youtube.com/watch?v=33cEcNOF2jo
  96. 투자가이드 - KB증권, 6월 14, 2025에 액세스, https://m.kbsec.com/go.able?linkcd=m05070007

 

728x90
728x90

개발을 하다 보면 가끔 "모노레포"라는 단어를 들어본 적이 있을 것이다.

프로젝트를 관리할 때 모노레포로 구성하면 관리하기 편하다고 하지만, 경험상 모노레포 구조를 가진 프로젝트들은 결국 확장됨에 따라 분리하는 절차를 밟게 되었었다.

오늘은 모노레포가 탄생한 배경, 그리고 어떨 때 적용하라고 만든 구조인지 알아보도록 하겠다.


Monorepo와 Polyrepo

Monorepo는 말 그대로 Mono(하나의) + Repo(Repository), 즉 여러 애플리케이션이나 라이브러리를 하나의 저장소에서 관리하는 구조이다.

그럼 지금까지 사용해 왔던 Polyrepo의 어떤 점을 보완하고자 나온 구조일까?

우선 Polyrepo의 장단점에 대해 알아보자.

Polyrepo는 다중 저장소를 이용하는 구조로, 프로젝트마다 별도의 저장소를 이용하는 구조이다.


Polyrepo의 장점

  • 각 프로젝트별 독립적인 모듈화가 가능하다.
  • 배포에 유연하다.
  • 서비스 수가 많아질수록 관리가 용이하다.

즉, 프로젝트들이 물리적으로 분리되어 있어 연관되지 않는 Merge 충돌과 같은 상황을 방지할 수 있는 등 물리적인 분리에서 오는 장점들이 존재한다.


Polyrepo의 단점

반대로 이러한 특징은 단점으로 적용되기도 한다.

  • 공통 라이브러리의 버전 반영이 번거롭다.
  • 프로젝트 간 동기화 및 호환성 유지가 어렵다.
  • 코드 리뷰 및 CI/CD 구성이 분산되어 있어 설정 비용이 증가한다.

이런 단점들을 개선하고자 등장한 구조가 바로 Monorepo다.


Monorepo의 장점

Monorepo는 여러 프로젝트를 하나의 저장소에서 관리한다.
이는 특히 다음과 같은 상황에서 큰 장점을 가진다.

  1. 공통 코드의 관리가 용이하다
    • 여러 서비스가 공통으로 사용하는 utilsdomain 모듈을 하나의 저장소에서 직접 수정 및 반영 가능
  2. 원자적 변경(Atomic Change)이 가능하다
    • 여러 프로젝트에 걸친 인터페이스 변경도 하나의 커밋으로 처리 가능
  3. 일관된 CI/CD 구성
    • 통합적인 CI 파이프라인 구성 가능, 디렉터리 기반 변경 감지 등 최적화 가능
  4. 코드 가시성과 협업에 유리하다
    • 전체 구조를 한눈에 파악할 수 있어 신규 입사자나 타 팀원 간 협업 시 유리

Monorepo의 단점

물론 Monorepo도 단점이 있다.
가장 대표적인 문제는 스케일에 따른 복잡성 증가다.

  1. 빌드 시간 증가
    • 빌드 시간이 오래 걸리며, 이를 해결하려면 Bazel, Nx, Turborepo 등의 도구 필요
  2. 접근 제어의 어려움
    • 디렉터리 단위 접근 권한 설정이 어렵다
  3. Git 성능 저하
    • 파일 수가 많아질수록 Git 자체가 느려질 수 있음
  4. 심리적 복잡성
    • 전체 코드량이 많아지며 구조 파악에 부담을 줄 수 있음

Monorepo를 적용하기 좋은 상황

다음과 같은 경우에 Monorepo 구조는 적합하다.

  • 여러 서비스가 같은 주기로 배포되고, 공통된 라이브러리를 사용하는 경우
  • 초기 스타트업 환경처럼 팀 규모가 작고 변경이 잦은 경우
  • 기능 단위의 동시 변경이 자주 필요한 경우
  • 전체 시스템을 하나의 흐름에서 통합 관리하고 싶은 경우

반면, 대규모 서비스나 팀에서는 신중한 검토가 필요하다.
Google도 Monorepo를 사용하고 있지만, 이를 위해 독자적인 빌드 시스템과 버전 관리 시스템을 따로 구축한 사례다.


MultiModule 구조와의 비교

MultiModule은 주로 하나의 프로젝트 안에서 여러 기능을 모듈화해 관리하는 방식이다.
Java 기반의 프로젝트(Spring 등)에서 자주 볼 수 있다.
이 구조는 물리적으로는 Monorepo, 논리적으로는 Polyrepo와 유사한 형태를 갖는다.

MultiModule의 특징

  • 하나의 Git 저장소 안에 여러 모듈 존재
  • core, common, domain 같은 공통 모듈을 다른 모듈들이 참조
  • 하나의 빌드 스크립트(Gradle 등)로 통합 관리

Monorepo vs MultiModule

항목 Monorepo MultiModule
저장소 구조 여러 프로젝트를 하나의 저장소에서 관리 하나의 프로젝트 안에서 모듈로 분리
독립성 높은 유연성 (서비스 단위 프로젝트 존재 가능) 하나의 애플리케이션 중심 (빌드 및 배포 단위가 동일)
공통 코드 관리 공통 라이브러리를 독립 패키지로도 구성 가능 대부분 동일한 버전을 공유
빌드 관리 고급 도구 필요 (Bazel, Nx 등) Gradle, Maven 기반 관리

즉, MultiModule은 단일 서비스 또는 애플리케이션의 모듈화를 위한 설계,
Monorepo는 복수의 애플리케이션 또는 서비스 단위까지 고려한 구조라는 차이가 있다.


마무리

정리하자면, Monorepo는 통합성과 효율성에서 큰 장점을 가지지만, 이를 유지하려면 명확한 설계 기준과 도구의 도움이 필요하다.
처음에는 편리하지만, 규모가 커지면 관리 비용도 함께 커진다는 점을 명심해야 한다.

 

Monorepo의 경우 Bazel과 같은 고급 도구가 필요한 만큼 팀과 프로젝트의 성격에 따라 Polyrepo, Monorepo, MultiModule 중 어떤 구조를 적용할지 신중하게 고민하여 적용하는 것이 필요하다 본다.

728x90
728x90

로컬에서 어떤 서비스가 특정 포트를 리스닝 중인데도 외부나 내부에서 접근이 안 되는 상황이 있었다.

예를 들어, API 서버가 6443 포트를 열고 있지만 nc, curl 등으로 접속이 실패하는 경우다.

# 테스트 커맨드
nc 127.0.0.1 6443 -zv -w 2
# 결과
nc: connect to 127.0.0.1 port 6443 (tcp) failed: Connection refused

이럴 때는 보통 3가지를 의심해 볼 수 있다.

  • 서비스가 작동 중이 아니다.
  • 포트가 잘못되었다. 즉, 호출 정보가 잘못되었다.
  • 방화벽이 막고 있다.

이번 글에서는 방화벽, iptables 때문에 막힌 경우 어떻게 해결할 수 있는지를 다루고자 한다.


1. iptables란?

iptables는 리눅스에서 네트워크 패킷을 필터링하거나 포트 포워딩, NAT 등을 설정할 수 있는 방화벽 도구다.
우리가 설정하지 않아도, 클라우드 이미지나 OS 배포판이 기본 규칙을 넣어두는 경우가 있다.


2. 지금 iptables이 어떤 규칙을 가지고 있는지 확인

sudo iptables -L -n -v

위 커멘드를 통해 iptable 정보들을 조회할 수 있다.

결과는 아래와 같은 형식으로 출력된다.

Chain INPUT (policy DROP 120 packets, 9600 bytes)
 pkts bytes target     prot opt in     out     source               destination
   10   800 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp dpt:22
  • INPUT 체인에서 policy가 DROP으로 설정되어 있다면, 기본적으로 모든 요청을 차단하고 예외만 허용하는 구조다.
  • 위 예시는 22번 포트(SSH)만 허용되고 있다는 뜻이다.

3. 포트 열기: iptables로 6443 포트 허용하기

예를 들어 Kubernetes API Server나 커스텀 서버가 6443 포트를 사용하고 있다면 다음과 같이 열 수 있다.

# TCP 6443 포트를 허용
sudo iptables -A INPUT -p tcp --dport 6443 -j ACCEPT

이후 해당 설정을 적용하기 위해서는 OS마다 조금 다를 수 있다.

 

이 글은 Ubuntu를 기준으로 작성하도록 하겠다.

sudo apt install iptables-persistent
sudo netfilter-persistent save

4. 방화벽 규칙 초기화

만약 작업 중인 환경이 테스트 환경이고, 방화벽 내 설정을 비우고 싶다면 아래와 같이 설정해 주면 된다.

# 모든 규칙 초기화
sudo iptables -F

# 기본 정책 ACCEPT로 변경
sudo iptables -P INPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -P OUTPUT ACCEPT

5. 외부 접속은 다른 문제일 수 있다.

내부에서 정상적으로 호출되지만 외부에서의 접속이 어렵다면, 이는 다른 레벨의 방화벽이 막고 있을 수 있다.

흔히 AWS의 InBound 규칙과 같은 규칙들을 생각할 수 있고, ufw 때문일 수도 있다.

 

ufw는 iptables를 기반으로 손쉽게 방화벽 설정을 할 수 있는 인터페이스이다.

그럼 iptables의 설정을 열었는데 왜 그 기반으로 동작하는 인터페이스인 ufw의 영향을 받게 되는가?

 

설정 자체는 iptables에 명시되어 있습니다. 다만 iptables의 규칙들은 서로 chain을 하고 있고, 설정 중에는 ufw에 대한 설정이 존재하게 된다.

 

즉, iptables에는 ACCEPT로 설정되어 있고, ufw에는 DROP으로 설정되어 있다면 해당 Connect 요청은 iptables까지 도달하지 못하고 ufw에서 막히는 상황이 발생할 수 있다.

 

정리하자면 iptables는 방화벽의 엔진, ufw는 그 위에 올라간 인터페이스일 뿐이지만,

ufw는 자신만의 규칙 체인을 만들기 때문에 차단되는 문제가 생길 수 있는 것이다.


마지막

개인 미니 PC에 Kubernetes를 설치하는 와중 특정 포트가 닫혀있는 것을 보게 되었고,

이를 해결하는 과정에서 왜 해당 설정이 필요한지, 어떤 내용들이 존재하는지를 기록하고자 글로 남기게 되었다.

 

가장 기본적인 부분이지만, 왜 방화벽 때문에 호출이 막히는 현상이 발생하는지가 궁금하였다면, 이 글이 기본적인 개념을 잡는 데에 도움이 될 것 같다.

728x90
728x90

Java를 사용하여 개발을 하기 위해서는 JDK, JRE, JVM을 필요로 한다.

 

오늘은 이것들이 무엇이며, 우리가 프로그램을 개발하고 실행되기까지 어떤 일들이 벌어지는지 알아보도록 하겠다.


1. JDK( Java Deployment Kit )

가장 먼저 알아볼 것은 자바 개발 도구이다.

JDK는 기본적으로 우리가 자바를 사용하여 개발하고, 실행하기 위해 필요한 것들이 담겨있다.

 

자바로 개발된 프로그램을 실행하기 위한 JRE와 필수적 그리고 기본적인 자바 개발 도구들(Java, Javac,...)등이 포함된다.

 

그럼 JDK만 설치되어 있다면 메모장만 사용해도 코드가 돌아가게 할 수 있나요?

 

물론이다. 이를 증명하기 위해 메모장으로 코딩을 진행해 보겠다.

우선, 텍스트 파일에 기본적인 코딩을 해보았다.

MacOs에서 진행

이후 해당 파일을 Java컴파일러로 컴파일하기 위해. java파일로 변경해 준다.

javac를 사용하여 컴파일 결과

javac명령어를 사용하여 컴파일을 진행한다.


왜 컴파일을 진행해야 할까?

Java 코드는 사람이 읽기 쉬운 고급 언어이다.

이는 사람은 이해할 수 있지만 컴퓨터는 이해할 수 없는 언어라는 의미이다.

 

그럼 외국인과 대화를 하기 위해 번역가가 필요하듯이 언어도 번역가가 필요한데 이 역할을 수행하는 것이 컴파일러다.

 

또한 컴파일과정을 거치며, 문법적으로 잘못된 부분까지 체크를 진행하게 되고, 이때 발생하는 오류가 CompileException이다.

즉, 개발을 진행하면서 오류가 발생하였다면 문법이 잘못되었거나 실행할 수 없는 파일이라 보면 된다.

 

자바 컴파일러가 변환작업을 진행하면 자바 코드 소스를 바이트코드로 변환하게 되는데, 이때 확장자는. class고 이때서야 JVM이 해당 소스를 실행시킬 수 있다.


이후 java 명령어를 통해 Class를 실행시키면 정상적으로 작동하는 것을 확인해 볼 수 있다.

 

이렇듯 JDK를 설치한다면 단순한 text로도 개발이 가능한 것을 확인해 볼 수 있다.


2. JRE ( Java Runtime Environment )

우리가 만든 Java프로그램이 동작하려면, 단순히 컴파일을 거쳐. class파일을 만들었다고 실행되는 게 아니다.

실행을 하기 위한 머신, 라이브러리, 파일들이 필요한데, JRE는 이를 모아놓은 패키지이다.

 

위 글에서 보았듯 JRE는 JDK에 포함되어 있어 JDK를 설치하면 함께 설치된다.

( 버전에 따라 다르다. )

 

JRE은 다음과 같은 구성으로 이루어져 있다.

구성요소 설명
JVM 바이트코드를 읽어 실행하는 엔진
Java 클래스 라이브러리 입출력, 네트워크, 컬렉션 등 기본 기능을 제공
Java 클래스 로더 필요한 클래스를 메모리에 동적으로 로드
런타임 라이브러리 및 지원 파일 JVM이 동작하는 데 필요한 추가 리소스 

 

이를 보면 알 수 있지만, JVM은 이론적으로 JRE 없이 단독 설치하는 것은 어려우며, 실용적이지 않다.

왜냐면 JVM은 JRE의 일부분이며, JRE가 JVM이 작동할 때 필요한 기능들을 제공하기 때문이다.


3. JVM ( Java Virtual Machine )

자바 가상 엔진으로 Java로 작성된 프로그램을 실행시키고 관리하는 실질적인 주체입니다.

 

"JVM은 JRE 없이 사용하기 어려우면 JRE가 주체 아닌가요?"

위와 같은 의문이 들었다면 JRE가 무엇인지 다시 확인해 볼 필요가 있습니다.

 

JRE는 실행 환경 전체를 말하는 "패키지"고,

그 안에 포함된 JVM이 실제로 프로그램을 실행하고 메모리를 관리하는 주체로 이해하면 된다.

 

JVM은 운영체제에 영향을 받는데, 이 영향은 JVM에 한정적이기 때문에 Java 프로그램은 모든 플랫폼에서 제약 없이 동작할 수 있다.

이는 Java로 개발된 프로그램의 가장 큰 이점인데, Java로 작성된 코드는 컴파일 후 운영체제와 상호작용을 하는 것이 아닌 JVM과 상호작용을 하고, JVM이 운영체제와 상호작용을 하기 때문에 Java로 개발된 프로그램은 이식성이 좋다.

window JVM, Linux JVM 따로 있다.

위 그림과 같이 컴파일된  바이트코드는 모든  JVM에서 동일하게 인식하기 때문에 운영체제에 맞는 JVM만 설치된다.

  1. 자바 컴파일러가. java를. class로 컴파일(바이트코드).
  2. JVM이 바이트코드를 바이너리코드로 변환.
  3. 변환된 바이너리코드를 CPU에서 실행.

여기까지가 간단하게 Java코드가 실행되기까지의 과정을 간단하게 다뤄보았다.

이제 내부적으로 어떤 일이 일어나는지 알아보도록 하자.


지금부터 알아볼 JVM의 구성요소이다.

  • Class Loader
  • Execution Engine
    • JIT ( Just In Time )
    • Interpreter
    • Garbage Collector
  • Runtime Data Area
    • Method Area
    • Heap
    • PC Register
    • JVM Stack
    • Native Mathod Stack

3.1. Class Loader

클래스 로더는. class 파일을 메모리에 올려 런타임에 사용할 수 있게 만드는 역할을 한다.

  • 클래스를 읽고( Loading )
  • 검증하고 ( Verification )
  • 필드와 메서드를 위한 메모리를 준비하고( Preparation )
  • 심볼릭 참조를 직접 참조로 바꾸고 ( Resolution )
  • 초기화 코드를 실행( Initialization )

여기까지 모든 클래스를 "사용 가능"하게 만드는 전체 파이프라인의 시작점이다.

이 작업들은 아래와 같이 3단계로 구분할 수 있다.

  1. Loading: 클래스 파일을 JVM의 메모리에 로드한다.
  2. Linking: 클래스 파일을 사용하기 위해 검증한다.
    - Verifying: 읽은 클래스가 JVM에 명시된 대로 구성되어 있는지 검사한다.
    - Preparing:
    클래스가 필요로 하는 메모리를 할당한다.
    - Resolving: 
    클래스의 상수 풀 내 모든 심볼릭 레퍼런스를 다이렉트 레퍼런스로 변경한다.
  3. Initializing: 클래스 변수들을 적절한 값으로 초기화한다. (Static 블록 실행 및 필드 초기화)
더보기

용어정리

상수 풀( Constant Pool ): 클래스 파일에 있는 다양한 정보 저장소(클래스명, 메서드명, 필드 정보 등)

심볼릭 레퍼런스( Symbolic Reference ): "이 클래스/메서드/필드는 이름으로 이렇게 적혀있어요"라는 문자열 기반 정보

다이렉트 레퍼런스( Direct Reference): JVM 내부에서 사용하는 메모리 주소 또는 포인터

해당과정이 무작정 이뤄지지는 않는다.

JVM은 클래스를 “필요할 때” Load 하는데 이는 다음과 같은 이유가 존재한다.

  • 메모리 효율성
  • 애플리케이션 실행 시작 시간 단축
  • 모듈화의 유연성 확보

즉, 처음에 모두 메모리에 적재할 경우 비효율성과 유연성을 떨어트리기 때문에 애플리케이션에서 필요로 할 때 메모리에 적재한다.


3.2. Execution Engine

실행엔진은 바이트코드를 해석하고, CPU가 이해할 수 있는 바이너리코드로 변환하여 실행한다.

변환하고 실행할 때 실행엔진은 코드를 실행하기 위해 InterpretrJIT을 사용한다.


3.2.1. Interpreter

  • 바이트코드 명령어를 하나씩 읽어 해석하고 실행한다.

3.2.2 JIT Compiler

  • Interpreter의 중복코드 중복 해석 및 실행에 대응하고자 도입.
  • 바이트코드 전체를 컴파일하여 NativeCode로 변경.
  • NativeCode로 변경한 바이트코드는 Interpreting 되지 않고 캐싱해 두었다 NativeCode로 직접 실행
    NativeCode는 C나 C++, 어셈블리어로 구성된 인터프리터언어를 의미한다.
  • 중복 코드 실행의 경우 계속 Interpreting 하는 것보다 성능이 좋지만, NativeCode로 변경하는데 자원이 소모되기 때문에 Interpreter방식으로 사용하다 일정 기준이 넘어가면 JIT Compile방식 사용.

3.2.3 Garbage Collector

JVM은 Heap 메모리 영역에서 더 이상 참조되지 않는 메모리회수하기 위해 Garbage Collecor를 사용한다.

 

개발자가 직접 사용하는 것이 아닌 자동으로 작동하기 때문에 더욱 손쉽게 메모리 관리를 할 수 있다.

더 이상 사용하지 않는 데이터의 경우 null로 초기화해 주면, 더욱 효율적으로 Garbage Collector를 이용할 수 있다.

 

Garbage Collector는 주기적으로 작동하는 프로세스로서 참조되지 않는 메모리가 언제 해제되는지 알 수 없으며, GC가 작동하게 되면 GC관련 Thread를 제외한 다른 Thread들이 중지되기 때문에 오버헤드가 발생한다.

더보기

STW( Stop The World ): GC를 수행하기 위해 JVM이 프로그램 실행을 멈추는 현상


3.3. Runtime Data Area

 

Runtime Data Area는 JVM 메모리 영역으로 자바 프로그램을 실행할 때 사용되는 데이터를 사용 목적에 맞춰 나누어져 있다.

 

아래와 같이 크게 2가지 특징으로 분리를 해볼 수 있다.

  • Thread-specific ( Thread마다 개별로 존재 )
    • PC Register
    • Stack
    • Native Method Stack
  • Shared (모든 Thread가 공유)
    • Heap
    • Method Area

Thread-specific은 Thread마다 개별로 존재하여 각 Thread 간 메모리 공유가 불가능하다.

Shared는 Thread와 별개로 할당된 메모리 영역으로 각 Thread들이 해당 메모리에 접근한다면 동일한 데이터를 사용할 수 있다.


3.3.1. PC Register

우리가 JVM의 PC Register를 이해하기 위해서는 CPU의 PC Register와 무엇이 다른지 이해해야 한다.

 

CPU의 PC Register는 현재 CPU가 실행할 다음 명령어의 주소를 저장하는 하드웨어 레벨 Register이다.

하지만 JVM의 PC Register는 물리적인 레지스터가 아니라 가상 머신 레벨에서의 명령어 실행 흐름 제어 구조이다.

 

그럼 왜 필요할까?

 

JVM이 바이트코드를 실행할 때 다음 구조를 따른다.

[바이트코드] → [PC Register (현재 위치)] → [Opcode 해석기] → [Operand Stack]

 

아래 코드를 사용하여 한스탭씩 따라가 보자.

int a = 1 + 2;

코드를 바이트코드로 컴파일하면 아래와 같은 결과물이 나온다.

iconst_1
iconst_2
iadd
istore_1

해당 코드를 실행한다면 PC Register는 iconst_1의 위치를 가르치고,

순차적으로 프로그램의 흐름을 추적한다.

 

그럼 PC Register가 가리키는 바이트코드를 Interpreter가 읽어 해당 명령에 대응되는 C/C++ 함수를 실행한다.

이후 Interpreter가 실행한 C/C++함수가 CPU를 작동시키게 된다.

 

이렇듯 Java는 CPU에게 바로 연산시키는 것이 아닌 현재 실행해야 하는 연산을 제공하여야 하며, 이를 위한 버퍼 공간으로 사용하기 위해 PC Register메모리 영역이 존재한다.

 

또한 PC Register는 Thread마다 각각 가지고 있다.

즉, "현재 Thread의 어떤 명령어가 실행 중인가?"에 대한 명령어 주소를 기억하고 있다.


3.3.2. Stack

스택은 원시타입( Primitive type ) 데이터와 참조타입(Reference type)의 주소값, 현재 실행 중인 메서드의 스택 프레임을 저장하는 메모리 영역이다.

 

LIFO구조로 push와 pop기능 방식으로 동작한다.

Thread마다 하나씩 존재하며, Thread가 시작될 때 할당되며, Thread가 종료되면 사라진다.

 

이때, 프로그램 실행 중 할당된 메모리를 벗어난 데이터들이 들어온다면 StackOverFlowError가 발생한다.


3.3.3. Native Method Stack

이는 실제 개발하면서 보기는 힘들고, 내부 라이브러리를 깊게 파보면 native선언을 해둔 것을 확인할 수 있다.

이는 Java로 구현된 것이 아닌 C/C++과 같은 언어로 구현되었다는 의미이며,

예시로 Thread Class를 보면 registerNatives 메서드는 native선언이 되어 있는 것을 확인할 수 있다.

public class Thread implements Runnable {
    /* Make sure registerNatives is the first thing <clinit> does. */
    private static native void registerNatives();
    static {
        registerNatives();
    }
}

 그럼 왜 Java로 작성하지 않고 C/C++로 대신 구현하는 것일까?

  • 시스템 리소스 접근
  • 성능이 중요한 로직을 C/C++로 최적화
  • 기존 C/C++ 라이브러리와 연동

그렇다 컴파일 언인 Java보다 인터프리터언어인 C/C++ 이 성능적으로 앞서 성능 최적화를 한다거나 시스템에 직접 접근하려 할 때 사용하는 것을 확인할 수 있다.

 

Native Method Stack을 통해 C함수 호출 프레임을 관리하여 JVM은 해당 기능을 사용할 수 있는 것이다.


3.3.4. Heap

힙영역은 참조타입( Reference type ) 데이터들이 저장되며, new연산자로 생성되는 Instance들이 저장된다.

 

해당 영역에 존재하는 데이터들은 Stack영역에서 참조하지 않으면 GC대상이 된다.


3.3.5. Method Area

 흔히 ClassStatic으로 선언된 변수 혹은 메서드들이 프로그램이 시작될 때 메모리에 로드되어 프로그램이 종료될 때까지 남아 있다.

 

Heap과 동일하게 모든 Thread가 공유하고, 여러 정보들을 저장하고 있다.

  • Field Info: 멤버 변수명, data type, 접근 제어자의 정보
  • Method Info: 메서드명, return type, 매개변수, 접근 제어자
  • Type Info: Class인지 Interface인지 저장, Type의 속성, Super Class의 이름

즉, 정적 필드와 클래스 구조만을 가지고 있다.(클래스는 new로 생성할 경우 Instance가 Heap에 생성된다.)


3.3.6. JNI

Java Native Interface로 다른 언어로 만들어진 애플리케이션과 상호 작용할 수 있는 인터페이스를 제공한다.


3.3.7. Native Method Library

C/C++로 작성된 라이브러리다.

 

자바에서 native 키워드로 선언된 메서드를 호출할 때, 필요에 따라 JNI를 통해 해당 네이티브 라이브러리를 호출하며, 이 과정에서 Native Method Stack이 사용된다.


4. 글을 마치며

JVM, JDK, JRE에 어떤 것들이 존재하고, 어떤 역할을 하는지에 대해 알아보았다.

이전부터 알고 있던 내용들도 있었지만, 시간을 충분히 투자하며 차근차근 공부해 보니 확실히 모르고 있었던 부분도 많이 보였던 거 같다.

 

"Java개발자가 JVM을 이렇게까지 알아야 하나요? 그냥 코드 잘 짜면 잘 돌아가잖아요."

 

어느 정도 맞는 말인 거 같다.

JVM내부 요소들을 건드리며 개발을 안 하더라도 서버 스펙만 좋다면 아무런 문제 없이 돌아갈 것이다.

개판으로 작성해도 잘 돌아갈 텐데 잘 짰으면 얼마나 잘 돌아갈까.

 

하지만 알고 있다면 메모리를 좀 더 신중하게 사용할 수 있을 것이고, 성능적으로 한 번쯤은 고민해보지 않을까?

그리고 어떤 문제가 발생했다면 이를 해결하기 위해 고민을 할 때 이러한 공부들은 많은 도움이 될 것이다.

 

그리고 도구를 사용하면 어떤 도구인지 알고 있으면 잘 사용하지 않겠나. 


References

https://inpa.tistory.com/entry/JAVA-%E2%98%95-JVM-%EB%82%B4%EB%B6%80-%EA%B5%AC%EC%A1%B0-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EC%98%81%EC%97%AD-%EC%8B%AC%ED%99%94%ED%8E%B8#%EB%9F%B0%ED%83%80%EC%9E%84_%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%98%81%EC%97%AD_runtime_data_area

https://d2.naver.com/helloworld/1230

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90
728x90

오늘은 필자가 경험한 인증 서비스 Refactoring 다뤄보도록 하겠다.

현업에서 다룬 만큼 어떻게 그리고 왜 Refactoring 했는지와 연관되지 않는 부분은 제거하고 작성하겠다.

 

앞서 해당 글에서 작성하면서 사용한 도메인의 설정을 정의하고 가겠다.

  • 상품: 유저가 구매하는 상품이며 보통 1년에 1~4개를 구매한다.
             상품 유형은 A, B, C, D 상품이 존재한다.
  • 인증: 유저가 상품을 구매한 구매자인지 인증하기 위한 도메인이며, 현재 인증기간일 경우 할인이 적용된다.

 

우선 필자가 만난 인증 서비스는 아래와 같았다.

Before

간단하게 유저가 상품을 구매하면 인증서버에 해당 유저가 상품을 구매했다고 상품에 명시되어 있는 인증기간 동안 구매자 인증을 해주는 시스템이다.

 

 해당 시스템은 매우 간단하지만 도메인전문가의 니즈는 조금 복잡했다.

  • 고객의 인증기간은 관리자가 조절할 수 있다.
  • 상품을 구매하지 않더라도 관리자가 임의로 인증기간을 할당할 수 있다.
  • 구매자가 현재 얼마만큼의 인증기간을 가지고 있는지 확인해야 한다.
  • 상품마다 인증기간이 다르며, 인증기간 사이에 비인증 기간이 존재할 수 있다.

또한 해당 서버에는 고질적인 문제가 있었다.

왜 어째서인지 고객이 상품을 구매하였지만 인증기간이 존재하지 않는 데이터들도 존재하는 것이었다.

 

왜 그럴까? 

우선 인증서버에서 인증 데이터를 어떤 것들을 저장하는지 확인해 보자.

A시작일 A종료일 B상품 B시작일 B종료일 C상품 C시작일 C종료일 D상품 D시작일 D종료일

 

위 칼럼을 확인 후 필자는 이와 같이 생각했다.

  • 인증은 A, B, C, D상품 인증일 중 하나라도 현재 인증 기간 범위 내에 존재한다면 구매자로 인증된다.
  • 구매한 상품의 타입이 같다면 인증기간을 기존 인증기간이 존재한다면 두 데이터를 비교하여 더 빠른 인증시작일과 더 늦게 종료되는 인증 종료일을 저장한다.
  • 스케줄링을 통해 인증 종료된 인증 데이터에 대해서는 빈칸으로 수정해 준다.( Mysql을 사용하였고, 해당 칼럼 타입 VARCHAR이었다. )

그리고 데이터에도 문제가 있다는 것을 확인하였다.

  • 상품을 구매하였지만 인증데이터가 생성되지 않는 유저가 존재한다.
  • 어째서인지 들어갈 수 없는 날짜가 인증 종료기간에 들어가 있다.
  • 인증기간은 존재하지만 상품 아이디가 없다.

그럼 상황을 정리해 보자.

  • 상품을 구매할 때마다 인증 데이터의 신뢰도가 떨어진다.
  • 현재 인증일인지 확인하기 복잡하다.
  • 테스트한 데이터가 운영 데이터베이스에 있다.
  • 인증 데이터에 상품 아이디가 존재하지 않는 이유는 관리자가 임의로 생성한 데이터였기 때문이다.
  • 이상한 날짜가 들어간 이유는 인증 종료일을 강제로 31일로 넣었기 때문이다.

필자는 위 상황을 정리하며 해당 시스템에 어떤 고객 니즈가 존재하는지, 기존 시스템을 파악하며 어떤 문제가 존재하는지를 파악하였다.

 

이제 이를 해결하기 위해 어떤 고민이 있었고, 어떻게 해결하였는지 알아보자.


Chapter 1. 상품을 구매할 때마다 인증 데이터의 신뢰도가 떨어진다.

필자가 맨 처음 고민한 부분이다.

 

위 인증 데이터는 상품을 구매할 경우 인증기간을 상품과 상관없이 인증기간을 인증 데이터에 저장하고 있었다.

이렇게 하였을 경우 문제점은 이와 같았다.

  • 정상적으로 인증 데이터가 생성되지 않을 수 있다.
  • 상품의 실제 인증기간과 별개의 인증기간이 만들어질 수 있다.
  • 현재 인증기간이 어떤 상품을 구매해서 생긴 것인지 정확히 알기 어렵다.

위와 같은 문제가 발생한다면 이는 또다시 이런 일이 발생하지 않도록 하는 게 좋다 생각했다.

 

그럼 어떻게 풀어낼 수 있을까?

 

우선 간단하게 생각했다.

 

상품을 구매할 때마다 인증기간을 생성한다면 인증기간을 신뢰도가 높고, 효율적으로 관리할 수 있을 것이라 생각했다.

그리하여 인증과 인증기간을 분리하기로 하였다.

인증 테이블

인증 아이디 고객 아이디

인증 기간 테이블

인증 기간 아이디 인증 아이디 상품 아이디 인증 시작일 인증 종료일

 

위와 같이 정규화를 하여 관리한다면 구매한 상품에 대한 인증기간을 정확하게 관리할 수 있다.

 

또한 상품 타입이 늘어나거나 줄어들 때마다 테이블 칼럼을 수정하지 않아도 된다.


Chapter 2. 현재 인증된 고객인지 빠르고 정확하게 확인하고 싶다.

기존 인증 데이터의 경우 A, B, C, D 상품 인증 시작일과 종료일을 하나의 Record로 관리하고 있었다.

 

따라서 sql을 작성한다고 가정하면 이렇다.

SELECT *
FROM 인증
WHERE 유저아이디 = :유저아이디
  AND (
    (A시작일 <= :현재날짜 AND A종료일 >= :현재날짜) OR
    (B시작일 <= :현재날짜 AND B종료일 >= :현재날짜) OR
    (C시작일 <= :현재날짜 AND C종료일 >= :현재날짜) OR
    (D시작일 <= :현재날짜 AND D종료일 >= :현재날짜)
  );

 

하지만 Chapter 1에서 정규화된 테이블을 사용한다면 이와 같이 작성될 것이다.

SELECT 인증아이디
FROM 인증
WHERE 유저아이디 = :유저아이디;


SELECT *
FROM 인증기간
WHERE 인증아이디 = :인증아이디
 AND 시작일 <= :현재날짜
 AND 종료일 >= :현재날짜;

 

 

비정규화 쿼리와 정규화 쿼리를 비교해 보자.

  비정규화 정규화
인덱스 활용도 낮음 높음
유지보수 어려움 (A~D 컬럼 늘어나면 쿼리 수정 필요) 쉬움
쿼리 단순성 조건문 복잡 명확하고 간결
확장성 나쁨 (인증 수 늘면 테이블 변경 필요) 좋음 (행으로 관리)
성능 느림 (OR 조건 병렬평가) 빠름 (범위 인덱스 활용 가능)

 

이와 같이 정규화를 적절하게 적용한다면 매우 많은 이점을 가질 수 있게 된다.

 

물론 서버에서 조회한 다음 로직으로 현재 인증일인지 판단한다 하면 성능자체는 비정규화 방식이 좋을 수도 있다 생각한다.

왜냐면 정규화를 한다면 최소 4배 이상의 데이터가 생길 것이기 때문이다.

 

하지만 유지보수성과 관리의 측면에서 바라본다면 좀 더 효율적으로 관리할 수 있을 것이다.


Chapter 3. 서버가 다운되더라도 인증 기간은 정상적으로 생성하고 싶다.

정규화를 통해 데이터를 잘 관리할 수 있게 되었다면 우리는 다음 문제를 해결해야 한다.

상품을 구매하였는데 인증 기간이 생기지 않는 상황이다.

 

이는 몇 가지 고민을 해볼 수 있다.

1. 하나의 트랜잭션으로 묶는다.

만약 MA라면 가장 간단할 거다.

 

하지만 여기서도 고민해 볼 것은 존재한다 생각한다.

인증 기간이 생성되지 않는다고 상품 구매를 원복 시킨다?

 

뭔가 배보다 배꼽이 커진 거 같다.

 

???: "상품을 구매하였기 때문에 인증 기간이 생성되어야 합니다."

???: "인증 기간이 생성되지 않았기 때문에 상품 구매는 취소됩니다."

 

논리적으로 앞뒤가 바뀐 거 같지 않은가?

 

필자는 이에 주도권은 상품에게 존재한다 생각하였다.

그렇기 때문에 하나의 트랜잭션으로 묶는 것은 적절하지 않다 생각한다.

2. 스케줄링을 돌려 인증 기간을 생성한다.

이 또한 간단하게 처리할 수 있는 방법이라 생각한다.

 

다만 구매한 상품들 중 인증 안된 상품을 어떻게 찾을 것인가?

만약 한다면 n초 전 구매한 상품들은 전부 인증기간을 생성해야 하는 가?

 

이러한 부분을 원활하게 처리하기 위해서는 스케줄링은 적합하지 않다 판단했다.

3. Event를 사용하여 비동기로 생성한다.

상품을 구매하면 상품정보와 고객 정보로 Message를 만들어 발행하는 것이다.

 

이렇게 진행한다면 인증 서비스에서는 해당 Topic으로 발행된 Message를 컨슈밍 하여 인증 기간을 생성하는 것으로 깔끔한 과정이 완성된다.

 

물론 과정만 깔끔하다 해서 해당 방법을 채택한 것은 아니었다.

  1. 고가용성 보장
    인증 기간 생성 중 서버 장애가 발생해도, 메시지를 재처리하여 복구 가능하다.
  2. 비동기 처리로 API 성능 향상
    인증 생성은 후속 작업이므로, 클라이언트 응답 속도에 영향을 주지 않는다.
  3. 프로세스 간 결합도 감소
    상품 구매와 인증 생성 로직이 분리되어 유지보수 용이하다.

이러한 장점을 적용시키기 위해 Event를 발행하는 방법으로 개발을 진행하였다.

After

 

이렇게 리펙토링 및 정규화 과정을 거치면서 도메인전문가의 니즈를 충족시키며 기존 발생했던 문제들 혹은 불편한 점들을 개선시킬 수 있었다.

  • 고객이 구매한 상품 인증기간을 관리자가 조절할 수 있다.
  • 상품을 구매하지 않더라도 관리자가 해당 유저의 인증기간을 새로 생성 혹은 기존 인증 기간을 수정할 수 있다.
  • 생성된 인증기간들을 통해 관리자는 유저가 보유한 인증기간을 쉽게 파악할 수 있다.
  • 상품마다 인증기간이 따로 관리되기 때문에 비인증 기간을 파악하기 편하다.

그럼 이렇게만 처리하면 모든 게 다 베스트인가?

완벽하게 잘 처리한 것인가?

 

필자는 주어진 자원 내에 최적의 방법을 선택하여 과제를 해결했다 생각한다.

다만 해당 처리에도 이슈들은 분명 존재한다.

  • Kafka관련 이슈들
  • 기존 데이터 마이그레이션

하지만 이와 관련된 처리는 다른 글에서 다루도록 하고, 여기선 우선 리팩터링 하는 과정에서 했던 고민들과 어떻게 해결하였는지만 다루도록 하겠다.

 

또한, 개발자인 필자가 위와 같이 판단하였다고 맘대로 진행하면 안 된다.

도메인전문가와 기획자와의 소통은 필수 요소이며, 소통을 얼마나 잘하느냐에 따라 결과물이 달라지기 때문이다.

 

똑같은 일 두 번 하기 싫으면 소통을 자주 하는 것을 권장한다.

 

더 좋은 방법 혹은 이야기해보고 싶은 내용이 있다면 댓글 부탁드립니다.

 

 

 

 

 

 

728x90
728x90

이번 글에서 필자는 EDA 즉 Event Driven Architecture를 적용해 보면서 했던 경험들과 고민들을 작성하고자 한다.

 

해당 글을 작성하기에 앞서 알아야 하는 개념들에 대해 정리 후 본론으로 들어가 보자.

  • Event란?
  • 비동기 or 동기
  • 트랜잭션

Event란?

본글에서 말하는 Event는 도메인 모델의 상태 변화 즉 변화를 일으키는 사건을 의미한다.

 

예를 들어 상품을 주문한다 가정해 보자.

  1. 상품 재고를 확인한다.
  2. 상품 재고를 차감한다.
  3. 주문을 생성한다.
  4. 주문 완료 알림을 보낸다.

위와 같은 프로세스를 가진다고 가정한다면 상품이라는 도메인은 '상품 재고가 차감되었다.'라는 이벤트를 발행하고,

주문은 '주문이 생성되었다'라는 이벤트를 발행하게 될 것입니다.


비동기 or 동기

비동기와 동기는 통신 방식입니다.

 

동기 방식의 통신은 현재 Thread가 요청을 보낸 후 응답을 받을 때까지 대기하는 것이고,

비동기는 현재 Thread가 요청을 보낸 후 응답을 받을 때까지 대기하지 않고, 후속 작업을 콜백이나 이벤트 기반으로 처리하는 것입니다.

 

즉 작업의 완료 여부를 어떻게 처리하느냐의 차이가 있습니다.


트랜잭션

업무 처리 단위를 의미합니다.

해당 업무는 ACID를 보장해야 하며 이를 보장하는 방법이 트랜잭션입니다.

  • Atomic(원자성): 트랜잭션 내 데이터들은 데이터베이스에 모두 반영되거나 전혀 반영되지 않아야 합니다.
  • Consistency(일관성): 트랜잭션의 작업 결과는 항상 일관성을 띄워야 합니다.
  • Isolation(독립성): 각각의 트랜잭션은 독립적으로 실행되어야 합니다.
  • Durability(영구성): 트랜잭션이 성공적으로 끝났을 때 결과는 영구적으로 반영되어야 합니다.

위의 4가지 원칙을 보장하여야 합니다.

  • Active(활성): 트랜잭션이 실행 중인 상태
  • Parially Committed(부분완료): 트랜잭션 내 연산이 모두 끝났지만 반영되지 않은 상태
  • Committed(완료): 트랜잭션이 종료되어 데이터베이스에 반영된 상태
  • Failed(실패): 트랜잭션 연산 중 오류가 발생한 상태
  • Aborted(철회): 트랜잭션이 비정상 종료되어 Rollback 연산을 수행한 상태

트랜잭션은 위와 같은 5가지 상태를 가지게 됩니다.

 

특이점으로 Parially Committed에서 Aborted로 가는 경우는 연산은 끝났지만 데이터베이스에 오류가 발생 혹은 종료되어 Commit상태로 가지 못하는 상황 등이 존재합니다.


서비스 간 직접 호출 방식과 Event발행 소비 방식

앞선 예시를 가져와 주문, 상품, 알림 이 3가지 서비스를 예시로 사용하여 두 방식 간의 차이가 무엇인지 알아보겠습니다.

  • OrderService: 주문 서비스
  • ProductService: 상품 서비스
  • NotifyService: 알림 서비스

 

Event발행 방식을 알기 전 저는 서비스 간 호출을 진행할 때 아래와 같이 코드를 작성하였습니다. 

public class OrderUsecase{
    private final OrderService orderService; 
    private final ProductService productService;
    private final NotifyService notifyService;
    
    public void order(...) {
    	// 상품 재고 차감
    	productService.reduceStock(...);
        // 주문 생성
        Order order = orderService.createOrder(...);
        // 주문 알림 발행
        notifyService.sendOrderNotification(order);
    }
}

 

이와 같이 코드를 작성하더라도 문제는 없을 것입니다.

 

상품재고가 없다면 reduceStock Transaction에서 오류가 발생하여 다음 Process를 진행하지 않을 것이고,

주문이 생성되지 않는다면 알림이 발행되지 않기 때문입니다.

 

여기서 고민해 볼 사항은 '알림 발행이 실시간성을 보장해야 하고 알림 발행에 실패한 것이 주문 프로세스에 영향을 끼쳐야 하는가?'입니다.

 

물론 간단하게 처리하려면 notifyService의 sendOrderNotification메소드에 @Async 어노테이션을 붙이면 간단하게 비동기로 처리할 수 있을 것입니다.

 

하지만 여기서 고민해 볼 부분은 만약 이렇게 개발을 계속하게 된다면 어떤 불편함이 존재할까요?

 

NotifyService는 알림을 발행하는 여러 서비스에서 불리게 될 것이며 종속성을 띄게 될 것입니다.

 

그럼 우리는 이 NotifyService의 알림 발행 기능을 수정하기 위해서는 여러 서비스를 돌아다니며 수정해야 하고, 이는 기능이 추가되면 추가될수록 관리가 힘들어진다는 불편함을 낳을 것입니다.

 

또한 알림을 발행하다 실패하거나 서버가 다운되어 버리면 알림이 발행되지 않는 상황이 발생할 수 있습니다.

 

그럼 어떻게 해야 이 불편함과 예외상황을 대응할 수 있을까요?

 

서버가 의도치 않게 다운되는 현상을 JVM에 Graceful Shutdown옵션을 주면서 어느 정도 해결할 수 있습니다.

다만, 이는 서버를 종료할 때 내부 작동 중인 작업을 모두 수행한 후 종료되는 방식으로 중간에 오류가 터졌다거나 아니면 컴퓨터가 나갔다거나 하는 상황은 대응할 수 없습니다. (ex: OOM, 하드웨어 장애, kill -9)

 

이런 상황을 대응하기 위해서는 몇 가지 방법을 생각해 볼 수 있습니다.


1. DB에 발행해야 하는 알림을 저장

첫 번째로 DB에 발행해야 하는 알림을 저장하고, 스케줄링을 통해 n개의 알림을 발행하는 방법입니다.

 

문자 단체발송이나 카카오톡 단체 메시지 발송의 경우 이와 같은 방법을 많이 사용하는 것을 봤는데요.

이는 스케줄링을 통해 n개의 메시지만 처리하기 때문에 메시지 발행 서버의 부하가 일정하다는 장점이 존재합니다.

 

다만 너무 많은 알림이 저장되게 된다면, 메시지 발생시간이 지연되게 되는 단점이 존재합니다.

또한, 발행한 메시지에 대해 flag값을  변경해 주거나 데이터를 삭제해주어야 하기 때문에 DB부하가 발생할 수 있습니다.


2. Event발행

문제점 중 첫 번째 NotifyService의 호출 서비스가 많아 NotifyService의 관리가 힘들다!

 

이 부분은 Event를 발행하여 소비하는 방법으로 변경하면서 간편하게 변경할 수 있습니다.

  1. 주문 생성
  2. OrderCreated Event발행
  3. NotifyEventHandler에서 OrderCreated Event 소비
  4. NotifyService 알림 발행

Event를 발행한다면 Order와 Notiry 간의 결합이 느슨한 결합이 되어 유연성과 확장성이 좋은 형태로 변경할 수 있습니다.

 

그럼 서버가 다운되어 버린다면 알림은 서버가 다시 살아났을 때 잘 발행할 수 있을까요?

 

이벤트 스트리밍 플랫폼(kafka, net, rabbitmq 등)을 사용한다면 서버가 다운되더라도 정상적인 알림 발행이 가능합니다.

 

왜 가능할까요?

 

우선 이벤트 스트리밍 플랫폼은 따로 Instance를 필요로 합니다.

즉 이벤트 관리 서버가 존재한다는 의미이죠.

 

이벤트가 발생하면 Message를 만들어 발행하 Queue에 담아 보관을 하게 됩니다.

즉, 메인 서비스 서버가 죽었다 하더라도 이벤트를 관리하는 서버가 죽지 않는다면 얼마든지 이벤트를 소비할 수 있다는 것이죠.

 

그럼 이벤트 스트리밍 서버 여기서가 다운된다면 메시지는 사라지는 거 아닌가요?

Kafka를 예시로 들면 Kafka는 메시지를 Log Segment로 저장하므로, Kafka가 다운된다 하더라도 문제가 없습니다.

 

다만 옵션에 따라 오래된 Log는 삭제하니 이에 문제가 발생할 수 있습니다.

 

하지만 이벤트 스트리밍 플랫폼은 이벤트에 대해 고가용성을 보장하는 만큼 어느 정도 신뢰를 가질 수 있습니다.

 

그럼 문제가 다 해결될까요?

 

우리가 위에 해결하고자 하는 불편함과 문제 상황 대응은 이렇게 충분한 것 같습니다.

Kafka와 같은 이벤트 스트리밍 플랫폼을 사용할 때 발생할 수 있는 문제들이 존재하지만,

이는 아래 글에서 다루도록 하겠습니다.

 


EDA가 뭔가요?

지금까지는 Event를 발행하면 어떤 문제점 및 문제 상황을 대응할 수 있을지 알아보았습니다.

하지만 결국 Event Driven Architecture가 무엇인지는 아직 잘 와닿지는 않네요.

 

Martin Fowler가 EDA 개념을 정리하면서 나오게 되었는데요,

EDA는 쉽게 Event를 발행하고 수신자가 Event를 소비하는 형태의 시스템 아키텍처입니다.

 

EDA는 크게 3가지 구성요소를 가지게 됩니다.

  • Event generator: 표준화된 형식의 이벤트를 생성
  • Event Producer: 이벤트를 필요로 하는 시스템까지 발송
  • Event Consumer: 이벤트를 구독하고 처리  

이렇게 Event를 사용하여 통신을 하게 되었을 때 장점은 무엇이 있을 까요?

  • 비동기 처리에 용이
  • Loose coupling

등이 존재한다 생각합니다.

 

단점은 어떤 점들이 존재할까요?

  • 트랜잭션 관리의 어려움
  • 디버깅의 어려움
  • Event관리의 어려움

이러한 장단점이 존재하므로 EDA를 적용한다면 현재 서비스에 어떤 문제를 해결하기 위해 적용하는지가 명확해야 합니다.

 

그럼 비동기 개발을 하려면 그냥 EDA적용하면 되는 건가요?

아닙니다. 앞서 말했듯이 무작정 EDA를 적용한다면 Event를 받아 발행하는 Message관리도 어려울 것이고,

관심사가 명확하지 않다면 오히려 복잡한 시스템으로 탄생하게 될 것입니다.

 

그럼 언제 적용하는 것이 좋을까요?

서버 간 결합을 낮춰야 할 때, 여러 작업이 비동기로 처리되어야 할 때와 같이 어떤 문제를 해결하고자 적용하는 것이 적절하다 생각합니다.

 

실제로 EDA를 적용하여 개발하였지만, 오히려 Event들을 처리하는 Process의 복잡도에 의해 리펙토링 하는 상황도 있었고,

실시간성을 보장해야 하지만 Event를 사용하여 비동기로 처리하게 되면서 실시간성을 훼손시키는 상황도 발생하였습니다.

 

즉 EDA든 Event든 만능치료제가 아니니 꼭 알고 사용하기를 권장드립니다. 

 


References

https://medium.com/dtevangelist/event-driven-microservice-%EB%9E%80-54b4eaf7cc4a

https://jaehun2841.github.io/2019/06/23/2019-06-23-event-driven-architecture/

 

 

728x90
728x90

요즘 공고를 보거나 이름 내놓으라는 기업들을 보다 보면 MSA라는 단어를  많이 접하게 된다.

 

본인이 개발할 때도 MSA로 서비스를 분리하여 개발하고 관리하였는데 과연 MSA가 무조건 정답일까?

그럼 이전 모놀리식 아키텍처를 사용하는 것은 잘못된 개발이었을까?라는 의문이 생길 수 있다.

 

오늘 이 글은 필자가 개발하고 공부하면서 고민했던 내용들을 정리하고자 작성한다.


모놀리식 아키텍처가 뭔가요?

해당 내용을 다루기 전에 모놀리식 아키텍처가 무엇인지 알아보자.

 

모놀리식 아키텍처란 프로그램을 하나의 코드베이스에 개발하는 전통적인 아키텍처 모델을 의미한다.

 

이게 무슨 말인가?

 

우리가 서비스를 제공한다 하면 기본적으로 아래와 같은 비즈니스 기능들을 제공하게 될 것이다.

  • 회원관리
  • 게시판
  • 알림

위와 같은 기능들을 제공한다 가정할 때 하나의 애플리케이션이 모든 비즈니스 기능들을 제공하는 책임을 가지는 것이다.

 

즉 Client가 회원관리 요청을 보내든 게시판관리 요청을 보내든 알림 관련 기능 요청을 혹은 응답을 보내든 하나의 서버에서 해당 기능들을 처리하는 것을 의미한다.

 

이렇게 개발하였을 때의 장점과 단점은 무엇일까?

 

우선 장점은 이와 같이 생각해 볼 수 있다.

1. 개발 시작이 간단하다.

하나의 코드베이스에서 모두 개발하기 때문에 간단한 설계 이후 바로 개발이 가능하다.

왜냐면 어차피 하나의 코드베이스에서 개발하기 때문에 추후 리펙토링이 간단하기 때문이다.

2. 배포가 간단하다.

하나의 코드베이스에서 개발하게 된다면 하나의 애플리케이션만 관리하면 되므로 하나만 잘 관리하면 문제 될 일이 없을 것이다.

3. 기술이 통합된다.

하나의 애플리케이션에서 개발하고 관리하게 되므로 사용하는 기술이 단일화될 것이다.


그렇다면 단점은 무엇이 있을까?

1. 확장이 어렵다.

새로운 기능이 추가될 때마다 애플리케이션의 크기가 거대해질 수밖에 없다.

이렇게 된다면 추후 유지보수성을 떨어트릴 뿐만 아니라 추가 기능구현에도 제약이 발생할 확률이 높다.

2. 배포가 어렵다.

애플리케이션에 간단한 수정내용을 반영하고 배포를 하게 된다면 통째로 재배포하게 된다.

이는 애플리케이션의 크기가 작다면 괜찮겠지만 크기가 커졌을 경우 배포시간이 길어지게 되면서 리소스를 많이 소모하게 되는 현상이 발생하게 된다.

3. 기술에 제약이 생긴다.

애플리케이션에서 사용하는 기술들이 통합되다 보니 추가적인 기술 도입이나 서로 다른 언어로 개발하는 것은 매우 어려운 일이 될 것이다.

예를 들어 Java/Spring으로 개발 중인 애플리케이션에 Python/Django를 사용해야 하는 상황이 발생한다면 이는 매우 어려운 길을 걷게 될 것이다.

 

위와 같은 장단점들을 보았을 때 모놀리식 아키텍처를 사용하는 것은 대규모 프로젝트 혹은 많은 비즈니스 기능들을 처리해야 하는 상황에서는 어려운 점들이 보일 것이다.

 

다만 소규모 프로젝트나 MVP처럼 빠른 시일 내에 개발하여야 하거나 적은 비즈니스 기능들을 처리하는 애플리케이션을 개발한다 할 때에는 오히려 개발 및 관리가 편한 아키텍처라 볼 수 있다.


MSA가 뭔가요?

그럼 우리가 이번글에서 비교하고자 하는 MSA는 무엇일까?

 

MSA란 Micro Service Architecture의 약자로 직역하자면 '작은 서비스 아키텍처'이다.

 

MSA는 서비스의 크기를 작게 나누는 개념이라고 볼 수 있다.

 

우리가 모놀리식 아키텍처를 사용하면서 가장 큰 불편함이 무엇인지를 생각해 보자.

기능이 추가됨에 따라 하나의 서비스가 커져 여러 불편한 상황이 발생하는 것이 문제점이라 생각한다.

 

즉, MSA는 기존에 하나의 서비스에 다 개발하였던 비즈니스 기능들을 관심사에 맞춰 부리한 여러 개의 서비스로 나눠 관리할 수 있는 아키텍처라고 보면 된다.

모놀리식 아키텍처를 MSA로 나눠보기

 

이와 같이 모놀리식 아키텍처에서 MSA를 적용하여 서비스들을 나눠볼 수 있다.

 

이렇게 보면 MSA를 적용했을 때의 장점은 다음과 같이 생각해 볼 수 있다.

1. 독립성 및 확장성

특정 비즈니스 기능들을 묶어 개발하게 되면서 각 서비스들은 특정 관심사를 책임지게 된다.

이는 각각의 서비스가 담당하는 비즈니스 기능들이 명확해지면서 추후 오류 추적이나 디버깅이 수월해질 수 있다.

 

또한 기능을 추가하더라도 각각의 관심사에 맞는 서비스에 기능을 추가하면 되므로 확장성과 유지보수성이 좋다.

2. 스케일의 용이

모놀리식의 경우 하나의 서비스를 관리하기 때문에 대용량 트래픽 혹은 대용량 데이터 처리와 같은 과제를 만나게 된다면 스케일 아웃과 같은 방법으로 처리하는 것은 매우 비효율적인 상황이 발생할 것이다.

 

하지만, MSA로 분리한 경우 대용량 트래픽이 몰리는 서비스만 스케일 업이나 스케일 아웃을 통해 해결하면 되므로 MA에 비해 컨트롤할 수 있는 방법이 많아진다.

3. 배포가 쉽다.

간단한 수정사항이 발생하였을 경우 해당 수정이 발생한 애플리케이션만 재배포를 진행하면 되므로 재배포에 대해 MA에 비해 적은 부담을 가지게 된다.

4. 기술적 제약이 적다

각각의 서비스가 물리적으로 분리되어있다 보니 특정 서비스의 기술을 다르게 개발할 수 있는 유연함이 생긴다.

 

즉 Java로 구현하든 Python으로 구현하든 Javascript로 구현하든 서로 영향을 미치는 범위가 적어 유연한 개발이 가능하다는 의미다.


장점이 있다면 단점 또한 존재하는 법 어떤 단점이 존재할까?

1. 설계의 복잡도

만약 처음부터 MSA를 적용하여 개발을 하게 된다면 어떤 기준으로 서비스들을 나누어야 하는지 설계의 고민이 필요하다.

설계가 잘못되어 하나의 서비스가 의도와 다르게 거대해진다면 이는 MSA를 적용하였지만 각각의 서비스는 MA를 적용하여 개발하는 것과 다를게 없어진다 생각한다.

2. 분산 시스템의 복잡도

여러 서비스로 나누다 보니 각각 어떤 통신을 하는지, 오류가 발생했을 때 해당 오류를 찾기 위해 여러 서비스를 확인해야 한다는 단점이 존재한다.

 

또한, 테스트를 진행할 때 특정 비즈니스 기능들이 모여있어 해당 기능들을 테스트하기는 수월하지만, 서비스 간 통신을 통한 비즈니스 기능들은 테스트하기 어려움이 존재한다.

 

트랜잭션 관리에 있어 어려움이 있으며, 이를 해결하기 위해 보상 트랜잭션과 같은 기능들이 구현해야 하기 때문에 자연스레 개발 난이도 및 유지보수 난이도가 올라간다.

3. 인프라 구축의 난이도 상승

각 서비스를 어떻게 관리할 것인지 또한 어떻게 배포할 것인지 각 서비스 간 통신은 어떻게 할 것인지에 대한 인프라가 구축되어야 한다.

 

이는 MA의 단순한 인프라에 비해 많은 리소스를 필요로 할 것이다.

 

이렇듯 MSA 또한 장점만 가지고 있는 것이 아닌 단점 또한 가지고 있다.


MSA 해보니 어땠나?

MSA를 경험하며 다양한 고민과 배움을 얻을 수 있었다.

 

혼자 사이드 프로젝트를 진행하면서 대규모 서비스들을 개발하는 경험은 쉽지 않다 생각한다.

현장에서 MSA로 구축된 프로젝트를 진행하면서 각 서비스를 나누는 기준과 어떤 어려움이 존재하는지를 경험할 수 있는 기회는 매우 소중한 경험이었다.

 

다만 무엇이든 잘못 설계하면 그렇듯이 너무 잘게 나누어 "굳이 나눌 필요가 있을까?"와 같은 고민들을 하게 될 수 있으며,

각 서비스 간 통신 방법에 대하여 동기와 비동기방식 중 어떤 것을 사용할지에 대해 고민하게 될 것이다.

 

처음부터 MSA를 도입하는 것은 어려운 선택일 수 있다.

먼저 모놀리식 아키텍처를 경험하며 그 한계를 느끼고, 이를 해결하는 과정에서 MSA를 도입하는 것이 더 좋은 학습 과정이 될 것이다.

 

처음에는 'MSA가 이미 적용되어 있으니 그대로 쓰면 되겠지'라는 생각을 했지만,

이는 왜 MSA로 구축하였는지에 대한 질문에 답변을 내놓지 못하는 상황이 발생할 수 있다.

 

MA와 MSA에 잘못된 아키텍처는 없다.

다만 "어떤 상황과 문제를 만났기 때문에 어떤 아키텍처를 적용하였다."를 답변하지 못한다면,

이는 스스로 잘못된 방향으로 경험을 쌓았다고 말하고 싶다.

 

아키텍처는 단순히 잘 돌아가는 것이 목표가 아니다.

주어진 환경에서 최적의 해결책을 찾기 위해 끊임없이 고민하고 실천하는 것이 진정한 개발자의 길이라 생각한다.

 

728x90

+ Recent posts