사람은 도로 사진을 보면 보행자, 자동차, 버스를 바로 알아본다. 하지만 컴퓨터에게 이미지는 픽셀의 숫자 덩어리일 뿐이다 컴퓨터 비전(Computer Vision) 은 컴퓨터가 이미지와 영상에서 의미 있는 정보를 이해하고 추론하도록 만드는 분야다. 이 글에서는 컴퓨터 비전의 대표 문제 세 가지와, 각각을 대표하는 모델을 하나씩 정리했다 1.같은 이미지, 다른 출력 같은 이미지라도 어떤 질문에 답하느냐에 따라 출력이 달라진다 1)Classification: 이미지 전체를 대표하는 클래스기 무엇인지 알아낸다 ->이미지 전체를 대표하는클래스 하나(예: 도심 도로) 2)Object Detection: 무엇이 어디에 있는지 알아낸다 -> 물체별 박스와 클래스 출력 3)Segmentation: 각 픽셀이 무엇인지 알아낸다 -> 픽셀별 클래스지도를 출력 2. CNN과 특징 추출 세 문제를 풀 때 공통으로 등장하는 단계가 특징 추출이다 이미지는 픽셀 숫자의 나열이라 그대로는 의미를 알기 어렵기 때문에, 먼저 물체를 구분하는 데 쓸 수 있는 특징을 뽑아내야 한다. 이 역할을 하는 대표 모델이 CNN(합성곱 신경망) 이다. 작은 필터(커널)가 이미지 위를 조금씩 이동하며 각 부분의 특징을 계산한다. 앞쪽 층에서는 선과 모서리 같은 단순한 특징을, 깊은 층으로 갈수록 눈,코,바퀴 같은 복잡한 특징을 학습한다 같은 필터를 이미지 전체에 재사용하기 때문에 파라미터가 적고, 물체가 이미지 어디에 있어도 찾아낼 수 있다 3. Classification와 ResNet 3-1)분류는 어떻게 이루어질까? 이미지 전체를 분석해 클래스별 점수를 계산하고 가장 높은 클래스를 선택한다 입력 이미지 → 특징 추출 → 클래스별 점수 → 가장 높은 클래스 선택 모델이 내놓은 점수(logits)는 그대로 비교하기 어렵기 때문에 softmax로 합이 100%인 확률로 바꾼다 예시에서는 golden retriever가 86%로 가장 높아 최종 답이 된다 3-2)ResNet과 Residual Connection 층을 깊게 쌓으면 성능이 좋아질 것 같지만 제로는 더 깊은 네트워크의 훈련 오차까지 증가하는 현상이 나타났다. 자료에서는 이를 degradation problem이라고 설명한다 그래프에서 56층 모델이 20층 모델보다 훈련 오차가 더 높다. 과적합이 아니라 학습 자체가 잘 안 되는 문제라는 점이 핵심 이다 -> 이때의 해결책이 Residual Connection (Shortcut Connection)이다 기존방식:원하는 출력 H(x)를 직접 학습한다 ResNet: 입력과 출력의 차이 F(x) = H(x) − x를 학습한다 최종 출력: H(x) = F(x) + x x는 이전 층에서 전달된 Feature Map이고, F(x)는 입력에서 필요한 변화량(Residual)이다 필요한 변화가 없다면 F(x)를 0에 가깝게 학습해 입력 x가 그대로 전달되도록 할 수 있다 문서를 처음부터 다시 쓰는 대신 고칠 부분만 수정하는 것과 비슷하다 층을 깊게 쌓아도 손해를 보지 않는 구조가 된다 4. 객체 탐지(Object Detection) 4-1) object Detection이란? 이미지 속 여러 물체의 종류와 위치를 함께 예측한다 입력 이미지 → 특징 추출 → 박스,래스,신뢰도 출력 4-2) Bounding Box와 Confidence Score 객체 탐지의 출력은 물체마다 박스, 클래스, 신뢰도 세 가지다 (1)Bounding Box: 물체를 둘러싸는 사각형이다. 보통 중심 좌표(x, y)와 너비·높이(w, h)로 위치를 나타낸다 (2)Confidence Score(신뢰도): 그 박스 안에 물체가 있다고 모델이 얼마나 확신하는지를 나타내는 값이다. 0~1 또는 %로 표시한다 (예: dog 82%, bicycle 91%) 5.YOLO YOLO(You Only Look Once)는 전체 이미지에서 물체의 위치와 클래스 확률을 * 하나의 네트워크로 동시에 예측한다 * (1) 이미지 크기 조정 : 입력 이미지를 네트워크가 처리할 수 있는 고정 크기로 변환한다 (2) 한 번의 Forward Pass : 하나의 CNN이 전체 이미지를 한 번 처리해 여러 박스와 클래스 확률을 동시에 예측한다 (3) NMS : 예측 이후 같은 물체를 가리키는 중복 박스를 정리한다 4-1)YOLOv1의 격자 방식 YOLOv1은 격자를 이용해 박스와 클래스를 예측하는 것이다 (1)이미지를 S×S 격자 칸으로 나눈다. (2)정답 박스의 중심점이 들어 있는 격자 셀 이 해당 물체를 담당한다. (3)각 셀은 여러 박스와 각 박스의 신뢰도, 그리고 객체의 클래스 확률을 예측한다. 6.이미지 분할(Segmentation)과 U-Net 6-1)이미지 분할이란? 분할의 출력은 원본 이미지와 대응되는 픽셀별 클래스 지도 다 감지는 물체를 사각형으로 찾고, 분할은 물체의 실제 모양을 픽셀 단위로 구분한다 6-2)U-Net과 Encoder–Decoder, Skip Connection U-Net은 이미지의 의미를 파악한 뒤, 해상도를 높여 픽셀별 분할 지도를 생성한다 Encoder : 해상도를 줄이며 넓은 문맥과 의미 특징을 학습한다 Decoder : 특징의 해상도를 높여 픽셀별 분할 지도를 생성한다 Skip Connection : Encoder의 고해상도 특징을 Decoder로 직접 전달해 결합한다. 줄이는 과정에서 사라진 세부 정보를 복원하는 역할이다 구조가 알파벳 U자 모양이라 U-Net이라는 이름이 붙었다
1. 목표 이 글을 읽고 나면 다음을 설명할 수 있다. RDBMS의 @Transactional 과 DynamoDB Transaction의 차이 RDS(MySQL)와 DynamoDB에서 트랜잭션을 처리하는 방식 MySQL과 DynamoDB를 함께 사용할 때 하나의 트랜잭션으로 묶기 어려운 이유 Saga와 이벤트를 이용해 서로 다른 서비스의 작업을 연결하고, Outbox와 Retry 등을 통해 데이터 일관성을 보완하는 방법 2. 개념 2-1. @Transactional 은 어떻게 동작하는가 @Transactional 은 트랜잭션 자체를 구현하는 기능이라기보다 메서드의 실행 범위를 하나의 트랜잭션으로 처리하도록 Spring에 알려주는 역할 을 한다. Spring 동작방식 Transaction Manager를 통해 데이터베이스 Connection의 트랜잭션을 시작하고, 메서드가 정상적으로 끝나면 Commit, 예외가 발생하면 Rollback한다. @Transactional 메서드 호출 ↓ Spring ↓ Transaction Manager ↓ JDBC Connection ↓ BEGIN ↓ MySQL ┌──┴──┐ 정상 종료 예외 발생 ↓ ↓ COMMIT ROLLBACK 실제로 데이터를 Commit하거나 Rollback하는 주체는 데이터베이스다. Spring은 Transaction Manager를 통해 하나의 Connection에서 여러 SQL 작업이 동일한 트랜잭션으로 처리되도록 연결한다. DynamoDB 동작방식 DynamoDB는 JDBC Connection을 사용하는 방식이 아니라 AWS API 요청 단위로 동작 한다. 예를 들어 다음과 같이 여러 번 save() 를 호출하면 각각 별도의 요청이 발생한다. save(orderInfo) → 요청 1 → 저장 save(item #1) → 요청 2 → 저장 save(item #2) → 요청 3 → 실패 이 경우 1, 2의 작업은 이미 DynamoDB에 반영되었기 때문에 3이 실패해도 앞선 작업까지 자동으로 되돌아가지 않는다. 따라서 일반적인 Spring @Transactional 만 사용하는 것으로 DynamoDB의 여러 save() 를 하나의 트랜잭션으로 묶을 수 없다. 2-2. RDS(MySQL)와 DynamoDB의 차이 RDS에서 @Transactional 이 동작하는 이유는 RDS에서 사용하는 데이터베이스가 MySQL 같은 RDBMS이기 때문 이다. 구분 RDS / MySQL DynamoDB 데이터베이스 RDBMS NoSQL 접근 방식 JDBC Connection AWS API 요청 트랜잭션 경계 Connection 내부 Transaction API 요청 Spring @Transactional 사용 가능 일반적인 방식으로는 적용되지 않음 여러 작업 묶기 DB Transaction TransactWriteItems 따라서 로컬에서 실행하는 MySQL과 AWS RDS의 MySQL은 애플리케이션 입장에서는 접속 대상만 다를 뿐, Spring이 JDBC/JPA를 통해 트랜잭션을 처리하는 방식은 동일하다. ★ 차이점: "트랜잭션 경계를 어디에서 관리하는가" RDBMS → 하나의 Connection에서 여러 SQL을 하나의 트랜잭션으로 처리 DynamoDB → DynamoDB Transaction API를 통해 여러 작업을 하나의 요청으로 묶음 2-3. DynamoDB Transaction DynamoDB는 여러 아이템에 대한 작업을 하나의 트랜잭션으로 처리할 수 있는 API를 제공한다. API 역할 TransactWriteItems 여러 Put , Update , Delete 를 하나의 원자적 작업으로 처리 TransactGetItems 여러 아이템을 트랜잭션 단위로 읽기 이 글에서는 쓰기 작업에 사용하는 TransactWriteItems 를 기준으로 살펴본다. 일반적인 save() 와 비교하면 차이가 명확하다. [일반 save()] orderInfo 저장 ✔ ↓ item #1 저장 ✔ ↓ item #2 저장 ✘ → orderInfo와 item #1은 남아 있음 [TransactWriteItems] orderInfo + item #1 + item #2 ↓ 하나의 요청 ↓ item #2 실패 ↓ 전체 취소 AWS SDK v2의 Enhanced Client를 사용하면 다음과 같이 여러 작업을 하나의 요청에 담을 수 있다. public void createOrder( ShopData orderInfo, List<ShopData> itemEntities ) { TransactWriteItemsEnhancedRequest.Builder builder = TransactWriteItemsEnhancedRequest.builder() .addPutItem(shopDataTable, orderInfo); itemEntities.forEach( item -> builder.addPutItem(shopDataTable, item) ); try { enhancedClient.transactWriteItems(builder.build()); } catch (TransactionCanceledException e) { throw new RuntimeException("주문 저장 트랜잭션 실패", e); } } 코드설명: addPutItem() 으로 필요한 작업을 하나의 요청에 담은 뒤 transactWriteItems() 로 실행 하나의 작업이라도 트랜잭션 조건을 만족하지 못하면 전체 작업이 취소된다. 사용 시 고려 사항: 한 트랜잭션에 최대 100개 작업 총 요청 크기 최대 4MB 동일 아이템을 하나의 트랜잭션에서 중복 처리할 수 없음 일반 쓰기보다 추가적인 용량이 사용되므로 원자성이 필요한 작업에 사용하는 것이 적절함 여기까지는 하나의 저장소 내부에서 트랜잭션을 처리하는 방법 이다. 문제는 MySQL과 DynamoDB처럼 서로 다른 저장소를 함께 사용할 때 발생한다. 3. MySQL + DynamoDB 3-1. 다른 데이터베이스를 하나의 트랜잭션으로 묶는 방법 각 저장소 내부에서는 트랜잭션을 사용할 수 있지만, 두 저장소의 트랜잭션을 단순한 @Transactional 하나로 묶을 수는 없다. MySQL과 DynamoDB는 각각 자신의 트랜잭션을 관리하기 때문이다. Spring ├── MySQL │ └── @Transactional │ └── DynamoDB └── TransactWriteItems 두 트랜잭션은 서로의 상태를 알지 못하기 때문에, 발생하는 문제점으로는 MySQL 저장(COMMIT)은 성공했으나, DynamoDB 저장이 실패할 수 있다. MySQL 저장 ✔ DynamoDB 저장 ✔ ↓ <COMMIT 완료> ↓ DynamoDB 저장 ✘ MySQL Commit ✘ 이 경우, 다른 DBMS 실패를 이유로 기존에 COMMIT된 DBMS를 자동으로 Rollback 할 수 없다. 이론적으로는 2PC(Two-Phase Commit) 같은 분산 트랜잭션 방식이 있지만, 구현 복잡도와 성능 부담이 있고 DynamoDB를 전통적인 XA 기반 분산 트랜잭션에 참여시키는 방식도 일반적이지 않다. 추천하는 방법은, MySQL과 DynamoDB를 함께 사용하는 경우 각 저장소의 로컬 트랜잭션을 사용하고, 이벤트로 작업을 연결하는 방식 이다. 이때 등장하는 대표적인 패턴이 Saga 다. 3-2. Saga와 Choreography Saga는 하나의 큰 트랜잭션 대신 각 서비스의 로컬 트랜잭션을 순차적으로 실행하고, 실패하면 보상 작업을 수행하는 방식 이다. Service A │ │ 로컬 트랜잭션 ↓ 성공 이벤트 ↓ Message Broker ↓ Service B │ │ 로컬 트랜잭션 ↓ 성공 이벤트 ↓ Message Broker ↓ Service C 중간 단계에서 실패하면 이전 작업을 ROLLBACK하는 것이 아니라 보상 트랜잭션(Compensating Transaction) 을 별도의 작업으로 실행한다. 예를 들어 주문을 취소해야 한다면 이미 Commit된 주문 데이터를 DB Rollback으로 되돌리는 것이 아니라 주문 상태를 CANCELED 로 변경하는 식이다. Saga의 조율 방식은 크게 두 가지다. 구분 Choreography Orchestration 조율 주체 없음 중앙 Orchestrator 다음 작업 이벤트를 받은 서비스가 판단 Orchestrator가 지시 서비스 간 결합 이벤트 기반 Orchestrator에 의존 전체 흐름 파악 상대적으로 어려움 상대적으로 쉬움 이번에는 Choreography 를 기준으로 살펴본다. 주문 서비스 ↓ 주문 생성 이벤트 ↓ Message Broker ↓ 상세 서비스 ↓ 상세 데이터 저장 각 서비스는 자신의 데이터베이스에 대한 로컬 트랜잭션만 관리한다. 따라서 모든 데이터가 동시에 변경되는 것이 아니라 이벤트가 전달되는 과정에서 잠시 차이가 발생할 수 있다. 이를 최종적 일관성(Eventual Consistency) 이라고 한다. 4. 이벤트 전달의 신뢰성 Saga에서는 이벤트가 다음 서비스로 전달되어야 다음 로컬 트랜잭션이 실행된다. 그런데 여기서 또 하나의 문제가 생긴다. DB에 데이터를 Commit하는 작업과 메시지 브로커에 이벤트를 발행하는 작업 역시 서로 다른 시스템에서 수행되기 때문이다. 메시지 브로커 종류 및 특징 기술 방식 특징 RabbitMQ Queue / Exchange 메시지 라우팅과 작업 큐에 적합 Apache Kafka Topic / Partition 대규모 이벤트 스트리밍, 메시지 보관 및 재처리에 적합 Amazon SQS Queue AWS 관리형 큐, 서버 운영 없이 사용 가능 4-1. 메시지 브로커 장애 주문 DB 저장 ✔ ↓ 이벤트 발행 ↓ Message Broker 장애 ✘ ↓ 상세 서비스 이벤트 수신 실패 주문 데이터는 이미 Commit됐지만 후속 작업은 실행되지 않을 수 있다. 즉, Saga를 사용한다고 해서 데이터 일관성 문제가 모두 해결되는 것은 아니다. DB 저장 ↓ ? 이벤트 발행 DB와 메시지 브로커 사이에서도 "한쪽은 성공했는데 다른 쪽은 실패하는 문제" 가 발생한다. 4-2. Outbox Pattern 이 문제를 해결하는 대표적인 방법이 Transactional Outbox Pattern 이다. 핵심은 이벤트를 바로 브로커에 보내지 않고, 비즈니스 데이터와 이벤트 정보를 같은 DB에 먼저 저장하는 것 이다. ┌──────────────────────┐ │ MySQL │ │ │ │ Order │ │ Outbox Event │ └──────────┬───────────┘ │ 같은 Transaction ↓ COMMIT │ ↓ Relay / Publisher │ ↓ Message Broker │ ↓ Consumer 예를 들어 주문 생성과 이벤트 기록을 같은 트랜잭션으로 처리한다. MySQL Transaction ├── Order 저장 └── Outbox Event 저장 ↓ COMMIT 둘 다 성공하거나 둘 다 실패한다. Commit 이후 별도의 Relay가 Outbox를 읽어 메시지 브로커로 이벤트를 발행한다. 브로커가 일시적으로 장애가 발생해도 이벤트 자체는 DB에 남아 있기 때문에 복구 후 다시 발행할 수 있다. DynamoDB를 사용하는 경우에도 같은 개념을 적용할 수 있다. DynamoDB Transaction ├── Order Item 저장 └── Outbox Item 저장 ↓ TransactWriteItems ↓ COMMIT 즉, 비즈니스 데이터와 이벤트를 같은 트랜잭션 경계 안에 넣어 이벤트 유실 가능성을 줄이는 것 이다. 4-3. Retry, DLQ, Idempotency Outbox를 사용한다고 장애가 없을 것 같으냐,. 아니다. 이 무슨. 이벤트를 전달하고 처리하는 과정에서도 실패와 중복이 발생할 수 있다. 방법 역할 Outbox 이벤트 유실 방지 Retry 일시적인 전송·처리 실패 재시도 DLQ 반복적으로 실패하는 메시지 격리 Idempotency 동일 메시지가 여러 번 처리되어도 결과가 중복되지 않도록 방어 Broker HA 브로커 장애 가능성을 낮춤 Outbox를 사용했을 때 발생하는 가장 큰 주의점은 Retry와 Outbox를 사용하면 중복 메시지 가 발생할 수 있다는 것이다. 이벤트 발행 ↓ Consumer 처리 성공 ↓ 응답 전달 실패 ↓ Retry ↓ 같은 이벤트 다시 전달 따라서 Consumer는 같은 이벤트를 여러 번 받아도 최종 결과가 한 번 처리한 것과 같도록 멱등성(Idempotency) 을 고려해야 한다. 계속 처리에 실패하는 메시지는 DLQ로 보내 별도로 확인하고 재처리할 수 있다. Broker HA는 브로커 자체의 장애 가능성을 줄이는 역할을 하지만 장애를 완전히 없애는 것은 아니다. 각 방법이 해결하는 문제는 다음과 같이 구분할 수 있다. Outbox ↓ 이벤트 유실 방지 Retry ↓ 일시적 실패 대응 ↓ 중복 가능 ↓ Idempotency Retry 반복 실패 ↓ DLQ Broker HA ↓ 브로커 장애 가능성 감소 5. 정리 트랜잭션을 어디까지 하나로 묶을 수 있는지는 데이터 저장소와 시스템의 경계 에 따라 달라진다. 범위 일관성을 관리하는 방법 단일 RDBMS @Transactional + DB Transaction 단일 DynamoDB TransactWriteItems 서로 다른 서비스·저장소 Saga + 이벤트 DB ↔ Message Broker Outbox + Retry / DLQ / Idempotency RDS의 MySQL에서는 Spring의 @Transactional 과 DB Transaction을 이용해 여러 SQL 작업을 하나로 묶을 수 있다. DynamoDB 내부에서 여러 아이템을 원자적으로 처리해야 한다면 TransactWriteItems 를 사용한다. MySQL과 DynamoDB처럼 서로 다른 저장소의 작업을 하나의 트랜잭션으로 묶으려면 각 저장소의 로컬 트랜잭션을 사용하고 Saga와 이벤트를 통해 서비스 간 작업을 연결할 수 있다. 이벤트 기반 구조에서는 DB와 메시지 브로커 사이에서도 동일한 문제가 발생한다. 이를 보완하기 위해 Outbox, Retry, DLQ, Idempotency 등을 함께 사용한다. 모든 작업을 하나의 트랜잭션으로 묶는 것이 아니라, 각 경계에서 어떤 방식으로 일관성을 보장할 것인지 결정하는 것 이 이번 글의 핵심이다. 참고 자료 Spring Framework — Transaction Management AWS — DynamoDB Transactions AWS SDK for Java 2.x — DynamoDB Enhanced Client Transactions AWS — DynamoDB TransactWriteItems API Reference RabbitMQ — RabbitMQ vs Kafka Apache Kafka — Introduction AWS — What is Amazon SQS?
0. 강의자료 https://bit.ly/4xSmcPI 1. 셋팅 1) 리눅스 설치 Ubuntu 24.04LTS 설치 2017년 Google Transform ROS / SLAM / Navigation ROS에서 제공하는 SLAM? 도마뱀로봇 우분투 멀티부팅해야함 2) 파이썬 설치 3) vscode 설치 4) liboffice설치 2. ROS2 로봇이랑 커뮤니케이션하는 것 문법을 배운다고 생각하면 됨! 로봇이 움직이는 것 = 강화학습 1) ROS2 설치 메뉴얼 3. SLAM 4. Navigation 선형대수가 필요하다 / 기하학 / 미적분 파이썬의 class 정도는 다룰 수 있어야함