logo
emoji
검색하기
어제 가장 많이 검색된 기술
emoji
가장 많이 읽은 글
logo
Qwen3 의 Hybrid thinking mode
2025년 4월 29일 새벽에 Alibaba의 Qwen3 가 릴리즈되었다.Technical report 가 공개되지 않고, 블로그로만 공개되었기 때문에 학습이 어떻게 이루어졌는지는 아주 제한적으로 공개되었다.모델은 총 6개로 MoE 모델 2개와 Dense 모델 6개로 구성되었다.MoE 모델은 235B (22B activate), 30B (3B activate), Dense 모델은 32B, 14B, 8B, 4B, 1.7B, 0.6B 의 사이즈다.블로그 글에 따르면 각각 가장 큰 모델만 학습한 뒤, strong-to-weak distillation 을 통해 나머지 모델들을 학습한 것으로 보인다.아마도 base model 들은 pruning 기법들을 통해서 사이즈를 줄인 것 같다. (예상컨데 절반정도씩 줄여나간 것이 아닐까 싶다)사실 technical report 가 공개되지 않아서 학습 방법에 대해서는 아직 확실하게 파악하기 어렵다.그러나 공개된 것 중에 흥미로운 부분이 있었는데, 바로 Hybrid Thinking mode 이라는 것이다.Qwen3 공식 블로그에 따르면 Qwen3 는 thinking, 그러니까 reasoning 이 필요한 어려운 문제나 정확도를 요구하는 task 를 해결할 때에는 test-time reasoning 을 사용하고,빠르게 답변이 필요한 경우에는 think 를 끄고 그냥 답변을 제공하도록 학습되었다.이는 Claude-sonnet-3.7 에서 처음으로 제공했던 방식인데, 내가 알기로 명시적으로 open-source 에서 이를 가능하게 한 것은 처음이다.그렇다면 어떻게 on/off 를 구현했는가? Qwen3 는 두 가지 방법으로 on/off 를 제어하고 있다.유저나 시스템 턴에 , 명령어를 명시적으로 사용하면 thinking 을 제어할 수 있다. 예시를 살펴보자.이에 대한 답변은그리고 옵션 사용한 경우에는이에 대한 답변은, 토큰을 사용하여 reasoning 을 하고, 최종 답변하는 것을 볼 수 있다.아마도 이는 학습 시 thinking 없는 데이터는 를, 있는 데이터는 을 사용하여 학습한 것으로 보인다.즉, 스위치 토큰을 학습에 사용하여, reasoning On/Off 를 제어하는 방법이라고 볼 수 있다.또 다른 방법은 이라는 파라미터를 사용하는 것이다. Qwen3 블로그를 보면 아래와 같은 방법이 나와 있다.과연 옵션을 주면 무엇이 달라지는 것일까?을 보면 Qwen3 의 chat_template 이 있다. 여기서 해당 옵션을 통해 달라지는 부분을 확인할 수 있다.즉 enable_thinking 이 false 인 경우 reasoning 이 없는 reasoning 파트를 assistant indicator 뒤에 강제로 붙여 넣어서, reasoning 이 없는 답변을 생성하는 것이다.이는 reasoning 이 assistant indicator 바로 뒤부터 시작한다는 점을 활용한 것인데, 개인적으로 굉장히 스마트하면서 강력한 방법이라고 생각한다.Qwen3 는 두 가지 방법으로 Hybrid thinking mode 를 구현하였다.첫 번째 방법인 , 명령어는 유저가 API 를 사용하거나 chat 서비스를 활용할 때 명시적으로 제어할 수 있는 방법이지만,학습을 통해 구현되는 것이기 때문에 실제로 를 사용하더라도 reasoning 을 할 가능성이 있다 (확률적으로는 낮겠지만, 어디까지나 가능성은 있다).반면 두 번째 방법인 은 빈 thinking 부분을 강제로 붙여버림으로써 reasoning 을 강력하게 꺼버리는 방법이다아무튼 두 방법 모두 아주 간단하면서도 스마트하게 hybrid think mode 를 구현하였다.이후 모델 학습에 참고해서 사용해 봐야겠다.
5/9/2025
logo
Qwen3 의 Hybrid thinking mode
2025년 4월 29일 새벽에 Alibaba의 Qwen3 가 릴리즈되었다.Technical report 가 공개되지 않고, 블로그로만 공개되었기 때문에 학습이 어떻게 이루어졌는지는 아주 제한적으로 공개되었다.모델은 총 6개로 MoE 모델 2개와 Dense 모델 6개로 구성되었다.MoE 모델은 235B (22B activate), 30B (3B activate), Dense 모델은 32B, 14B, 8B, 4B, 1.7B, 0.6B 의 사이즈다.블로그 글에 따르면 각각 가장 큰 모델만 학습한 뒤, strong-to-weak distillation 을 통해 나머지 모델들을 학습한 것으로 보인다.아마도 base model 들은 pruning 기법들을 통해서 사이즈를 줄인 것 같다. (예상컨데 절반정도씩 줄여나간 것이 아닐까 싶다)사실 technical report 가 공개되지 않아서 학습 방법에 대해서는 아직 확실하게 파악하기 어렵다.그러나 공개된 것 중에 흥미로운 부분이 있었는데, 바로 Hybrid Thinking mode 이라는 것이다.Qwen3 공식 블로그에 따르면 Qwen3 는 thinking, 그러니까 reasoning 이 필요한 어려운 문제나 정확도를 요구하는 task 를 해결할 때에는 test-time reasoning 을 사용하고,빠르게 답변이 필요한 경우에는 think 를 끄고 그냥 답변을 제공하도록 학습되었다.이는 Claude-sonnet-3.7 에서 처음으로 제공했던 방식인데, 내가 알기로 명시적으로 open-source 에서 이를 가능하게 한 것은 처음이다.그렇다면 어떻게 on/off 를 구현했는가? Qwen3 는 두 가지 방법으로 on/off 를 제어하고 있다.유저나 시스템 턴에 , 명령어를 명시적으로 사용하면 thinking 을 제어할 수 있다. 예시를 살펴보자.이에 대한 답변은그리고 옵션 사용한 경우에는이에 대한 답변은, 토큰을 사용하여 reasoning 을 하고, 최종 답변하는 것을 볼 수 있다.아마도 이는 학습 시 thinking 없는 데이터는 를, 있는 데이터는 을 사용하여 학습한 것으로 보인다.즉, 스위치 토큰을 학습에 사용하여, reasoning On/Off 를 제어하는 방법이라고 볼 수 있다.또 다른 방법은 이라는 파라미터를 사용하는 것이다. Qwen3 블로그를 보면 아래와 같은 방법이 나와 있다.과연 옵션을 주면 무엇이 달라지는 것일까?을 보면 Qwen3 의 chat_template 이 있다. 여기서 해당 옵션을 통해 달라지는 부분을 확인할 수 있다.즉 enable_thinking 이 false 인 경우 reasoning 이 없는 reasoning 파트를 assistant indicator 뒤에 강제로 붙여 넣어서, reasoning 이 없는 답변을 생성하는 것이다.이는 reasoning 이 assistant indicator 바로 뒤부터 시작한다는 점을 활용한 것인데, 개인적으로 굉장히 스마트하면서 강력한 방법이라고 생각한다.Qwen3 는 두 가지 방법으로 Hybrid thinking mode 를 구현하였다.첫 번째 방법인 , 명령어는 유저가 API 를 사용하거나 chat 서비스를 활용할 때 명시적으로 제어할 수 있는 방법이지만,학습을 통해 구현되는 것이기 때문에 실제로 를 사용하더라도 reasoning 을 할 가능성이 있다 (확률적으로는 낮겠지만, 어디까지나 가능성은 있다).반면 두 번째 방법인 은 빈 thinking 부분을 강제로 붙여버림으로써 reasoning 을 강력하게 꺼버리는 방법이다아무튼 두 방법 모두 아주 간단하면서도 스마트하게 hybrid think mode 를 구현하였다.이후 모델 학습에 참고해서 사용해 봐야겠다.
2025.05.09
emoji
좋아요
emoji
별로에요
logo
코드 품질 개선 기법 10편: 적절한 거리 유지에 신경 쓰자
안녕하세요. 커뮤니케이션 앱 LINE의 모바 일 클라이언트를 개발하고 있는 Ishikawa입니다.저희 회사는 높은 개발 생산성을 유지하기 위해 코드 품질 및 개발 문화 개선에 힘쓰고 있습니다. 이를 위해 다양한 노력을 하고 있는데요. 그중 하나가 Review Committee 활동입니다.Review Committee에서는 머지된 코드를 다시 리뷰해 리뷰어와 작성자에게 피드백을 주고, 리뷰하면서 얻은 지식과 인사이트를 Weekly Report라는 이름으로 매주 공유하고 있습니다. 이 Weekly Report 중 일반적으로 널리 적용할 수 있는 주제를 골라 블로그에 코드 품질 개선 기법 시리즈를 연재하고 있습니다.이번에 블로그로 공유할 Weekly Report의 제목은 '적절한 거리 유지에 신경 쓰자'입니다.정렬된 목록을 표시하는 UI를 구현한다고 가정해 봅시다. 이 목록 상단에는 의 총 개수를 표시하는 헤더가 있습니다. 다음은 목록 표시 예시입니다.목록 및 총 개수 표시에는 다음과 같은 사양이 있습니다.• 목록에 표시할 수 있는 개수는 처음 100개까지• 100 개를 초과하는 이 있는 경우 총 개수는 "100+"로 표시총 개수가 100을 초과할 때 표시 형식은 다음과 같습니다.이 사양을 구현하기 위해 모델 클래 스 과 및 를 다음과 같이 정의했습니다.한편 UI에서 총 개수를 표시하는 텍스트를 결정하는 로직은 개수가 를 초과하는지 아닌지에 따라 분기됩니다.이 코드에 문제가 있을까요?'+1'만큼의 거리를 유지하자코드를 여러 레이어나 컴포넌트로 나눌 때에는 '어떤 레이어나 컴포넌트가 어떤 정보를 가져야 하는지'를 고려해서 설계하는 것이 좋습니다. 하지만 위 코드는 UI와 리포지터리 레이어 간에 '암묵적인 정보'를 공유하고 있기 때문에 사양을 변경했을 때 버그가 발생하기 쉬운 구조입니다.구체적으로 살펴보겠습니다. 먼저 리포지터리 레이어는 UI의 세부 사항에 대해 알 필요가 없는데요. 라는 주석은 이에 반해 세부 사항을 알리고 있습니다.반대로 UI 측도 리포지터리 레 이어의 세부 사항에 의존하고 있습니다. UI 측에서 를 구하는 로직이 리포지터리 레이어의 ' 를 초과하는 이 있을 경우 보다 큰 목록을 반환한다'는 동작에 의존하고 있기 때문입니다.이 문제를 해결하기 위해서는 다음과 같이 '목록에 다 들어갈 수 없는 이 있는지'를 나타내는 속성을 에 추가하면 됩니다.이렇게 하면 리포지터리 레이어는 UI 세부 사항을 신경 쓰지 않고 모델 클래스의 인스턴스 생성에 집중할 수 있습니다.또한 UI 레이어는 더 이상 에 대한 정보가 없어도 됩니다.그런데 ITEM_LIST_MAX_COUNT는 리포지터리 레이어에 있어도 괜찮을까?관련 정보를 어디에 넣을지에 대해서는 몇 가지 선택지가 있습니다.예를 들어 비즈니스 로직 레이어를 마련하고 그곳에서 를 정의할 수 있습니다. 비즈니스 로직 레이어는 채택하는 아키텍처에 따라 도메인, 서비스, 유스 케이스 등 다양한 형태가 될 수 있습니다.만약 비즈니스 로직 레이어를 만드는 것이 과하다고 생각한다면 모델 클래스에 해당 정보를 넣는 것도 한 가지 방법입니다.다만 이 방법은 '알고리즘 -> 데이터 구조'라는 의존 관계의 방향이 모호해지기 때문에 주의해야 합니다. 특히 기능 고유의 로직을 범용적으로 사용되는 데이터 모델에 포함시키지 않도록 조심해야 합니다.
5/9/2025
logo
코드 품질 개선 기법 10편: 적절한 거리 유지에 신경 쓰자
안녕하세요. 커뮤니케이션 앱 LINE의 모바 일 클라이언트를 개발하고 있는 Ishikawa입니다.저희 회사는 높은 개발 생산성을 유지하기 위해 코드 품질 및 개발 문화 개선에 힘쓰고 있습니다. 이를 위해 다양한 노력을 하고 있는데요. 그중 하나가 Review Committee 활동입니다.Review Committee에서는 머지된 코드를 다시 리뷰해 리뷰어와 작성자에게 피드백을 주고, 리뷰하면서 얻은 지식과 인사이트를 Weekly Report라는 이름으로 매주 공유하고 있습니다. 이 Weekly Report 중 일반적으로 널리 적용할 수 있는 주제를 골라 블로그에 코드 품질 개선 기법 시리즈를 연재하고 있습니다.이번에 블로그로 공유할 Weekly Report의 제목은 '적절한 거리 유지에 신경 쓰자'입니다.정렬된 목록을 표시하는 UI를 구현한다고 가정해 봅시다. 이 목록 상단에는 의 총 개수를 표시하는 헤더가 있습니다. 다음은 목록 표시 예시입니다.목록 및 총 개수 표시에는 다음과 같은 사양이 있습니다.• 목록에 표시할 수 있는 개수는 처음 100개까지• 100 개를 초과하는 이 있는 경우 총 개수는 "100+"로 표시총 개수가 100을 초과할 때 표시 형식은 다음과 같습니다.이 사양을 구현하기 위해 모델 클래 스 과 및 를 다음과 같이 정의했습니다.한편 UI에서 총 개수를 표시하는 텍스트를 결정하는 로직은 개수가 를 초과하는지 아닌지에 따라 분기됩니다.이 코드에 문제가 있을까요?'+1'만큼의 거리를 유지하자코드를 여러 레이어나 컴포넌트로 나눌 때에는 '어떤 레이어나 컴포넌트가 어떤 정보를 가져야 하는지'를 고려해서 설계하는 것이 좋습니다. 하지만 위 코드는 UI와 리포지터리 레이어 간에 '암묵적인 정보'를 공유하고 있기 때문에 사양을 변경했을 때 버그가 발생하기 쉬운 구조입니다.구체적으로 살펴보겠습니다. 먼저 리포지터리 레이어는 UI의 세부 사항에 대해 알 필요가 없는데요. 라는 주석은 이에 반해 세부 사항을 알리고 있습니다.반대로 UI 측도 리포지터리 레 이어의 세부 사항에 의존하고 있습니다. UI 측에서 를 구하는 로직이 리포지터리 레이어의 ' 를 초과하는 이 있을 경우 보다 큰 목록을 반환한다'는 동작에 의존하고 있기 때문입니다.이 문제를 해결하기 위해서는 다음과 같이 '목록에 다 들어갈 수 없는 이 있는지'를 나타내는 속성을 에 추가하면 됩니다.이렇게 하면 리포지터리 레이어는 UI 세부 사항을 신경 쓰지 않고 모델 클래스의 인스턴스 생성에 집중할 수 있습니다.또한 UI 레이어는 더 이상 에 대한 정보가 없어도 됩니다.그런데 ITEM_LIST_MAX_COUNT는 리포지터리 레이어에 있어도 괜찮을까?관련 정보를 어디에 넣을지에 대해서는 몇 가지 선택지가 있습니다.예를 들어 비즈니스 로직 레이어를 마련하고 그곳에서 를 정의할 수 있습니다. 비즈니스 로직 레이어는 채택하는 아키텍처에 따라 도메인, 서비스, 유스 케이스 등 다양한 형태가 될 수 있습니다.만약 비즈니스 로직 레이어를 만드는 것이 과하다고 생각한다면 모델 클래스에 해당 정보를 넣는 것도 한 가지 방법입니다.다만 이 방법은 '알고리즘 -> 데이터 구조'라는 의존 관계의 방향이 모호해지기 때문에 주의해야 합니다. 특히 기능 고유의 로직을 범용적으로 사용되는 데이터 모델에 포함시키지 않도록 조심해야 합니다.
2025.05.09
emoji
좋아요
emoji
별로에요
logo
FE News 25년 5월 소식을 전해드립니다!
주요내용25년 5월 소식에서는 다음과 같은 유용한 정보들을 만나보실 수 있습니다.React Compiler RCuseMemo 없이도 성능 최적화를 자동으로 처리해주는 새로운 리액트 컴파일러가 드디어 RC 단계에 도달했다.proposal-record-tuple is withdrawn값 기반 데이터 구조 도입을 목표로 했던 R&T가 철회되고, 더 유연한 대안인 Composite 제안이 새롭게 부상 중이다.Features That Every JavaScript Developer Must Know in 2025알아두면 실무에서 바로 쓸 수 있는 JS 기능들을 사례와 함께 정리한다.LLM-first Web FrameworkLLM이 이해하고 생성하기 쉬운 웹 코드를 위해, 정적·동적 값을 동일하게 다루는 프레임워크를 Revolt 기반으로 설계한 사례를 소개한다.>> FE News 25년 5월 소식 보러가기 FE News란? 네이버 FE 엔지니어들이 엄선한 양질의 FE 및 주요한 기술 소식들을 큐레이션해 공유하는 것을 목표로 하며, 이를 통해 국내 개발자들에게 지식 공유에 대한 가치 인식과 성장에 도움을 주고자 하는 기술소식 공유 프로젝트 입니다. 매월 첫째 주 수요일, 월 1회 발행 되고 있으니 많은 관심 부탁드립니다. 구독하기
5/8/2025
logo
FE News 25년 5월 소식을 전해드립니다!
주요내용25년 5월 소식에서는 다음과 같은 유용한 정보들을 만나보실 수 있습니다.React Compiler RCuseMemo 없이도 성능 최적화를 자동으로 처리해주는 새로운 리액트 컴파일러가 드디어 RC 단계에 도달했다.proposal-record-tuple is withdrawn값 기반 데이터 구조 도입을 목표로 했던 R&T가 철회되고, 더 유연한 대안인 Composite 제안이 새롭게 부상 중이다.Features That Every JavaScript Developer Must Know in 2025알아두면 실무에서 바로 쓸 수 있는 JS 기능들을 사례와 함께 정리한다.LLM-first Web FrameworkLLM이 이해하고 생성하기 쉬운 웹 코드를 위해, 정적·동적 값을 동일하게 다루는 프레임워크를 Revolt 기반으로 설계한 사례를 소개한다.>> FE News 25년 5월 소식 보러가기 FE News란? 네이버 FE 엔지니어들이 엄선한 양질의 FE 및 주요한 기술 소식들을 큐레이션해 공유하는 것을 목표로 하며, 이를 통해 국내 개발자들에게 지식 공유에 대한 가치 인식과 성장에 도움을 주고자 하는 기술소식 공유 프로젝트 입니다. 매월 첫째 주 수요일, 월 1회 발행 되고 있으니 많은 관심 부탁드립니다. 구독하기
2025.05.08
emoji
좋아요
emoji
별로에요
logo
Reasoning 모델 기반의 AI 검색 고도화
안녕하세요. SK텔레콤에서 검색/추천 모델링을 담당하고 있는 김선겸입니다.오늘 Reasoning 모델 기반의 AI 검색 고도화의 주제로 이야기 해 보려고 합니다.AI 검색 이전에는 주로 키워드 매칭이나 임베딩 기반 벡터 유사도를 기반으로 Relevance Score가 높은 Top-N 결과를 사용자에게 제시하는 방식으로 정보를 제공해 왔습니다.이 접근 방식은 빠르고 효율적인 검색을 가능하게 했지만, 질문의 의도나 문맥에 대한 이해가 부족해 사용자가 직접 결과를 해석하고 선택해야 하는 한계를 지니고 있었습니다.특히 복잡한 정보의 연결이나 다단계 추론이 필요한 고차원 질의에서는 이러한 방식의 한계가 더욱 뚜렷하게 드러납니다.이러한 한계를 극복하고자 최근에는 Reasoning 능력을 내재한 대형 언어 모델이 검색 시스템에 통합되고 있습니다.단순히 관련 정보를 나열하는 데 그치지 않고, 사용자의 질문을 단계적으로 분석하고 논리적으로 사고하여최종 답변을 직접 도출하거나 보다 명확한 정보로 정리해 제시하는 형태로 진화하고 있는 것입니다.이번 글에서는 Reasoning 모델의 핵심 개념과 주요 특징을 살펴본 뒤, 대표적인 추론 방식인 Chain-of-Thought(CoT)의 활용법과 이를 기반으로 한 모델 학습 과정에 대해 소개합니다.또한 이러한 Reasoning 기반 언어 모델이 실제 SKT AI 검색 시스템과 어떻게 결합되어 고도화를 이끌고 있는지도 함께 살펴보겠습니다.전통적인 대형 언어 모델(LLM)들이 문맥을 기반으로 한 언어 생성 및 예측에 집중했던 것과 달리,Reasoning 모델은 문제 해결 과정에서 인간의 사고 과정을 모방하여, 더 깊고 체계적인 사고를 가능하게 합니다.Reasoning 모델의 핵심 개념과 특징에 대해 알아보도록 하겠습니다.• None• None CoT는 문제를 한 번에 해결하려고 시도하는 대신, 이를 여러 하위 단계로 세분화하여 단계별로 사고 과정을 전개해 나가는 방식입니다. 이 기법은 모델이 각 단계에서 중간 추론을 명시적으로 수행하게 유도함으로써, 복잡한 문제라도 보다 체계적이고 논리적으로 접근할 수 있도록 만듭니다. 결과적으로 CoT를 적용하면 모델이 인간처럼 "생각을 풀어가는 과정"을 모방하며, 최종 결론에 도달하는 과정을 투명하게 보여줄 수 있습니다.• None ToT는 사고 과정을 단일 경로로 제한하지 않고, 여러 가능한 추론 경로를 동시에 생성하여 탐색하는 접근 방식입니다. 문제 해결을 위해 다양한 가설이나 방법을 고려하고, 각각의 경로를 평가하면서 가장 합리적이고 타당한 답을 선택하는 전략을 취합니다. 이 과정에서 비효율적이거나 부정확한 경로는 가지치기(pruning)하고, 유망한 경로는 더욱 깊게 탐색해 나갑니다. ToT는 CoT보다 훨씬 더 복잡하고 다양한 가능성을 포괄할 수 있으며, 특히 경로 선택이나 탐색 최적화가 중요한 문제 상황에서 강력한 성능을 발휘합니다.• None• None Reasoning 모델은 복잡한 수학 문제, 논리적 추론, 코딩 문제처럼 단일 답변 생성만으로는 쉽게 해결할 수 없는 과제들에 대해 탁월한 성능을 발휘합니다. 이 모델은 문제를 해결하는 과정에서 단계별 사고 과정을 명시적으로 노출함으로써, 단순한 정답 예측을 넘어 보다 깊이 있고 신뢰성 있는 문제 해결을 가능하게 만듭니다. 특히 Reasoning 모델은 다음과 같은 주요 장점을 가지고 있습니다• None Reasoning 모델은 문제를 여러 단계로 분해하고 각 단계에서 검증 가능한 추론을 거치기 때문에, 전체적인 오답률이 크게 낮아집니다. 단순히 직관에 의존하는 답변보다, 체계적으로 축적된 추론을 기반으로 한 답변이기 때문에 정확성이 한층 강화됩니다.• None 모델이 사고 과정을 외부에 투명하게 드러내기 때문에, 사용자는 답변이 어떻게 도출되었는지 구체적인 설명을 확인할 수 있습니다. 이러한 해석 가능성은 특히 고신뢰가 요구되는 분야(예: 의료, 법률, 과학)에서 모델의 활용 가치를 크게 높여줍니다.• None Reasoning 모델은 문제 해결의 각 단계를 점검하는 구조를 가지고 있어, 중간 추론 과정에서 발생할 수 있는 오류나 비현실적인 답변 생성(일명 "환각(hallucination)" 현상)을 줄이는 데 매우 효과적입니다. 이를 통해 모델의 답변 신뢰성과 일관성이 한층 강화됩니다. 결국, Reasoning 모델은 단순 정답 생성 모델을 넘어, "왜"라는 질문에 답할 수 있는 설명력과, 복잡한 문제를 다루는 데 필요한 높은 정확도와 안정성을 함께 제공하는 방향으로 진화하고 있습니다.• None• None 대부분의 벤치마크 결과에서 DeepSeek-R1(Reasoning 모델)이 DeepSeek-V3(Non-Reasoning 모델) 대비 더 높은 성능을 보이는 것을 확인할 수 있습니다. 특히 AIME 2024, Codeforces, GPQA Diamond와 같은 벤치마크에서는 두 모델 간 성능 차이가 두드러지게 나타납니다. 이러한 결과는 수학, 과학, 프로그래밍처럼 추론이 요구되는 도메인에서 Reasoning 모델이 더욱 효과적임을 보여줍니다. 다만, 일부 벤치마크에서는 DeepSeek-R1의 성능이 더 높긴 하지만 그 차이가 크지 않은 경우도 관찰됩니다.• None 비용 효율성과 추론 속도 측면에서 우수한 GPT-4o mini와 GPT-o3-mini를 비교한 결과는 위와 같습니다. 두 모델은 아키텍처와 파라미터 규모에서 차이가 있기 때문에 절대적으로 공정한 비교는 어렵지만, Reasoning 특화 모델인 GPT-o3-mini는 전반적인 성능 면에서 우위를 보였습니다. 특히 수학, 논리, 코드 생성 등 고차원 추론이 요구되는 과제에서는 성능 격차가 더욱 명확하게 드러났습니다.• None GPT-4o mini의 상대적으로 낮은 성능을 고려하여, 동일 계열의 상위 모델인 GPT-4o와 성능을 비교해보았습니다. 그 결과, AIME 및 Codeforces와 같은 고난도 추론 중심의 벤치마크에서는 두 모델 간 성능 차이가 뚜렷하게 나타났으며, 반면 MMLU나 Simple QA처럼 비교적 단순한 언어 이해 과제에서는 GPT-4o mini가 오히려 더 우수한
5/8/2025
logo
Reasoning 모델 기반의 AI 검색 고도화
안녕하세요. SK텔레콤에서 검색/추천 모델링을 담당하고 있는 김선겸입니다.오늘 Reasoning 모델 기반의 AI 검색 고도화의 주제로 이야기 해 보려고 합니다.AI 검색 이전에는 주로 키워드 매칭이나 임베딩 기반 벡터 유사도를 기반으로 Relevance Score가 높은 Top-N 결과를 사용자에게 제시하는 방식으로 정보를 제공해 왔습니다.이 접근 방식은 빠르고 효율적인 검색을 가능하게 했지만, 질문의 의도나 문맥에 대한 이해가 부족해 사용자가 직접 결과를 해석하고 선택해야 하는 한계를 지니고 있었습니다.특히 복잡한 정보의 연결이나 다단계 추론이 필요한 고차원 질의에서는 이러한 방식의 한계가 더욱 뚜렷하게 드러납니다.이러한 한계를 극복하고자 최근에는 Reasoning 능력을 내재한 대형 언어 모델이 검색 시스템에 통합되고 있습니다.단순히 관련 정보를 나열하는 데 그치지 않고, 사용자의 질문을 단계적으로 분석하고 논리적으로 사고하여최종 답변을 직접 도출하거나 보다 명확한 정보로 정리해 제시하는 형태로 진화하고 있는 것입니다.이번 글에서는 Reasoning 모델의 핵심 개념과 주요 특징을 살펴본 뒤, 대표적인 추론 방식인 Chain-of-Thought(CoT)의 활용법과 이를 기반으로 한 모델 학습 과정에 대해 소개합니다.또한 이러한 Reasoning 기반 언어 모델이 실제 SKT AI 검색 시스템과 어떻게 결합되어 고도화를 이끌고 있는지도 함께 살펴보겠습니다.전통적인 대형 언어 모델(LLM)들이 문맥을 기반으로 한 언어 생성 및 예측에 집중했던 것과 달리,Reasoning 모델은 문제 해결 과정에서 인간의 사고 과정을 모방하여, 더 깊고 체계적인 사고를 가능하게 합니다.Reasoning 모델의 핵심 개념과 특징에 대해 알아보도록 하겠습니다.• None• None CoT는 문제를 한 번에 해결하려고 시도하는 대신, 이를 여러 하위 단계로 세분화하여 단계별로 사고 과정을 전개해 나가는 방식입니다. 이 기법은 모델이 각 단계에서 중간 추론을 명시적으로 수행하게 유도함으로써, 복잡한 문제라도 보다 체계적이고 논리적으로 접근할 수 있도록 만듭니다. 결과적으로 CoT를 적용하면 모델이 인간처럼 "생각을 풀어가는 과정"을 모방하며, 최종 결론에 도달하는 과정을 투명하게 보여줄 수 있습니다.• None ToT는 사고 과정을 단일 경로로 제한하지 않고, 여러 가능한 추론 경로를 동시에 생성하여 탐색하는 접근 방식입니다. 문제 해결을 위해 다양한 가설이나 방법을 고려하고, 각각의 경로를 평가하면서 가장 합리적이고 타당한 답을 선택하는 전략을 취합니다. 이 과정에서 비효율적이거나 부정확한 경로는 가지치기(pruning)하고, 유망한 경로는 더욱 깊게 탐색해 나갑니다. ToT는 CoT보다 훨씬 더 복잡하고 다양한 가능성을 포괄할 수 있으며, 특히 경로 선택이나 탐색 최적화가 중요한 문제 상황에서 강력한 성능을 발휘합니다.• None• None Reasoning 모델은 복잡한 수학 문제, 논리적 추론, 코딩 문제처럼 단일 답변 생성만으로는 쉽게 해결할 수 없는 과제들에 대해 탁월한 성능을 발휘합니다. 이 모델은 문제를 해결하는 과정에서 단계별 사고 과정을 명시적으로 노출함으로써, 단순한 정답 예측을 넘어 보다 깊이 있고 신뢰성 있는 문제 해결을 가능하게 만듭니다. 특히 Reasoning 모델은 다음과 같은 주요 장점을 가지고 있습니다• None Reasoning 모델은 문제를 여러 단계로 분해하고 각 단계에서 검증 가능한 추론을 거치기 때문에, 전체적인 오답률이 크게 낮아집니다. 단순히 직관에 의존하는 답변보다, 체계적으로 축적된 추론을 기반으로 한 답변이기 때문에 정확성이 한층 강화됩니다.• None 모델이 사고 과정을 외부에 투명하게 드러내기 때문에, 사용자는 답변이 어떻게 도출되었는지 구체적인 설명을 확인할 수 있습니다. 이러한 해석 가능성은 특히 고신뢰가 요구되는 분야(예: 의료, 법률, 과학)에서 모델의 활용 가치를 크게 높여줍니다.• None Reasoning 모델은 문제 해결의 각 단계를 점검하는 구조를 가지고 있어, 중간 추론 과정에서 발생할 수 있는 오류나 비현실적인 답변 생성(일명 "환각(hallucination)" 현상)을 줄이는 데 매우 효과적입니다. 이를 통해 모델의 답변 신뢰성과 일관성이 한층 강화됩니다. 결국, Reasoning 모델은 단순 정답 생성 모델을 넘어, "왜"라는 질문에 답할 수 있는 설명력과, 복잡한 문제를 다루는 데 필요한 높은 정확도와 안정성을 함께 제공하는 방향으로 진화하고 있습니다.• None• None 대부분의 벤치마크 결과에서 DeepSeek-R1(Reasoning 모델)이 DeepSeek-V3(Non-Reasoning 모델) 대비 더 높은 성능을 보이는 것을 확인할 수 있습니다. 특히 AIME 2024, Codeforces, GPQA Diamond와 같은 벤치마크에서는 두 모델 간 성능 차이가 두드러지게 나타납니다. 이러한 결과는 수학, 과학, 프로그래밍처럼 추론이 요구되는 도메인에서 Reasoning 모델이 더욱 효과적임을 보여줍니다. 다만, 일부 벤치마크에서는 DeepSeek-R1의 성능이 더 높긴 하지만 그 차이가 크지 않은 경우도 관찰됩니다.• None 비용 효율성과 추론 속도 측면에서 우수한 GPT-4o mini와 GPT-o3-mini를 비교한 결과는 위와 같습니다. 두 모델은 아키텍처와 파라미터 규모에서 차이가 있기 때문에 절대적으로 공정한 비교는 어렵지만, Reasoning 특화 모델인 GPT-o3-mini는 전반적인 성능 면에서 우위를 보였습니다. 특히 수학, 논리, 코드 생성 등 고차원 추론이 요구되는 과제에서는 성능 격차가 더욱 명확하게 드러났습니다.• None GPT-4o mini의 상대적으로 낮은 성능을 고려하여, 동일 계열의 상위 모델인 GPT-4o와 성능을 비교해보았습니다. 그 결과, AIME 및 Codeforces와 같은 고난도 추론 중심의 벤치마크에서는 두 모델 간 성능 차이가 뚜렷하게 나타났으며, 반면 MMLU나 Simple QA처럼 비교적 단순한 언어 이해 과제에서는 GPT-4o mini가 오히려 더 우수한
2025.05.08
emoji
좋아요
emoji
별로에요
logo
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
logo
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 자원의 최적화와 운영 비용의 효율적 관리가 가능합니다.
2025.05.07
grafana
kubernetes
prometheus
emoji
좋아요
emoji
별로에요
logo
내가 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
logo
내가 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와 같이 접근성이 좋은 곳에 외부 기고를 하겠습니다.
2025.05.07
junit
emoji
좋아요
emoji
별로에요
logo
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
logo
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)의 기본 형태입니다.  스푼봇에서
2025.05.07
spring
emoji
좋아요
emoji
별로에요
logo
소프트웨어 접근성과 한컴오피스
접근성은 모든 사람이 제품, 서비스, 환경을 동등하게 이용할 수 있도록 하는 개념입니다. 이는 경사로, 엘리베이터, 점자 표지판 등 물리적 접근성에서 시작해, 디지털 환경(웹 접근성, 소프트웨어 접근성, 전자 문서 접근성 등)에서의 제품 설계, 서비스 제공, 정보 전달 방식까지 다양한 영역으로 확장되었습니다.접근성의 핵심은 다양한 능력을 갖춘 사람들이 장벽 없이 독립적으로 참여할 수 있게 하는 것입니다.접근성의 대상은 장애인뿐만 아니라 고령자, 비장애인 등 모든 사용자를 포함합니다. 음성 안내나 시각 보조 도구가 필요한 전맹 혹은 저시력 시각 장애인, 자막이나 시각적 알림이 필요한 청각 장애인, 손쉽게 조작할 수 있어야 하는 뇌 병변 및 지체 장애인, 일시적인 장애를 겪고 있는 경우나 일반 사용자까지도 고려 대상입니다.웹 접근성(정보통신접근성)은 앞서 설명한 접근성의 개념을 웹 콘텐츠에 적용한 것입니다. 「지능정보화기본법」에 따라 장애인이나 고령자들이 웹 사이트에서 제공하는 정보를 비장애인과 동등하게 접근하고 이용할 수 있도록 보장하는 것을 의미하며, 웹 접근성 준수는 법적 의무 사항입니다. 국내의 웹 접근성 관련 법규와 지침들은 어떤 것들이 있는지 살펴보겠습니다.한국에서는 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
logo
소프트웨어 접근성과 한컴오피스
접근성은 모든 사람이 제품, 서비스, 환경을 동등하게 이용할 수 있도록 하는 개념입니다. 이는 경사로, 엘리베이터, 점자 표지판 등 물리적 접근성에서 시작해, 디지털 환경(웹 접근성, 소프트웨어 접근성, 전자 문서 접근성 등)에서의 제품 설계, 서비스 제공, 정보 전달 방식까지 다양한 영역으로 확장되었습니다.접근성의 핵심은 다양한 능력을 갖춘 사람들이 장벽 없이 독립적으로 참여할 수 있게 하는 것입니다.접근성의 대상은 장애인뿐만 아니라 고령자, 비장애인 등 모든 사용자를 포함합니다. 음성 안내나 시각 보조 도구가 필요한 전맹 혹은 저시력 시각 장애인, 자막이나 시각적 알림이 필요한 청각 장애인, 손쉽게 조작할 수 있어야 하는 뇌 병변 및 지체 장애인, 일시적인 장애를 겪고 있는 경우나 일반 사용자까지도 고려 대상입니다.웹 접근성(정보통신접근성)은 앞서 설명한 접근성의 개념을 웹 콘텐츠에 적용한 것입니다. 「지능정보화기본법」에 따라 장애인이나 고령자들이 웹 사이트에서 제공하는 정보를 비장애인과 동등하게 접근하고 이용할 수 있도록 보장하는 것을 의미하며, 웹 접근성 준수는 법적 의무 사항입니다. 국내의 웹 접근성 관련 법규와 지침들은 어떤 것들이 있는지 살펴보겠습니다.한국에서는 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
emoji
좋아요
emoji
별로에요
logo
무신사 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
logo
무신사 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
emoji
좋아요
emoji
별로에요
logo
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
logo
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
emoji
좋아요
emoji
별로에요
Copyright © 2025. Codenary All Rights Reserved.