logo
기술 블로그
logo
Req-Saver로 캐시의 골칫거리 'Thundering Herd 문제' 쉽게 풀기!
안녕하세요. LINE+ Contents Service Engineering 조직에서 백엔드 개발을 맡고 있는 양강현, 이병찬입니다. 저희가 속해 있는 Contents Server Engineering에서는 Tech Group이라는 조직을 운영하고 있습니다. Tech Group은 여러 조직이 공통으로 직면한 문제를 해결하기 위해 활동하면서, 특히 대량의 트래픽을 효율적으로 처리하는 방안을 모색했습니다. 이 과정에서 캐싱 프로세스를 고도화하는 작업을 진행했고, 그 결과 'Req-Saver'라는 사내용 라이브 러리를 개발했습니다.이 글에서는 Req-Saver를 개발한 배경과 세부 기능을 상세히 소개하고자 합니다.일반적으로 애플리케이션이 캐시를 활용하는 방법보통 애플리케이션이 캐시를 이용하는 모습은 아래와 같습니다.클라이언트가 어떤 요청을 했을 때 그 요청에 맞는 내용이 캐시에 있으면 클라이언트는 바로 응답을 받습니다. 만약 캐시에 없다면 캐시 뒤에 위치한 백엔드 데이터 스토어(DB, 서버, 파일 등)에서 데이터를 가져온 후 캐시에 저장합니다(위 그림에서는 편의상 'MySQL'로 표현).이와 같은 구조에서 만약 N개의 클라이언트 요청이 들어왔다고 가정해 보겠습니다. 이때 캐시에 N개의 요청에 맞는 내용이 없으면 N개 요청 모두가 백엔드 데이터 스토어에 데이터를 요청하며, N개의 요청이 원하는 값이 같다고 해도 N번의 요청이 그대로 진행됩니다. 더불어 특별한 조치를 취하지 않는다면 백엔드 데이터 스토어에서 받은 데이터를 캐시에 N번 기록하는 작업도 진행됩니다. 이는 백엔드 스토어와 캐시 모두에 부하를 일으키는 원인이 되며, 이를 'Thundering Herd 문제'라고도 합니다.Req-Saver 개발은 바로 이 'Thundering Herd 문제'를 해결할 수 있는 방법을 모색하는 과정에서 시작됐습니다.Req-Saver의 아이디어이 문제는 백엔드 데이터 스토어를 향하는 클라이언트의 요청을 어떻게 하면 줄일 수 있을지가 관건이었고, 캐시 히트 여부에 따라 두 가지 아이디어를 적용할 수 있다고 생각했습니다.요청받은 데이터가 캐시에 존재하지 않을 때요청받은 데이터가 캐시에 존재하지 않아 백엔드 스토어에서 가져와 캐시에 적재해야 할 때, 애플리케이션 단에서 로컬 혹은 글로벌 락(lock)을 이용해 특정 요청만 백엔드 스토어로 보내고 나머지 요청은 락을 잡은 요청이 캐시에 데이터를 생성할 때까지 대기한다면 문제를 해결할 수 있습니다.요청받은 데이터가 캐시에 존재할 때요청받은 데이터가 캐시에 존재해 바로 클라이언트에게 응답하는 경우에도 미래를 위한 예방 조치를 할 수 있습니다. 예를 들어 조회하고자 하는 캐시의 TTL(time to live)이 10초이고 클라이언트가 해당 캐시를 조회할 때 TTL이 2~3초 정도 남은 시점이라면 캐시 만료를 기다리지 말고 바로 캐시 TTL을 갱신하는 것입니다. 이를 통해 일정한 트래픽이 들어온다는 전제하에 캐시가 만료되는 공백 시간 없이 마치 캐시가 연속적으로 존재하는 것과 같은 효과를 기대할 수 있습니다.위 내용 을 시간 그래프 형태로 비교하면 아래와 같습니다.각 아이디어를 어떻게 구현했는지 하나씩 살펴보겠습니다.요청받은 데이터가 캐시에 존재하지 않을 때이 경우에는 락(lock) 메커니즘을 적극 활용했습니다.락은 크게 로컬 락과 글로벌 락이 있는데요. 먼저 글로벌 락은 라이브러리 입장에서 개발자가 어떤 분산(distributed) 락을 사용할지 모르기 때문에 단순히 함수를 주입받는 방법으로 구현했습니다. 개발자가 Req-Saver의 인스턴스를 생성할 때 주입한 글로벌 락 함수를 애플리케이션 단에서 실행함으로써 글로벌 락을 취득했다고 인식한 후, 락을 취득한 요청이 대표로 데이터 취득 및 캐시 적재 작업을 진행합니다. 락을 취득하지 못한 요청들은 설정된 시간 동안 데이터가 캐시에 적재되기를 기다립니다.로컬 락은 세마포어(semaphore)를 적극 사용 중이며, 락 취득이 서버 인스턴스마다 진행된다는 점만 빼고 나머지 작동 방식은 위 그림과 같습니다.요청받은 데이터가 캐시에 존재할 때이 경우 역시 락 메커니즘을 적극적으로 활용하지만 전자와 살짝 다른 부분이 있습니다.우선 캐시에 데이터가 존재하기 때문에 락을 취득하지 못한 요청들이 캐시에 데이터가 적재되기를 기다릴 필요가 없습니다. 바로 클라이언트에게 응답하면 됩니다. 락을 취득한 요청 역시 바로 클라이언트에게 응답하며, 비동기로 캐시 갱신을 진행합니다.Req-Saver의 작동 원리를 순서도로 정리하면 아래와 같습니다.Req-Saver의 모듈은 크게 코어 모듈과 Spring 모듈, 지원 모듈로 나눌 수 있습니다. 각 모듈을 살펴보겠습니다.코어 모듈은 각 플랫폼에 맞게 사용할 수 있도록 아래 세 가지로 구성했습니다. 각 모듈에는 메인 메서드와 설정 파일이 포함돼 있습니다.• core: 일반적인 순차적 블로킹(sequencial-blocking) 메서드 환경 하에서의 코어 로직이 포함되어 있습니다.• core-reactor: Reactor 기반의 코어 로직이 포함되어 있습니다.• core-kotlin-coroutine: Kotlin Coroutine 기반의 코어 로직이 포함되어 있습니다.개발자는 각자의 환경에 맞는 코어 모듈을 로 가져와서 설정 작업을 진행한 후 인스턴스 생성과 동시에 메인 메서드를 실행해 Req-Saver의 기능을 사용할 수 있습니다.아래는 Req-Saver 인스턴스를 생성한 후 실제 캐시 데이터 취득 및 저장에 활용하는 샘플 코드입니다.Spring 프레임워크에서 아래와 같이 Bean으로 생성한 후 사용할 수도 있습니다.코어 모듈에서 더 나아가, Req-Saver를 Spring 프레임워크에서 흔히 사용하는 , 같은 애너테이션(annotation)처럼 편리하게 사용할 수 있도록 Spring 기반의 모듈도 구성했습니다.Spring 기반 모듈은 앞서 말씀드린 코어 모듈을 기반으로 , 라는 애너테이션으로 Req-Saver를 사용할 수 있도록 제공하며, 저희 개발 팀에서 주로 사용하는 기술 스택에 맞게 MVC와 WebFlux, WebFlux Kotlin Coroutine의 세 가지 모듈로 구성했습니다.
라인
·
오늘
logo
[K8S 보안] DevSecOps
Kubernetes 보안 연재를 마무리를 어떤 주제로 마무리해야 하나 고민 했다.사실 필자는 Policy란 조금은 모호한 주제를 선택했고 앞으로 기술할 내용도 Policy에 대한 것 이다.하지만 Policy는 너무 광의에 뜻 이지 않은가? 이글을 쓰는 의도를 좀더 분명하게 전달 할 수 있는 제목이 필요했다.고민 끝에 크게 내키지는 않지만 DevSecOps란 Keyword를 사용하기로 했다. (사실 필자는 세상의 Buzz word를 극도로 싫어한다.물론 Cooking을 위해서 필요한 일인 건 맞지만 코에 걸면 코걸이 귀에 걸면 귀걸이로 변질 되면서, 수많은 숙제만 양산하기에 때문이다.)여하튼, 마지막 주제는 DevSecOps다. 땅땅땅IT의 몰락과 우리의 밥벌이다소 과격한 표현이지만, DevOps 더 나아가서 DevSecOps 등이 중요해 지는 이유는 무엇일까?이런저런 이야기가 많지만 대 부분 DevOps던 Agile던 Micro Service던 지향점은 빠르고/자주 SW를 Update하는 것 이다.하지만 이는 빠르다는 기준이 1년에 한번인지 하루에 한번인지에 따라 다를 뿐이자, Hardware가 아닌 Software가 태생적으로 갖는 특징이지 않은가?즉 그닥 새로울 것이 없는 것 이다. 그렇다면 이 시기에 왜 이리 시끄러운 것 일까?지금 부터는 필자의 개인적인 생각을 풀어 보겠다. 개인적인 생각이니 만약 필자의 생각과 다르다고 생각되면 빠르게 지나쳐가시면 된다.주의!! 결코 두 회사에 대해서 좋고 나쁨을 이야기하는 것이 아니다. 워낙 대표적인 회사라서 언급한다.우리 모두가 알고 있듯이 Computer Science (잘 생각해 보면 이름도 요상하다 -_-;)에 Terminology라는게 명확히 정의하기가 어렵다.사실 SW는 특정 목적으로 개발되었지만 쓰는 사람이 그 용도를 변경 할 수도 있고, 과거 그 무언가에 영감을 받을 수 있었으나,결국 개발자 개인의 초자아(?)에 따라 우리가 생각한 것과는 조금씩 다른 그 무언가로 완성되고, 또 누군가의 손에 의해서 끊임없이 변화하기 때문이다.IT(Information Technology)란 과거 하버드 비즈니스 스쿨에서 처음 쓴 용어라고 위키피디아 어딘가에서 본 적이 있다.그 당시 IBM이 출퇴근 여부를 자동으로 체크하는 출퇴근 카드 시스템을 만들었다고 한다.이것을 본 똘똘이 선배님이 "아~~ 미래에는 Business의 본질에 사람은 집중하고, 그외 기타 운영을 도와주는 것 들이 많이 나올거야... 우린 그것을 정보기술 이라 부르자고" 라고 기술 했다.즉 IT의 기원, 본 글에서의 IT는 특정 사업을 지원하는 사업지원 시스템을 의미한다.과거 Fax / 인터폰 등이 대표적 이었고 최근에는 ERP, 근태관리 등이 대표적이다. 특히 컴퓨터/스마트폰의 보급으로 HW기반 정보기술은 SW기반 정보 기술로 바뀐지 오래다.따라서 많은 과거 선배 개발자들은 IBM과 같은 SW Solution 을 만드는 회사에서 물건을 만들고 납품을 하는 B2B 시장 SI 시장에서 많이 일했다.하지만 Google이 나타나면서 큰 변화가 생기게 되었다. 과거 SW는 B2B 혹은 Game용이 대부분 이었는데,Google / Facebook 과 같이 B2C를 대상으로 하는 서비스를 직접 구축하는 업체들이 대두되기 시작한 것이다.심지어 Apple이나 Tesla와 같이 HW를 파는 업체들의 경쟁력중 SW의 비중이 높아지면, 개발자들이 갈 업체가 확 늘어난 것 이다.여기서 현실적인 이야기를 해 보자. 사장이 아닌 개발자 입장에서 본인의 서비스를 직접개발하는 회사에서 일하고 싶은가? 아니면 SI를 하고 싶은가?MSA를 보면 필자가 느낀것은 이전 Micro Kernel과 Monolic Kernel의 싸움이 생각났다.또한 Distributed System과 Centralized System의 대결도 생각났다. RISC와 CISC도 생각나더라.이들의 공통점이 무엇일까? 필자는 모듈화를 통한 개별적 발전의 신속성과 집중화를 통한 최적화에 대한 것 이라 생각한다.지금 그렇다면 모듈화를 통해 개발적 발전(쉽게 말하면 난 모르겠고 내일만 정확히 하면되게 해죠.)이 중요해진 이유에 대해서 고찰해 봤다.Google과 같은 서비스업체의 등장으로 개발자들이 대거 이동했기 때문에, SI Biz에서는 개발자 모으기가 어려워졋기 때문이다.또한 Google과 같은 서비스 업체가 늘어나면 서비스업체간 개발자의 이동도 빈번하니 새로운 개발자 풀이 기존의 룰 및 Legacy에 종속되지 않게(즉, 러닝커브를 줄여 바로 투입할수 있게)하기 위해서 MSA는 매우 매력적이다. MSA의 육각형은 구현이 없으면 사랑은 러브와 같은 공허한 외침일 뿐이다.하지만 Kuberentes를 통해 정말 독립적이면서 저화로운 육갹형(오각형인가?)를 구현할 수 있게 되었다.여러팀이 다른 팀의 환경에 종속적이지 않으면서도 Common한 OAM 체계를 유지 할 수 있는 Kubernetes를 통해 MSA가 실현될 수 있었다.하지만 환경에 대한 제어가 안되니 여러 보안 이슈가 발생 할 수 있고 몇몇 빌런들이 자원을 독점하는 등, 나만 잘되면 그만 정신이 스믈스믈 자라나기 쉽다.따라서, MSA로 구성되는 시스템을 구축하는 팀간은 무엇가 약속이 필요하다. 보통 이 약속을 강제하고 수립하는 것을 Governance라 한다.그럼 이 Governance를 어떻게 실현 할 것 인가? 크게 두 방향이 있다.첫번째는 Code, 즉 행동강령이다.두번째는 Constraint, 즉 하지말 것을 정하는 것 이다.Governance를 자동으로 제어하려면 Constraint를 사용 할 수 밖에 없다.하지만 필자는 언어가 주는 무서움(?) 때문에 Policy란 표현을 쓴다.더 풀어 쓰자면 하지말아야할 것에 대한 정책이다.DevOps는 이런 저련 고차원적인 이야기가 있겠지만, 결국은 CI/CD 더 쉽게 말하면 Jenkins로 대표되는 SW의 설치 변경에 대한 자동화다.즉 Dev가 개발하고 Ops가 설치/운영하는 데, 이를 시스템화 한 것 이다.따라서 CI/CD pipeline도 기본적인 Build --> Deploy 사이에 여러가지 Test / Verification
SK텔레콤
·
오늘
logo
skirr한 AWS SES 구축기
안녕하세요, 올해 1월에 여기어때컴퍼니 SRE팀에 새롭게 합류하게 된 엘리입니다.올해 Yahoo와 Gmail에서 이메일과 관련된 새로운 정책을 발표하였습니다. 이에 따라 여기어때도 보다 안전하고 효율적인 메일박스 관리를 위해 관련 시스템 업데이트를 시행하였으며 해당 내용을 공유하고자 합니다.🚨메일박스에서 새로운 이메일 정책 발표🚨Yahoo와 Gmail에서 하루에 5000개 이상의 메일을 보내거나, 수신자 중 상당수가 메일을 스팸으로 표시하는 사람들을 대상으로 새로운 요구사항을 발표했습니다!더욱 엄격한 도메인 인증 준수수신자에게 대량 메일 구독을 쉽게 취소할 수 있는 방법 제공스팸 불만 비율 모니터링 및 0.3% 임곗값 미만으로 유지왜 이메일 정책이 진화할까요❓1️⃣ 발신자 인증을 통한 보안 강화본격적으로 글을 시작하기 전에 아이스 브레이킹 퀴즈를 하나 준비해봤습니다!!!example@gmail.comexampIe@gmail.com위 두 가지 이메일의 차이가 보이시나요?🧐....🫣....첫번째는 examp'l’e은 L의 소문자이고, 두번째 examp'I’e은 i의 대문자입니다.이와 같이 이메일 주소를 의도적으로 교묘하게 다르게 보냄으로써 사용자가 익숙한 메일을 무심코 클릭하게 만듭니다.이처럼 이메일 주소를 교묘하게 바꿔 사용자를 속이는 사이버 범죄가 급증하고 있습니다. 이는 사용자의 개인 정보를 빼앗거나, 악성 코드를 전송하는 등 다양한 방식의 범죄에 이용됩니다. 그렇기 때문에 “발신자 인증”은 원활한 이메일 송수신을 보장하고, 스팸이나 악성 코드를 방지하는 역할을 함으로써 사용자의 메일함을 안전하게 지켜줍니다. 그렇기 때문에 발신자 인증을 유심히 확인해야 하고, 발신자 인증을 통해 보안을 강화해야 합니다.2️⃣ 스팸 메일을 줄여 이메일 품질 향상두 번째는 '무분별한 광고 알림'으로 인한 이메일 품질의 저하입니다. 이메일은 우리의 일상 속에서 중요한 소통 도구로 작용하지만, 무차별적인 광고 알림 때문에 그 가치가 퇴색되고 있습니다. 무수히 쌓여있는 광고 메일들은 우리의 이메일을 '광고함'으로 전락시키며, 알림을 확인하는 것 자체가 부담이 되곤 합니다. 특히, 이런 광고 메일들의 구독 취소가 복잡하거나 불가능하다면 더욱 더 사용자들의 불만을 증폭시킵니다.스팸 메일이나 피싱 공격 등의 문제로 인해, 이메일 서비스 제공 업체인 Gmail과 Yahoo에서는 새로운 이메일 정책을 도입하게 되었습니다.오늘은 이 새로운 정책 중에서 가장 중요한 부분인 '도메인 인증'에 대해 알아보려고 합니다. 이메일이 우리 생활의 일부가 되면서, 그 중요성이 점점 더 커지고 있습니다. 그래서 이 글을 계기고 이메일 보안에 대해 깊이 있게 알아보려 합니다.이메일 인증 → 도메인 인증이메일을 보낼 때 보안 인증 유형은 이메일 인증과 도메인 인증이 있습니다.이메일 인증의 한계위조 가능성: 이메일 인증은 특정 이메일 주소의 소유권을 확인하는 과정입니다. 하지만, 이메일 주소는 위조가 가능하며, 악의적인 사용자가 정당한 이메일 주소를 사칭할 수 있습니다. 이는 보안 문제를 야
여기어때컴퍼니
·
2일 전
logo
Transpiler, “사용”말고 “활용”하기
안녕하세요. 토스뱅크 프론트엔드 개발자 강현구입니다.프론트엔드 개발자라면 transpiler를 한 번쯤은 들어보거나 사용해 봤을 거예요. 프론트엔드 생태계가 빠르게 발전하면서, transpiler는 애플리케이션을 만들고 배포하는 과정에서 빠질 수 없는 필수 요소가 되었어요.토스뱅크에서는 개발 경험을 향상하기 위해서 transpiler를 다양하게 활용하고 있는데요. 오늘은 transpiler로 로깅 과정을 개선한 사례를 소개 드릴게요.Transpiler는 코드를 변환하는 도구를 의미해요. JavaScript의 ES6 문법을 ES5 문법으로 변환하거나, React의 JSX 및 Typescript 코드를 브라우저가 이해할 수 있는 Javascript로 변환하는 도구에요. Transpiler 덕에 여러 브라우저 호환성을 유지하면서 다양한 문법을 활용할 수 있죠.대표적인 transpiler로는 Babel과 SWC가 있어요. 토스뱅크는 마이크로 프론트엔드 구조로 여러 서비스들의 각자 입맛에 맞게 Babel과 SWC를 사용하고 있어요.언급한 내용만으로도 transpiler가 개발자에게 가져다준 편의성은 굉장해요. 비즈니스 로직에만 집중할 수 있도록 코드를 작성하는데 편리함을 제공하고, 부가적인 작업은 알아서 처리해 주는 거죠. 매일 이렇게 “사용”만 하는 transpiler, 토스뱅크에서는 한 단계 더 잘 “활용”해 보기로 했어요.토스뱅크는 데이터 기반으로 의사결정이 이루어져요. 올바른 결정을 위해서 개인정보 등 민감 정보를 제외한 유저의 클릭, 페이지뷰 등 다양한 유저 활동에 대한 데이터를 수집하고 있어요. 이 과정을 이라고 해요. (유저의 데이터는 개인정보 처리 동의를 기반으로 수집하고 이용해요)로깅은 대부분의 서비스 코드에서 필요해요. 그래서 적절히 추상화하여 비즈니스 로직과 구분할 필요가 있어요. 전반적인 개발 경험을 해치지 않으면서 유저 데이터를 쌓기 위해서죠.또한 효율적으로 데이터를 수집하려면 화면에서 발생하는 모든 클릭 이벤트를 로깅하지 않고, 유의미한 정보만 로깅해야 해요. 예를 들어, 실제로 clickable한 버튼을 클릭했을 경우엔 로깅하고, clickable하지 않은 글자나 빈 화면을 클릭한 경우는 무시해야겠죠.여러분은 로깅을 어떻게 설계할 것 같나요? 크게는 아래 두 가지 방식이 있어요.• None 수동으로 로깅 함수를 실행하는 방식• None 추상화된 로깅 컴포넌트를 활용하는 방식이외에도 여러 다양하고 창의적인 방식들이 많을 것 같아요. 하지만 아무것도 하지 않아도 로깅이 알아서 되면 어떨까요? 토스뱅크에서는 원래 로깅을 어떻게 하고 있었고, transpiler로 로깅을 자동화한 방법을 알려드릴게요.기존에 토스뱅크 프론트엔드 챕터가 선택한 클릭 로깅 방식은 다음과 같아요. 이벤트 캡처링(window listen)과 data attribute 두 가지를 활용해서 로깅을 처리했어요.유저가 버튼을 클릭했을 때, click event를 캡처링을 통해 인지하고, 클릭 타깃에서 가장 가까운 속성을 지닌 DOM을 찾아요. 찾은 DOM의 t
비바리퍼블리카
·
2일 전
logo
GPT-4o vs Gemini의 멀티모달 LLM 글쓰기 능력 비교
최근 OpenAI에서 GPT-4o를 발표하면서 AI기술 발전 수준에 대해 전세계가 놀라고 있어요.영화 배우 스칼렛 요한슨의 목소리를 닮은 여성의 목소리와 다양한 어조를 흉내내며 영화속의 AI가 현실로 다가오고 있음을 체감하게 하고 있습니다.기술적인 진보에 대한 놀라움으로 이슈가 되었고, 또 허락 받지 않은 스칼렛 요한슨의 닮은 목소리를 사용해 개인 생체정보 사용도 이슈가 되었습니다.OpenAI가 스칼렛 요한슨에게 그녀의 목소리를 쓰려고 제안하였으나 거절 당하고 대신 비슷한 음성을 가진 여성의 목소리로 대체 했다는 후문이 있습니다.데모 영상 중에 GPT-4o가 그래프, 차트 등 여러 이미지와 음성 지시에 대해서도 상당히 띄어나게 응답할 수 있음을 보여 주었어요.과연 실제 사용가능 수준은 어떨까요? 이번 포스팅에서는 OpenAI와 Google의 멀티모달 기술 수준이 어느 정도인지 직접 코드로 구현하고 비교해 보고자 합니다.멀티모달 Input으로 간략한 지시 프롬트트와 이미지를 사용하려고 합니다. 우선 두 LLM에게 지시할 프롬프트를 블로그 포스트 용으로 비교적 간결하게 작성해 보시죠.다음은 GPT-4o와 Gemini vision API를 연동하여 블로그 글을 쓰는 가장 심플한 파이썬 코드를 작성해 봅니다.API 연동을 위한 필요한 모듈을 설치하고, max_tokens가 작으면 답변이 잘릴 수 있으니, max_tokens=2000으로 충분하게 설정하는 것이 좋습니다.이제 미드저니로 그린 그림을 가지고 테스트 해 봅니다.여러분, 오늘은 저의 특별한 여정을 소개해드리고자 합니다. 위 사진을 보면, 맑고 투명한 바닷물과 그 속에서 신나게 뛰어노는 아이들이 보입니다. 이 사진은 바로 제가 어린 시절 즐겨 찾았던 해변을 떠올리게 합니다. 그 해변은 언제나 나에게 자유와 행복을 선물해주었습니다. 맨발로 모래사장을 걷고, 파도가 부딪히는 소리를 듣고, 반짝이는 물 위를 달리는 순간들은 저에게 그 무엇과도 바꿀 수 없는 소중한 기억입니다. 그래서인지 어른이 된 지금도 가끔은 그곳을 찾게 됩니다. 어릴 적 저와 친구들은 끝없이 펼쳐진 수평선을 바라보며 새로운 꿈을 키웠습니다. 그때는 바다가 마치 끝없는 가능성을 상징하는 것 같았죠. 꿈은 저 먼 수평선 저편에 있는 보물처럼 느껴졌습니다. 행복했던 과거를 기반으로 저는 제 꿈을 향해 한 걸음씩 나아갈 수 있었습니다. 바다와 함께한 나의 여정은 그렇게 시작되었습니다. 매번 바다를 찾을 때면 마치 새로운 출발점에 선 기분이 듭니다. 바다가 주는 무한한 영감 속에서 저는 늘 새로운 에너지를 얻곤 합니다. 여러분도 바다와 함께한 특별한 기억을 가지고 계신가요? 그 기억 속에서 꿈과 희망을 찾으시길 바랍니다. 저처럼 바다의 무한한 매력 속에서 다시금 힘을 얻을 수 있을 것입니다.본인의 스타일은 아니지만 GPT4-o의 묘사력과 글솜씨는 제법입니다.API 연동을 위한 필요한 모듈을 설치하고, max_output_tokens=2000으로 답변이 모자라지 않도록 충분히 주었습니다.Gemini api의 차이점은 그림 입력시 url을 넣는 것이 아니고 파이썬 이미지 분석, 처리 모듈인 PIL을 사용해서 이미지를 열어서 입력해야 합니다.이 그림은 세 자매가 바다를 걷는 모습을 그린 것입니다. 바다는 푸른색 물결이 일렁이고, 하늘은 맑고 푸른색입니다. 해변은 모래사장으로, 자매들은 맨발로 모래사장을 걷고 있습니다. 자매들은 모두 긴 머리에, 핑크색과 흰색의 드레스를 입고 있습니다. 그들은 손을 잡고 걸으며, 바다의 아름다움을 즐기고 있습니다. 이 그림은 포르투갈의 도시인 카스카이스에서 그렸습니다. 카스카이스는 리스본에서 약 30km 떨어진 곳에 위치한 아름다운 해안 도시입니다. 카스카이스는 온화한 기후와 아름다운 해변으로 유명합니다. 많은 사람들이 휴양과 스포츠를 즐기기 위해 카스카이스를 찾습니다. 저는 카스카이스를 방문했을 때 이 그림을 그렸습니다. 저는 카스카이스의 아름다운 바다와 해변에 매료되었습니다. 저는 이 그림을 통해 카스카이스의 아름다움을 표현하고 싶었습니다. 저는 이 그림을 그리는 동안 많은 것을 느꼈습니다. 저는 카스카이스의 아름다움을 느꼈고, 세 자매의 행복을 느꼈습니다. 저는 또한 그림 을 그리는 재미를 느꼈습니다. 저는 이 그림을 통해 카스카이스의 아름다움을 전하고 싶습니다. 저는 또한 그림을 그리는 재미를 전하고 싶습니다. 저는 이 그림이 많은 사람들에게 행복을 가져다 주기를 바랍니다.전반적으로 디테일한 묘사가 괜찮습니다.그런데 카스카이스라는 지역에 가본적도 없고, 생성한 그림을 보고 비슷하게 생긴 지역인지 조차도 확인하기 어렵습니다.그래서 본인이 직접 방문해서 찍은 스페인 명소 사진들을 가지고 테스트 해 봅니다.이제 이미지를 바꾸어가며 글쓰기 능력을 비교해 봅니다.안녕하세요 여러분! 오늘은 제가 다녀온 멋진 여행지에 대해 여러분께 소개해 드리려고 합니다. 아래 사진은 제가 최근에 다녀온 스페인의 놀라운 관광지, 론다(Ronda)의 풍경입니다. 사진 속에 보이는 것은 론다의 상징인 누에보 다리(Puente Nuevo)입니다. 이 다리는 두 개의 거대한 절벽 사이에 걸쳐져 있으며, 높이 100 미터 이상으로 그 웅장함은 정말 압도적입니다. 이곳에 서서 다리를 바라보면 말 그대로 시간의 흐름이 느껴진다고 할 수 있어요. 다리는 18세기에 완공되었으며, 그 위에서 바라보는 경치는 정말 잊을 수 없을 만큼 아름답습니다. 보시는 것처럼 절벽 위에 자리 잡은 하얀색 건물들은 이 곳의 전통적인 아라비아풍 건축 양식을 그대로 보여줍니다. 시내 중심지와 강이 내려다보이는 이 곳에서 저는 무척이나 평화롭고 신비로운 분위기를 만끽할 수 있었습니다. 이번 여행은 저에게 정말 특별한 의미를 지니고 있었습니다. 론다에서 산책를 하며 느꼈던 그 놀라운 정적과 아름다운 경치는 제 일상의 스트레스를 모두 날려버릴 만큼 위로가 되었습니다. 또한 현지인들과의 따뜻한 교류를 통해 이곳의 문화와 역사에 대해 더욱 깊이 이해하게 되었습니다. 론다를 여행하며 느낀 점은, 세상은 정말 넓고 아직도 제가 경험하지 못한 아름다움이 많다는 것이었습니다. 여러분도 언젠가 꼭 이곳을 방문해보시
SK텔레콤
·
2일 전
logo
AI foundation 모델의 근간이 되었던 대조학습, 그 시작에는 metric learning이 있었다
최근에 LLM 모델이 트렌드를 이끌고 있는데요, 또 다른 트렌드로는 foundation model이 있습니다. (아래 뉴스기사 참고!)파운데이션 모델이란 무엇인가? | NVIDIA Blog그리고 그 파운데이션 모델에 근간이 되었던 contrastive learning을 알아보기 전에 metric learning에 대해 먼저 간단하게 알아보는 시간을 가지려고 합니다.Metric learning은 다양하게 사용되고 있으며 다음과 같은 application이 있습니다.우선 제목 그대로 metric 이란 무엇일까요? metric 이란 두 점 x와 y 간의 거리 함수를 의미합니다. 거리 함수를 만족하려면 다음과 같은 네 가지 조건을 만족해야 합니다!이러한 거리 함수를 바탕으로 metric learning은 고전 통계 method와 deep learning method로 나뉠 수 있습니다.고전 통계 method로는 유클리디안 distance와 마할라노비스 distance를 이용한 method들이 존재합니다.하지만 이미지 차원에서의 distance는 매우 직관적이지 못하며,pixel-wise euclidean distance는 차원 간의 독립성을 전제하에 수행하기 때문에 (LDA를 참고) 올바르지 못한 metric learning 일 수 있습니다.자 그럼 deep learning에서는 어떠한 방식으로 접근했을까요?저는 크게 softmax based approach와 contrastive learning based approach 이렇게 두 가지로 간추려서 말씀드리고자 합니다.이번엔 softmax based approach만 다뤄보도록 하겠습니다!단순 decision boundary를 구분하도록 학습된 초기 metric learning 입니다.초기 metric learning은 단순하게 softmax와 cross entropy로 multi-class classifier를 훈련시켜 metric learning을 시도했습니다.softmax 수식을 우선 분해해볼게요. (글씨가 너무 악필이네요 ㅠㅠ)여기서 f 는 learned feature vector이며, FC layer의 input이고 a는 FC의 output 입니다.W는 마지막으로 FC layer의 weight이며, W는 class j 의 linear classifier라고 해석할 수 있습니다.Softmax가 주로 사용되는 문제에서는 다음과 같은 모델 작동 순서가 주로 존재합니다.이때 FC layer는 linear classifier로서 decision boundary를 잡아주는 역할을 하게 됩니다.softmax로 학습했을 때의 CNN feature를 t-SNE로 visualize한 결과.따라서 다른 approach와 달리 positive와 negative에 대해서 distance를 학습하려고 하지는 않습니다.• None Liu et. al.는 class 별로 이렇게 겹치는 특징들이 왜 생기는지, class별로 feature의 분포를 어떻게해야 더 잘 모아줄지 고민했습니다. Liu et. al.는 CNN feature가 FC layer를 거쳐 softmax까지 오는 과정을 Fig.1 의 수식으로 이미 보여주었습니다!우리는 내적을 W^Tx 와 ||W|| ||x||cosθ 두 가지 꼴로 나타낼 수 있습니다.후자의 경우로 다시 FC layer의 수식을 전개하면,fj=||Wj|| ||xi|| cos(θj) where θj (0≤θj≤π) 이고, 여기서 softmax activation 까지 적용하면 다음과 같습니다.여기서 softmax function은 주로 Cross entropy loss를 이용하여 학습하기 때문에 단적인 예로 1번 class라면 [1,0], 2번 클래스라면 [0,1]이 나와야 합니다.따라서 W1와 W2 의 벡터는 각도를 중심으로 클래스 벡터끼리 더 모이는 쪽으로 학습됩니다.여기에 추가적으로 각도를 중심으로 양쪽으로 밀어내어 학습을 시키면 다음과 같은 t-SNE 결과를 보여줍니다.margin을 강하게 주어 학습할수록 더 뾰족한 형태의 t-SNE 결과를 보여줍니다.최종적으로 L-softmax는 클래스 별로 각을 벌려서 discriminative를 학습합니다.Liu et. al. 는 단순히 ||W|| 크기에 따라 적절한 decision boundary를 구분하는 게 아닌 오로지 “각도”로만 boundary를 나누고자 했습니다.따라서 mapping을 hypersphere의 껍질로 보내기 위하여 ||W||=1, bias=0 으로 고정하여 원점을 중심으로 하는 구를 가정합니다.일반적으로 class 1과 class 2의 decision boundary는 다음과 같다. 수식의 편의를 위하여 class 1으로 예측했다고 가정하해볼게요.최종적으로 L-softmax처럼 우리가 벌리고자 하는 class 별 margin을 대입하면 다음과 같은 결과를 얻을 수 있습니다.거의 다 왔습니다!이전 연구들은 weight를 normalize 했지만 Arcface는 weight 뿐만 아니라 input x에서도 normalize를 진행합니다.이 아이디어는 arcface에서 나온게 아닙니다 (자세한건 Cosface를 참고해보시길!!)W 만 normalize 한다면 cos(θ)는 차이가 너무 작은데 비슷한 L2 distance를 가지는 x1, x2 가 있다면 우리가 원하지 않는 결과를 가져올 수 있습니다.따라서 x에 대해서도 a값으로 scaling 하는 것으로 이러한 현상을 방지합니다.feature와 weight 둘 다 normalize를 진행하고 정말 “각도”로만 decision boundary를 구분합니다.학습된 embedding features는 결국 radius가 a인 hypersphere에 분산됩니다.본 논문의 저자는 ||xi||를 L2 norm한 이후에 s 로 다시 re-scale 합니다.해당 figure에서 arcface에 대한 모든 철학이 담겨있는데요. 차근차근 step을 밟아보겠습니다.step을 밟는데 어려움이 있을까봐 수식을 첨부하겠습니다.여기에 추가로 constant한 margin을 추가하면 끝.Wyi 과 fθ(Xi) 의 유사도는 커지도록,
SK텔레콤
·
2일 전
기술 블로그 더 보기
Copyright © 2024. Codenary All Rights Reserved.