logo
emoji
검색하기
어제 가장 많이 검색된 기술
emoji
가장 많이 읽은 글
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의 세 가지 모듈로 구성했습니다.
kotlin
redis
spring
5/24/2024
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의 세 가지 모듈로 구성했습니다.
2024.05.24
kotlin
redis
spring
emoji
좋아요
emoji
별로에요
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
kubernetes
5/24/2024
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
2024.05.24
kubernetes
emoji
좋아요
emoji
별로에요
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에서는 새로운 이메일 정책을 도입하게 되었습니다.오늘은 이 새로운 정책 중에서 가장 중요한 부분인 '도메인 인증'에 대해 알아보려고 합니다. 이메일이 우리 생활의 일부가 되면서, 그 중요성이 점점 더 커지고 있습니다. 그래서 이 글을 계기고 이메일 보안에 대해 깊이 있게 알아보려 합니다.이메일 인증 → 도메인 인증이메일을 보낼 때 보안 인증 유형은 이메일 인증과 도메인 인증이 있습니다.이메일 인증의 한계위조 가능성: 이메일 인증은 특정 이메일 주소의 소유권을 확인하는 과정입니다. 하지만, 이메일 주소는 위조가 가능하며, 악의적인 사용자가 정당한 이메일 주소를 사칭할 수 있습니다. 이는 보안 문제를 야
awsses
5/23/2024
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에서는 새로운 이메일 정책을 도입하게 되었습니다.오늘은 이 새로운 정책 중에서 가장 중요한 부분인 '도메인 인증'에 대해 알아보려고 합니다. 이메일이 우리 생활의 일부가 되면서, 그 중요성이 점점 더 커지고 있습니다. 그래서 이 글을 계기고 이메일 보안에 대해 깊이 있게 알아보려 합니다.이메일 인증 → 도메인 인증이메일을 보낼 때 보안 인증 유형은 이메일 인증과 도메인 인증이 있습니다.이메일 인증의 한계위조 가능성: 이메일 인증은 특정 이메일 주소의 소유권을 확인하는 과정입니다. 하지만, 이메일 주소는 위조가 가능하며, 악의적인 사용자가 정당한 이메일 주소를 사칭할 수 있습니다. 이는 보안 문제를 야
2024.05.23
awsses
emoji
좋아요
emoji
별로에요
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
5/23/2024
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
2024.05.23
emoji
좋아요
emoji
별로에요
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세기에 완공되었으며, 그 위에서 바라보는 경치는 정말 잊을 수 없을 만큼 아름답습니다. 보시는 것처럼 절벽 위에 자리 잡은 하얀색 건물들은 이 곳의 전통적인 아라비아풍 건축 양식을 그대로 보여줍니다. 시내 중심지와 강이 내려다보이는 이 곳에서 저는 무척이나 평화롭고 신비로운 분위기를 만끽할 수 있었습니다. 이번 여행은 저에게 정말 특별한 의미를 지니고 있었습니다. 론다에서 산책를 하며 느꼈던 그 놀라운 정적과 아름다운 경치는 제 일상의 스트레스를 모두 날려버릴 만큼 위로가 되었습니다. 또한 현지인들과의 따뜻한 교류를 통해 이곳의 문화와 역사에 대해 더욱 깊이 이해하게 되었습니다. 론다를 여행하며 느낀 점은, 세상은 정말 넓고 아직도 제가 경험하지 못한 아름다움이 많다는 것이었습니다. 여러분도 언젠가 꼭 이곳을 방문해보시
5/23/2024
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세기에 완공되었으며, 그 위에서 바라보는 경치는 정말 잊을 수 없을 만큼 아름답습니다. 보시는 것처럼 절벽 위에 자리 잡은 하얀색 건물들은 이 곳의 전통적인 아라비아풍 건축 양식을 그대로 보여줍니다. 시내 중심지와 강이 내려다보이는 이 곳에서 저는 무척이나 평화롭고 신비로운 분위기를 만끽할 수 있었습니다. 이번 여행은 저에게 정말 특별한 의미를 지니고 있었습니다. 론다에서 산책를 하며 느꼈던 그 놀라운 정적과 아름다운 경치는 제 일상의 스트레스를 모두 날려버릴 만큼 위로가 되었습니다. 또한 현지인들과의 따뜻한 교류를 통해 이곳의 문화와 역사에 대해 더욱 깊이 이해하게 되었습니다. 론다를 여행하며 느낀 점은, 세상은 정말 넓고 아직도 제가 경험하지 못한 아름다움이 많다는 것이었습니다. 여러분도 언젠가 꼭 이곳을 방문해보시
2024.05.23
emoji
좋아요
emoji
별로에요
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) 의 유사도는 커지도록,
5/23/2024
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) 의 유사도는 커지도록,
2024.05.23
emoji
좋아요
emoji
별로에요
logo
iOS 멀티 프레임워크 환경에서 리소스 효율적으로 관리하기
안녕하세요. 카카오페이 iOS 개발팀 데일입니다. 현재 카카오페이를 포함한 많은 회사에서 빌드 속도, 생산성 등 다양한 이유로 프로젝트를 멀티 모듈로 구성해서 앱을 개발하고 있는데요. 많은 모듈이 있는 큰 프로젝트를 운영하다 보면 여러 가지 문제를 마주합니다. 최근 카카오페이에서도 이러한 멀티 모듈 환경에서 늘어나는 앱 용량을 어떻게 관리할지 고민했습니다. 앱 용량에 영향을 끼치는 여러 요소가 있지만, 그중 리소스(이미지, 애니메이션, 컬러 등)는 앱 용량에 직접적인 영향을 주는데요. 많은 개발자들이 한 프로젝트에서 작업하는 만큼 그에 따라 리소스도 많이 추가하다보니 앱 용량이 점점 커졌습니다. 관리가 필요하다는 걸 더욱 느꼈습니다.결과적으로, 리소스 모듈을 만들어 리소스를 관리하도록 개선했는데요. 나아가 이를 자동화하여 편하게 리소스를 사용하게 되었습니다. 그 과정에 있었던 이야기를 공유드리고자 합니다.에피소드(갑자기 앱 용량이 10MB가 늘었다)여느 때와 같이 개발을 하는 중, 카카오페이의 특정 모듈 용량이 10MB가 늘어났다는 제보를 받았습니다.모듈 용량이 증가하면 앱 용량이 증가하는 데 직접적인 영향을 끼치는데요. 결국 다운로드 시간이 늘어나면서 사용자에게 부정적인 영향을 끼칠 수 있습니다.또한 카카오페이 핵심 기능(결제, 송금 등)은 공통 모듈 형태로 관리하고 있는데, 이 공통 모듈은 카카오페이뿐만 아니라, 카카오톡에 들어가는 페이 서비스, 카카오페이 사장님플러스까지 총 3개의 앱에 포함됩니다. 즉, 공통 모듈 용량이 증가하게 되면 여러 앱에 영향을 끼치게 되는데요. 때문에 카카오페이에서는 앱 용량을 굉장히 중요한 요소로 관리하고 있습니다. 위 사례에서 모듈 용량이 증가한 건 PNG에 적합한 이미지 리소스를 SVG로 추가하면서 이미지 사이즈가 비효율적으로 증가했기 때문입니다. PNG로 다시 치환하여 간단하게 해결했습니다.하지만 “이런 문제를 개발자가 개발하면서 발견할 수 없을까?”, “앱 내의 다양한 리소스(이미지, 애니메이션, 색상 등)를 사용하면서 발생하는 비효율을 줄일 수 없을까?” 고민하게 되었고, 이를 해소하기 위해 작업했던 내용들을 공유드리고자 합니다.앞서 설명드렸듯 카카오페이 프로젝트는 많은 모듈로 구성되어 있습니다. 각 팀에서 모듈을 개발하고 있고, 앱이 커짐에 따라 모듈 개수는 계속해서 많아지고 있습니다. 분리된 공간에서도 각 모듈로 여러 기능을 빠르게 만들고 있지만, 이러한 환경에서 리소스를 효율적으로 관리하기란 쉽지 않았습니다. 위 사례와 같이 큰 리소스를 갑작스럽게 추가했을 때 개발자가 변화를 매번 인지하기란 쉽지 않습니다. 결국 본의아니게 동일하거나 비슷한 이미지를 여러 벌 추가하고 있었습니다.이러한 문제를 해결하기 위해 리소스를 관리하는 리소스 모듈을 만들어, 프로젝트 내의 리소스를 한 곳에 모아 가시성을 높여 중복과 용량을 쉽게 파악하고자 했습니다. 하지만 리소스 모듈을 통합하는 작업은 프로젝트 전반적으로 큰 변화가 있는 작업이라 고민이었는데요. iOS 길드데이에서 동료들에게 이러한 고민을 공유하고,
5/23/2024
logo
iOS 멀티 프레임워크 환경에서 리소스 효율적으로 관리하기
안녕하세요. 카카오페이 iOS 개발팀 데일입니다. 현재 카카오페이를 포함한 많은 회사에서 빌드 속도, 생산성 등 다양한 이유로 프로젝트를 멀티 모듈로 구성해서 앱을 개발하고 있는데요. 많은 모듈이 있는 큰 프로젝트를 운영하다 보면 여러 가지 문제를 마주합니다. 최근 카카오페이에서도 이러한 멀티 모듈 환경에서 늘어나는 앱 용량을 어떻게 관리할지 고민했습니다. 앱 용량에 영향을 끼치는 여러 요소가 있지만, 그중 리소스(이미지, 애니메이션, 컬러 등)는 앱 용량에 직접적인 영향을 주는데요. 많은 개발자들이 한 프로젝트에서 작업하는 만큼 그에 따라 리소스도 많이 추가하다보니 앱 용량이 점점 커졌습니다. 관리가 필요하다는 걸 더욱 느꼈습니다.결과적으로, 리소스 모듈을 만들어 리소스를 관리하도록 개선했는데요. 나아가 이를 자동화하여 편하게 리소스를 사용하게 되었습니다. 그 과정에 있었던 이야기를 공유드리고자 합니다.에피소드(갑자기 앱 용량이 10MB가 늘었다)여느 때와 같이 개발을 하는 중, 카카오페이의 특정 모듈 용량이 10MB가 늘어났다는 제보를 받았습니다.모듈 용량이 증가하면 앱 용량이 증가하는 데 직접적인 영향을 끼치는데요. 결국 다운로드 시간이 늘어나면서 사용자에게 부정적인 영향을 끼칠 수 있습니다.또한 카카오페이 핵심 기능(결제, 송금 등)은 공통 모듈 형태로 관리하고 있는데, 이 공통 모듈은 카카오페이뿐만 아니라, 카카오톡에 들어가는 페이 서비스, 카카오페이 사장님플러스까지 총 3개의 앱에 포함됩니다. 즉, 공통 모듈 용량이 증가하게 되면 여러 앱에 영향을 끼치게 되는데요. 때문에 카카오페이에서는 앱 용량을 굉장히 중요한 요소로 관리하고 있습니다. 위 사례에서 모듈 용량이 증가한 건 PNG에 적합한 이미지 리소스를 SVG로 추가하면서 이미지 사이즈가 비효율적으로 증가했기 때문입니다. PNG로 다시 치환하여 간단하게 해결했습니다.하지만 “이런 문제를 개발자가 개발하면서 발견할 수 없을까?”, “앱 내의 다양한 리소스(이미지, 애니메이션, 색상 등)를 사용하면서 발생하는 비효율을 줄일 수 없을까?” 고민하게 되었고, 이를 해소하기 위해 작업했던 내용들을 공유드리고자 합니다.앞서 설명드렸듯 카카오페이 프로젝트는 많은 모듈로 구성되어 있습니다. 각 팀에서 모듈을 개발하고 있고, 앱이 커짐에 따라 모듈 개수는 계속해서 많아지고 있습니다. 분리된 공간에서도 각 모듈로 여러 기능을 빠르게 만들고 있지만, 이러한 환경에서 리소스를 효율적으로 관리하기란 쉽지 않았습니다. 위 사례와 같이 큰 리소스를 갑작스럽게 추가했을 때 개발자가 변화를 매번 인지하기란 쉽지 않습니다. 결국 본의아니게 동일하거나 비슷한 이미지를 여러 벌 추가하고 있었습니다.이러한 문제를 해결하기 위해 리소스를 관리하는 리소스 모듈을 만들어, 프로젝트 내의 리소스를 한 곳에 모아 가시성을 높여 중복과 용량을 쉽게 파악하고자 했습니다. 하지만 리소스 모듈을 통합하는 작업은 프로젝트 전반적으로 큰 변화가 있는 작업이라 고민이었는데요. iOS 길드데이에서 동료들에게 이러한 고민을 공유하고,
2024.05.23
emoji
좋아요
emoji
별로에요
logo
운송 관리 시스템(TMS)의 탄생부터 현장에서 사용하기까지
운송 관리 시스템(TMS)의 탄생부터 현장에서 사용하기까지지난 2023년 5월 우아한형제들의 새로운 중앙 물류기지인 인천기지가 오픈을 했습니다. 그리고 기존 위탁 운영 방식이 아닌 우아한청년들이 직운영 하는 방식으로 배차 관리를 하게 되었습니다. 이에 따라 센터 간 운송을 위한 배차 관리 시스템이 필요하게 되었습니다.• 우아한청년들 중앙물류기지 소개 글: 기지(wit)가 발휘되는 물류 기지(Base)💡 중앙물류기지란? 물류기지에서는 상온, 냉장, 냉동의 상품을 입고 받아 보관 및 관리하며, 각 피패킹센터로 상품을 공급합니다. 최고의 품질을 유지하면서도, 정확한 분류와 전달을 통해 피패킹센터가 언제나 고객 앞에 스탠드바이 할 수 있도록 지원합니다.💡 피패킹센터란?도심 곳곳에 위치하고 있는 피패킹센터(Picking & Packing Center)에서는 물류기지에서 상품을 받아 보관하다가 주문이 들어오면 즉시 정확하게 피킹 및 패킹(포장)하여 라이더가 배달을 할 수 있도록 준비합니다.인천기지 오픈에 맞추어 기본적인 배차 기능을 제공하는 신규 물류플랫폼 TMS를 오픈했습니다. 그런데 정작 현장에서는 TMS를 사용하지 않았습니다. (사용률 0%… 🥲) 처음에는 새로운 방식이 익숙하지 않아서 못 쓰고 계신다고만 생각했고, 몇 가지 현장 요구사항을 개선하고 나면 사용하실 것으로 기대했습니다. 하지만 시간이 지나도 이 상황은 개선되지 않았습니다. 이래선 안 되겠다 싶었던 저희는 근본 원인을 파악하기 위해 현장에 방문했습니다.2.1 안 쓰는 이유 첫 번째 : 현장 프로세스와의 괴리현장에 방문한 저희는 배차 담당자분들과의 인터뷰를 시작으로 이동 물량 카운팅 및 배차, 상차, 출차 과정을 관찰하였습니다. 그 결과 크게 세 가지 TMS를 사용하기 어려운 이유를 찾아냈습니다.• 예상 수량 기반 배차 생성• 실 수량과 괴리가 있는 Unit 기반 환산 방식으로 배차 생성• 다양한 차량유형 (차량톤수, 차폭 등)이 고려되지 않은 단일 유형의 배차 생성 및 물량 분배• 정보 수정의 유연성 부족• 계획과 실행의 프로세스가 분리되지 않음• 현장 Case를 적용하려면, 운영관리자 – 운송사 양측 승인과 변경이 필요한 상황이러한 현장 프로세스와의 괴리로 ‘바쁘게 움직이는 현장’에서 사용하는 데 무리가 있는 것을 확인하였습니다. 당시 현장에서는 엑셀을 활용하여 배차를 진행하고 있었습니다. 운송사와의 계약 구조(정규차와 용차 등)와 차량 유형별 적재 가능한 수량을 반영하여 고정 차량에 자동으로 이동 물량을 분배하고, 정보 수정이 유연한 엑셀의 특성을 활용해 배차 정보 변경 및 멀티 드롭(한 차량이 여러 목적지로 운송) 적용 등 현장의 다양한 케이스에 대응하고 있었습니다. 따라서 현장에서는 엑셀 대비 TMS를 사용할 필요성을 느끼기 어려운 상황이었습니다.현장에서 실상을 확인한 저희는 먼저 아래와 같이 방향성을 재수립 했습니다.• 현장 배차 프로세스에 맞는 신규 프로세스 수립• 현장에서 발생하는 다양한 상황에 유연하게 대응 가능한 구조 및 UX 디자인• 계약 정보를 바탕으로 운임
5/22/2024
logo
운송 관리 시스템(TMS)의 탄생부터 현장에서 사용하기까지
운송 관리 시스템(TMS)의 탄생부터 현장에서 사용하기까지지난 2023년 5월 우아한형제들의 새로운 중앙 물류기지인 인천기지가 오픈을 했습니다. 그리고 기존 위탁 운영 방식이 아닌 우아한청년들이 직운영 하는 방식으로 배차 관리를 하게 되었습니다. 이에 따라 센터 간 운송을 위한 배차 관리 시스템이 필요하게 되었습니다.• 우아한청년들 중앙물류기지 소개 글: 기지(wit)가 발휘되는 물류 기지(Base)💡 중앙물류기지란? 물류기지에서는 상온, 냉장, 냉동의 상품을 입고 받아 보관 및 관리하며, 각 피패킹센터로 상품을 공급합니다. 최고의 품질을 유지하면서도, 정확한 분류와 전달을 통해 피패킹센터가 언제나 고객 앞에 스탠드바이 할 수 있도록 지원합니다.💡 피패킹센터란?도심 곳곳에 위치하고 있는 피패킹센터(Picking & Packing Center)에서는 물류기지에서 상품을 받아 보관하다가 주문이 들어오면 즉시 정확하게 피킹 및 패킹(포장)하여 라이더가 배달을 할 수 있도록 준비합니다.인천기지 오픈에 맞추어 기본적인 배차 기능을 제공하는 신규 물류플랫폼 TMS를 오픈했습니다. 그런데 정작 현장에서는 TMS를 사용하지 않았습니다. (사용률 0%… 🥲) 처음에는 새로운 방식이 익숙하지 않아서 못 쓰고 계신다고만 생각했고, 몇 가지 현장 요구사항을 개선하고 나면 사용하실 것으로 기대했습니다. 하지만 시간이 지나도 이 상황은 개선되지 않았습니다. 이래선 안 되겠다 싶었던 저희는 근본 원인을 파악하기 위해 현장에 방문했습니다.2.1 안 쓰는 이유 첫 번째 : 현장 프로세스와의 괴리현장에 방문한 저희는 배차 담당자분들과의 인터뷰를 시작으로 이동 물량 카운팅 및 배차, 상차, 출차 과정을 관찰하였습니다. 그 결과 크게 세 가지 TMS를 사용하기 어려운 이유를 찾아냈습니다.• 예상 수량 기반 배차 생성• 실 수량과 괴리가 있는 Unit 기반 환산 방식으로 배차 생성• 다양한 차량유형 (차량톤수, 차폭 등)이 고려되지 않은 단일 유형의 배차 생성 및 물량 분배• 정보 수정의 유연성 부족• 계획과 실행의 프로세스가 분리되지 않음• 현장 Case를 적용하려면, 운영관리자 – 운송사 양측 승인과 변경이 필요한 상황이러한 현장 프로세스와의 괴리로 ‘바쁘게 움직이는 현장’에서 사용하는 데 무리가 있는 것을 확인하였습니다. 당시 현장에서는 엑셀을 활용하여 배차를 진행하고 있었습니다. 운송사와의 계약 구조(정규차와 용차 등)와 차량 유형별 적재 가능한 수량을 반영하여 고정 차량에 자동으로 이동 물량을 분배하고, 정보 수정이 유연한 엑셀의 특성을 활용해 배차 정보 변경 및 멀티 드롭(한 차량이 여러 목적지로 운송) 적용 등 현장의 다양한 케이스에 대응하고 있었습니다. 따라서 현장에서는 엑셀 대비 TMS를 사용할 필요성을 느끼기 어려운 상황이었습니다.현장에서 실상을 확인한 저희는 먼저 아래와 같이 방향성을 재수립 했습니다.• 현장 배차 프로세스에 맞는 신규 프로세스 수립• 현장에서 발생하는 다양한 상황에 유연하게 대응 가능한 구조 및 UX 디자인• 계약 정보를 바탕으로 운임
2024.05.22
emoji
좋아요
emoji
별로에요
logo
패키지 매니저의 과거, 토스의 선택, 그리고 미래
토스 기술 조직의 각 챕터는 라이트닝 토크에서 다양한 주제에 대한 인사이트와 아이디어를 자유롭게 공유합니다. 기록을 통해 생생한 라이트닝 토크 현장을 함께 느껴보세요!오늘 다룰 내용은, 많아요. 사실 이렇게 많을 줄 몰랐어요! 주제는 패키지 매니저 인데요. 어떤 기술을 왜 선택했는지 그 배경을 이해하려면 먼저 개념을 명확히 알아야 해요. 그래서 JavaScript 패키지 매니저가 무엇인지 먼저 다룬 뒤에, 패키지 매니저가 동작하는 세 가지 단계를 설명할게요. 그리고 npm, pnpm, 그리고 Yarn, 이 세 가지 패키지 매니저가 어떻게 다른지 서로 다른 패키지 매니저의 특징을 살펴보고, 마지막으로 토스는 왜 Yarn을 선택했고, 앞으로는 어떤 방향성이 될 것인지 소개하겠습니다.패키지 매니저의 정의부터 시작해보죠. 잘 아시는 분들도 많을 텐데요. JavaScript나 TypeScript를 사용하면 이렇게 나 구문을 사용해서 외부 의존성을 참조하잖아요. 그걸 올바르게 참조할 수 있도록 보장해주는 프로그램이라고 생각하시면 돼요.JavaScript 표준인 ECMAScript에 따르면, 원래는 정확한 절대 경로나 상대 경로를 통해서만 할 수 있어요. 실제로 Deno나 브라우저의 JavaScript 표준 문법을 보면 다 정확한 절대 경로를 사용하고 있죠. 하지만 실제로 이렇게 쓰지 않잖아요. 우리는 보통 이렇게 쓰고 싶어 하죠.하지만 이렇게 하면 문제가 생깁니다. 예를 들어, 가 정확히 어떤 버전인지, 이 어떤 버전인지 모호하다는 문제인데요. 예를 들면 React는 18.0.1일 수도, 18.3.1일 수도 있고, 최근에 나온 19 베타일 수도 있잖아요. @toss/utils도 버전이 많고, lodash 라이브러리도 마찬가지죠. 그러면 정확한 정보는 어디서 제공할까요? 우리는 소스 코드보다 상위 디렉토리인 파일에 명시해요.이렇게 명시된 의존성 정보를 바탕으로, 모든 소스 코드 파일이 특정 버전의 라이브러리를 사용할 수 있도록 보장합니다. 일반적으로 파일에 디펜던시를 명시하고, 혹은 을 하면, 해당 의존성의 명시된 버전을 설치하게 됩니다. 즉, 패키지 매니저가 앞서 이야기 한 모호한 버저닝 문제를 해결해주는 거예요.패키지 매니저의 정의를 이야기 해봤어요. 이렇게 보면 패키지 매니저가 생각보다 간단하게 느껴지는데요. 버저닝 문제를 해결하기 위해 실제 동작하는 방식을 살펴보면 꽤 복잡해요.다음은 패키지 매니저 중 하나인 Yarn을 터미널에 실행했을 때 볼 수 있는 화면인데요.Yarn을 포함한 패키지 매니저는 이렇게 ‘Resolution’, ‘Fetch’, ‘Link’ 세 단계로 동작해요. 각 단계를 알아볼게요.첫 번째는 Resolution 단계예요. 영어 뜻을 생각해보면 ‘문제를 해결하다’라고 이해할 수 있죠. 어떤 문제를 해결하는 지가 중요할 텐데요. 첫 번째 문제는 라이브러리를 정확한 버전으로 고정하는 문제예요. 패키지 매니저는 Resolution 단계에서 파일에 명시된 버전 범위에 따라 정확한 버전을 결정합니다. 예를 들어, “react: ^18.
javascript
nodejs
reactjs
5/22/2024
logo
패키지 매니저의 과거, 토스의 선택, 그리고 미래
토스 기술 조직의 각 챕터는 라이트닝 토크에서 다양한 주제에 대한 인사이트와 아이디어를 자유롭게 공유합니다. 기록을 통해 생생한 라이트닝 토크 현장을 함께 느껴보세요!오늘 다룰 내용은, 많아요. 사실 이렇게 많을 줄 몰랐어요! 주제는 패키지 매니저 인데요. 어떤 기술을 왜 선택했는지 그 배경을 이해하려면 먼저 개념을 명확히 알아야 해요. 그래서 JavaScript 패키지 매니저가 무엇인지 먼저 다룬 뒤에, 패키지 매니저가 동작하는 세 가지 단계를 설명할게요. 그리고 npm, pnpm, 그리고 Yarn, 이 세 가지 패키지 매니저가 어떻게 다른지 서로 다른 패키지 매니저의 특징을 살펴보고, 마지막으로 토스는 왜 Yarn을 선택했고, 앞으로는 어떤 방향성이 될 것인지 소개하겠습니다.패키지 매니저의 정의부터 시작해보죠. 잘 아시는 분들도 많을 텐데요. JavaScript나 TypeScript를 사용하면 이렇게 나 구문을 사용해서 외부 의존성을 참조하잖아요. 그걸 올바르게 참조할 수 있도록 보장해주는 프로그램이라고 생각하시면 돼요.JavaScript 표준인 ECMAScript에 따르면, 원래는 정확한 절대 경로나 상대 경로를 통해서만 할 수 있어요. 실제로 Deno나 브라우저의 JavaScript 표준 문법을 보면 다 정확한 절대 경로를 사용하고 있죠. 하지만 실제로 이렇게 쓰지 않잖아요. 우리는 보통 이렇게 쓰고 싶어 하죠.하지만 이렇게 하면 문제가 생깁니다. 예를 들어, 가 정확히 어떤 버전인지, 이 어떤 버전인지 모호하다는 문제인데요. 예를 들면 React는 18.0.1일 수도, 18.3.1일 수도 있고, 최근에 나온 19 베타일 수도 있잖아요. @toss/utils도 버전이 많고, lodash 라이브러리도 마찬가지죠. 그러면 정확한 정보는 어디서 제공할까요? 우리는 소스 코드보다 상위 디렉토리인 파일에 명시해요.이렇게 명시된 의존성 정보를 바탕으로, 모든 소스 코드 파일이 특정 버전의 라이브러리를 사용할 수 있도록 보장합니다. 일반적으로 파일에 디펜던시를 명시하고, 혹은 을 하면, 해당 의존성의 명시된 버전을 설치하게 됩니다. 즉, 패키지 매니저가 앞서 이야기 한 모호한 버저닝 문제를 해결해주는 거예요.패키지 매니저의 정의를 이야기 해봤어요. 이렇게 보면 패키지 매니저가 생각보다 간단하게 느껴지는데요. 버저닝 문제를 해결하기 위해 실제 동작하는 방식을 살펴보면 꽤 복잡해요.다음은 패키지 매니저 중 하나인 Yarn을 터미널에 실행했을 때 볼 수 있는 화면인데요.Yarn을 포함한 패키지 매니저는 이렇게 ‘Resolution’, ‘Fetch’, ‘Link’ 세 단계로 동작해요. 각 단계를 알아볼게요.첫 번째는 Resolution 단계예요. 영어 뜻을 생각해보면 ‘문제를 해결하다’라고 이해할 수 있죠. 어떤 문제를 해결하는 지가 중요할 텐데요. 첫 번째 문제는 라이브러리를 정확한 버전으로 고정하는 문제예요. 패키지 매니저는 Resolution 단계에서 파일에 명시된 버전 범위에 따라 정확한 버전을 결정합니다. 예를 들어, “react: ^18.
2024.05.22
javascript
nodejs
reactjs
emoji
좋아요
emoji
별로에요
logo
Java 를 아시면 Kotlin 을 배워 보세요
Kotlin 은 JVM 과 완벽하게 호환되는 언어 입니다.Java 와 100% 상호호환을 하는 것을 목표로 하는 Kotlin 은 Java 언어를 아시면 보다 쉬운 이해가 가능 합니다.Java 보다 더 간결한 언어를 사용할 수 있고 1급 함수를 지원하기 때문에 함수형 프로그래밍을 보다 적극적으로 사용할 수 있는 장점이 있습니다.또한 Google Android 공식언어로 Kotlin 이 추가되었고 이에 편승하여 많은 인기를 얻고 있습니다.2. Kotlin 은 언제, 어디서 탄생했을까요?Kotlin 은 2011년 경 부터 개발을 진행해서 2016년 2월 V 1.0 이 출시 되었습니다. (현재는 1.9.24 버전이 최신 입니다)Kotlin 은 만든 회사는 여러분들이 잘 아실 만한 JetBrain 입니다. (Intelli-J를 만든 회사죠)[JetBrain 사의 회사 로고]Kotlin 이란 이름은 JetBrain 의 개발센터가 있는 러시아의 상트페리트루르크에 있는 코틀린 섬에서 이름을 따왔다고 합니다.(참고로 JetBrain 은 체코의 회사 입니다). 우리는 언제쯤 "월미도", "제주도" 이런 프로그램을 만들 수 있을까요?[블로그 내용과 별 상관이 없는 코틀린 섬의 지도]Kotlin 은 Java 와 100% 호환을 목표로 하고 있습니다.그렇기에 기존 Java Library 를 그대로 사용할 수 있으며, 반대로 Java 에서도 Kotlin 을 사용할 수 있습니다.Kotlin 은 일반적으로 서버상의 코드(웹 애플리켕션의 Back-End), 안드로이드 디바이스에서 실행되는 모바일 애플리케이션에 사용할 수 있습니다.그리고 특이하게 자바 스크립트를 지원해서 브라우저나 Node 에서도 실행이 가능 합니다.Java 와 마찬가지로 컴파일에 타입을 검사하는 정적 타입을 지원합니다.하지만, Java 와 다른 점은 타입 추론 (type infernece) 를 통해서 변수의 타입을 생략 할 수도 있습니다Java에서도 Functional Interface 와 Lambda 를 통해 일부 함수형 프로그래밍을 지원하지만 Kotlin 에서는 보다 완벽하게 함수형 프로그래밍을 지원합니다.즉, 함수를 파라미터로 받거나 함수를 반환할 수 있습니다.컴파일러, 라이브러리 및 도구등이 모두 오픈 소스이며 Apache2 라이선스를 사용해서 무료료 사용할 수 있습니다.Intelli-J Commucation 버전 및 Ultimate(이건 구매해야 되죠) 지원이 가능합니다.Kotlin 에서는 val, var 라는 변수 타입을 지원합니다.먼저 val 은 value 의 약자이며 Java 의 final 변수와 동일합니다.(한번 값이 지정되면 변경 불가능)var 는 variable 의 약자이며 Java 의 final 이 아닌 변수와 동일합니다.(값 변경 가능)kotlin 에서는 언어적 특성상 변수를 가급적 val 로 선언하는 것을 권고하고 있습니다.변수명 뒤에 : 를 입력하고 타입명을 적어 주시면 됩니다.변수의 이름은 name 이고 타입은 String 입니다. (식의 마지막 ; 는 생략 가능합니다, 코드에서는 생략했지만 final 이기 때문에 ``값을 무조건 대입해줘야 합니다)"David" 은 명시적으로 타입이 String 이기 때문에 타입 생략이 가능 합니다.name을 윗줄의 코드에서 val 로 지정했기 때문에 다른 이름을 지정하면 컴파일 오류가 발생합니다.java 에서는 항상 매개변수를 사용하기전에 null 체크를 해줘야 합니다.Java8 이후부터는 Optional 이 도입되면서 null 체크에 보다 유연성이 생겼지만, 그래도 이 부분은 항시 신경을 써야 합니다.Kotlin 에서는 변수 선언시에 이 변수가 null 을 허용할 것인지, 안 할 것인지를 선언할 수 있습니다.변수의 이름은 age 이며 타입 뒤에 ? 를 표시해서 Null 이 들어올 수도 있습니다.**Safe call **: 와 같이 프로퍼티에 직접 접근할 경우 age 가 Null 이면 NPE(Null Point Exception)이 발생할 수 있씁니다.safe call 은 ? 를 사용해서 프로퍼티에 접근하며, 만약 프로퍼티가 null 일 경우에는 Null 을 반환해 줍니다. (null 이 아닐 경우에는 프로퍼티의 값을 반환하겠죠)Elvis 연산자 : Java 에서는 Ternary Expression 이 있습니다. ? : 를 사용해서 식을 값으로 표현할 수 있는데, Kotlin 에서는 Elvis 연산자를 사용해서 간단하게 표현이 가능합니다.Elvis 연산자는 좌항의 식이 null 을 반환하면 우항의 값을 반환하게 표현할 수 있습니다.return person?.age ?: throw IllegalArgumentException("나이가 null 입니다")위 예제에서는 Safe Call 을 사용해서 age가 Null 일 경우 null 을 만들어내고, 엘비스 연산자(?:) 의 좌항이 null 이 됐기 때문에 연산자의 우항인 IllegalArgumentException 이 발생합니다.참고로, Elvis 연산자는 엘비스 프레슬리의 머리모양을 따서 만들었다고 합니다.[왜 엘비스인지 아직도 이해가 안되는 그림]Kotlin 에서는 대부분의 문(statement)를 값으로 표현할 수 있는 표현식(statement) 로 간주합니다.그러다보니 Java 에서는 불가능했던 if 문을 표현식인 값으로 표현할 수 있습니다.(변수에 할당하거나 바로 리턴할 수 있습니다)위와 같은 코드로 if를 표현식으로 바로 리턴 할 수도 있습니다.그리고 자바의 switch 문과 비슷한 when 을 사용해서 조건 식을 보다 세밀하고 다양하게 표현할 수 있습니다.when 또한 표현식으로 간주되어 변수에 값을 할당할 수도 있고 바로 리턴을 할 수도 있습니다.when 으로 조건을 세분해서 String 으로 리턴 합니다. in 과 .. 을 사용해서 조건이 포함되는지를 표현하고 -> 사용해서 조건에 해당하는 값을 지정 합니다.대표적인 반복문인 for 언어를 살펴 보겠습니다. Java 에서는 로 조건문의 분기값을 지정하는데,Kotlin 에서는 when 에서 살펴봤던 in 과 .. 을 통해 증감을 표현합니다.숫자가 내려갈 경우에
java
kotlin
5/22/2024
logo
Java 를 아시면 Kotlin 을 배워 보세요
Kotlin 은 JVM 과 완벽하게 호환되는 언어 입니다.Java 와 100% 상호호환을 하는 것을 목표로 하는 Kotlin 은 Java 언어를 아시면 보다 쉬운 이해가 가능 합니다.Java 보다 더 간결한 언어를 사용할 수 있고 1급 함수를 지원하기 때문에 함수형 프로그래밍을 보다 적극적으로 사용할 수 있는 장점이 있습니다.또한 Google Android 공식언어로 Kotlin 이 추가되었고 이에 편승하여 많은 인기를 얻고 있습니다.2. Kotlin 은 언제, 어디서 탄생했을까요?Kotlin 은 2011년 경 부터 개발을 진행해서 2016년 2월 V 1.0 이 출시 되었습니다. (현재는 1.9.24 버전이 최신 입니다)Kotlin 은 만든 회사는 여러분들이 잘 아실 만한 JetBrain 입니다. (Intelli-J를 만든 회사죠)[JetBrain 사의 회사 로고]Kotlin 이란 이름은 JetBrain 의 개발센터가 있는 러시아의 상트페리트루르크에 있는 코틀린 섬에서 이름을 따왔다고 합니다.(참고로 JetBrain 은 체코의 회사 입니다). 우리는 언제쯤 "월미도", "제주도" 이런 프로그램을 만들 수 있을까요?[블로그 내용과 별 상관이 없는 코틀린 섬의 지도]Kotlin 은 Java 와 100% 호환을 목표로 하고 있습니다.그렇기에 기존 Java Library 를 그대로 사용할 수 있으며, 반대로 Java 에서도 Kotlin 을 사용할 수 있습니다.Kotlin 은 일반적으로 서버상의 코드(웹 애플리켕션의 Back-End), 안드로이드 디바이스에서 실행되는 모바일 애플리케이션에 사용할 수 있습니다.그리고 특이하게 자바 스크립트를 지원해서 브라우저나 Node 에서도 실행이 가능 합니다.Java 와 마찬가지로 컴파일에 타입을 검사하는 정적 타입을 지원합니다.하지만, Java 와 다른 점은 타입 추론 (type infernece) 를 통해서 변수의 타입을 생략 할 수도 있습니다Java에서도 Functional Interface 와 Lambda 를 통해 일부 함수형 프로그래밍을 지원하지만 Kotlin 에서는 보다 완벽하게 함수형 프로그래밍을 지원합니다.즉, 함수를 파라미터로 받거나 함수를 반환할 수 있습니다.컴파일러, 라이브러리 및 도구등이 모두 오픈 소스이며 Apache2 라이선스를 사용해서 무료료 사용할 수 있습니다.Intelli-J Commucation 버전 및 Ultimate(이건 구매해야 되죠) 지원이 가능합니다.Kotlin 에서는 val, var 라는 변수 타입을 지원합니다.먼저 val 은 value 의 약자이며 Java 의 final 변수와 동일합니다.(한번 값이 지정되면 변경 불가능)var 는 variable 의 약자이며 Java 의 final 이 아닌 변수와 동일합니다.(값 변경 가능)kotlin 에서는 언어적 특성상 변수를 가급적 val 로 선언하는 것을 권고하고 있습니다.변수명 뒤에 : 를 입력하고 타입명을 적어 주시면 됩니다.변수의 이름은 name 이고 타입은 String 입니다. (식의 마지막 ; 는 생략 가능합니다, 코드에서는 생략했지만 final 이기 때문에 ``값을 무조건 대입해줘야 합니다)"David" 은 명시적으로 타입이 String 이기 때문에 타입 생략이 가능 합니다.name을 윗줄의 코드에서 val 로 지정했기 때문에 다른 이름을 지정하면 컴파일 오류가 발생합니다.java 에서는 항상 매개변수를 사용하기전에 null 체크를 해줘야 합니다.Java8 이후부터는 Optional 이 도입되면서 null 체크에 보다 유연성이 생겼지만, 그래도 이 부분은 항시 신경을 써야 합니다.Kotlin 에서는 변수 선언시에 이 변수가 null 을 허용할 것인지, 안 할 것인지를 선언할 수 있습니다.변수의 이름은 age 이며 타입 뒤에 ? 를 표시해서 Null 이 들어올 수도 있습니다.**Safe call **: 와 같이 프로퍼티에 직접 접근할 경우 age 가 Null 이면 NPE(Null Point Exception)이 발생할 수 있씁니다.safe call 은 ? 를 사용해서 프로퍼티에 접근하며, 만약 프로퍼티가 null 일 경우에는 Null 을 반환해 줍니다. (null 이 아닐 경우에는 프로퍼티의 값을 반환하겠죠)Elvis 연산자 : Java 에서는 Ternary Expression 이 있습니다. ? : 를 사용해서 식을 값으로 표현할 수 있는데, Kotlin 에서는 Elvis 연산자를 사용해서 간단하게 표현이 가능합니다.Elvis 연산자는 좌항의 식이 null 을 반환하면 우항의 값을 반환하게 표현할 수 있습니다.return person?.age ?: throw IllegalArgumentException("나이가 null 입니다")위 예제에서는 Safe Call 을 사용해서 age가 Null 일 경우 null 을 만들어내고, 엘비스 연산자(?:) 의 좌항이 null 이 됐기 때문에 연산자의 우항인 IllegalArgumentException 이 발생합니다.참고로, Elvis 연산자는 엘비스 프레슬리의 머리모양을 따서 만들었다고 합니다.[왜 엘비스인지 아직도 이해가 안되는 그림]Kotlin 에서는 대부분의 문(statement)를 값으로 표현할 수 있는 표현식(statement) 로 간주합니다.그러다보니 Java 에서는 불가능했던 if 문을 표현식인 값으로 표현할 수 있습니다.(변수에 할당하거나 바로 리턴할 수 있습니다)위와 같은 코드로 if를 표현식으로 바로 리턴 할 수도 있습니다.그리고 자바의 switch 문과 비슷한 when 을 사용해서 조건 식을 보다 세밀하고 다양하게 표현할 수 있습니다.when 또한 표현식으로 간주되어 변수에 값을 할당할 수도 있고 바로 리턴을 할 수도 있습니다.when 으로 조건을 세분해서 String 으로 리턴 합니다. in 과 .. 을 사용해서 조건이 포함되는지를 표현하고 -> 사용해서 조건에 해당하는 값을 지정 합니다.대표적인 반복문인 for 언어를 살펴 보겠습니다. Java 에서는 로 조건문의 분기값을 지정하는데,Kotlin 에서는 when 에서 살펴봤던 in 과 .. 을 통해 증감을 표현합니다.숫자가 내려갈 경우에
2024.05.22
java
kotlin
emoji
좋아요
emoji
별로에요
Copyright © 2024. Codenary All Rights Reserved.