
NEW
NVIDIA GPU Operator로 GPU 모니터링 PoC 구축하기
GPU를 활용한 클라우드 환경에서는 비용 효율적이고 안정적인 운영을 위해 GPU 자원의 성능 지표(Metric)를 정확하게 수집하고 분석할 수 있는 모니터링 시스템 구축이 필수적입니다.특히 GPU 인스턴스는 높은 성능만큼 비용도 상대적으로 높아 효율적인 자원 관리와 비용 최적화가 매우 중요합니다.본 글에서는 이러한 과제를 해결하기 위해 AWS의 GPU 스팟(Spot) 인스턴스(g4dn, g5, g6)를 기반으로 Kubernetes(EKS) NodeGroup을 구성하고,NVIDIA GPU Operator를 통해 GPU 자원을 모니터링하는 PoC(Proof of Concept) 환경을 구축하는 방법을 소개합니다.스팟 인스턴스는 온디맨드 인스턴스 대비 약 70~80%까지 비용을 절감할 수 있지만,모든 리전 및 가용영역(AZ)에서 사용할 수 있는 것은 아니므로, 사전에 각 인스턴스 타입의 비용과 가용성을 확인하는 것이 중요합니다.본 가이드에서는 다음과 같은 작업을 진행하겠습니다.• None AWS에서 GPU 스팟 인스턴스를 이용한 EKS 클러스터 및 NodeGroup 구성이 글을 통해 GPU 기반 클라우드 자원의 효율적인 관리 방안을 확인하고, 비용 효율성을 높이는 실질적인 방법을 익힐 수 있습니다.AWS에서 GPU 스팟 인스턴스를 이용한 EKS 클러스터 및 NodeGroup 구성K8s 클러스터를 생성하기 위해 필수적인 정보를 입력한 cluster.yaml 파일을 생성합니다.eksctl 명령어를 이용하여 K8s 클러스터를 생성합니다.성공적으로 구성이 완료되었다면, 다음 명령어를 통해 kubeconfig를 업데이트하고 노드를 조회합니다.NVIDIA GPU Operator는 Kubernetes 환경에서 GPU 자원을 효율적으로 관리할 수 있도록 지원하는 오픈소스 솔루션입니다.GPU Operator는 NVIDIA 드라이버 설치부터, GPU 자원 할당 및 관리, 성능 모니터링까지의 전체 과정을 자동화합니다.이를 통해 GPU 기반 워크로드의 배포와 관리가 쉬워지고, 운영 효율성을 높일 수 있습니다.• None NVIDIA GPU 드라이버의 자동 설치 및 관리GPU Operator는 Helm을 사용하여 Kubernetes 클러스터에 쉽게 설치할 수 있습니다. 아래와 같은 순서로 진행합니다:모든 Pod가 정상적으로 실행되고 있으면 설치가 성공적으로 완료된 것입니다.Prometheus는 Kubernetes 환경에서 메트릭을 수집하고 저장하는 대표적인 모니터링 시스템입니다.Grafana는 수집된 메트릭을 시각화하여 분석할 수 있게 지원합니다.본 글에서는 Prometheus와 Grafana를 Helm을 사용하여 설치하는 방법을 안내합니다.브라우저에서 http://localhost:9090 으로 접속할 수 있습니다.DCGM 메트릭을 입력하여 정상적으로 조회되는지 확인합니다.Prometheus 로 수집된 메트릭을 시각적으로 확인하기 위해서 Grafana 대시보드를 사용합니다.메트릭에 따라 사전에 정의된 대시보드가 있으며 Grafana 공식사이트에서 조회 후 대시보드 ID를 복사하여 사용하거나, 기존에 사용하는 대시보드를 json 파일로 등록할 수 있습니다.대시보드 ID를 클립보드에 복사합니다.배포한 Grafana에 접속하여 복사한 대시보드 ID를 로드합니다.Grafana에서 NVIDIA DCGM Exporter Dashboard를 가져오면 GPU 사용률, 전력 소비량, 메모리 사용량 등을 시각화할 수 있습니다.값이 조회되지 않는 경우에는 편집 모드로 변경 후 Metrics browser의 메트릭 값을 복사하여 Prometheus 콘솔에서 조회되는지 확인합니다.이제 AWS GPU 인스턴스 환경에서 NVIDIA GPU Operator를 활용하여 GPU 자원 모니터링이 가능합니다.Kubernetes 환경에 구축된 Prometheus와 Grafana를 통해 GPU 성능 데이터를 실시간으로 수집하고 분석할 수 있습니다.본 글에서 구축한 환경은 클라우드뿐만 아니라 On-Premise 환경에서도 활용 가능하며, 이를 통해 GPU 자원의 최적화와 운영 비용의 효율적 관리가 가능합니다.
grafana
kubernetes
prometheus
5/7/2025

NVIDIA GPU Operator로 GPU 모니터링 PoC 구축하기
NEW
GPU를 활용한 클라우드 환경에서는 비용 효율적이고 안정적인 운영을 위해 GPU 자원의 성능 지표(Metric)를 정확하게 수집하고 분석할 수 있는 모니터링 시스템 구축이 필수적입니다.특히 GPU 인스턴스는 높은 성능만큼 비용도 상대적으로 높아 효율적인 자원 관리와 비용 최적화가 매우 중요합니다.본 글에서는 이러한 과제를 해결하기 위해 AWS의 GPU 스팟(Spot) 인스턴스(g4dn, g5, g6)를 기반으로 Kubernetes(EKS) NodeGroup을 구성하고,NVIDIA GPU Operator를 통해 GPU 자원을 모니터링하는 PoC(Proof of Concept) 환경을 구축하는 방법을 소개합니다.스팟 인스턴스는 온디맨드 인스턴스 대비 약 70~80%까지 비용을 절감할 수 있지만,모든 리전 및 가용영역(AZ)에서 사용할 수 있는 것은 아니므로, 사전에 각 인스턴스 타입의 비용과 가용성을 확인하는 것이 중요합니다.본 가이드에서는 다음과 같은 작업을 진행하겠습니다.• None AWS에서 GPU 스팟 인스턴스를 이용한 EKS 클러스터 및 NodeGroup 구성이 글을 통해 GPU 기반 클라우드 자원의 효율적인 관리 방안을 확인하고, 비용 효율성을 높이는 실질적인 방법을 익힐 수 있습니다.AWS에서 GPU 스팟 인스턴스를 이용한 EKS 클러스터 및 NodeGroup 구성K8s 클러스터를 생성하기 위해 필수적인 정보를 입력한 cluster.yaml 파일을 생성합니다.eksctl 명령어를 이용하여 K8s 클러스터를 생성합니다.성공적으로 구성이 완료되었다면, 다음 명령어를 통해 kubeconfig를 업데이트하고 노드를 조회합니다.NVIDIA GPU Operator는 Kubernetes 환경에서 GPU 자원을 효율적으로 관리할 수 있도록 지원하는 오픈소스 솔루션입니다.GPU Operator는 NVIDIA 드라이버 설치부터, GPU 자원 할당 및 관리, 성능 모니터링까지의 전체 과정을 자동화합니다.이를 통해 GPU 기반 워크로드의 배포와 관리가 쉬워지고, 운영 효율성을 높일 수 있습니다.• None NVIDIA GPU 드라이버의 자동 설치 및 관리GPU Operator는 Helm을 사용하여 Kubernetes 클러스터에 쉽게 설치할 수 있습니다. 아래와 같은 순서로 진행합니다:모든 Pod가 정상적으로 실행되고 있으면 설치가 성공적으로 완료된 것입니다.Prometheus는 Kubernetes 환경에서 메트릭을 수집하고 저장하는 대표적인 모니터링 시스템입니다.Grafana는 수집된 메트릭을 시각화하여 분석할 수 있게 지원합니다.본 글에서는 Prometheus와 Grafana를 Helm을 사용하여 설치하는 방법을 안내합니다.브라우저에서 http://localhost:9090 으로 접속할 수 있습니다.DCGM 메트릭을 입력하여 정상적으로 조회되는지 확인합니다.Prometheus 로 수집된 메트릭을 시각적으로 확인하기 위해서 Grafana 대시보드를 사용합니다.메트릭에 따라 사전에 정의된 대시보드가 있으며 Grafana 공식사이트에서 조회 후 대시보드 ID를 복사하여 사용하거나, 기존에 사용하는 대시보드를 json 파일로 등록할 수 있습니다.대시보드 ID를 클립보드에 복사합니다.배포한 Grafana에 접속하여 복사한 대시보드 ID를 로드합니다.Grafana에서 NVIDIA DCGM Exporter Dashboard를 가져오면 GPU 사용률, 전력 소비량, 메모리 사용량 등을 시각화할 수 있습니다.값이 조회되지 않는 경우에는 편집 모드로 변경 후 Metrics browser의 메트릭 값을 복사하여 Prometheus 콘솔에서 조회되는지 확인합니다.이제 AWS GPU 인스턴스 환경에서 NVIDIA GPU Operator를 활용하여 GPU 자원 모니터링이 가능합니다.Kubernetes 환경에 구축된 Prometheus와 Grafana를 통해 GPU 성능 데이터를 실시간으로 수집하고 분석할 수 있습니다.본 글에서 구축한 환경은 클라우드뿐만 아니라 On-Premise 환경에서도 활용 가능하며, 이를 통해 GPU 자원의 최적화와 운영 비용의 효율적 관리가 가능합니다.
2025.05.07
grafana
kubernetes
prometheus

좋아요

별로에요

NEW
내가 JUnit5에 병렬화를 도입한 이야기 - 메서드 단위
안녕하세요, Junit-team/junit5, spring/spring-boot, apache/seata, naver/fixture-monkey 등 여러 오픈소스 프로젝트에 기여한 YongGoose입니다.처음에는 오픈소스 기여에 대한 관심을 높이려는 의도로 글을 쓰기 시작했지만, 점점 나의 소중한 자식들(?)을 소개하는 재미가 생기네요.이번 글은 아래의 글의 후속 편입니다. (미리 읽고 오시면 좋습니다)JUnit5에 병렬화를 도입한 이야기 - 클래스 단위저번 글에서는 JUnit의 Vintage 엔진에 클래스 단위의 병렬화를 도입한 것을 설명했습니다.여러 개의 테스트 클래스를 실행할 때는 해당 기능으로 인해 성능 향상을 기대할 수 있지만,만약 하나의 테스트 클래스에 있는 여러 개의 메서드를 실행할 때는 성능 향상을 기대하기 어렵습니다.그로 인해 메서드 단위의 병렬화도 메인테이너님께 제안을 드렸고, 긍정적인 답변을 받아 작업을 하게 되었습니다.메인테이너님의 코멘트에서 볼 수 있다시피 클래스 단위 병렬화에서 사용하던 스레드 풀을 활용하면 쉽게 해결이 되는 듯했습니다.그래서 위 다이어그램과 같이 Runner가 ParentRunner인 경우, 모든 childStatement(메서드)를 스레드 풀을 활용해 비동기로 실행하도록 구현했습니다.하지만, 제 기대와 달리 교착 상태가 발생하였습니다.위 이미지는 Github Actions의 워크플로우 결과 이미지인데 6시간 동안 실행을 한 뒤, 시간이 초과되어 자동으로 실패한 것을 볼 수 있습니다.이때 교착 상태는 클래스와 메서드에서 모두 병렬화를 활성화시키고, 테스트 클래스의 수보다 스레드 풀의 크기가 작을 때 발생하였습니다.클래스와 메서드 단위에서 병렬화를 모두 활성화시키면 다음과 같은 순서로 실행이 됩니다.이때 교착 상태는 테스트 클래스의 개수보다 스레드 풀의 크기가 작을 때 발생했습니다. (동일할 때도 발생했습니다)자세히 디버깅한 결과, 현재 사용 중인 스레드 풀의 특성과 연관하여 교착 상태가 발생한 원인을 확인할 수 있었습니다.실행 순서 중, 2번(각 상위 작업에 대해 실행 시작)을 할 때 하나의 스레드가 할당이 됩니다.그리고 해당 스레드는 모든 하위 작업이 완료되어 상위 작업이 완료가 되면 스레드가 반환이 됩니다.만약 스레드 풀의 크기가 3이고, 테스트 클래스의 개수가 3, 각 하위 메서드의 개수도 3이라면모든 스레드는 상위 클래스가 점유하게 되어 하위 메서드는 작업 큐에만 저장이 될 뿐 실행이 되지 않아 교착상태가 발생하는 것입니다.교착상태가 일어나는 4가지 조건과 함께 더 자세히 설명드리겠습니다.우선, 교착 상태가 일어나는 4가지 조건은 아래와 같습니다.그러면 현재의 상태에 대입해 설명하겠습니다.• None 상호 배제 : 스레드는 한 번에 하나의 작업만 사용할 수 있습니다.• None 점유 대기 : 상위 작업(클래스)은 각각 스레드를 점유한 상태에서 하위 작업(메서드)을 제출하고 완료를 기다립니다.• None 비선점 : 현재 사용 중인 스레드는 점유된 스레드를 강제로 해제하거나 다른 작업에 재할당 하지 않습니다.• None 순환 대기 : 상위 작업(클래스)은 각각 하위 작업(메서드)의 완료를 기다리고, 하위 작업(메서드)은 상위 작업(클래스)이 완료되어 스레드가 반환되기를 기다리고 있습니다.아래의 그림은 다이어그램으로 설명한 그림입니다. (조금 난잡해 보이더라도 순서대로 읽으시면 잘 이해가 될 거라고 생각합니다...)그래서 메인테이너님과 현재 상황에 대해 토론을 한 결과 ForkJoinPool을 사용하기로 결정이 되었습니다.ForkJoinPool은 작업 큐에 작업이 남아있는 경우 스레드가 블로킹되지 않고 다른 작업을 처리하는 특성을 가지고 있습니다.그래서 교착상태가 발생하는 4가지 조건 중, 순환 대기를 해결할 수 있다는 장점이 있습니다.각각의 작업이 서로의 작업의 완료를 기다리고 있는 상태가 순환 대기인데 ForkJoinPool을 활용하여 서로의 작업의 완료를 기다리지 않고 다른 작업을 처리하도록 구현하였습니다.Jupiter 엔진의 경우 이미 병렬화에서 ForkJoinPool을 사용하고 있었습니다.아래의 코드는 ForkJoinPool을 활용해 교착상태를 해결하고 메서드 단위의 병렬화를 구현한 코드입니다.work stealing을 허용하기 위해 Future.get()을 각각 호출한 것을 볼 수 있습니다.아래의 이미지는 교착상태를 해결한 흐름을 나타내는 다이어그램입니다.결과적으로는 6시간 동안 실행을 했던 Github Actions도 정상적으로 완료가 되었고, 스레드 풀의 크기에 상관없이 교착상태가 더 이상 발생하지 않고 정상적으로 실행이 되는 것을 확인했습니다.아래의 공식 문서에서 클래스, 메서드 수준의 병렬화를 스레드 사용 예시와 함께 볼 수 있습니다.이번 글이 올라왔을 때는 아래의 PR이 병합되었을 것이라고 생각합니다. (현재 문서화 작업 마무리 중)대부분의 티스토리, 벨로그 글을 보면 ExtensionContext를 활용해 테스트 간 자원을 공유하는 것을 확인할 수 있습니다.하지만, 이러한 자원 공유는 범위가 병확하지 않아 특정 시점이나 테스트 세션 간 자원 관리가 복잡해질 수 있습니다.아래의 PR은 JUnit 플랫폼에서 자원 공유를 request / session 이라는 두 가지 범위로 나누어 관리할 수 있도록 하는 기능을 추가하고 있습니다.이를 통해 자원을 더 세밀하게 제어하고, 테스트 실행 간의 자원의 재사용성을 높이는 것이 목표입니다.해당 기능은 잘 모르고 사용한다면 기존의 ExtensionContext와 별 다르게 사용할 수 없다고 생각합니다.하지만 잘 알고 사용한다면 자원 공유를 매우 효율적으로 사용할 수 있습니다.각종 tech blog들에서도 분명 해당 기능이 merge가 된 후 배포가 되면 자세히 다룰 것으로 예상합니다.하지만, 문서와 코드를 보고 글을 작성하는 분들보다는 직접 만든 사람이 더 잘 알 것이라고 생각합니다. ㅎㅎ해당 글도 DEVOCEAN와 같이 접근성이 좋은 곳에 외부 기고를 하겠습니다.
junit
5/7/2025

내가 JUnit5에 병렬화를 도입한 이야기 - 메서드 단위
NEW
안녕하세요, Junit-team/junit5, spring/spring-boot, apache/seata, naver/fixture-monkey 등 여러 오픈소스 프로젝트에 기여한 YongGoose입니다.처음에는 오픈소스 기여에 대한 관심을 높이려는 의도로 글을 쓰기 시작했지만, 점점 나의 소중한 자식들(?)을 소개하는 재미가 생기네요.이번 글은 아래의 글의 후속 편입니다. (미리 읽고 오시면 좋습니다)JUnit5에 병렬화를 도입한 이야기 - 클래스 단위저번 글에서는 JUnit의 Vintage 엔진에 클래스 단위의 병렬화를 도입한 것을 설명했습니다.여러 개의 테스트 클래스를 실행할 때는 해당 기능으로 인해 성능 향상을 기대할 수 있지만,만약 하나의 테스트 클래스에 있는 여러 개의 메서드를 실행할 때는 성능 향상을 기대하기 어렵습니다.그로 인해 메서드 단위의 병렬화도 메인테이너님께 제안을 드렸고, 긍정적인 답변을 받아 작업을 하게 되었습니다.메인테이너님의 코멘트에서 볼 수 있다시피 클래스 단위 병렬화에서 사용하던 스레드 풀을 활용하면 쉽게 해결이 되는 듯했습니다.그래서 위 다이어그램과 같이 Runner가 ParentRunner인 경우, 모든 childStatement(메서드)를 스레드 풀을 활용해 비동기로 실행하도록 구현했습니다.하지만, 제 기대와 달리 교착 상태가 발생하였습니다.위 이미지는 Github Actions의 워크플로우 결과 이미지인데 6시간 동안 실행을 한 뒤, 시간이 초과되어 자동으로 실패한 것을 볼 수 있습니다.이때 교착 상태는 클래스와 메서드에서 모두 병렬화를 활성화시키고, 테스트 클래스의 수보다 스레드 풀의 크기가 작을 때 발생하였습니다.클래스와 메서드 단위에서 병렬화를 모두 활성화시키면 다음과 같은 순서로 실행이 됩니다.이때 교착 상태는 테스트 클래스의 개수보다 스레드 풀의 크기가 작을 때 발생했습니다. (동일할 때도 발생했습니다)자세히 디버깅한 결과, 현재 사용 중인 스레드 풀의 특성과 연관하여 교착 상태가 발생한 원인을 확인할 수 있었습니다.실행 순서 중, 2번(각 상위 작업에 대해 실행 시작)을 할 때 하나의 스레드가 할당이 됩니다.그리고 해당 스레드는 모든 하위 작업이 완료되어 상위 작업이 완료가 되면 스레드가 반환이 됩니다.만약 스레드 풀의 크기가 3이고, 테스트 클래스의 개수가 3, 각 하위 메서드의 개수도 3이라면모든 스레드는 상위 클래스가 점유하게 되어 하위 메서드는 작업 큐에만 저장이 될 뿐 실행이 되지 않아 교착상태가 발생하는 것입니다.교착상태가 일어나는 4가지 조건과 함께 더 자세히 설명드리겠습니다.우선, 교착 상태가 일어나는 4가지 조건은 아래와 같습니다.그러면 현재의 상태에 대입해 설명하겠습니다.• None 상호 배제 : 스레드는 한 번에 하나의 작업만 사용할 수 있습니다.• None 점유 대기 : 상위 작업(클래스)은 각각 스레드를 점유한 상태에서 하위 작업(메서드)을 제출하고 완료를 기다립니다.• None 비선점 : 현재 사용 중인 스레드는 점유된 스레드를 강제로 해제하거나 다른 작업에 재할당 하지 않습니다.• None 순환 대기 : 상위 작업(클래스)은 각각 하위 작업(메서드)의 완료를 기다리고, 하위 작업(메서드)은 상위 작업(클래스)이 완료되어 스레드가 반환되기를 기다리고 있습니다.아래의 그림은 다이어그램으로 설명한 그림입니다. (조금 난잡해 보이더라도 순서대로 읽으시면 잘 이해가 될 거라고 생각합니다...)그래서 메인테이너님과 현재 상황에 대해 토론을 한 결과 ForkJoinPool을 사용하기로 결정이 되었습니다.ForkJoinPool은 작업 큐에 작업이 남아있는 경우 스레드가 블로킹되지 않고 다른 작업을 처리하는 특성을 가지고 있습니다.그래서 교착상태가 발생하는 4가지 조건 중, 순환 대기를 해결할 수 있다는 장점이 있습니다.각각의 작업이 서로의 작업의 완료를 기다리고 있는 상태가 순환 대기인데 ForkJoinPool을 활용하여 서로의 작업의 완료를 기다리지 않고 다른 작업을 처리하도록 구현하였습니다.Jupiter 엔진의 경우 이미 병렬화에서 ForkJoinPool을 사용하고 있었습니다.아래의 코드는 ForkJoinPool을 활용해 교착상태를 해결하고 메서드 단위의 병렬화를 구현한 코드입니다.work stealing을 허용하기 위해 Future.get()을 각각 호출한 것을 볼 수 있습니다.아래의 이미지는 교착상태를 해결한 흐름을 나타내는 다이어그램입니다.결과적으로는 6시간 동안 실행을 했던 Github Actions도 정상적으로 완료가 되었고, 스레드 풀의 크기에 상관없이 교착상태가 더 이상 발생하지 않고 정상적으로 실행이 되는 것을 확인했습니다.아래의 공식 문서에서 클래스, 메서드 수준의 병렬화를 스레드 사용 예시와 함께 볼 수 있습니다.이번 글이 올라왔을 때는 아래의 PR이 병합되었을 것이라고 생각합니다. (현재 문서화 작업 마무리 중)대부분의 티스토리, 벨로그 글을 보면 ExtensionContext를 활용해 테스트 간 자원을 공유하는 것을 확인할 수 있습니다.하지만, 이러한 자원 공유는 범위가 병확하지 않아 특정 시점이나 테스트 세션 간 자원 관리가 복잡해질 수 있습니다.아래의 PR은 JUnit 플랫폼에서 자원 공유를 request / session 이라는 두 가지 범위로 나누어 관리할 수 있도록 하는 기능을 추가하고 있습니다.이를 통해 자원을 더 세밀하게 제어하고, 테스트 실행 간의 자원의 재사용성을 높이는 것이 목표입니다.해당 기능은 잘 모르고 사용한다면 기존의 ExtensionContext와 별 다르게 사용할 수 없다고 생각합니다.하지만 잘 알고 사용한다면 자원 공유를 매우 효율적으로 사용할 수 있습니다.각종 tech blog들에서도 분명 해당 기능이 merge가 된 후 배포가 되면 자세히 다룰 것으로 예상합니다.하지만, 문서와 코드를 보고 글을 작성하는 분들보다는 직접 만든 사람이 더 잘 알 것이라고 생각합니다. ㅎㅎ해당 글도 DEVOCEAN와 같이 접근성이 좋은 곳에 외부 기고를 하겠습니다.
2025.05.07
junit

좋아요

별로에요

NEW
RAG 도입기 챗봇을 만들다, 조용히 그리고 낭만적으로
RAG 도입기 챗봇을 만들다, 조용히 그리고 낭만적으로 안녕하세요.스푼랩스 Business Platform Team의 임용근(Whale )입니다.요즘 캠핑하기 너무 좋은 날씨입니다.가끔 혼자 캠핑가서 쉬다 오는데요, 이날도 교외로 나가 한적한 캠핑장에서 맥주 한캔과 함께 노트북 두드리며 이 글을 쓰고 있습니다.조금 낭만적이기도 하고요. 버즈의 민경훈이 운영하는 집밖으로 캠핑장 2박3일 푹 쉬다 왔습니다. ️지난 포스트 이후 어느덧 반년이 흘렀네요.그동안 정말 바쁘게, 정신없이 보낸 것 같습니다.AI 관련 세미나 참석 (MS 세미나)AWS AI 세미나 참석사내 세미나 발표 진행그리고 오늘 소개드릴, RAG 기반 챗봇 개발이전 글에서는 다음과 같은 고민을 남겼었죠.RAG 아키텍처를 어떻게 구성하지?검색 대상은 어떤 데이터를 써야 할까?품질은 어떻게 끌어올릴까?고급 구성은 언제 시도해볼까?Slack 같은 외부 시스템과 연동해볼 수 있을까?질문 하나하나에 부딪히고, 하나씩 답을 찾으면서 만든 게 이번 포스트의 주제이자 결과물입니다.이제는 실제 서비스로 동작하는 RAG 기반 챗봇이 만들어졌습니다. 물론 아직은 조금 서툰 아기봇 이지만요. 이번 포스트에서는 FAQ 기반의 ChatBot을 어떻게 Spring AI + AWS로 구현했는가 에 대한 과정을 6단계로 나눠서 정리합니다.구조 자체는 특이하거나 멋진 구조는 아니지만, 실무에서 바로 써먹을 수 있는 구성으로 굉장히 심플하고 실용적이라고 생각합니다.LangChain, LangGraph가 대세인 요즘이지만, 저희가 사용한 기술 스택은 다음과 같습니다Kotlin / SpringBootSpring AIAWS OpenSearchAWS Bedrock (Claude Sonnet 3.5 v2)RAG라는 기술을 접하면서, (무리하게 ) 세가지를 준비했으나!!세가지 모두 이 포스트에서 다루기에는 양이 너무 방대하여, 나누어 진행하도록 하겠습니다.(오늘주제) ChatBot FAQ (자주하는 질문) 질의 요약WIKI(Confluence)Text To SQL사실 순서로 보면 WIKI 부터 하였으나, 사내 서비스에 적용할 정도로 품질을 올리는게 쉽지 않더라구요.혼자 해결할 수 있는 부분은 어느정도 해두었으나, 전사적으로 규칙을 정할 필요가 있어, 서두르지 않고 천천히 진행하고 있습니다.또한, 매출 통계 / 추이 / 분석으로 Text To SQL(TTS)도 함께 진행예정입니다.지난 반년동안 진행해오면서 TTS에 대한 정보도 접하고 있는데요. 방향을 살짝 틀어야 할것같아, 제 TODO LIST에 고이 모셔두었습니다.ChatBot챗봇이라는 단어, 요즘은 너무 흔하죠.병원 예약부터 쇼핑몰까지 어디에나 있는 기능이 되었습니다.솔직히 1년 전만해도 저도 안일하게 생각했던 것 같습니다.카테고리별로 정해진 답변만 하면 되는 거 아냐? 생각보다 단순하겠는데?하지만 직접 만들고 보니 생각이 완전히 달라졌습니다.모든 챗봇이 그렇지는 않겠지만, LLM과 결합한 챗봇은 단순한 정답형 QA(Question/Answer) 그 이상이더라고요.검색된 문서 조각을 문맥에 맞게 합치고,관련도를 평가해서 필터링하고,정밀하게 설계한 Prompt를 기반으로LLM이 최종 응답을 생성하는 일련의 과정.이걸 직접 다뤄보지 않으면 결코 알 수 없었던 구조와 복잡성이 있었습니다.RAG는 검색 기반 QA나 문서 요약 같은 기능을 만들 때 거의 필수에 가깝습니다.그리고 챗봇은 그 흐름을 가장 자연스럽게 구현하고 실험해볼 수 있는 좋은 주제였습니다.크게 새로울 건 없지만, 실전 연습용으로는 완벽한 예제로서, 검색부터 응답 생성까지, RAG의 전 단계를 모두 거치는 구조였기에 정말 많은 시행착오가 있었고, 그 과정을 이 글에 담아보려고 합니다.RAG 아키텍처, 어떻게 설계했을까?이번 글에서는 스푼랩스에서 진행한 챗봇 프로젝트, 일명 스푼봇의 전체적인 네트워크 구성을 소개하려고 합니다.구조 자체는 실제보다 조금 단순화했지만, 전체 흐름을 이해하는데엔 무리가 없도록 재구성했습니다.CHATBOT 기본 구성아마 많은 분들이 예상하셨겠지만, 이러한 아키텍처는 어디서나 비슷비슷한 모양새를 하고 있죠.이제 각 구성 요소들이 어떤 역할을 하고 있는지 살펴보면서, 중간중간 디테일도 함께 이야기 해보겠습니다. 주요 구성 요소User바로 여러분입니다. 질문을 입력하는 최종 사용자죠.DB고객지원팀에서 관리하는 FAQ 데이터들이 저장되어 있는 곳입니다.Batch Batch 라는 이름의 별도 서버가 있습니다. 이 서버는 DB에서 FAQ 데이터를 가져와서, 정제한 다음 OpenSearch에 적재하는 일을 맡고 있습니다.한마디로, 데이터 준비 담당자라고 보면 됩니다.ChatBot Server실제로 RAG가 수행되는 핵심 서버입니다. 사용자의 질문을 받아 OpenSearch와 LLM을 오가며 응답을 생성하죠.OpenSearch이전 블로그에서도 소개했었죠. 벡터 기반 Text Embedding과 키워드 기반 검색을 함께 수행하는 Hybrid Search 엔진입니다.저희는 임베딩 모델을 Cohere로 바꿔서 사용하고 있습니다.S3동의어 사전과 사용자 정의 사전이 저장되어 있는 저장소입니다.이 데이터는 OpenSearch 패키지를 통해 로딩되도록 설정되어있습니다.AWS BedrockLLM(대규모 언어 모델) API를 제공해주는 AWS 서비스입니다.저희는 Anthropic Claude Sonnet 3.5 v2 모델을 사용 중입니다.이 구조에서 특히 중요한 건 Batch 서버와 ChatBot 서버입니다.이 두 영역에 시간을 가장 많이 들였고, 아마 이 글을 보시는 분들도 이 부분이 제일 궁금하실 거라 생각해요. 그래서 다음 글에서는 이 두 서버가 어떤 형태로 데이터를 처리하고, RAG 흐름 안에서 어떤 역할을 하는지 좀 더 깊게 다뤄보려고 합니다.Batch 부터 뜯어봅시다!RAG 아키텍처 구성 중, 가장 처음이 되는 Batch 파트부터 살펴보려 합니다.데이터를 로드하고 쿵짝쿵짝( ) 처리해서 어딘가로 보내는 구조 익숙하시죠? 우리가 잘 아는 ETL(Extract, Transform, Load)의 기본 형태입니다. 스푼봇에서
spring
5/7/2025

RAG 도입기 챗봇을 만들다, 조용히 그리고 낭만적으로
NEW
RAG 도입기 챗봇을 만들다, 조용히 그리고 낭만적으로 안녕하세요.스푼랩스 Business Platform Team의 임용근(Whale )입니다.요즘 캠핑하기 너무 좋은 날씨입니다.가끔 혼자 캠핑가서 쉬다 오는데요, 이날도 교외로 나가 한적한 캠핑장에서 맥주 한캔과 함께 노트북 두드리며 이 글을 쓰고 있습니다.조금 낭만적이기도 하고요. 버즈의 민경훈이 운영하는 집밖으로 캠핑장 2박3일 푹 쉬다 왔습니다. ️지난 포스트 이후 어느덧 반년이 흘렀네요.그동안 정말 바쁘게, 정신없이 보낸 것 같습니다.AI 관련 세미나 참석 (MS 세미나)AWS AI 세미나 참석사내 세미나 발표 진행그리고 오늘 소개드릴, RAG 기반 챗봇 개발이전 글에서는 다음과 같은 고민을 남겼었죠.RAG 아키텍처를 어떻게 구성하지?검색 대상은 어떤 데이터를 써야 할까?품질은 어떻게 끌어올릴까?고급 구성은 언제 시도해볼까?Slack 같은 외부 시스템과 연동해볼 수 있을까?질문 하나하나에 부딪히고, 하나씩 답을 찾으면서 만든 게 이번 포스트의 주제이자 결과물입니다.이제는 실제 서비스로 동작하는 RAG 기반 챗봇이 만들어졌습니다. 물론 아직은 조금 서툰 아기봇 이지만요. 이번 포스트에서는 FAQ 기반의 ChatBot을 어떻게 Spring AI + AWS로 구현했는가 에 대한 과정을 6단계로 나눠서 정리합니다.구조 자체는 특이하거나 멋진 구조는 아니지만, 실무에서 바로 써먹을 수 있는 구성으로 굉장히 심플하고 실용적이라고 생각합니다.LangChain, LangGraph가 대세인 요즘이지만, 저희가 사용한 기술 스택은 다음과 같습니다Kotlin / SpringBootSpring AIAWS OpenSearchAWS Bedrock (Claude Sonnet 3.5 v2)RAG라는 기술을 접하면서, (무리하게 ) 세가지를 준비했으나!!세가지 모두 이 포스트에서 다루기에는 양이 너무 방대하여, 나누어 진행하도록 하겠습니다.(오늘주제) ChatBot FAQ (자주하는 질문) 질의 요약WIKI(Confluence)Text To SQL사실 순서로 보면 WIKI 부터 하였으나, 사내 서비스에 적용할 정도로 품질을 올리는게 쉽지 않더라구요.혼자 해결할 수 있는 부분은 어느정도 해두었으나, 전사적으로 규칙을 정할 필요가 있어, 서두르지 않고 천천히 진행하고 있습니다.또한, 매출 통계 / 추이 / 분석으로 Text To SQL(TTS)도 함께 진행예정입니다.지난 반년동안 진행해오면서 TTS에 대한 정보도 접하고 있는데요. 방향을 살짝 틀어야 할것같아, 제 TODO LIST에 고이 모셔두었습니다.ChatBot챗봇이라는 단어, 요즘은 너무 흔하죠.병원 예약부터 쇼핑몰까지 어디에나 있는 기능이 되었습니다.솔직히 1년 전만해도 저도 안일하게 생각했던 것 같습니다.카테고리별로 정해진 답변만 하면 되는 거 아냐? 생각보다 단순하겠는데?하지만 직접 만들고 보니 생각이 완전히 달라졌습니다.모든 챗봇이 그렇지는 않겠지만, LLM과 결합한 챗봇은 단순한 정답형 QA(Question/Answer) 그 이상이더라고요.검색된 문서 조각을 문맥에 맞게 합치고,관련도를 평가해서 필터링하고,정밀하게 설계한 Prompt를 기반으로LLM이 최종 응답을 생성하는 일련의 과정.이걸 직접 다뤄보지 않으면 결코 알 수 없었던 구조와 복잡성이 있었습니다.RAG는 검색 기반 QA나 문서 요약 같은 기능을 만들 때 거의 필수에 가깝습니다.그리고 챗봇은 그 흐름을 가장 자연스럽게 구현하고 실험해볼 수 있는 좋은 주제였습니다.크게 새로울 건 없지만, 실전 연습용으로는 완벽한 예제로서, 검색부터 응답 생성까지, RAG의 전 단계를 모두 거치는 구조였기에 정말 많은 시행착오가 있었고, 그 과정을 이 글에 담아보려고 합니다.RAG 아키텍처, 어떻게 설계했을까?이번 글에서는 스푼랩스에서 진행한 챗봇 프로젝트, 일명 스푼봇의 전체적인 네트워크 구성을 소개하려고 합니다.구조 자체는 실제보다 조금 단순화했지만, 전체 흐름을 이해하는데엔 무리가 없도록 재구성했습니다.CHATBOT 기본 구성아마 많은 분들이 예상하셨겠지만, 이러한 아키텍처는 어디서나 비슷비슷한 모양새를 하고 있죠.이제 각 구성 요소들이 어떤 역할을 하고 있는지 살펴보면서, 중간중간 디테일도 함께 이야기 해보겠습니다. 주요 구성 요소User바로 여러분입니다. 질문을 입력하는 최종 사용자죠.DB고객지원팀에서 관리하는 FAQ 데이터들이 저장되어 있는 곳입니다.Batch Batch 라는 이름의 별도 서버가 있습니다. 이 서버는 DB에서 FAQ 데이터를 가져와서, 정제한 다음 OpenSearch에 적재하는 일을 맡고 있습니다.한마디로, 데이터 준비 담당자라고 보면 됩니다.ChatBot Server실제로 RAG가 수행되는 핵심 서버입니다. 사용자의 질문을 받아 OpenSearch와 LLM을 오가며 응답을 생성하죠.OpenSearch이전 블로그에서도 소개했었죠. 벡터 기반 Text Embedding과 키워드 기반 검색을 함께 수행하는 Hybrid Search 엔진입니다.저희는 임베딩 모델을 Cohere로 바꿔서 사용하고 있습니다.S3동의어 사전과 사용자 정의 사전이 저장되어 있는 저장소입니다.이 데이터는 OpenSearch 패키지를 통해 로딩되도록 설정되어있습니다.AWS BedrockLLM(대규모 언어 모델) API를 제공해주는 AWS 서비스입니다.저희는 Anthropic Claude Sonnet 3.5 v2 모델을 사용 중입니다.이 구조에서 특히 중요한 건 Batch 서버와 ChatBot 서버입니다.이 두 영역에 시간을 가장 많이 들였고, 아마 이 글을 보시는 분들도 이 부분이 제일 궁금하실 거라 생각해요. 그래서 다음 글에서는 이 두 서버가 어떤 형태로 데이터를 처리하고, RAG 흐름 안에서 어떤 역할을 하는지 좀 더 깊게 다뤄보려고 합니다.Batch 부터 뜯어봅시다!RAG 아키텍처 구성 중, 가장 처음이 되는 Batch 파트부터 살펴보려 합니다.데이터를 로드하고 쿵짝쿵짝( ) 처리해서 어딘가로 보내는 구조 익숙하시죠? 우리가 잘 아는 ETL(Extract, Transform, Load)의 기본 형태입니다. 스푼봇에서
2025.05.07
spring

좋아요

별로에요

NEW
소프트웨어 접근성과 한컴오피스
접근성은 모든 사람이 제품, 서비스, 환경을 동등하게 이용할 수 있도록 하는 개념입니다. 이는 경사로, 엘리베이터, 점자 표지판 등 물리적 접근성에서 시작해, 디지털 환경(웹 접근성, 소프트웨어 접근성, 전자 문서 접근성 등)에서의 제품 설계, 서비스 제공, 정보 전달 방식까지 다양한 영역으로 확장되었습니다.접근성의 핵심은 다양한 능력을 갖춘 사람들이 장벽 없이 독립적으로 참여할 수 있게 하는 것입니다.접근성의 대상은 장애인뿐만 아니라 고령자, 비장애인 등 모든 사용자를 포함합니다. 음성 안내나 시각 보조 도구가 필요한 전맹 혹은 저시력 시각 장애인, 자막이나 시각적 알림이 필요한 청각 장애인, 손쉽게 조작할 수 있어야 하는 뇌 병변 및 지체 장애인, 일시적인 장애를 겪고 있는 경우나 일반 사용자까지도 고려 대상입니다.웹 접근성(정보통신접근성)은 앞서 설명한 접근성의 개념을 웹 콘텐츠에 적용한 것입니다. 「지능정보화기본법」에 따라 장애인이나 고령자들이 웹 사이트에서 제공하는 정보를 비장애인과 동등하게 접근하고 이용할 수 있도록 보장하는 것을 의미하며, 웹 접근성 준수는 법적 의무 사항입니다. 국내의 웹 접근성 관련 법규와 지침들은 어떤 것들이 있는지 살펴보겠습니다.한국에서는 2008년부터 정보통신 관련 조항이 포함된 「장애인차별금지법(장차법)」이 시행되어 웹 접근성 준수가 의무화되었고, 제21조, 제23조 등에서 해당 내용을 확인할 수 있습니다. 이는 공공기관과 민간 기업의 웹 사이트, 모바일 앱, 키오스크 등에 적용됩니다.이 외에도 정보통신 및 의사소통을 위해 제공되어야 하는 항목을 담고 있는 「장애인차별금지법 시행령 제14조」, 장애인과 고령자의 정보 접근 보장을 다루는 「지능정보화기본법 제46조」와 「지능 정보화 기본법 시행령 제34조」등의 조항과 관련되어 있습니다.국제적으로는 W3C의 웹 콘텐츠 접근성 지침(WCAG)이 가장 널리 사용됩니다. WCAG는 인식의 용이성, 운용의 용이성, 이해의 용이성, 견고성의 4가지 원칙을 제시합니다. 현재 WCAG 2.0(2008), 2.1(2018), 2.2(2023) 버전이 있습니다.국내에서는 WCAG를 기반으로 한국형 웹 콘텐츠 접근성 지침(KWCAG)을 개발했으며, KWCAG 2.1은 13개 지침, 24개 검사 항목으로 구성되고 국가 표준(KS X 3253)으로 제정되어 있습니다.접근성은 웹 환경에서만 준수되어야 하는 항목은 아닙니다. 이에 따라 운영 체제(OS) 별로 소프트웨어와 하드웨어 사이에서 접근성 기능이 동작할 수 있도록 자체적인 프레임워크와 API를 제공하고 있습니다. 각 OS는 이러한 프레임워크 또는 API를 통해 보조 기술과 응용 프로그램 간의 통신을 지원합니다. 어떤 흐름으로 접근성 기능이 동작하는지 알아보겠습니다.Windows는 Microsoft UI Automation(UIA)을 주요 접근성 프레임워크로 사용합니다. 이 프레임워크는 UI 요소의 속성(이름, 역할, 상태), 패턴(호출, 확장, 선택 등), 이벤트(포커스 변경 등)를 정의합니다. 이전에는 MSAA(Microsoft Active Accessibility)가 사용되었으나 현재는 UIA로 대체되고 있으며, UIA는 Windows Vista 이후 모든 버전에서 제공됩니다.다음은 UIA 프레임워크의 접근성 기능 흐름도입니다.UIA 프레임워크는 Narrator(스크린리더)가 UI 요소의 속성 정보를 요청하면 UI Automation이 중개자 역할을 하여 UI 요소에 속성을 질의하고 응답을 받아 Narrator에 전달하며, UI 요소의 상태 변경 시에는 이벤트가 발생하여 UI Automation을 통해 Narrator로 전달되는 방식으로 작동합니다.Apple 기기는 NSAccessibility와 UIAccessibility 프레임워크를 사용합니다. VoiceOver, 확대 기능, 색상 필터 등의 내장 접근성 기능은 이 API를 통해 앱과 통합됩니다. 접근성 속성(레이블, 값, 힌트) 과 액션(활성화, 증가, 감소)을 정의하여 보조 기술과의 상호작용을 지원합니다.다음은 NSAccessibility 프레임워크의 접근성 기능 흐름도입니다.NSAccessibility 프레임워크는 VoiceOver가 UI 요소에 속성을 요청하면 NSAccessibility가 중개자 역할을 하여 UI 요소로부터 응답을 받고 다시 VoiceOver에 전달하며, 상태 변경 시에는 UI 요소가 NSAccessibilityPostNotification()을 통해 알림을 발생시켜 VoiceOver가 이를 사용자에게 전달하는 방식으로 작동합니다.Android는 Android Accessibility Framework를 제공합니다. 이는 TalkBack, Voice Access, Switch Access 등의 보조 기술과 앱 간 통신을 지원합니다. AccessibilityNodeInfo와 AccessibilityEvent 클래스를 통해 UI 요소의 속성과 상태 변화를 보조 기술에 전달합니다.다음은 Android Accessibility Framework 프레임워크의 접근성 기능 흐름도입니다.Android Accessibility Framework는 TalkBack이 앱 UI 요소의 정보를 요청하면 Accessibility 서비스가 중개자 역할을 하여 UI 요소로부터 접근성 정보를 수집하여 TalkBack에 전달하고, UI 요소의 상태 변경 시에는 이벤트가 발생하여 Accessibility 서비스를 통해 TalkBack으로 전달되는 방식으로 작동합니다.웹에서는 WAI-ARIA가 중요한 역할을 합니다. ARIA는 HTML을 확장하여 웹 콘텐츠의 접근성을 높이는 기술입니다. 역할(role), 상태(state), 속성(property)을 정의하여 동적 콘텐츠, 복잡한 UI의 접근성을 개선합니다. HTML5의 시맨틱 태그(header, nav, main 등), 접근성 속성도 웹 접근성을 지원합니다.다음은 WAI-ARIA의 접근성 기능 흐름도입니다.웹 개발자가 HTML 요소에 ARIA 역할, 속성, 상태를 적용하면 브라우저가 이를 접근성 트리로 변환하여 스크린리더에 전달하고, 상태 변경 시 이벤트가
5/7/2025

소프트웨어 접근성과 한컴오피스
NEW
접근성은 모든 사람이 제품, 서비스, 환경을 동등하게 이용할 수 있도록 하는 개념입니다. 이는 경사로, 엘리베이터, 점자 표지판 등 물리적 접근성에서 시작해, 디지털 환경(웹 접근성, 소프트웨어 접근성, 전자 문서 접근성 등)에서의 제품 설계, 서비스 제공, 정보 전달 방식까지 다양한 영역으로 확장되었습니다.접근성의 핵심은 다양한 능력을 갖춘 사람들이 장벽 없이 독립적으로 참여할 수 있게 하는 것입니다.접근성의 대상은 장애인뿐만 아니라 고령자, 비장애인 등 모든 사용자를 포함합니다. 음성 안내나 시각 보조 도구가 필요한 전맹 혹은 저시력 시각 장애인, 자막이나 시각적 알림이 필요한 청각 장애인, 손쉽게 조작할 수 있어야 하는 뇌 병변 및 지체 장애인, 일시적인 장애를 겪고 있는 경우나 일반 사용자까지도 고려 대상입니다.웹 접근성(정보통신접근성)은 앞서 설명한 접근성의 개념을 웹 콘텐츠에 적용한 것입니다. 「지능정보화기본법」에 따라 장애인이나 고령자들이 웹 사이트에서 제공하는 정보를 비장애인과 동등하게 접근하고 이용할 수 있도록 보장하는 것을 의미하며, 웹 접근성 준수는 법적 의무 사항입니다. 국내의 웹 접근성 관련 법규와 지침들은 어떤 것들이 있는지 살펴보겠습니다.한국에서는 2008년부터 정보통신 관련 조항이 포함된 「장애인차별금지법(장차법)」이 시행되어 웹 접근성 준수가 의무화되었고, 제21조, 제23조 등에서 해당 내용을 확인할 수 있습니다. 이는 공공기관과 민간 기업의 웹 사이트, 모바일 앱, 키오스크 등에 적용됩니다.이 외에도 정보통신 및 의사소통을 위해 제공되어야 하는 항목을 담고 있는 「장애인차별금지법 시행령 제14조」, 장애인과 고령자의 정보 접근 보장을 다루는 「지능정보화기본법 제46조」와 「지능 정보화 기본법 시행령 제34조」등의 조항과 관련되어 있습니다.국제적으로는 W3C의 웹 콘텐츠 접근성 지침(WCAG)이 가장 널리 사용됩니다. WCAG는 인식의 용이성, 운용의 용이성, 이해의 용이성, 견고성의 4가지 원칙을 제시합니다. 현재 WCAG 2.0(2008), 2.1(2018), 2.2(2023) 버전이 있습니다.국내에서는 WCAG를 기반으로 한국형 웹 콘텐츠 접근성 지침(KWCAG)을 개발했으며, KWCAG 2.1은 13개 지침, 24개 검사 항목으로 구성되고 국가 표준(KS X 3253)으로 제정되어 있습니다.접근성은 웹 환경에서만 준수되어야 하는 항목은 아닙니다. 이에 따라 운영 체제(OS) 별로 소프트웨어와 하드웨어 사이에서 접근성 기능이 동작할 수 있도록 자체적인 프레임워크와 API를 제공하고 있습니다. 각 OS는 이러한 프레임워크 또는 API를 통해 보조 기술과 응용 프로그램 간의 통신을 지원합니다. 어떤 흐름으로 접근성 기능이 동작하는지 알아보겠습니다.Windows는 Microsoft UI Automation(UIA)을 주요 접근성 프레임워크로 사용합니다. 이 프레임워크는 UI 요소의 속성(이름, 역할, 상태), 패턴(호출, 확장, 선택 등), 이벤트(포커스 변경 등)를 정의합니다. 이전에는 MSAA(Microsoft Active Accessibility)가 사용되었으나 현재는 UIA로 대체되고 있으며, UIA는 Windows Vista 이후 모든 버전에서 제공됩니다.다음은 UIA 프레임워크의 접근성 기능 흐름도입니다.UIA 프레임워크는 Narrator(스크린리더)가 UI 요소의 속성 정보를 요청하면 UI Automation이 중개자 역할을 하여 UI 요소에 속성을 질의하고 응답을 받아 Narrator에 전달하며, UI 요소의 상태 변경 시에는 이벤트가 발생하여 UI Automation을 통해 Narrator로 전달되는 방식으로 작동합니다.Apple 기기는 NSAccessibility와 UIAccessibility 프레임워크를 사용합니다. VoiceOver, 확대 기능, 색상 필터 등의 내장 접근성 기능은 이 API를 통해 앱과 통합됩니다. 접근성 속성(레이블, 값, 힌트) 과 액션(활성화, 증가, 감소)을 정의하여 보조 기술과의 상호작용을 지원합니다.다음은 NSAccessibility 프레임워크의 접근성 기능 흐름도입니다.NSAccessibility 프레임워크는 VoiceOver가 UI 요소에 속성을 요청하면 NSAccessibility가 중개자 역할을 하여 UI 요소로부터 응답을 받고 다시 VoiceOver에 전달하며, 상태 변경 시에는 UI 요소가 NSAccessibilityPostNotification()을 통해 알림을 발생시켜 VoiceOver가 이를 사용자에게 전달하는 방식으로 작동합니다.Android는 Android Accessibility Framework를 제공합니다. 이는 TalkBack, Voice Access, Switch Access 등의 보조 기술과 앱 간 통신을 지원합니다. AccessibilityNodeInfo와 AccessibilityEvent 클래스를 통해 UI 요소의 속성과 상태 변화를 보조 기술에 전달합니다.다음은 Android Accessibility Framework 프레임워크의 접근성 기능 흐름도입니다.Android Accessibility Framework는 TalkBack이 앱 UI 요소의 정보를 요청하면 Accessibility 서비스가 중개자 역할을 하여 UI 요소로부터 접근성 정보를 수집하여 TalkBack에 전달하고, UI 요소의 상태 변경 시에는 이벤트가 발생하여 Accessibility 서비스를 통해 TalkBack으로 전달되는 방식으로 작동합니다.웹에서는 WAI-ARIA가 중요한 역할을 합니다. ARIA는 HTML을 확장하여 웹 콘텐츠의 접근성을 높이는 기술입니다. 역할(role), 상태(state), 속성(property)을 정의하여 동적 콘텐츠, 복잡한 UI의 접근성을 개선합니다. HTML5의 시맨틱 태그(header, nav, main 등), 접근성 속성도 웹 접근성을 지원합니다.다음은 WAI-ARIA의 접근성 기능 흐름도입니다.웹 개발자가 HTML 요소에 ARIA 역할, 속성, 상태를 적용하면 브라우저가 이를 접근성 트리로 변환하여 스크린리더에 전달하고, 상태 변경 시 이벤트가
2025.05.07

좋아요

별로에요

무신사 Web 테스트 자동화 2.0: 더 빠르고 효율적인 테스트 환경 만들기
안녕하세요, 무신사 QA팀 플랫폼 파트에서 Web 테스트 자동화를 담당하고 있는 신호철입니다.무신사 서비스가 2.0으로 개편됨에 따라 테스트 자동화도 함께 변화했습니다. 이번 글에서는 Web 테스트 자동화 2.0의 주요 변경 사항을 중심으로 소개하고자 합니다.왜 변경해야 했나요?무신사의 Web 테스트 자동화는 그동안 원활하게 운영되어 왔습니다. 그러나 무신사 2.0 개편으로 UI가 크게 달라지면서, 기존 자동화 방식을 그대로 재활용하기가 어렵게 되었습니다.이로 인해 아래와 같은 문제가 발생하여, 새로운 방식으로의 전환이 필요하다고 판단했습니다.무신사 2.0 개편으로 기존 스크립트 재활용이 어려움무신사 2.0에서는 UI가 대폭 변경되었습니다. 이와 함께 테스트 케이스도 전면적으로 수정해야 했는데,기존 테스트 케이스를 하나하나 분석하고 보완하기보다는 새로운 구조로 처음부터 다시 작성하는 것이 더 효율적이라 판단했습니다.또한, 저희 팀은 Selenium을 활용하여 Web 요소를 제어할 때 XPath를 사용하고 있습니다.UI가 변경될 때마다 XPath도 변경되므로, 기존 테스트 케이스를 수정하는 것보다 새로운 XPath를 찾는 것이 더 효과적이라고 판단했습니다.수동 테스트 케이스(Manual TC)와 자동화 테스트 케이스(Auto TC) 의 차이로 인한 유지보수 비용 증가수동 테스트 케이스와 자동화 테스트 케이스는 테스트 수행 방식이 다릅니다. 자동화 테스트에서는 테스트 간 전환 과정에서 이루어지는 모든 동작을 일일이 정의해야 하기 때문입니다. ID 입력 후 로그인 버튼 선택 시 오류 메시지를 확인 하는 테스트 PW 입력 후 로그인 버튼 선택 시 오류 메시지를 확인 하는 테스트첫 번째 테스트가 끝나면, 두 번째 테스트를 수행하기 전에 이미 입력되어 있던 ID를 삭제해야 하는데, 이는 수동 테스트 케이스에는 명시되어 있지 않지만 자동화 테스트에서는 반드시 고려해야 하는 부분입니다.이처럼 자동화 테스트는 특정 시나리오를 중심으로 동작 하므로, 일부 기능이 변경될 경우 수동 테스트 케이스와 자동화 테스트 케이스를 모두 수정해야 하는 문제가 발생합니다.결국, 이러한 반복 수정이 누적되어 자동화 테스트의 유지보수가 더욱 복잡해지는 원인이 되었습니다.어떤것이 변경됐나요?CI/CD 파이프라인 단순해졌어요as-is기존(1.0) 자동화 환경에서는 Spinnaker를 사용해 스케줄러와 Webhook Trigger를 구성하고, 이를 통해 Jenkins로부터 전달받은 배포 요청을 처리한 뒤 Kubernetes에 애플리케이션을 배포했습니다.to-be2.0으로 전환하면서는 Github Actions만으로 CI/CD 파이프라인을 구성하여 Jenkins나 Spinaker 의 별도 서버 유지보수 할 필요 없어졌습니다. 또한 Github Actions에서 모든 테스트 실행 및 배포가 가능해 졌으므로, 단일 환경에서 모든 정보를 확인 할 수 있습니다.실행 트리거 역시 유연해져,PR(풀 리퀘스트) 생성 시특정 브랜치에 병합될 때일정 시간 간격으로(스케줄 실행)와 같이 다양한 조건으로 자동 실행을 설정할 수 있습니다.단순한 테스트 데이터 수정은 DB에서 해결 가능해요2023년 기준으로, 한 달 동안의 테스트 스크립트 유지보수 작업 중 약 30%가 XPath 수정과 같은 단순 작업이었습니다.기존에는 테스트 데이터가 코드에 포함되어 있어, 간단한 데이터 변경에도 브랜치를 생성하고 PR을 올린 후 병합 및 배포까지 진행해야 했습니다. 이 과정에는 최소 15분 이상이 소요되었습니다.xpath 관리 web pagexpath 관리 xpath 상세 페이지2.0에서는 테스트 데이터를 전부 DB화하여 코드 수정 없이 Web 페이지에서 직접 수정할 수 있게 되었습니다.이를 통해 중복되는 XPath를 최소화하고, 유지보수 비용을 절감할 수 있었습니다.수동 테스트 케이스와 자동화 테스트 케이스가 하나로 통일됐어요수동 테스트 케이스 구조와 자동화 테스트 케이스 구조자동화 테스트(Auto TC)의 수행 단위를 수동 테스트(Manual TC)와 동일하게 맞추기 위해, step 기반 구조를 새롭게 도입하고, pytest의 fixture 기능을 적극 활용하는 방식으로 개선했습니다.step 단위는 개별적인 기능으로 관리합니다. 예를 들어, 로그인 테스트의 경우 다음과 같은 단위로 나누어집니다.ID 입력 stepPW 입력 step로그인 버튼 클릭 step이렇게 분리된 step은 재사용이 가능하며, 하나만 수정해도 전체 테스트 케이스에 일괄 반영할 수 있어 유지보수가 훨씬 쉬워집니다.또한, pytest의 fixture를 활용하여 step을 재사용할 수 있어 테스트 유지보수가 더욱 쉬워졌습니다.fixture는 Python의 decorator 문법 중 하나로, pytest에서는 테스트의 사전 조건을 자동으로 설정하거나 초기화하는 데 활용됩니다.예를 들어, 다음과 같은 테스트 케이스가 있다고 가정해 보겠습니다.기대 결과: 로그인 버튼을 선택하면 마이페이지로 이동한다. 보통 이 테스트 케이스에서는 사전 조건으로 ID와 PW 입력이 필요합니다. 이때, fixture를 사용하면 자동화 테스트 케이스가 실행되기 전에 ID와 PW를 입력하도록 설정할 수 있으며, 테스트 케이스에서 로그인 버튼 선택 step만 호출하여 수행 절차를 간결하게 만들 수 있습니다.이렇게 자동화 테스트 케이스를 사전 조건과 수행 절차로 나누어 작성하면, 아래와 같은 장점 있습니다.실제 결함인지, 환경적 요인으로 인해 실패한 것인지 쉽게 구분할 수 있습니다.로그인이 필요한 테스트 시나리오를 수행하기 전에 미리 로그인 상태를 설정할 수 있습니다.테스트 종료 후 로그아웃을 자동으로 실행하여 계정 상태를 초기화하는 것도 가능합니다.testrail의 실제 테스트 케이스코드로 구현된 자동화 테스트 케이스실제 테스트에서는 로그인 및 주문서 이동과 같은 사전 조건을 auto_login, move_order 같은 fixture로 분리하여 처리하고 있습니다.각 테스트 케이스의 기대 결과는 자동화 테스트 케이스 내부에 정의되어 있으며, 이를 통해 수동 테스트 케이스와 동일한 흐름으로 자동화 테스트를 수행할
5/6/2025

무신사 Web 테스트 자동화 2.0: 더 빠르고 효율적인 테스트 환경 만들기
안녕하세요, 무신사 QA팀 플랫폼 파트에서 Web 테스트 자동화를 담당하고 있는 신호철입니다.무신사 서비스가 2.0으로 개편됨에 따라 테스트 자동화도 함께 변화했습니다. 이번 글에서는 Web 테스트 자동화 2.0의 주요 변경 사항을 중심으로 소개하고자 합니다.왜 변경해야 했나요?무신사의 Web 테스트 자동화는 그동안 원활하게 운영되어 왔습니다. 그러나 무신사 2.0 개편으로 UI가 크게 달라지면서, 기존 자동화 방식을 그대로 재활용하기가 어렵게 되었습니다.이로 인해 아래와 같은 문제가 발생하여, 새로운 방식으로의 전환이 필요하다고 판단했습니다.무신사 2.0 개편으로 기존 스크립트 재활용이 어려움무신사 2.0에서는 UI가 대폭 변경되었습니다. 이와 함께 테스트 케이스도 전면적으로 수정해야 했는데,기존 테스트 케이스를 하나하나 분석하고 보완하기보다는 새로운 구조로 처음부터 다시 작성하는 것이 더 효율적이라 판단했습니다.또한, 저희 팀은 Selenium을 활용하여 Web 요소를 제어할 때 XPath를 사용하고 있습니다.UI가 변경될 때마다 XPath도 변경되므로, 기존 테스트 케이스를 수정하는 것보다 새로운 XPath를 찾는 것이 더 효과적이라고 판단했습니다.수동 테스트 케이스(Manual TC)와 자동화 테스트 케이스(Auto TC) 의 차이로 인한 유지보수 비용 증가수동 테스트 케이스와 자동화 테스트 케이스는 테스트 수행 방식이 다릅니다. 자동화 테스트에서는 테스트 간 전환 과정에서 이루어지는 모든 동작을 일일이 정의해야 하기 때문입니다. ID 입력 후 로그인 버튼 선택 시 오류 메시지를 확인 하는 테스트 PW 입력 후 로그인 버튼 선택 시 오류 메시지를 확인 하는 테스트첫 번째 테스트가 끝나면, 두 번째 테스트를 수행하기 전에 이미 입력되어 있던 ID를 삭제해야 하는데, 이는 수동 테스트 케이스에는 명시되어 있지 않지만 자동화 테스트에서는 반드시 고려해야 하는 부분입니다.이처럼 자동화 테스트는 특정 시나리오를 중심으로 동작 하므로, 일부 기능이 변경될 경우 수동 테스트 케이스와 자동화 테스트 케이스를 모두 수정해야 하는 문제가 발생합니다.결국, 이러한 반복 수정이 누적되어 자동화 테스트의 유지보수가 더욱 복잡해지는 원인이 되었습니다.어떤것이 변경됐나요?CI/CD 파이프라인 단순해졌어요as-is기존(1.0) 자동화 환경에서는 Spinnaker를 사용해 스케줄러와 Webhook Trigger를 구성하고, 이를 통해 Jenkins로부터 전달받은 배포 요청을 처리한 뒤 Kubernetes에 애플리케이션을 배포했습니다.to-be2.0으로 전환하면서는 Github Actions만으로 CI/CD 파이프라인을 구성하여 Jenkins나 Spinaker 의 별도 서버 유지보수 할 필요 없어졌습니다. 또한 Github Actions에서 모든 테스트 실행 및 배포가 가능해 졌으므로, 단일 환경에서 모든 정보를 확인 할 수 있습니다.실행 트리거 역시 유연해져,PR(풀 리퀘스트) 생성 시특정 브랜치에 병합될 때일정 시간 간격으로(스케줄 실행)와 같이 다양한 조건으로 자동 실행을 설정할 수 있습니다.단순한 테스트 데이터 수정은 DB에서 해결 가능해요2023년 기준으로, 한 달 동안의 테스트 스크립트 유지보수 작업 중 약 30%가 XPath 수정과 같은 단순 작업이었습니다.기존에는 테스트 데이터가 코드에 포함되어 있어, 간단한 데이터 변경에도 브랜치를 생성하고 PR을 올린 후 병합 및 배포까지 진행해야 했습니다. 이 과정에는 최소 15분 이상이 소요되었습니다.xpath 관리 web pagexpath 관리 xpath 상세 페이지2.0에서는 테스트 데이터를 전부 DB화하여 코드 수정 없이 Web 페이지에서 직접 수정할 수 있게 되었습니다.이를 통해 중복되는 XPath를 최소화하고, 유지보수 비용을 절감할 수 있었습니다.수동 테스트 케이스와 자동화 테스트 케이스가 하나로 통일됐어요수동 테스트 케이스 구조와 자동화 테스트 케이스 구조자동화 테스트(Auto TC)의 수행 단위를 수동 테스트(Manual TC)와 동일하게 맞추기 위해, step 기반 구조를 새롭게 도입하고, pytest의 fixture 기능을 적극 활용하는 방식으로 개선했습니다.step 단위는 개별적인 기능으로 관리합니다. 예를 들어, 로그인 테스트의 경우 다음과 같은 단위로 나누어집니다.ID 입력 stepPW 입력 step로그인 버튼 클릭 step이렇게 분리된 step은 재사용이 가능하며, 하나만 수정해도 전체 테스트 케이스에 일괄 반영할 수 있어 유지보수가 훨씬 쉬워집니다.또한, pytest의 fixture를 활용하여 step을 재사용할 수 있어 테스트 유지보수가 더욱 쉬워졌습니다.fixture는 Python의 decorator 문법 중 하나로, pytest에서는 테스트의 사전 조건을 자동으로 설정하거나 초기화하는 데 활용됩니다.예를 들어, 다음과 같은 테스트 케이스가 있다고 가정해 보겠습니다.기대 결과: 로그인 버튼을 선택하면 마이페이지로 이동한다. 보통 이 테스트 케이스에서는 사전 조건으로 ID와 PW 입력이 필요합니다. 이때, fixture를 사용하면 자동화 테스트 케이스가 실행되기 전에 ID와 PW를 입력하도록 설정할 수 있으며, 테스트 케이스에서 로그인 버튼 선택 step만 호출하여 수행 절차를 간결하게 만들 수 있습니다.이렇게 자동화 테스트 케이스를 사전 조건과 수행 절차로 나누어 작성하면, 아래와 같은 장점 있습니다.실제 결함인지, 환경적 요인으로 인해 실패한 것인지 쉽게 구분할 수 있습니다.로그인이 필요한 테스트 시나리오를 수행하기 전에 미리 로그인 상태를 설정할 수 있습니다.테스트 종료 후 로그아웃을 자동으로 실행하여 계정 상태를 초기화하는 것도 가능합니다.testrail의 실제 테스트 케이스코드로 구현된 자동화 테스트 케이스실제 테스트에서는 로그인 및 주문서 이동과 같은 사전 조건을 auto_login, move_order 같은 fixture로 분리하여 처리하고 있습니다.각 테스트 케이스의 기대 결과는 자동화 테스트 케이스 내부에 정의되어 있으며, 이를 통해 수동 테스트 케이스와 동일한 흐름으로 자동화 테스트를 수행할
2025.05.06

좋아요

별로에요

MLC LLM을 이용한 안드로이드 On-device AI 맛보기
AI 기술이 급속도로 발전하면서 이제는 클라우드뿐만 아니라 모바일 기기에서도 인공지능 모델을 직접 구동할 수 있는 시대가 되었습니다.특히, 대형 언어 모델(LLM)을 경량화하여 스마트폰에서 직접 실행할 수 있다면 네트워크 연결 없이도 AI 기능을 활용할 수 있고, 개인정보 보호 측면에서도 큰 장점이 있습니다.이 글은 AI 분야에 깊은 지식이 없더라도, 안드로이드 디바이스에서 LLM을 직접 구동해보며 AI를 경험해보고 싶은 소프트웨어 개발자들을 위해 작성되었습니다.제목에 소개된 MLC LLM은 다양한 플랫폼에서 LLM을 효율적으로 실행할 수 있게 해주는 오픈소스 프로젝트로,이를 활용하면 복잡한 AI 지식 없이도 모바일 환경에서 대화형 AI 애플리케이션을 구현할 수 있습니다.MLC LLM을 사용하기 위해서는 Python 환경이 필요합니다. 그리고 추가로 안드로이드 라이브러리화하는 과정에서 Python뿐만 아니라 여러 가지 도구들이 함께 사용됩니다.이 글에 설명된 설치 가이드는 x86_64 기반의 Ubuntu 22.04 (jammy) 환경에서 테스트되었습니다.Python 3.11 버전과 Rust를 설치합니다. Python 패키지를 독립된 환경에서 사용하기 위해 도 같이 설치합니다.를 사용하여 MLC LLM 작업을 위한 독립된 Python 환경을 생성합니다.다음으로, Android 개발 환경을 설치합니다. Android Studio 자체는 MLC LLM을 빌드하는 데 필요는 없지만, 차후 IDE를 이용한 앱 개발을 진행한다고 가정하고 같이 설치해 줍니다.sdkmanager를 사용하기 위해 환경 변수를 설정합니다.이제 를 사용하여 추가로 필요한 패키지를 설치합니다.환경변수에 cmake와 ndk 정보를 추가합니다.이렇게 해서 기본적인 준비 과정을 완료했습니다.MLC LLM은 친절하게 미리 빌드된 패키지(Prebuilt package)를 제공하고 있어 명령으로 쉽게 설치할 수 있습니다.물론, 필요할 경우 소스를 통한 빌드도 함께 제공합니다. 자세한 내용은 공식 문서를 참고 바랍니다.설치가 정상적으로 완료되면 아래와 같이 명령을 터미널에서 사용할 수 있습니다.에서 제공하는 명령으로 독립된 mlc python 환경을 종료합니다.이제 모든 준비 과정이 끝났습니다. 다음 단계에서 MLC LLM을 Android 라이브러리로 빌드하는 과정을 알아보겠습니다.MLC LLM은 두 가지 안드로이드 샘플 앱을 제공합니다. MLCChat과 MLCEngineExample 각각의 빌드 방법을 알아보겠습니다.먼저 코드를 다운로드 받습니다.샘플 코드는 디렉토리에서 찾을 수 있습니다.앱 빌드를 위한 사전 단계로 라는 명령을 사용하게 되는데, 이 때 추가로 필요로 하는 모듈들이 있어 아래와 같이 명령으로 의존성 모듈들을 같이 준비합니다.또한, 추가로 설정이 필요한 환경변수가 있어 마지막으로 아래와 같이 설정합니다.참고로 지금까지 추가된 환경변수들을 정리하면 아래와 같습니다. 쉘 설정 파일( )에 추가하면 좀 더 편리하게 사용할 수 있습니다.빌드 환경 설정이 모두 완료되었습니다. 이제 예제 애플리케이션을 빌드하여 테스트해 보겠습니다. 전체적인 진행 과정은 아래 그림과 같습니다.두 애플리케이션 모두 기본적인 설정 및 빌드 과정은 유사하지만, MLCEngineExample의 경우 최소화된 기능만 제공하므로 몇 가지 작업을 수동으로 추가해야 합니다.그리고 Hugging Face의 mlc-ai 저장소에서 제공하는 모델을 사용할 경우 큰 수정 없이 진행할 수 있으나, 다른 모델을 사용하려면 별도의 변환 과정이 필요합니다.다음 단계에서 이 과정을 더 자세히 살펴보겠습니다.MLCChat (경로: )은 모델 다운로드 기능이 포함된 채팅 형태의 애플리케이션입니다.사용하고 있는 모델 목록은 파일에 아래와 같이 정의되어 있습니다.명령을 수행하면, 위 파일의 에 정의된 각 모델을 다운로드 후 이를 기반으로 안드로이드 앱 빌드를 위한 라이브러리를 생성합니다.따라서, 앱에서 사용할 모델 정보 변경이 필요할 경우 위 json 파일을 수정하고 다시 명령을 실행해야 합니다.모델 다운로드와 TVM Unity 컴파일 과정이 시작되며, 이 과정은 다소 시간이 걸릴 수 있습니다. 작업 진행중 다음과 같은 로그가 출력됩니다.모델에 대한 작업이 끝나면 아래와 같이 로그가 출력됩니다.이후 와 Android NDK를 이용한 빌드가 진행됩니다.MLC LLM 준비가 모두 끝났습니다. 이제 을 이용해 안드로이드 애플리케이션을 빌드합니다.설치 후 실행하면 아래와 같이 모델 목록 화면이 나타나는데, 테스트를 원하는 모델을 찾아 다운로드 버튼을 선택하면 모델 다운로드가 진행됩니다.일부 대형 모델의 경우 스마트폰 메모리 부족으로 다운로드 후 채팅을 시작할 때 앱이 강제 종료될 수 있으니 유의해야 합니다.참고로, Gemma2-2B 모델의 경우 Galaxy S23 기기에서 정상적으로 동작했습니다.Gemma2-2B 모델의 다운로드가 완료된 후 채팅 아이콘을 선택하면 모델 로딩이 시작됩니다.모델에 따라 로딩 시간이 오래 걸릴 수 있습니다. 로딩이 완료되면, 아래와 같이 'Ready to chat' 메시지가 표시됩니다.이제 챗봇 사용자 인터페이스를 이용해서 질문을 입력하고 AI 응답을 받을 수 있습니다."What is the capital of France?" 라고 입력하니 "The capital of France is Paris." 라고 잘 답변하는 것을 확인할 수 있습니다.MLCEngineExample은 MLCChat과 달리 UI 중심의 앱이 아니라 MLCEngine API를 보여주는 코드 중심의 예제 애플리케이션입니다.앱을 실행하면 미리 정의된 프롬프트에 대한 응답을 생성합니다. 빌드 과정은 MLCChat과 동일한데, 모델 사용 방식이 조금 다릅니다.코드에서 모델을 직접 명시한 후, 앱을 빌드하고 apk를 설치한 뒤 명령으로 모델 파일을 안드로이드 디바이스에 수동으로 복사해야 합니다.명령이 정상적으로 완료되면, MLCChat과 다르게 소스코드 수정 과정이 추가로 필요합니다.위 로그 정보에서 얻은 값을 파일에 반영합니다.이후 안드로이드 앱 빌드 과정은 동일합니다.MLCEngi
python
5/2/2025

MLC LLM을 이용한 안드로이드 On-device AI 맛보기
AI 기술이 급속도로 발전하면서 이제는 클라우드뿐만 아니라 모바일 기기에서도 인공지능 모델을 직접 구동할 수 있는 시대가 되었습니다.특히, 대형 언어 모델(LLM)을 경량화하여 스마트폰에서 직접 실행할 수 있다면 네트워크 연결 없이도 AI 기능을 활용할 수 있고, 개인정보 보호 측면에서도 큰 장점이 있습니다.이 글은 AI 분야에 깊은 지식이 없더라도, 안드로이드 디바이스에서 LLM을 직접 구동해보며 AI를 경험해보고 싶은 소프트웨어 개발자들을 위해 작성되었습니다.제목에 소개된 MLC LLM은 다양한 플랫폼에서 LLM을 효율적으로 실행할 수 있게 해주는 오픈소스 프로젝트로,이를 활용하면 복잡한 AI 지식 없이도 모바일 환경에서 대화형 AI 애플리케이션을 구현할 수 있습니다.MLC LLM을 사용하기 위해서는 Python 환경이 필요합니다. 그리고 추가로 안드로이드 라이브러리화하는 과정에서 Python뿐만 아니라 여러 가지 도구들이 함께 사용됩니다.이 글에 설명된 설치 가이드는 x86_64 기반의 Ubuntu 22.04 (jammy) 환경에서 테스트되었습니다.Python 3.11 버전과 Rust를 설치합니다. Python 패키지를 독립된 환경에서 사용하기 위해 도 같이 설치합니다.를 사용하여 MLC LLM 작업을 위한 독립된 Python 환경을 생성합니다.다음으로, Android 개발 환경을 설치합니다. Android Studio 자체는 MLC LLM을 빌드하는 데 필요는 없지만, 차후 IDE를 이용한 앱 개발을 진행한다고 가정하고 같이 설치해 줍니다.sdkmanager를 사용하기 위해 환경 변수를 설정합니다.이제 를 사용하여 추가로 필요한 패키지를 설치합니다.환경변수에 cmake와 ndk 정보를 추가합니다.이렇게 해서 기본적인 준비 과정을 완료했습니다.MLC LLM은 친절하게 미리 빌드된 패키지(Prebuilt package)를 제공하고 있어 명령으로 쉽게 설치할 수 있습니다.물론, 필요할 경우 소스를 통한 빌드도 함께 제공합니다. 자세한 내용은 공식 문서를 참고 바랍니다.설치가 정상적으로 완료되면 아래와 같이 명령을 터미널에서 사용할 수 있습니다.에서 제공하는 명령으로 독립된 mlc python 환경을 종료합니다.이제 모든 준비 과정이 끝났습니다. 다음 단계에서 MLC LLM을 Android 라이브러리로 빌드하는 과정을 알아보겠습니다.MLC LLM은 두 가지 안드로이드 샘플 앱을 제공합니다. MLCChat과 MLCEngineExample 각각의 빌드 방법을 알아보겠습니다.먼저 코드를 다운로드 받습니다.샘플 코드는 디렉토리에서 찾을 수 있습니다.앱 빌드를 위한 사전 단계로 라는 명령을 사용하게 되는데, 이 때 추가로 필요로 하는 모듈들이 있어 아래와 같이 명령으로 의존성 모듈들을 같이 준비합니다.또한, 추가로 설정이 필요한 환경변수가 있어 마지막으로 아래와 같이 설정합니다.참고로 지금까지 추가된 환경변수들을 정리하면 아래와 같습니다. 쉘 설정 파일( )에 추가하면 좀 더 편리하게 사용할 수 있습니다.빌드 환경 설정이 모두 완료되었습니다. 이제 예제 애플리케이션을 빌드하여 테스트해 보겠습니다. 전체적인 진행 과정은 아래 그림과 같습니다.두 애플리케이션 모두 기본적인 설정 및 빌드 과정은 유사하지만, MLCEngineExample의 경우 최소화된 기능만 제공하므로 몇 가지 작업을 수동으로 추가해야 합니다.그리고 Hugging Face의 mlc-ai 저장소에서 제공하는 모델을 사용할 경우 큰 수정 없이 진행할 수 있으나, 다른 모델을 사용하려면 별도의 변환 과정이 필요합니다.다음 단계에서 이 과정을 더 자세히 살펴보겠습니다.MLCChat (경로: )은 모델 다운로드 기능이 포함된 채팅 형태의 애플리케이션입니다.사용하고 있는 모델 목록은 파일에 아래와 같이 정의되어 있습니다.명령을 수행하면, 위 파일의 에 정의된 각 모델을 다운로드 후 이를 기반으로 안드로이드 앱 빌드를 위한 라이브러리를 생성합니다.따라서, 앱에서 사용할 모델 정보 변경이 필요할 경우 위 json 파일을 수정하고 다시 명령을 실행해야 합니다.모델 다운로드와 TVM Unity 컴파일 과정이 시작되며, 이 과정은 다소 시간이 걸릴 수 있습니다. 작업 진행중 다음과 같은 로그가 출력됩니다.모델에 대한 작업이 끝나면 아래와 같이 로그가 출력됩니다.이후 와 Android NDK를 이용한 빌드가 진행됩니다.MLC LLM 준비가 모두 끝났습니다. 이제 을 이용해 안드로이드 애플리케이션을 빌드합니다.설치 후 실행하면 아래와 같이 모델 목록 화면이 나타나는데, 테스트를 원하는 모델을 찾아 다운로드 버튼을 선택하면 모델 다운로드가 진행됩니다.일부 대형 모델의 경우 스마트폰 메모리 부족으로 다운로드 후 채팅을 시작할 때 앱이 강제 종료될 수 있으니 유의해야 합니다.참고로, Gemma2-2B 모델의 경우 Galaxy S23 기기에서 정상적으로 동작했습니다.Gemma2-2B 모델의 다운로드가 완료된 후 채팅 아이콘을 선택하면 모델 로딩이 시작됩니다.모델에 따라 로딩 시간이 오래 걸릴 수 있습니다. 로딩이 완료되면, 아래와 같이 'Ready to chat' 메시지가 표시됩니다.이제 챗봇 사용자 인터페이스를 이용해서 질문을 입력하고 AI 응답을 받을 수 있습니다."What is the capital of France?" 라고 입력하니 "The capital of France is Paris." 라고 잘 답변하는 것을 확인할 수 있습니다.MLCEngineExample은 MLCChat과 달리 UI 중심의 앱이 아니라 MLCEngine API를 보여주는 코드 중심의 예제 애플리케이션입니다.앱을 실행하면 미리 정의된 프롬프트에 대한 응답을 생성합니다. 빌드 과정은 MLCChat과 동일한데, 모델 사용 방식이 조금 다릅니다.코드에서 모델을 직접 명시한 후, 앱을 빌드하고 apk를 설치한 뒤 명령으로 모델 파일을 안드로이드 디바이스에 수동으로 복사해야 합니다.명령이 정상적으로 완료되면, MLCChat과 다르게 소스코드 수정 과정이 추가로 필요합니다.위 로그 정보에서 얻은 값을 파일에 반영합니다.이후 안드로이드 앱 빌드 과정은 동일합니다.MLCEngi
2025.05.02
python

좋아요

별로에요

OpenStack VM 전원 동기화 로직 분석
OpenStack 에서 Nova API 를 호출하여 명시적으로 전원을 종료하지 않고 VM 내에서 전원을 종료한다거나 VM Crash 등으로 전원 상태가 바뀌면 Nova 에서 이를 어떻게 감지하고 DB 에 동기화할까?내부 로직을 살펴보고 이해할 수 있도록 정리하고자 합니다.분석 환경은 다음과 같습니다.위 Workflow 는 큰 흐름을 이해하기 위한 다이어그램입니다. (아래 내부 로직에서 더 자세히 설명)• None nova-compute 서비스가 구동되면 libvirt 에 연결하여 VM event 를 폴링• None VM 전원 상태가 변경되면 이벤트를 감지하고 이를 event queue 에 적재• None 이벤트를 적재했다는 알림을 Pipe 를 통해 전달• None 이벤트를 디스패치하여 ComputeManager 로 이벤트를 내보냄• None ComputeManager 는 변경된 전원 상태를 DB 에 업데이트nova 는 libvirt-python 라이브러리를 이용해 Libvirt 의 domain lifecycle 이벤트를 수신하도록 구현되어 있습니다.nova-compute 가 구동되면 libvirt driver 가 초기화되면서 libvirtd 에 연결할 때 domainEventRegisterAny() 로 이벤트 리스너를 등록하여 VM 이벤트를 수신할 수 있게 됩니다.• None 11 라인에서 domainEventRegisterAny() 를 이용해 이벤트 리스너를 등록• None libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE : 이벤트 ID 기반 lifecycle 이벤트만 수신 한다는 의미테스트를 위해 테스트 코드를 작성하였습니다.• None libvirt 에 이벤트 리스너를 등록하고 이벤트 감지 시 event_lifecycle_callback() 콜백함수를 실행하는 코드입니다.• None event_lifecycle_callback() 콜백함수는 이벤트 ID 와 Detail 이벤트 ID 를 출력합니다.테스트 코드를 실행하고 VM 을 종료/시작 해보았습니다.• None shutdown 시 이벤트 ID 6번과 Detail ID 1번을 수신합니다.• None shutdown 시 이벤트 ID 5번과 Detail ID 0번을 수신합니다.• None start 시 이벤트 ID 4번과 Detail ID 0 번을 수신합니다.• None start 시 이벤트 ID 2번과 Detail ID 0 번을 수신합니다.이벤트 ID 와 Detail ID 의 의미는 libvirt.py 라이브러리 내의 상수로 정의되어 있습니다.• None 위 의미를 기반으로 shutdown 시 전달된 두 개의 이벤트를 해석해 보면 다음과 같습니다.• None• None VM 종료가 완료되었다는 의미다음으로 이벤트 감지 후 실행되는 콜백 함수에 대해 살펴보겠습니다.• None 위에서 살펴본 libvirt 의 이벤트와 Detail 이벤트를 nova 의 virtevnet 와 매핑하여 transition 을 정의 한 다음• None 49 라인에서 _queue_event() 를 호출하여 이벤트를 큐에 보내게 됩니다.nova 의 virtevent 는 다음과 같이 정의됩니다.다음으로 콜백 함수에서 _queue_event() 를 통해 큐로 전달된 이벤트가 어떻게 처리되는지 이어서 살펴보겠습니다.우선 이벤트를 담을 큐는 초기화 시 다음과 같이 생성됩니다.• None 8 라인에서 event queue 는 native_Queue.Queue() 객체를 이용해 생성됩니다.• None native_Queue 는 python 내장 queue 모듈이며, 큐의 데이터를 관리• None 추가로 11,12 라인에서 _event_notify_send() 및 recv() 함수를 정의합니다.• None 역할은 큐에 데이터가 적재되면 적재되었다고 리시버에게 알리는 역할• None os.pipe() 로 리눅스 운영체제의 파이프를 이용하며, python eventlet 의 greenio.GreenPipe() 를 이용해 비동기로 알람을 보냄• None wb 와 rb 의 차이는 wb 는 write 권한 및 binary 모드로 파이프를 open 하는 의미이고,• None rb 는 read 및 binary 모드로 파이프를 open 하는 의미다시 돌아와 콜백함수에서 이벤트 전달 시 사용한 _queue_event() 를 살펴보겠습니다.• None 13 라인에서 _event_queue.put() 으로 이벤트를 큐에 적재• None 이후 16 ~ 18 라인에서 공백 문자(' ') 를 바이트로 encode() 후 _event_notify_send.write() 로 파이프를 통해 큐에 데이터가 적재되었다는 알람을 보냄• None flush 는 버퍼를 플러쉬하는 함수인데, 버퍼가 있으면 알람이 안갈 수 있어 즉시 플러쉬다음으로 큐에 적재된 이벤트를 어떻게 가져와 처리하는지 살펴보겠습니다.이벤트가 큐에 적재되었다는 알림이 보내지면 이를 디스패치 스레드가 감지하게 되어있습니다.위 디스패치 스레드가 무한 루프 돌리는 _dispatch_events() 는 큐에서 이벤트를 꺼내 내보내는 역할을 합니다.• None 11 라인에서 파이프에서 1바이트를 읽어 신호가 왔음을 감지• None 22 라인에서 큐에서 이벤트를 하나씩 꺼냄• None 27 라인에서 InstanceEvent 인 이벤트이면 _event_emit_delayed() 메서드를 호출하여 이벤트를 내보냄다음으로 위에서 살펴본 디스패치 이벤트에서 이벤트를 내보낼 때 사용한 _event_emit_delayed() 메서드를 살펴보겠습니다._event_emit_delayed() 는 이벤트를 ComputeManager 로 내보내는 역할을 합니다.• None Instacne 이벤트가 STOPPED 이면 일정시간 딜레이 후 처리하게 되어있음 (17라인)• None 이유는 재부팅인 VM 인 경우 곧바로 start 가 올 수 있어 딜레이를 줌• None 그 외 이벤트는 28 라인에서 _event_emit() 메서드를 호출하여 이벤트를 내보내게 됩니다.• None _event_emit 는 _lifecycle_event_handle
5/2/2025

OpenStack VM 전원 동기화 로직 분석
OpenStack 에서 Nova API 를 호출하여 명시적으로 전원을 종료하지 않고 VM 내에서 전원을 종료한다거나 VM Crash 등으로 전원 상태가 바뀌면 Nova 에서 이를 어떻게 감지하고 DB 에 동기화할까?내부 로직을 살펴보고 이해할 수 있도록 정리하고자 합니다.분석 환경은 다음과 같습니다.위 Workflow 는 큰 흐름을 이해하기 위한 다이어그램입니다. (아래 내부 로직에서 더 자세히 설명)• None nova-compute 서비스가 구동되면 libvirt 에 연결하여 VM event 를 폴링• None VM 전원 상태가 변경되면 이벤트를 감지하고 이를 event queue 에 적재• None 이벤트를 적재했다는 알림을 Pipe 를 통해 전달• None 이벤트를 디스패치하여 ComputeManager 로 이벤트를 내보냄• None ComputeManager 는 변경된 전원 상태를 DB 에 업데이트nova 는 libvirt-python 라이브러리를 이용해 Libvirt 의 domain lifecycle 이벤트를 수신하도록 구현되어 있습니다.nova-compute 가 구동되면 libvirt driver 가 초기화되면서 libvirtd 에 연결할 때 domainEventRegisterAny() 로 이벤트 리스너를 등록하여 VM 이벤트를 수신할 수 있게 됩니다.• None 11 라인에서 domainEventRegisterAny() 를 이용해 이벤트 리스너를 등록• None libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE : 이벤트 ID 기반 lifecycle 이벤트만 수신 한다는 의미테스트를 위해 테스트 코드를 작성하였습니다.• None libvirt 에 이벤트 리스너를 등록하고 이벤트 감지 시 event_lifecycle_callback() 콜백함수를 실행하는 코드입니다.• None event_lifecycle_callback() 콜백함수는 이벤트 ID 와 Detail 이벤트 ID 를 출력합니다.테스트 코드를 실행하고 VM 을 종료/시작 해보았습니다.• None shutdown 시 이벤트 ID 6번과 Detail ID 1번을 수신합니다.• None shutdown 시 이벤트 ID 5번과 Detail ID 0번을 수신합니다.• None start 시 이벤트 ID 4번과 Detail ID 0 번을 수신합니다.• None start 시 이벤트 ID 2번과 Detail ID 0 번을 수신합니다.이벤트 ID 와 Detail ID 의 의미는 libvirt.py 라이브러리 내의 상수로 정의되어 있습니다.• None 위 의미를 기반으로 shutdown 시 전달된 두 개의 이벤트를 해석해 보면 다음과 같습니다.• None• None VM 종료가 완료되었다는 의미다음으로 이벤트 감지 후 실행되는 콜백 함수에 대해 살펴보겠습니다.• None 위에서 살펴본 libvirt 의 이벤트와 Detail 이벤트를 nova 의 virtevnet 와 매핑하여 transition 을 정의 한 다음• None 49 라인에서 _queue_event() 를 호출하여 이벤트를 큐에 보내게 됩니다.nova 의 virtevent 는 다음과 같이 정의됩니다.다음으로 콜백 함수에서 _queue_event() 를 통해 큐로 전달된 이벤트가 어떻게 처리되는지 이어서 살펴보겠습니다.우선 이벤트를 담을 큐는 초기화 시 다음과 같이 생성됩니다.• None 8 라인에서 event queue 는 native_Queue.Queue() 객체를 이용해 생성됩니다.• None native_Queue 는 python 내장 queue 모듈이며, 큐의 데이터를 관리• None 추가로 11,12 라인에서 _event_notify_send() 및 recv() 함수를 정의합니다.• None 역할은 큐에 데이터가 적재되면 적재되었다고 리시버에게 알리는 역할• None os.pipe() 로 리눅스 운영체제의 파이프를 이용하며, python eventlet 의 greenio.GreenPipe() 를 이용해 비동기로 알람을 보냄• None wb 와 rb 의 차이는 wb 는 write 권한 및 binary 모드로 파이프를 open 하는 의미이고,• None rb 는 read 및 binary 모드로 파이프를 open 하는 의미다시 돌아와 콜백함수에서 이벤트 전달 시 사용한 _queue_event() 를 살펴보겠습니다.• None 13 라인에서 _event_queue.put() 으로 이벤트를 큐에 적재• None 이후 16 ~ 18 라인에서 공백 문자(' ') 를 바이트로 encode() 후 _event_notify_send.write() 로 파이프를 통해 큐에 데이터가 적재되었다는 알람을 보냄• None flush 는 버퍼를 플러쉬하는 함수인데, 버퍼가 있으면 알람이 안갈 수 있어 즉시 플러쉬다음으로 큐에 적재된 이벤트를 어떻게 가져와 처리하는지 살펴보겠습니다.이벤트가 큐에 적재되었다는 알림이 보내지면 이를 디스패치 스레드가 감지하게 되어있습니다.위 디스패치 스레드가 무한 루프 돌리는 _dispatch_events() 는 큐에서 이벤트를 꺼내 내보내는 역할을 합니다.• None 11 라인에서 파이프에서 1바이트를 읽어 신호가 왔음을 감지• None 22 라인에서 큐에서 이벤트를 하나씩 꺼냄• None 27 라인에서 InstanceEvent 인 이벤트이면 _event_emit_delayed() 메서드를 호출하여 이벤트를 내보냄다음으로 위에서 살펴본 디스패치 이벤트에서 이벤트를 내보낼 때 사용한 _event_emit_delayed() 메서드를 살펴보겠습니다._event_emit_delayed() 는 이벤트를 ComputeManager 로 내보내는 역할을 합니다.• None Instacne 이벤트가 STOPPED 이면 일정시간 딜레이 후 처리하게 되어있음 (17라인)• None 이유는 재부팅인 VM 인 경우 곧바로 start 가 올 수 있어 딜레이를 줌• None 그 외 이벤트는 28 라인에서 _event_emit() 메서드를 호출하여 이벤트를 내보내게 됩니다.• None _event_emit 는 _lifecycle_event_handle
2025.05.02

좋아요

별로에요

MCP 개념 및 LINE Messaging API를 활용한 MCP 서버 구축 사례 소개
최근 Anthropic에서 Claude LLM을 통해 모델 컨텍스트 프로토콜(Model Context Protocol, 이하 MCP)을 발표했습니다. MCP는 대형 언어 모델(large language model, 이하 LLM)이 외부 데이터 소스나 기능을 사용할 수 있도록 돕는 프로토콜로, Anthropic 에서 누구나 사용할 수 있는 오픈 프로토콜로 공개했습니다(참고). 이에 따라 많은 서비스에서 MCP를 지원하기 시작했고, 많은 사용자가 MCP를 사용해 LLM과 외부 서비스를 연결하는 방법에 관심을 갖기 시작했습니다.이번 글에서는 많은 관심을 받고 있는 MCP의 개념과 아키텍처를 설명하고, LINE Messaging API를 활용해 MCP 서버를 구현하는 방법을 소개하겠습니다.MCP는 LLM이 외부 기능을 사용할 수 있도록 지원하는 프로토콜입니다. 아래는 LLM만 단독으로 사용하는 경우와 MCP를 활용한 경우를 비교한 그림입니다.예를 들어 LINE의 오픈소스 라이브러리인 Armeria에서 특정 코드를 검색하고 싶을 때 LLM 애플리케이션에 프롬프트를 작성해 요청하면, LLM 애플리케이션은 실제 GitHub에 접속해서 Armeria 라이브러리를 조사하는 것이 아니라 기존에 학습한 모델을 바탕으로 응답할 것입니다. AI 할루시네이션이 발생할 수 있는 상황이죠.반면 GitHub MCP를 사용하면 LLM 애플리케이션이 GitHub에 접속해 실제 Armeria 리포지터리에서 해당 코드를 검색한 뒤 검색 결과를 기준으로 응답합니다. 다만 이를 위해서는 외부 서비스인 GitHub에서 MCP 서버를 제공해야 하며, 사용하는 LLM 애플리케이션에서도 이 MCP를 사용해 호출해야 하는데요. 이와 같이 LLM 애플리케이션에서 외부 기능을 사용할 수 있도록 정의한 프로토콜을 MCP라고 합니다(참고로 GitHub은 실제로 GitHub MCP를 제공하고 있습니다).MCP는 기본적으로 호스트의 클라이언트가 서버와 연결되는 클라이언트-서버 아키텍처를 따릅니다.이 아키텍처는 호스트, 클라이언트, 서버, 이 세 가지 주체로 구성되며, 각 주체의 역할은 다음과 같습니다.• 호스트: MCP를 사용하는 주체인 LLM 애플리케이션을 가리키며, 사용자의 요청을 받아 응답하는 애플리케이션입니다. 이후 예제에서 'Claude 데스크톱 애플리케이션'이 호스트에 해당합니다.• 클라이언트: 호스트의 내부 모듈로 MCP 서버에 요청을 전송한 뒤 응답을 받아 호스트에게 전달합니다.• 서버: 호스트 외부에 존재하며 MCP 클라이언트로부터 받은 요청을 처리하고 응답하는 애플리케이션입니다.MCP 호스트가 사용할 수 있는 요소는 다양합니다. 그중 가장 핵심적인 요소인 툴과 리소스를 소개하겠습니다.툴(tools)은 MCP의 핵심 요소로 외부 기능을 실행할 수 있도록 MCP 서버가 제공하는 요소입니다. MCP 서버는 실행할 수 있는 툴 목록을 확인할 수 있는 엔드포인트인 와, 원하는 툴을 호출할 수 있는 엔드포인트인 를 제공합니다. MCP 호스트는 사용자 프롬프트에 대한 응답을 처리하는 과정에서 외부 기능 호출이 필요한 경우 MCP 클라이언트를 통해 MCP 서버가 제공하는 툴을 사용합니다.예를 들어 GitHub MCP 서버에서는 라는 툴을 제공하며, 사용자는 프롬프트를 통해 이 툴을 이용해 새로운 PR을 만들 수 있습니다.리소스(resources) 역시 MCP의 핵심 요소로, MCP 서버가 제공할 수 있는 다양한 형태의 데이터나 콘텐츠를 의미합니다. 리소스는 파일 내용이나 데이터베이스 레코드, API 응답 등 다양한 형태로 존재할 수 있습니다. MCP 클라이언트는 MCP 서버에 사용할 수 있는 리소스 목록을 요청해 받은 뒤, 다시 필요한 리소스를 요청해서 데이터를 가져올 수 있습니다. MCP 클라이언트가 가져온 데이터는 MCP 호스트로 전달되며, MCP 호스트는 이 데이터를 사용자의 프롬프트 응답에 활용할 수 있습니다.예를 들어 GitHub MCP 서버에서는 API 리소스를 통해 특정 리포지터리의 소스 코드를 제공합니다.MCP는 어떻게 구현하느냐에 따라서 다양한 방식으로 작동할 수 있는데요. 이 글에서는 아래 그림과 함께 가장 기초적인 방식을 알아보겠습니다.• MCP 호스트가 실행될 때 MCP 클라이언트를 통해 MCP 서버의 엔드포인트를 호출해 사용 가능한 툴 목록을 받아옵니다.• 사용자가 MCP 호스트에게 프롬프트를 보냅니다.• MCP 호스트는 사용자의 프롬프트와 사전에 받아온 툴 목록을 LLM 모델로 전달합니다. LLM 모델은 툴 목록 중 사용이 필요하다고 판단된 툴들을 사용하겠다고 응답합니다.• MCP 호스트는 MCP 클라이언트를 통해 MCP 서버의 엔드포인트로 해당 툴 사용을 요청합니다.• MCP 호스트는 MCP 서버의 툴 응답과 기존 사용자의 프롬프트를 다시 LLM 모델로 전달하고, LLM 모델은 이를 기반으로 최종 응답을 생성합니다.• MCP 호스트는 LLM 모델로부터 받은 최종 응답을 가공해 사용자에게 전달합니다.LINE Messaging API와 함께 하는 MCP 활용 사례이제 LINE의 Messaging API를 활용해 MCP를 직접 사용해 보겠습니다. LINE은 LINE 공식 계정(Official Account, OA)을 위한 Messaging API를 제공하고 있으며, 이를 통해 공식 계정을 친구로 등록한 사용자에게 메시지를 보내는 등의 행동을 할 수 있는데요. 이를 활용해 MCP 서버를 구축해 보겠습니다. MCP 공식 사용자 가이드의 For Server Developers 문서와 LINE Developers 사이트의 Messaging API 문서를 함께 참고하시면 좋을 것 같습니다.LINE Messaging API를 활용해 MCP 서버를 구축하기 위해서는 다음 준비가 필요합니다.• LINE Messaging API 사용 준비• LINE Developers의 Get started with the Messaging API 문서를 참고해 공식 계정 생성 후 Messaging API 활성화해 채널 생성• LINE Developer Console에 접속해 앞서 생성한 채널의 Messaging API 탭 하단에서 채
github
5/2/2025

MCP 개념 및 LINE Messaging API를 활용한 MCP 서버 구축 사례 소개
최근 Anthropic에서 Claude LLM을 통해 모델 컨텍스트 프로토콜(Model Context Protocol, 이하 MCP)을 발표했습니다. MCP는 대형 언어 모델(large language model, 이하 LLM)이 외부 데이터 소스나 기능을 사용할 수 있도록 돕는 프로토콜로, Anthropic 에서 누구나 사용할 수 있는 오픈 프로토콜로 공개했습니다(참고). 이에 따라 많은 서비스에서 MCP를 지원하기 시작했고, 많은 사용자가 MCP를 사용해 LLM과 외부 서비스를 연결하는 방법에 관심을 갖기 시작했습니다.이번 글에서는 많은 관심을 받고 있는 MCP의 개념과 아키텍처를 설명하고, LINE Messaging API를 활용해 MCP 서버를 구현하는 방법을 소개하겠습니다.MCP는 LLM이 외부 기능을 사용할 수 있도록 지원하는 프로토콜입니다. 아래는 LLM만 단독으로 사용하는 경우와 MCP를 활용한 경우를 비교한 그림입니다.예를 들어 LINE의 오픈소스 라이브러리인 Armeria에서 특정 코드를 검색하고 싶을 때 LLM 애플리케이션에 프롬프트를 작성해 요청하면, LLM 애플리케이션은 실제 GitHub에 접속해서 Armeria 라이브러리를 조사하는 것이 아니라 기존에 학습한 모델을 바탕으로 응답할 것입니다. AI 할루시네이션이 발생할 수 있는 상황이죠.반면 GitHub MCP를 사용하면 LLM 애플리케이션이 GitHub에 접속해 실제 Armeria 리포지터리에서 해당 코드를 검색한 뒤 검색 결과를 기준으로 응답합니다. 다만 이를 위해서는 외부 서비스인 GitHub에서 MCP 서버를 제공해야 하며, 사용하는 LLM 애플리케이션에서도 이 MCP를 사용해 호출해야 하는데요. 이와 같이 LLM 애플리케이션에서 외부 기능을 사용할 수 있도록 정의한 프로토콜을 MCP라고 합니다(참고로 GitHub은 실제로 GitHub MCP를 제공하고 있습니다).MCP는 기본적으로 호스트의 클라이언트가 서버와 연결되는 클라이언트-서버 아키텍처를 따릅니다.이 아키텍처는 호스트, 클라이언트, 서버, 이 세 가지 주체로 구성되며, 각 주체의 역할은 다음과 같습니다.• 호스트: MCP를 사용하는 주체인 LLM 애플리케이션을 가리키며, 사용자의 요청을 받아 응답하는 애플리케이션입니다. 이후 예제에서 'Claude 데스크톱 애플리케이션'이 호스트에 해당합니다.• 클라이언트: 호스트의 내부 모듈로 MCP 서버에 요청을 전송한 뒤 응답을 받아 호스트에게 전달합니다.• 서버: 호스트 외부에 존재하며 MCP 클라이언트로부터 받은 요청을 처리하고 응답하는 애플리케이션입니다.MCP 호스트가 사용할 수 있는 요소는 다양합니다. 그중 가장 핵심적인 요소인 툴과 리소스를 소개하겠습니다.툴(tools)은 MCP의 핵심 요소로 외부 기능을 실행할 수 있도록 MCP 서버가 제공하는 요소입니다. MCP 서버는 실행할 수 있는 툴 목록을 확인할 수 있는 엔드포인트인 와, 원하는 툴을 호출할 수 있는 엔드포인트인 를 제공합니다. MCP 호스트는 사용자 프롬프트에 대한 응답을 처리하는 과정에서 외부 기능 호출이 필요한 경우 MCP 클라이언트를 통해 MCP 서버가 제공하는 툴을 사용합니다.예를 들어 GitHub MCP 서버에서는 라는 툴을 제공하며, 사용자는 프롬프트를 통해 이 툴을 이용해 새로운 PR을 만들 수 있습니다.리소스(resources) 역시 MCP의 핵심 요소로, MCP 서버가 제공할 수 있는 다양한 형태의 데이터나 콘텐츠를 의미합니다. 리소스는 파일 내용이나 데이터베이스 레코드, API 응답 등 다양한 형태로 존재할 수 있습니다. MCP 클라이언트는 MCP 서버에 사용할 수 있는 리소스 목록을 요청해 받은 뒤, 다시 필요한 리소스를 요청해서 데이터를 가져올 수 있습니다. MCP 클라이언트가 가져온 데이터는 MCP 호스트로 전달되며, MCP 호스트는 이 데이터를 사용자의 프롬프트 응답에 활용할 수 있습니다.예를 들어 GitHub MCP 서버에서는 API 리소스를 통해 특정 리포지터리의 소스 코드를 제공합니다.MCP는 어떻게 구현하느냐에 따라서 다양한 방식으로 작동할 수 있는데요. 이 글에서는 아래 그림과 함께 가장 기초적인 방식을 알아보겠습니다.• MCP 호스트가 실행될 때 MCP 클라이언트를 통해 MCP 서버의 엔드포인트를 호출해 사용 가능한 툴 목록을 받아옵니다.• 사용자가 MCP 호스트에게 프롬프트를 보냅니다.• MCP 호스트는 사용자의 프롬프트와 사전에 받아온 툴 목록을 LLM 모델로 전달합니다. LLM 모델은 툴 목록 중 사용이 필요하다고 판단된 툴들을 사용하겠다고 응답합니다.• MCP 호스트는 MCP 클라이언트를 통해 MCP 서버의 엔드포인트로 해당 툴 사용을 요청합니다.• MCP 호스트는 MCP 서버의 툴 응답과 기존 사용자의 프롬프트를 다시 LLM 모델로 전달하고, LLM 모델은 이를 기반으로 최종 응답을 생성합니다.• MCP 호스트는 LLM 모델로부터 받은 최종 응답을 가공해 사용자에게 전달합니다.LINE Messaging API와 함께 하는 MCP 활용 사례이제 LINE의 Messaging API를 활용해 MCP를 직접 사용해 보겠습니다. LINE은 LINE 공식 계정(Official Account, OA)을 위한 Messaging API를 제공하고 있으며, 이를 통해 공식 계정을 친구로 등록한 사용자에게 메시지를 보내는 등의 행동을 할 수 있는데요. 이를 활용해 MCP 서버를 구축해 보겠습니다. MCP 공식 사용자 가이드의 For Server Developers 문서와 LINE Developers 사이트의 Messaging API 문서를 함께 참고하시면 좋을 것 같습니다.LINE Messaging API를 활용해 MCP 서버를 구축하기 위해서는 다음 준비가 필요합니다.• LINE Messaging API 사용 준비• LINE Developers의 Get started with the Messaging API 문서를 참고해 공식 계정 생성 후 Messaging API 활성화해 채널 생성• LINE Developer Console에 접속해 앞서 생성한 채널의 Messaging API 탭 하단에서 채
2025.05.02
github

좋아요

별로에요

NPU: AI 효율을 극대화하는 전용 프로세서
인공지능(AI) 기술이 비약적으로 발전하면서, 대량의 연산을 빠르게 처리할 수 있는 전용 하드웨어의 필요성이 대두되었습니다. 기존의 CPU와 GPU가 범용성과 병렬 처리에 강점을 보였지만, AI 특히 딥러닝 모델의 추론(inference) 작업에서는 한계가 있었습니다. 이러한 상황에서 등장한 것이 바로 Neural Processing Unit(NPU) 입니다. 이번 글에서는 NPU의 개념과 등장 배경, CPU 및 GPU와의 차이, 장단점을 분석하고, 특히 로보틱스 분야에서 NPU가 제공하는 혁신적 가능성에 대해 다루겠습니다.NPUNPU는 인공 신경망 연산에 최적화된 전용 프로세서로, 대규모 행렬 연산과 병렬 처리를 통해 AI 모델의 추론 속도를 크게 향상시킵니다. 기존의 CPU는 범용 처리를, GPU는 그래픽 및 대량의 병렬 연산을 처리하는 데 특화되어 있는 반면, NPU는 딥러닝 알고리즘의 특징인 곱셈-누적 연산을 매우 효율적으로 수행할 수 있도록 설계되었습니다. 예를 들어, 모바일 기기에서는 NPU 덕분에 얼굴 인식, 음성 명령 처리 등 복잡한 AI 기능을 실시간으로 수행할 수 있게 됐습니다.NPU는 AI 가속기(AI Accelerator), 딥러닝 프로세서(DLP, Deep Learning Processor), 딥러닝 가속기(DLA, Deep Learning Accelerator)와 같이 여러 이름이 있지만, 본 글에서는 NPU로 통일하여 표현하였습니다.CPU, GPU와의 비교그렇다면, 많은 분야에서 널리 사용되는 CPU와 GPU랑 비교하면 NPU는 어떤 차이점을 갖고 있을까요? NPU는 아키텍처 및 병렬성을 바탕으로 CPU, GPU와 차이점이 있어 전력 효율과 성능 측면에서 두각을 드러냅니다. 하지만, CPU 및 GPU와 비교하면 그 역사가 길지 않아 개발 생태계가 충분히 갖추어져 있지 않는 한계도 있습니다.아키텍처 및 병렬성NPU는 AI 최적화를 위해 CPU 및 GPU와 비교하여 다른 구조를 갖고 있다는 점이 가장 중요한 차이점입니다.CPU: 소수의 고성능 코어를 활용해 순차적 작업을 빠르게 처리하지만, 대규모 병렬 처리에는 한계가 있습니다.GPU: 수백에서 수천 개의 코어를 사용해 병렬 연산에 강점을 가지며, 주로 그래픽 처리 및 딥러닝 학습에 적합합니다.NPU: 신경망 연산에 특화된 구조를 도입해, 불필요한 연산을 최소화하고 메모리 접근을 최적화하여 낮은 전력 소모로 높은 연산 성능을 발휘합니다.전력 효율과 성능구조의 차이로 인해 NPU는 AI 처리에 더욱 효율적입니다. CPU와 GPU는 높은 연산 능력을 제공하지만, 특히 GPU는 전력 소모와 발열 문제가 발생할 수 있습니다. 반면 NPU는 필요한 연산만을 전용 회로로 수행하기 때문에 에너지 효율성이 뛰어나며, 로봇을 포함한 배터리 기반의 모바일 기기나 임베디드 시스템에서 실시간 AI 처리를 가능하게 합니다.개발 및 배포 환경CPU와 GPU는 오랜 기간 축적된 성숙한 소프트웨어 생태계를 갖추고 있어 개발자들이 쉽게 활용할 수 있습니다. 그러나 NPU는 제조사마다 지원하는 SDK나 도구가 달라, 개발 및 최적화 과정이 상대적으로 복잡할 수 있습니다. 최신 NPU 제품들은 이러한 문제를 개선하려는 노력이 계속되고 있으므로, 점차 더 나은 개발 환경이 구축되고 있습니다.NPU의 장단점NPU는 AI 연산에 최적화된 구조를 통해 더 빠르면서 효율적으로 연산을 수행하며 실시간성(저지연)을 포함한 여러 장점을 갖고 있습니다. 하지만, 충분히 성숙되지 않은 분야로 점차 완성도를 갖춰나가는 모습을 보이고 있기도 합니다.장점높은 AI 연산 성능: NPU는 인공 신경망 연산에 최적화되어 있어, CPU나 GPU보다 훨씬 빠른 추론 속도를 제공함우수한 전력 효율성: 전용 하드웨어 설계 덕분에 동일한 작업을 처리할 때 소비 전력이 적어, 배터리 구동 기기에서 유리함낮은 지연 시간: 클라우드에 의존하지 않고 기기 내에서 데이터를 처리함으로써, 네트워크 지연이 줄어들어 실시간 응답이 요구되는 애플리케이션에 적합함단점개발 복잡성: 제조사마다 상이한 도구와 SDK로 인해 개발 및 최적화 과정이 까다로울 수 있음범용성 제한: AI 추론에 특화되어 있어, 범용 연산이나 복잡한 제어 로직 처리에는 적합하지 않음비용 문제: 전용 NPU를 설계 및 제조하는 데 추가 비용이 발생할 수 있으며, 시스템 통합 시 호환성 문제도 고려해야 함적용 분야NPU는 이미 다양한 분야에서 활용되고 있으며, AI를 사용하는 다양한 분야에서 응용되고 있습니다. AI 기능에 대한 수요가 많이지면서 AI를 효율적으로 처리하는 NPU에 대한 수요와 관심도 점점 높아지는 추세입니다.모바일 및 IoT 디바이스: 스마트폰, 태블릿, 스마트 스피커 등에서 실시간 이미지 및 음성 인식을 구현함데이터 센터 및 클라우드: AI 추론 작업을 가속하여, 대규모 사용자 요청에 대한 응답 시간을 단축함자율주행 및 첨단 운전자 보조 시스템(ADAS): 센서 데이터를 빠르게 처리해 실시간으로 도로 상황을 판단하고 대응함산업용 및 보안 카메라: 현장에서 실시간으로 데이터를 분석하여, 빠른 대응과 프라이버시 보호를 지원함로보틱스에서의 NPU로보틱스 분야는 NPU의 실시간 데이터 처리 능력과 낮은 전력 소모 덕분에 큰 혜택을 보고 있습니다. 로봇은 주행, 물체 인식, 경로 계획 등 다양한 작업을 수행하는데, NPU가 탑재된 시스템은 다음과 같은 이점을 제공합니다:실시간 컴퓨터 비전: 카메라와 센서를 통해 들어오는 데이터를 즉각 분석하여 장애물을 피하거나 목표물을 식별함에너지 효율성: 배터리로 구동되는 로봇에서 NPU는 전력 소모를 줄여 운용 시간을 늘려 더 오래 서비스가 가능함현장 내 자율 판단: 네트워크 지연 없이 기기 자체에서 데이터 처리 및 판단을 내림으로써, 로봇이 독립적으로 작동하게 함개인정보 보호: 로봇에서 AI에 필요한 데이터를 처리해 민감 정보가 로봇 밖으로 보내지지 않음NPU의 미래AI 기술이 지속적으로 발전함에 따라 NPU의 역할은 더욱 중요해질 것입니다. 향후 NPU는 CPU와 GPU와의 이기종 통합 시스템의 핵심 부품으로 자리잡을 가능성이 높으며, 소형 임베디드 시스템에서도 AI
5/1/2025

NPU: AI 효율을 극대화하는 전용 프로세서
인공지능(AI) 기술이 비약적으로 발전하면서, 대량의 연산을 빠르게 처리할 수 있는 전용 하드웨어의 필요성이 대두되었습니다. 기존의 CPU와 GPU가 범용성과 병렬 처리에 강점을 보였지만, AI 특히 딥러닝 모델의 추론(inference) 작업에서는 한계가 있었습니다. 이러한 상황에서 등장한 것이 바로 Neural Processing Unit(NPU) 입니다. 이번 글에서는 NPU의 개념과 등장 배경, CPU 및 GPU와의 차이, 장단점을 분석하고, 특히 로보틱스 분야에서 NPU가 제공하는 혁신적 가능성에 대해 다루겠습니다.NPUNPU는 인공 신경망 연산에 최적화된 전용 프로세서로, 대규모 행렬 연산과 병렬 처리를 통해 AI 모델의 추론 속도를 크게 향상시킵니다. 기존의 CPU는 범용 처리를, GPU는 그래픽 및 대량의 병렬 연산을 처리하는 데 특화되어 있는 반면, NPU는 딥러닝 알고리즘의 특징인 곱셈-누적 연산을 매우 효율적으로 수행할 수 있도록 설계되었습니다. 예를 들어, 모바일 기기에서는 NPU 덕분에 얼굴 인식, 음성 명령 처리 등 복잡한 AI 기능을 실시간으로 수행할 수 있게 됐습니다.NPU는 AI 가속기(AI Accelerator), 딥러닝 프로세서(DLP, Deep Learning Processor), 딥러닝 가속기(DLA, Deep Learning Accelerator)와 같이 여러 이름이 있지만, 본 글에서는 NPU로 통일하여 표현하였습니다.CPU, GPU와의 비교그렇다면, 많은 분야에서 널리 사용되는 CPU와 GPU랑 비교하면 NPU는 어떤 차이점을 갖고 있을까요? NPU는 아키텍처 및 병렬성을 바탕으로 CPU, GPU와 차이점이 있어 전력 효율과 성능 측면에서 두각을 드러냅니다. 하지만, CPU 및 GPU와 비교하면 그 역사가 길지 않아 개발 생태계가 충분히 갖추어져 있지 않는 한계도 있습니다.아키텍처 및 병렬성NPU는 AI 최적화를 위해 CPU 및 GPU와 비교하여 다른 구조를 갖고 있다는 점이 가장 중요한 차이점입니다.CPU: 소수의 고성능 코어를 활용해 순차적 작업을 빠르게 처리하지만, 대규모 병렬 처리에는 한계가 있습니다.GPU: 수백에서 수천 개의 코어를 사용해 병렬 연산에 강점을 가지며, 주로 그래픽 처리 및 딥러닝 학습에 적합합니다.NPU: 신경망 연산에 특화된 구조를 도입해, 불필요한 연산을 최소화하고 메모리 접근을 최적화하여 낮은 전력 소모로 높은 연산 성능을 발휘합니다.전력 효율과 성능구조의 차이로 인해 NPU는 AI 처리에 더욱 효율적입니다. CPU와 GPU는 높은 연산 능력을 제공하지만, 특히 GPU는 전력 소모와 발열 문제가 발생할 수 있습니다. 반면 NPU는 필요한 연산만을 전용 회로로 수행하기 때문에 에너지 효율성이 뛰어나며, 로봇을 포함한 배터리 기반의 모바일 기기나 임베디드 시스템에서 실시간 AI 처리를 가능하게 합니다.개발 및 배포 환경CPU와 GPU는 오랜 기간 축적된 성숙한 소프트웨어 생태계를 갖추고 있어 개발자들이 쉽게 활용할 수 있습니다. 그러나 NPU는 제조사마다 지원하는 SDK나 도구가 달라, 개발 및 최적화 과정이 상대적으로 복잡할 수 있습니다. 최신 NPU 제품들은 이러한 문제를 개선하려는 노력이 계속되고 있으므로, 점차 더 나은 개발 환경이 구축되고 있습니다.NPU의 장단점NPU는 AI 연산에 최적화된 구조를 통해 더 빠르면서 효율적으로 연산을 수행하며 실시간성(저지연)을 포함한 여러 장점을 갖고 있습니다. 하지만, 충분히 성숙되지 않은 분야로 점차 완성도를 갖춰나가는 모습을 보이고 있기도 합니다.장점높은 AI 연산 성능: NPU는 인공 신경망 연산에 최적화되어 있어, CPU나 GPU보다 훨씬 빠른 추론 속도를 제공함우수한 전력 효율성: 전용 하드웨어 설계 덕분에 동일한 작업을 처리할 때 소비 전력이 적어, 배터리 구동 기기에서 유리함낮은 지연 시간: 클라우드에 의존하지 않고 기기 내에서 데이터를 처리함으로써, 네트워크 지연이 줄어들어 실시간 응답이 요구되는 애플리케이션에 적합함단점개발 복잡성: 제조사마다 상이한 도구와 SDK로 인해 개발 및 최적화 과정이 까다로울 수 있음범용성 제한: AI 추론에 특화되어 있어, 범용 연산이나 복잡한 제어 로직 처리에는 적합하지 않음비용 문제: 전용 NPU를 설계 및 제조하는 데 추가 비용이 발생할 수 있으며, 시스템 통합 시 호환성 문제도 고려해야 함적용 분야NPU는 이미 다양한 분야에서 활용되고 있으며, AI를 사용하는 다양한 분야에서 응용되고 있습니다. AI 기능에 대한 수요가 많이지면서 AI를 효율적으로 처리하는 NPU에 대한 수요와 관심도 점점 높아지는 추세입니다.모바일 및 IoT 디바이스: 스마트폰, 태블릿, 스마트 스피커 등에서 실시간 이미지 및 음성 인식을 구현함데이터 센터 및 클라우드: AI 추론 작업을 가속하여, 대규모 사용자 요청에 대한 응답 시간을 단축함자율주행 및 첨단 운전자 보조 시스템(ADAS): 센서 데이터를 빠르게 처리해 실시간으로 도로 상황을 판단하고 대응함산업용 및 보안 카메라: 현장에서 실시간으로 데이터를 분석하여, 빠른 대응과 프라이버시 보호를 지원함로보틱스에서의 NPU로보틱스 분야는 NPU의 실시간 데이터 처리 능력과 낮은 전력 소모 덕분에 큰 혜택을 보고 있습니다. 로봇은 주행, 물체 인식, 경로 계획 등 다양한 작업을 수행하는데, NPU가 탑재된 시스템은 다음과 같은 이점을 제공합니다:실시간 컴퓨터 비전: 카메라와 센서를 통해 들어오는 데이터를 즉각 분석하여 장애물을 피하거나 목표물을 식별함에너지 효율성: 배터리로 구동되는 로봇에서 NPU는 전력 소모를 줄여 운용 시간을 늘려 더 오래 서비스가 가능함현장 내 자율 판단: 네트워크 지연 없이 기기 자체에서 데이터 처리 및 판단을 내림으로써, 로봇이 독립적으로 작동하게 함개인정보 보호: 로봇에서 AI에 필요한 데이터를 처리해 민감 정보가 로봇 밖으로 보내지지 않음NPU의 미래AI 기술이 지속적으로 발전함에 따라 NPU의 역할은 더욱 중요해질 것입니다. 향후 NPU는 CPU와 GPU와의 이기종 통합 시스템의 핵심 부품으로 자리잡을 가능성이 높으며, 소형 임베디드 시스템에서도 AI
2025.05.01

좋아요

별로에요

Simplicity 4 : AI 아바타가 발표하는 온라인 컨퍼런스 제작기
Simplicity는 더 나은 사용자 경험을 만들기 위해, 토스가 치열하게 고민해온 과정을 나누는 디자인 컨퍼런스예요. 우리의 실험과 시도들이 사용자 경험을 고민하는 다른 디자이너들에게도 영감이 되기를 바라며 시작했어요.2021년부터 토스 디자인 챕터가 정기적으로 개최하고 있죠. 내용뿐 아니라 메시지를 어떻게 전달할지도 늘 중요하게 여겼기 때문에, 2023년부터는 유튜브 영상이 아닌 웹 기반 인터랙티브 사이트로 전환해 운영하고 있어요.디자인 챕터에게 심플리시티는 거의 종합 예술에 가까운 프로젝트예요. 운영, 디자인, 개발, 대본, 촬영, 녹음, 홍보까지—모든 과정이 고도화된 협업으로 이루어지죠.한 번으로 끝나는 행사가 아니라, 매년 반복되는 시즌제 컨퍼런스이기 때문에 ‘지속 가능성’이 정말 중요한 주제였어요. 매년 퀄리티와 지속 가능성 사이의 균형을 고민해야 했죠. 그 과정에서 많은 부분을 효율적으로 만들어왔지만, 촬영만큼은 늘 어려운 과제였어요.촬영을 하려면 대본이 완성되어야 하는데, 그 과정만 무려 두 달이 넘게 걸려요. 내부 피드백, 법무·보안·개인정보 검토를 거치며 수차례 수정되고, 최종적으로는 발표자 톤에 맞춰 구어체로 다시 다듬어야 하거든요. 대본이 늦어지면 촬영도 늦어지고, 전체 일정이 밀리기도 하죠.그런데 이게 끝이 아니에요. 혹여라도 대본상의 문제를 나중에 발견하게 되면, 다시 촬영을 해야 해야 하거든요. 촬영은 디자인 챕터의 전문 영역이 아니라 항상 외부 전문가나 다른 팀의 도움을 받아야 하는 구조적 제약도 있었죠.더 큰 문제는, 발표 경험이 익숙하지 않은 연사들에게도 부담이 컸다는 거예요. 실제로 워크숍에서 연사자들이 가장 꺼리는 일로 “발표하기, 촬영하기, 녹음하기”를 꼽았을 정도였죠. 컨퍼런스인데, 발표가 가장 하기 싫다니—아이러니하죠?그래서 자연스럽게 이런 질문이 생겼어요AI 아바타가 발표한다면그래서 이번 시즌에는 새로운 방식을 시도했어요. AI 아바타가 발표를 대신해보는 실험이었죠. 혹시 눈치채신 분 계실까요?간단할 거라고 생각했지만, 막상 해보니 쉽지만은 않았어요. AI 서비스들의 한국어 지원이 매끄럽지 않아서, 자연스러운 음성을 만들기가 어려웠거든요. 그래서 여러 번 테스트를 거쳐, 최적의 방법을 찾아냈어요.기존의 방식이라면 연사자는 발표 내용을 자연스럽게 말하기 위해 여러 번 연습하고, 촬영 중간에 한 번이라도 말을 더듬거나 버벅이면 처음부터 다시 찍어야 했어요. 하지만 이번에는 딱 한 번만 찍어도 AI 아바타를 만드는 데 충분했어요.촬영 자체도 훨씬 간편해졌어요. AI 아바타 생성을 위한 학습용 데이터로만 쓰이다 보니, 연사자가 회의실에 들어와서 나갈 때까지 30분이면 촬영이 끝났거든요.덕분에 연사자의 부담은 확 줄었고, 일정도 유연하게 조율할 수 있었어요. 심지어 오픈을 일주일 앞두고도 대본 수정이 가능한 정도였죠.촬영은 어떻게 했냐고요? 아마 들으면 깜짝 놀라실 거예요. 스튜디오도, 전문 장비도 없었어요. 회의실에서, 아이폰 전면 카메라로, 스노우 앱을 켜고 녹화했거든요. 말 그대로 셀카 찍듯 촬영했
5/1/2025

Simplicity 4 : AI 아바타가 발표하는 온라인 컨퍼런스 제작기
Simplicity는 더 나은 사용자 경험을 만들기 위해, 토스가 치열하게 고민해온 과정을 나누는 디자인 컨퍼런스예요. 우리의 실험과 시도들이 사용자 경험을 고민하는 다른 디자이너들에게도 영감이 되기를 바라며 시작했어요.2021년부터 토스 디자인 챕터가 정기적으로 개최하고 있죠. 내용뿐 아니라 메시지를 어떻게 전달할지도 늘 중요하게 여겼기 때문에, 2023년부터는 유튜브 영상이 아닌 웹 기반 인터랙티브 사이트로 전환해 운영하고 있어요.디자인 챕터에게 심플리시티는 거의 종합 예술에 가까운 프로젝트예요. 운영, 디자인, 개발, 대본, 촬영, 녹음, 홍보까지—모든 과정이 고도화된 협업으로 이루어지죠.한 번으로 끝나는 행사가 아니라, 매년 반복되는 시즌제 컨퍼런스이기 때문에 ‘지속 가능성’이 정말 중요한 주제였어요. 매년 퀄리티와 지속 가능성 사이의 균형을 고민해야 했죠. 그 과정에서 많은 부분을 효율적으로 만들어왔지만, 촬영만큼은 늘 어려운 과제였어요.촬영을 하려면 대본이 완성되어야 하는데, 그 과정만 무려 두 달이 넘게 걸려요. 내부 피드백, 법무·보안·개인정보 검토를 거치며 수차례 수정되고, 최종적으로는 발표자 톤에 맞춰 구어체로 다시 다듬어야 하거든요. 대본이 늦어지면 촬영도 늦어지고, 전체 일정이 밀리기도 하죠.그런데 이게 끝이 아니에요. 혹여라도 대본상의 문제를 나중에 발견하게 되면, 다시 촬영을 해야 해야 하거든요. 촬영은 디자인 챕터의 전문 영역이 아니라 항상 외부 전문가나 다른 팀의 도움을 받아야 하는 구조적 제약도 있었죠.더 큰 문제는, 발표 경험이 익숙하지 않은 연사들에게도 부담이 컸다는 거예요. 실제로 워크숍에서 연사자들이 가장 꺼리는 일로 “발표하기, 촬영하기, 녹음하기”를 꼽았을 정도였죠. 컨퍼런스인데, 발표가 가장 하기 싫다니—아이러니하죠?그래서 자연스럽게 이런 질문이 생겼어요AI 아바타가 발표한다면그래서 이번 시즌에는 새로운 방식을 시도했어요. AI 아바타가 발표를 대신해보는 실험이었죠. 혹시 눈치채신 분 계실까요?간단할 거라고 생각했지만, 막상 해보니 쉽지만은 않았어요. AI 서비스들의 한국어 지원이 매끄럽지 않아서, 자연스러운 음성을 만들기가 어려웠거든요. 그래서 여러 번 테스트를 거쳐, 최적의 방법을 찾아냈어요.기존의 방식이라면 연사자는 발표 내용을 자연스럽게 말하기 위해 여러 번 연습하고, 촬영 중간에 한 번이라도 말을 더듬거나 버벅이면 처음부터 다시 찍어야 했어요. 하지만 이번에는 딱 한 번만 찍어도 AI 아바타를 만드는 데 충분했어요.촬영 자체도 훨씬 간편해졌어요. AI 아바타 생성을 위한 학습용 데이터로만 쓰이다 보니, 연사자가 회의실에 들어와서 나갈 때까지 30분이면 촬영이 끝났거든요.덕분에 연사자의 부담은 확 줄었고, 일정도 유연하게 조율할 수 있었어요. 심지어 오픈을 일주일 앞두고도 대본 수정이 가능한 정도였죠.촬영은 어떻게 했냐고요? 아마 들으면 깜짝 놀라실 거예요. 스튜디오도, 전문 장비도 없었어요. 회의실에서, 아이폰 전면 카메라로, 스노우 앱을 켜고 녹화했거든요. 말 그대로 셀카 찍듯 촬영했
2025.05.01

좋아요

별로에요