Skip to content

Commit

Permalink
Copy files from TIL
Browse files Browse the repository at this point in the history
  • Loading branch information
rlaisqls committed Mar 2, 2024
1 parent 7e56c3d commit 04f557e
Show file tree
Hide file tree
Showing 678 changed files with 65,269 additions and 2 deletions.
6 changes: 4 additions & 2 deletions .github/workflows/copy-files-from-til.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,19 @@ jobs:
rm ${{ env.destination }}/README.md
rm -rf TIL
- name: Set current date as env
run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_ENV

- name: Commit and push
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: "Copy files from TIL"
commit_message: "${{ env.date }} TIL 문서 복사"
repository: .
branch: main
file_pattern: '.'
push_options: '--force'
commit_options: '--no-verify --signoff'
commit_user_name: rlaisqls
commit_user_email: rlaisqls@gmail.com
commit_author: rlaisqls <rlaisqls@gmail.com>
env:
GITHUB_TOKEN: ${{ secrets.PAT }}
19 changes: 19 additions & 0 deletions src/content/docs/TIL/개발/Apache/Spark.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
title: 'Spark'
lastUpdated: '2024-03-02'
---

Apache Spark는 빅 데이터 워크로드에 주로 사용되는 오픈 소스 분산 처리 시스템이다. Apache Spark는 빠른 성능을 위해 인 메모리 캐싱과 최적화된 실행을 사용하며, 일반 배치 처리, 스트리밍 분석, 기계 학습, 그래프 데이터베이스 및 임시 쿼리를 지원한다.

## 장점

- **빠른 성능:** Apache Spark는 방향성 비순환 그래프(DAG) 실행 엔진을 사용함으로써 데이터 변환에 대한 효율적인 쿼리 계획을 생성할 수 있다. 또한, Apache Spark는 입력, 출력 및 중간 데이터를 인 메모리에 RDD(Resilient Distributed Dataset)로 저장하므로, I/O 비용 없이 반복 또는 대화형 워크로드를 빠르게 처리하고 성능을 높일 수 있다.

- **애플리케이션을 신속하게 개발:** Apache Spark는 기본적으로 Java, Scala 및 Python 등 애플리케이션을 구축할 수 있는 다양한 언어를 제공한다. 또한, Spark SQL 모듈을 사용하여 SQL 또는 HiveQL 쿼리를 Apache Spark에 제출할 수 있다. 애플리케이션을 실행하는 것 외에도, Apache Spark API를 Python과 대화식으로 사용하거나 클러스터의 Apache Spark 셸에서 Scala를 직접 사용할 수 있다. Zeppelin을 사용하여 데이터 탐색과 시각화를 위한 대화형 협업 노트북을 생성할 수도 있다.

- **다양한 워크플로 생성:** Apache Spark에는 기계 학습(MLlib), 스트림 처리(Spark Streaming) 및 그래프 처리(GraphX)용 애플리케이션을 구축하는 데 도움이 되는 몇 가지 라이브러리가 포함되어 있다. 이러한 라이브러리는 Apache Spark 에코시스템과 긴밀하게 통합되며, 다양한 사용 사례를 해결하는 데 바로 활용할 수 있다.

---
참고
- https://spark.apache.org/
- https://cloud.google.com/learn/what-is-apache-spark?hl=ko
125 changes: 125 additions & 0 deletions src/content/docs/TIL/개발/CustomAnnotation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
---
title: 'CustomAnnotation'
lastUpdated: '2024-03-02'
---

개발시 프레임워크를 사용하다보면 여러 Annotation들을 볼 수 있다. (ex: `@NotNull`, `@Controller`, `@Data` 등)

이러한 어노테이션들은 라이브러리에 미리 정의되어있는 것인데, 우리가 직접 이 어노테이션을 생성하여 AOP로 기능을 부여해줄 수 있다.

## Annotation class 정의

Annotation을 정의하고 싶다면, `@interface`를 클래스 키위드 뒤에 붙이면 된다.

```java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String param() default "paramsPost.content";
Class<?> checkClazz() default ParamsPost.class;
}
```

코틀린에선 아래와 같이 작성할 수 있다.

```kotlin
@Target(AnnotationTarget.METHOD)
@Retention(AnnotationRetention.RUNTIME)
annotation class MyAnnotation() {
val param: String = "paramPost.content",
val checkClazz: KClass<*> = ParamsPost.class
}
```

## Annotation을 위한 Annotation

Annotation을 정의할떄, Annotation의 성질을 정해줄 수 있는 Annotation들에 대해 알아보자.

## `@Retention`

해당 Annotation의 정보를 어느 범위까지 유지할 것인지를 설정한다. 즉, Annotation을 언제까지 작동시킬 것인지를 정하는 것이다.

#### RetentionPolicy의 종류

- **SOURCE :** <br/>
Annotation을 사실상 주석처럼 사용하는 것이다. 컴파일러가 컴파일할때 해당 어노테이션의 메모리를 버린다.

- **CLASS** : <br/>
컴파일러가 컴파일에서는 Annotation의 메모리를 가져가지만 실질적으로 런타임시에는 사라지게된다. 런타임시에 사라진다는 것은 리플렉션으로 선언된 Annotation 데이터를 가져올 수 없다는 뜻이다. (Default). <br/>
Lombok의 `@Getter`, `@Setter`처럼 컴파일시 바이트코드를 생성한 후 사라지는 경우, 이 전략을 사용한다.

- **RUNTIME** : <br/>
Annotation을 런타임시에까지 사용할 수 있다. JVM이 자바 바이트코드가 담긴 class 파일에서 런타임환경을 구성하고 런타임을 종료할 때까지 메모리에 살아있다. <br/>
스프링에서 빈이나 Transaction 등록하는 것과 같은 동작은 모두 어플리케이션이 시작한 후에 실행되기 때문에, 그와 관련된 어노테이션은 이 전략을 사용한다.

```java
/**
* Contains the list of possible annotation's retentions.
*
* Determines how an annotation is stored in binary output.
*/
public enum class AnnotationRetention {
/** Annotation isn't stored in binary output */
SOURCE,
/** Annotation is stored in binary output, but invisible for reflection */
BINARY,
/** Annotation is stored in binary output and visible for reflection (default retention) */
RUNTIME
}
```

## `@Target`

해당 어노테이션이 사용되는 위치를 결정한다.

List로 여러가지를 선택할 수 있으며, 선언한 어노테이션이 이 어노테이션으로 명시하지 않은 곳에 붙어있을 경우 컴파일시 에러가 발생한다.

이름만 보면 이해할 수 있는 것들이 많기 때문에 설명은 생략하고 ENUM 파일을 읽어보자.

```java
public enum class AnnotationTarget {
/** Class, interface or object, annotation class is also included */
CLASS,
/** Annotation class only */
ANNOTATION_CLASS,
/** Generic type parameter */
TYPE_PARAMETER,
/** Property */
PROPERTY,
/** Field, including property's backing field */
FIELD,
/** Local variable */
LOCAL_VARIABLE,
/** Value parameter of a function or a constructor */
VALUE_PARAMETER,
/** Constructor only (primary or secondary) */
CONSTRUCTOR,
/** Function (constructors are not included) */
FUNCTION,
/** Property getter only */
PROPERTY_GETTER,
/** Property setter only */
PROPERTY_SETTER,
/** Type usage */
TYPE,
/** Any expression */
EXPRESSION,
/** File */
FILE,
/** Type alias */
@SinceKotlin("1.1")
TYPEALIAS
}
```

## `@Inherited`

어노테이션이 붙은 클래스 뿐만 아니라 그 클래스를 상속받은 하위 클래스까지 모두 전파하도록 하는 어노테이션이다.

## `@Repeatable`

어노테이션을 여러번 중복해서 붙여도 괜찮다는 의미이다.

## `@Documented`

JavaDoc 생성 시 Document에 포함되도록하는 어노테이션이다.
21 changes: 21 additions & 0 deletions src/content/docs/TIL/개발/FineGrained와 CoarseGrained.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
title: 'FineGrained와 CoarseGrained'
lastUpdated: '2023-12-11'
---
<img src="https://github.com/rlaisqls/TIL/assets/81006587/dbef4d66-8107-48e8-8767-5a65c7f8a637" height=300px>

Fine-grained는 사전적으로 "결이 고운", "미세한"이라는 의미를 가지고, Coarse-grained는 "결이 거친", "조잡한"의 의미를 가진다. Grain은 곡식 혹은 낱알을 뜻하는데, 알갱이가 거칠고 큼직큼직헌지, 곱고 세밀한지에 따라서 Coarse와 Fine으로 나누어 표현한다고 이해할 수 있다.

# Fine-Grained
- 하나의 작업을 작은 단위의 프로세스로 나눈 뒤, 다수의 호출을 통해, 작업 결과를 생성해내는 방식
- 예를 들어, `Do`라는 동작이 있다면 해당 함수를 `First_Do()`, `Second_Do()`로 나누어 작업 결과를 생성해냄
- 다양한 **"Flexible System"** 상에서 유용하게 쓰일 수 있음

# Coarse-Grained
- 하나의 작업을 큰 단위의 프로세스로 나눈 뒤, "Single Call" 을 통해, 작업 결과를 생성해내는 방식
- 예를 들어, `Do` 라는 동작이 있다면 단순히, `Do()`를 호출해 작업 결과를 생성해내는 방식
- **"Distributed System"** 상에서 유용하게 쓰일 수 있음

---
참고
- https://coderanch.com/t/99845/engineering/Coarse-grained-fine-grained-objects
73 changes: 73 additions & 0 deletions src/content/docs/TIL/개발/GTM.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
---
title: 'GTM'
lastUpdated: '2024-03-02'
---

- GTM은 ‘코드추적을 용이하게 해주는 도구이자 태그 관리 툴’이다.
- 기존에는 Google Analytics(GA), 페이스북 픽셀 등과 같은 트래킹 툴을 각각 설정해야 했다. 하지만 GTM은 트래킹을 위한 코드의 삽입, 수정, 삭제 모두를 효율적으로 관리할 수 있게 해준다.
- GTM 코드만 삽입하면, 새로운 마케팅 툴을 여러 개 추가하더라도 추가적인 코드작업 없이 손쉽게 설치 할 수 있다.

## 핵심 용어

<img width="471" alt="image" src="https://github.com/rlaisqls/TIL/assets/81006587/66772700-03d5-4615-9c97-94093404fe32">

### **태그**
- 데이터를 어디로 전달할 지를 정의한다.
- 데이터를 추적해 활용하는 트레이싱 툴을 등록하면 된다.

<img width="360" alt="image" src="https://github.com/rlaisqls/TIL/assets/81006587/a28cfeac-13f0-4d08-9348-55d5f17307e9">


### **트리거**

- 어떤 경우에 실행할 지를 정의한다. 트리거 조건을 충족했을 경우 데이터가 전송된다.
- 트리거 유형은 사용자의 창 로드, 클릭, 스크롤 등이 될 수 있다.

<img width="736" alt="image" src="https://github.com/rlaisqls/TIL/assets/81006587/60423552-404e-4a3d-bd8f-a91397acd0ab">

### **변수**

- 어떤 데이터, 값을 전달할 지를 정의한다.
- 태그 실행시마다 변경되는 값을 관리하는 데 사용된다.

<img width="436" alt="image" src="https://github.com/rlaisqls/TIL/assets/81006587/320189e8-a412-442d-bb29-3c8d34832f0a">

## 효과

1. 다양한 툴 삽입가능
- GTM은 우선 한 번 웹사이트에 심어 놓으면 개발자의 도움 없이도 다양한 툴을 테스트해볼 수 있다.
2. 다양한 데이터를 간단하게 사용
- GA에서 수집할 수 있는 데이터 외에 다른 데이터들이 궁금해질 때 GTM을 통해 간단히 수집할 수 있다.
3. 손쉽게 반복적인 TEST 가능
- GTM에서는 버전 관리 기능을 통해 새로운 데이터를 수집하거나 설치한 툴을 여러 번 테스트해볼 수 있고, 결과가 마음에 들지 않으면 이전으로 되돌릴 수도 있다. 즉, 원하는 정보를 얻기 위해 다양한 실험을 반복해볼 수 있다.

## 데이터 레이어

- 웹사이트에서 GTM 컨테이너로 정보를 전달할 때 사용되는 자바스크립트 개체를 데이터 레이어라고 부른다.
- 홈페이지와 GTM 간의 데이터 송수신을 위한 매개체라고 할 수 있다.

```js
// 초기화
window.dataLayer = window.dataLayer || [];

// 데이터 추가
window.dataLayer.push({
event: "이벤트명",
변수명1: "값1",
변수명2: "값2",
변수명3: "값3"
});
```

GTM에서는 데이터 레이어를 아래와 같은 절차로 처리한다.

1. GTM 컨테이너가 로드됨.
2. 데이터레이어 푸시 메시지 중 처음 수신한 메시지를 가장 먼저 처리함.
3. 수신한 메시지에 이벤트가 있을 경우 해당 이벤트를 트리거로 하는 모든 태그를 실행함.
4. 메시지 처리 및 태그 실행이 완료되면 다음 수신한 메시지를 한 번에 하나씩 처리함. (선입선출)

---
참고
- https://marketingplatform.google.com/intl/ko/about/tag-manager/
- https://support.google.com/tagmanager/answer/6164391?hl=ko
- https://developers.google.com/tag-platform/tag-manager/datalayer
69 changes: 69 additions & 0 deletions src/content/docs/TIL/개발/Gradle/DependencyHandler.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
title: 'DependencyHandler'
lastUpdated: '2024-03-02'
---

[DependencyHandler](https://docs.gradle.org/current/javadoc/org/gradle/api/artifacts/dsl/DependencyHandler.html)는 Gradle의 종속성(Dependencies)을 생성해주는 인터페이스이다.

```kotlin
public interface DependencyHandler extends ExtensionAware {

@Nullable
Dependency add(String configurationName, Object dependencyNotation);

Dependency add(String configurationName, Object dependencyNotation, Closure configureClosure);

<T, U extends ExternalModuleDependency> void addProvider(String configurationName, Provider<T> dependencyNotation, Action<? super U> configuration);

<T> void addProvider(String configurationName, Provider<T> dependencyNotation);

<T, U extends ExternalModuleDependency> void addProviderConvertible(String configurationName, ProviderConvertible<T> dependencyNotation, Action<? super U> configuration);
...
}
```

그중 Dependencies를 생성할때 일반적으로 쓰이는 것은 맨 위에 있는 `add` 메서드이다. dependencies 부분에 implement를 추가하면 저 메서드로 자동으로 연결되어서 실행된다.

(kotlinDSL을 사용하면 아래와 같은 코드로 명시적으로 이어주는 것 같다.)

```kotlin
fun DependencyHandler.`implementation`(dependencyNotation: Any): Dependency? =
add("implementation", dependencyNotation)
```

dependencies에서 그냥 add 메서드를 바로 실행해줘도 종속성이 정상적으로 등록된다.

```kotlin
dependencies {
add("implementation", "org.jetbrains.kotlin:kotlin-reflect")
}
```

---

그리고 신기하게도

```kotlin
fun DependencyHandler.implementationDependencies(libraries: List<Pair<String, ImplementationType>>) {
libraries.forEach { (dependency, type) ->
add(type.originalName, dependency)
}
}
```

이렇게 코드를 작성하면

```kotlin
dependencies {
implementationDependencies(
listOf(
"org.jetbrains.kotlin:kotlin-reflect" to IMPLEMENTATION,
"org.jetbrains.kotlin:kotlin-stdlib-jdk8" to IMPLEMENTATION
)
)
}
```

이런식으로 호출할 수가 있는데, 이를 이용하여 아래 링크의 코드와 같이 buildSrc를 정의할 수도 있다.

https://github.com/rlaisqls/HelloWorld/tree/master/buildSrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
title: 'Git action gradle caching'
lastUpdated: '2024-03-02'
---

Gradle은 빌드할때 의존성 패키지들을 모두 다운받는다. 이때 Gradle은 빌드 시간과 네트워크 통신을 줄이기 위해 의존성 패키지를 캐싱해서 재사용하는 방법을 사용한다.

하지만 Github Actions의 workflow는 매 실행하다 새로운 환경을 구축하고, 매번 새롭게 의존성 패키지들을 가지고 와야 한다. 이는 전체 빌드 시간의 증가로 이어진다. 빌드 시간의 단축을 위해서 우리는 Github Actions의 actions/cache를 사용해서 gradle의 의존성을 캐싱할 수 있다.

```yml
- name: Gradle Caching
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Grant execute permission for gradlew
run: chmod +x ./gradlew
shell: bash

- name: Build with Gradle
run: ./gradlew build
shell: bash
```
- path : 캐시의 저장과 복원에 사용되는 runner 내 파일 경로이다.
- key : 캐시를 저장, 복원에 사용되는 키. 여러 값들을 조합해서 512자 제한으로 생성할 수 있다.
- restore-keys : 내가 설정한 key로 cache miss가 발생할때 사용할 수 있는 후보군 키들이다.
gradle에 정의된 git action을 활용하면 아래와 같이 사용할 수 있다.
`gradle-build-action`의 용도와 의미에 대해선 추후 별도의 문서로 작성할 예정이다.

```yml
- name: Build Gradle
uses: gradle/gradle-build-action@v2
with:
arguments: |
build
--build-cache
--no-daemon
```
Loading

0 comments on commit 04f557e

Please sign in to comment.