안녕세계
스레드 로컬이란? 여러 스레드가 같은 인스턴스의 필드에 접근하면 최초 스레드가 보관한 데이터는 다른 스레드에 의해서 덮어 씌워질 수 있습니다. 예를 들어, ThreadA가 특정 인스턴스의 필드에 `userA`라는 값을 저장하고 이후 ThreadB가 동일한 인스턴스의 필드에 `userB`라는 값을 저장하면 ThreadA가 인스턴스 필드에 저장한 `userA` 값이 `userB` 값으로 덮어 씌워집니다. 이후 ThreadA가 인스턴스의 필드를 조회할 때 `userB`가 조회되면서 의도하지 않은 동작을 하게 됩니다. 이러한 문제점을 해결하기 위해서 스레드 로컬(Java에서는 java.lang.ThreadLocal 클래스를 제공)을 사용하는 것을 고려해볼 수 있습니다. 스레드 로컬(Thread Local)이란 ..
2023년 1월 29일부터 2023년 7월 16일까지 약 6개월 간의 글또 8기 활동을 마무리하며 4L 회고 글을 작성해 봅니다. 지난 글또 8기 다짐 글은 여기에서 확인하실 수 있습니다. Liked 글또 8기 활동을 하면서 좋았던 점은? 결과적으로 매달 글을 발행하게 되어서 좋았습니다. 글또 활동 없이 개인적으로 글을 작성하려고 했다면 아마도 매달 글을 발행하는 것은 쉽지 않았을 거로 생각합니다. 그래서 꾸준히 글을 발행했다는 결과가 글또 8기 활동하면서 가장 좋았습니다. 그리고 메모 형식의 글이 아닌 제가 아는 것을 읽는 이에게 공유하는 형식의 글을 쓸 수 있었던 것도 글또 멤버 중 누군가 제 글을 읽을 수 있다는 생각에 글을 작성할 때 좀 더 신경 썻던 것 같습니다. Lacked 글또 8기 활동을 ..
고차 함수란? 고차 함수는 다른 함수를 인자로 받거나 함수를 반환하는 함수를 의미합니다. 람다나 함수 참조를 인자로(argument)로 넘길 수 있으면 고차 함수이다. 예: 표준 라이브러리 함수인 filter는 술어 함수(predicate function)를 인자로 받으므로 고차 함수이다. 술어 함수란? 반환 값으로 진리 값(참/거짓)을 반환하는 함수 람다나 함수 참조를 반환하면 고차 함수이다. 함수 타입 람다를 인자로 받는 함수를 정의하기 위해서는 람다 인자의 타입을 선언하는 방법에 대해 먼저 알아야합니다. 코틀린의 타입 추론으로 인해 변수 타입을 지정하지 않아도 람다를 변수(variable)에 대입할 수 있으므로 다음과 같이 정의할 수 있습니다. val sum = { x: Int, y: Int -> ..
Delegation 이란? Delegation(위임)은 클래스나 프로퍼티의 기능을 다른 객체에 위임하는 디자인 패턴입니다. Kotlin에서는 보일러 플레이트 코드 없이 `by` 키워드를 사용해서 `Delegation Pattern`을 구현할 수 있는 방법을 지원합니다. 클래스 위임 클래스 위임은 특정 인스턴스의 메서드 호출시 해당 기능을 다른 클래스에게 위임합니다. 다음 예제는 `Child` 클래스의 `pay`를 호출하면 `Parent` 클래스의 `pay` 메서드를 실행합니다. 이때 `Child` 클래스 선언에 `by` 키워드를 사용했으며, `Parent` 클래스의 인스턴스를 생성자 파라미터로 전달합니다. 이제 `Child` 클래스가 `pay` 기능을 사용하면 `Parent` 클래스에게 위임하여 `pa..
확장 함수란? 확장 함수는 Kotlin 기능 중 하나로, 기존 클래스에 새로운 함수를 추가하는 것 입니다. 즉, 이미 존재하는 클래스에 대해 확장 함수를 정의하여 해당 클래스의 인스턴스에서 멤버 함수처럼 호출할 수 있습니다. 확장 함수는 기존 클래스의 내부에 접근하지 않고도 외부에서 확장 함수를 작성하여 사용할 수 있습니다. 이를 통해 기존 클래스의 기능을 확장하거나, 특정 작업을 수행하는 유틸리티 함수를 제공할 수 있습니다. 확장 함수는 점 표기법을 사용하여 호출되며, 호출 대상 객체는 `수신 객체(receiver object)`라고 불립니다. 확장 함수를 선언할 때는 해당 확장 함수가 적용될 클래스를 수신 객체 타입으로 지정하고 그 뒤에 확장 함수 이름을 지정합니다. 그럼 이제 확장 함수를 선언하고 ..
Kotlin을 시작한지 얼마되지 않았을 때 Kotlin 문법 중 `Scope Functions`의 차이점과 용도 구분이 어려웠습니다. 본 포스팅에서는 Kotlin 공식 문서에서 소개하고 있는 Scope Functions의 목적, 각 함수들의 차이점과 사용 사례를 알아봅니다. Scope Functions 란? Scope Functions는 Kotlin 표준 라이브러리로 객체의 문맥(context of an object) 안에서 코드 블럭을 실행하는 것이 목적인 함수들 입니다. 람다 표현식이 제공된 객체에서 Scope Function을 호출하면 임시 스코프가 생성되며, 임시 스코프에서는 이름 없이 객체에 접근할 수 있습니다. 이러한 함수들을 Scope Functions라고 부르며 `let`, `run`, ..
들어가기 전에 API 요청과 응답에는 entity를 사용하지 않고, API 스펙에 따라 별도의 DTO를 만드는 것을 권장합니다. 🙅♀️ 요청/응답에 entity를 사용하면? 특정 API 전용의 DTO가 아니기 때문에 어떤 요청이 넘어올지 알기 어렵습니다. entity 정의가 바뀌면 API 스펙이 변경되어 API가 깨집니다. 🙆♂️ 요청/응답에 DTO를 사용하면? entity와 presentation layer를 분리할 수 있습니다. entity는 DB에서 사용되는 데이터 구조를 정의하고 DB와 상호작용하는 클래스입니다. persentation layer는 클라이언트가 요청한 데이터를 받아 그 데이터를 가공하여 응답하는 역할을 합니다. 예제 entity 정의 @Entity @Table(name = "o..
그라파나와 로키 그리고 프롬테일 그라파나(Grafana) 그라파나는 오픈소스 데이터 시각화 및 분석 도구입니다. 그라파나는 다양한 데이터소스로부터 데이터를 가져와서 대시보드와 그래프 등으로 데이터를 시각화할 수 있으며 프로메테우스(Prometheus), 로키(Loki), 엘라스틱서치(ElasticSearch, ES) 등과 통합이 잘 되어 있습니다. 로키(Loki) 로키는 프로메테우스와 함께 사용하기 위해 개발된 시스템으로 프로메테우스와 마찬가지로 그라파나 랩스(Grafana Labs)에서 개발하고 있습니다. 프로메테우스는 수집된 메트릭을 저장하고 그래프로 시각화할 수 있도록 지원하는 시스템입니다. 하지만, 로그 데이터를 수집하고 검색하는 기능은 제공하지 않습니다. 이에 반해 로키는 프로메테우스의 기본 데..