Skip to content

Commit

Permalink
Change the line spacing of posts
Browse files Browse the repository at this point in the history
  • Loading branch information
Chaerim1001 committed Jan 10, 2024
1 parent 6a77745 commit 7650d3d
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 63 deletions.
3 changes: 1 addition & 2 deletions _posts/2022-08-25-TypeORM으로 Transaction 처리하기.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ tags: [TypeORM, Transaction]
> [typeorm-tracsactional](https://www.npmjs.com/package/typeorm-transactional) 0.1.1
{: .prompt-info }

# Transaction이란?
## Transaction이란?
{: .mt-4 .mb-4 }

우선 `트랜잭션(Transaction)`이란 무엇일까요? <br>
Expand Down Expand Up @@ -186,7 +186,6 @@ transaction을 처리하는 `Service` 코드입니다. 앞서 본 queryRunner를
}
```


<br>

> 참고 <br>
Expand Down
19 changes: 10 additions & 9 deletions _posts/2022-09-06-Mysql 공간 데이터 정리.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ NestJS를 사용하는 프로젝트를 진행하다가 사용자의 경로 데
> [Mysql](https://dev.mysql.com/downloads/mysql/5.7.html) 5.7
{: .prompt-info }

# 공간 데이터베이스란?
## 공간 데이터베이스란?
{: .mt-4 .mb-4 }

**공간 데이터베이스**란 말 그대로 공간 정보를 저장할 수 있는 데이터베이스를 뜻합니다.
좀 더 명확한 개념을 이야기해보자면 **공간에 존재하는 점, 선, 폴리곤등을 포함하는 객체의 데이터를 저장하고, 검색하는데 최적화된 데이터베이스**라고 정의할 수 있습니다.

공간 데이터베이스는 단순히 공간 데이터를 저장해줄 뿐 아니라 공간 데이터를 활용한 **공간 함수**을 함께 제공합니다.

# Mysql의 공간 데이터 타입
## Mysql의 공간 데이터 타입
Mysql에서는 공간 데이터를 저장할 수 있도록 타입을 제공하고 있습니다.

<img src="https://blog.kakaocdn.net/dn/0ExKk/btqDurscnn8/rK3KBj5ixQNkUdaK6QKit0/img.png" alt="공간 데이터 타입">
Expand All @@ -37,7 +37,7 @@ Mysql에서는 공간 데이터를 저장할 수 있도록 타입을 제공하
| GeomCollection | 모든 공간 데이터들의 집합 | GEOMETRYCOLLECTION(POINT(10 10), LINESTRING(20 20, 30 30)) |


# Mysql의 공간 함수
## Mysql의 공간 함수
{: .mt-7 .mb-4 }
Mysql에서는 다양한 공간 함수를 제공하고 있습니다. 그 중에서 자주 사용되는 함수들은 아래의 표와 같습니다.

Expand All @@ -61,12 +61,12 @@ Mysql에서는 다양한 공간 함수를 제공하고 있습니다. 그 중에
다양한 함수들이 많으니 공식 문서를 참고해서 원하는 기능의 함수를 잘 찾아서 사용하면 좋을 것 같습니다.
<a href="https://dev.mysql.com/doc/refman/5.7/en/spatial-function-reference.html">Mysql 공간 함수</a>

# Example
## Example
{: .mt-7 .mb-4 }
> 지금부터는 NestJS에서 TypeORM을 활용하여 공간 데이터를 사용하고 저장하는 방법에 대해 알아보곘습니다.
{: .prompt-tip }

## (1) Entity
### (1) Entity
`TypeORM``wkx` 라이브러리를 사용하여 정의한 Route 엔티티입니다.

```typescript
Expand All @@ -89,7 +89,7 @@ export class Route {

npm을 통해 설치해주어야 사용이 가능합니다. <a href="https://www.npmjs.com/package/wkx"> npm-wkx </a>

## (2) DTO
### (2) DTO
프론트에서 전달받는 위치 정보는 `latitude``longitude`로 이루어진 배열 데이터라고 가정하겠습니다. <br>
이는 `eachPoint` 타입을 정의해서 사용하였고 경로 데이터는 2개 이상의 Point가 필수적으로 필요하기 때문에 `@ArrayMinSize(2)`으로 설정해줍니다.

Expand All @@ -108,7 +108,7 @@ export class CreateRouteDto {
}
```

## (3) Service
### (3) Service
Point 타입과 LineString 타입 데이터를 저장할 때에는 위의 표에 있는 예시와 같이 입력해줘야 하기 때문에 그에 맞게 데이터 형식을 바꿔주는 작업이 필요합니다.

데이터 저장은 TypeORM의 `queryBuilder`를 사용하여 세부적인 쿼리문을 작성할 수 있으며, `ST_GeomFromText` 함수를 사용해서 문자열 데이터를 공간 데이터 타입으로 변환하여 저장할 수 있습니다.
Expand Down Expand Up @@ -141,9 +141,10 @@ Point 타입과 LineString 타입 데이터를 저장할 때에는 위의 표에
}
```

## (4) 결과 확인
### request-body
### (4) 결과 확인

```javascript
// request-body
{
"routeData": [{
"latitude": 0,
Expand Down
33 changes: 17 additions & 16 deletions _posts/2022-09-14-Redis 활용하여 랭킹 기능 구현하기.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ tags: [Redis]
> [Redis](https://redis.io/download/) 7.0
{: .prompt-info }

# 데이터베이스 쿼리가 아닌 Redis를 사용한 이유는?
## 데이터베이스 쿼리가 아닌 Redis를 사용한 이유는?
{: .mt-4 .mb-4 }

**속도 차이 !!!**
단순하게 생각해보면 랭킹 기능은 DB에 저장된 데이터를 count 하여 구현할 수도 있습니다. 하지만 그렇게 하면 데이터 양이 증가할수록 count를 계산하고 결과를 가져오는 시간이 오래 걸리기 때문에 성능면에서 좋지 않습니다.

그래서 속도 개선을 위해 **in-memory DB****Redis** 사용을 결정하였습니다.

# Memcached가 아닌 Redis를 사용한 이유
## Memcached가 아닌 Redis를 사용한 이유
{: .mt-7 .mb-4 }
**in-memory DB****Redis****Memcached** 두 가지를 많이 사용합니다.

Expand All @@ -28,68 +28,68 @@ tags: [Redis]

즉, 랭킹 기능을 구현하는데 있어 `Redis`에서 제공하는 `sorted-set`을 사용하면 빠르고 용이하게 개발을 할 수 있을 것이라고 생각하여 `Redis`를 사용하였습니다.

# 랭킹 구현에 sorted set이 적합한 이유
## 랭킹 구현에 sorted set이 적합한 이유
{: .mt-7 .mb-4 }
1. 집합이기 때문에 중복을 해결해 준다. (1등이 두 명이 될 수는 없다는 랭킹의 특징을 쉽게 나타낼 수 있다)
2. score를 하나하나 내가 비교할 필요가 없다. (score 값을 비교하여 정렬을 하기 때문에 내가 일일이 score 값을 비교할 필요가 없다)


# sorted set 명령 알아보기
## sorted set 명령 알아보기
{: .mt-7 .mb-4 }
## (0) redis-cli 접속하기
### (0) redis-cli 접속하기
```console
$ redis-cli
```
## (1) member 추가하기
### (1) member 추가하기
```console
$ ZADD <key> <score> <member>
```

<img src="https://velog.velcdn.com/images/chaerim1001/post/039c066d-b68c-45b7-9613-cd4b255b8afb/image.png" alt="add_member">

## (2) member의 score 값 조회하기
### (2) member의 score 값 조회하기
```console
$ ZSCORE <key> <member>
```

<img src="https://velog.velcdn.com/images/chaerim1001/post/eee28bb4-ab61-4ac4-84ff-7b486e237cd7/image.png" alt="get_score_1">

## (3) score 작은 순서로 순위 조회하기
### (3) score 작은 순서로 순위 조회하기
1순위부터 보고 싶다면 0을 사용해야 합니다.
```console
$ ZRANGE <key> <시작> <>
```

<img src="https://velog.velcdn.com/images/chaerim1001/post/29181690-241b-47ae-aaa6-7b83142c7aad/image.png" alt="get_score_2">

## (4) score 큰 순서로 순위 조회하기
### (4) score 큰 순서로 순위 조회하기
```console
$ ZRANGE <key> <시작> <> REV
```

<img src="https://velog.velcdn.com/images/chaerim1001/post/c691eaaf-517d-4e3d-b367-9c260cf085a6/image.png" alt="get_score_3>

## (5) score가 작은 순서대로 정렬했을 때 member 순위 조회하기
### (5) score가 작은 순서대로 정렬했을 때 member 순위 조회하기
```console
$ ZRANK <key> <member>
```

<img src="https://velog.velcdn.com/images/chaerim1001/post/c4cc556f-7c01-477c-8e2b-fa1c7e919b32/image.png" alt="get_rank_1">

## (6) score가 큰 순서대로 정렬했을 때 member 순위 조회하기
### (6) score가 큰 순서대로 정렬했을 때 member 순위 조회하기
```console
$ ZREVRANK <key> <member>
```

<img src="https://velog.velcdn.com/images/chaerim1001/post/69ffea0a-4b80-4083-b326-cf6a4f0f6c79/image.png" alt="get_rank_2">


# Example
## Example
{: .mt-7 .mb-4 }
> 지금부터는 NestJS에서 Redis의 Sorted Set을 활용하여 랭킹 기능을 구현해 보겠습니다.
{: .prompt-tip }

## (1) docker-compose.yml
### (1) docker-compose.yml
NestJS와 Mysql을 이미 docker-compose로 묶어서 사용하고 있어 redis도 docker image를 사용하였습니다.
각각 변수들은 `.env`로 관리할 수 있습니다.

Expand All @@ -104,12 +104,12 @@ redis:
command: redis-server --requirepass ${REDIS_PASSWORD}
```
## (2) 라이브러리 설치
### (2) 라이브러리 설치
```console
$ npm install @liaoliaots/nestjs-redis ioredis
```

## (3) app.module.ts
### (3) app.module.ts
라이브러리에서 제공하는 `RedisModule`을 사용하여 `app.module.ts`에 redis 연결을 위한 설정을 해줍니다.
```typescript
import { RedisModule } from '@liaoliaots/nestjs-redis';
Expand All @@ -130,7 +130,7 @@ import { RedisModule } from '@liaoliaots/nestjs-redis';
export class AppModule {}
```

## (4) service.ts
### (4) service.ts
호출할 때마다 해당 user의 score 값을 1씩 증가시키는 `setRank` 함수와 순위를 가져오는 `getRank` 함수를 작성하였습니다. (라이브러리에서 대부분의 함수를 redis-cli에서 사용하는 명령어 이름으로 작성해두었기 때문에 원하는 기능의 함수를 찾기 편했습니다 ㅎㅎ)

```typescript
Expand Down Expand Up @@ -158,6 +158,7 @@ docker image를 실행시킬 때 redis에 비밀번호 설정을 해주었기

<img src="https://velog.velcdn.com/images/chaerim1001/post/24ca874f-7e54-4085-a5fc-c6098dfc911e/image.png" alt="docker_redis_login">

<br>

> 참고 <br>
> ttps://redis.io/docs/data-types/sorted-sets/ <br>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ tags: [Docker, Github Actions, CI/CD, AWS]
{: .prompt-info }


# 지속적 통합: CI(Continuous Integration)
## 지속적 통합: CI(Continuous Integration)

## (1) Dockerfile 작성하기
### (1) Dockerfile 작성하기
Docker image 생성을 위해 Dockerfile을 작성해 줍니다.
```yml
FROM node:16.15.1
Expand All @@ -28,7 +28,7 @@ EXPOSE 3000
CMD ["npm", "run", "start:dev"]
```

## (2) docker-compose.yml
### (2) docker-compose.yml
데이터베이스는 mysql을 사용하였습니다.

```yml
Expand Down Expand Up @@ -65,7 +65,7 @@ networks:
server:
```
## (3) docker-ci.yml
### (3) docker-ci.yml
master 브랜치에 해당 이벤트가 발생하면 도커허브에 로그인하여 변경사항이 반영된 이미지를 생성해 올리도록 작업을 설정해 줍니다.
여기서 사용하는 변수들은 repository secret 변수에 등록해주어야 사용이 가능합니다. (CD 뒷 부분에 방법 참고!)
```yml
Expand Down Expand Up @@ -101,23 +101,23 @@ jobs:
```
# 지속적 배포: CD(Continuous Deployment)
## 지속적 배포: CD(Continuous Deployment)
배포는 AWS를 활용하였습니다. (프리 티어!)
## (1) AWS EC2 인스턴스 생성
### (1) AWS EC2 인스턴스 생성
### (1) AMI 선택
#### (1) AMI 선택
AMI는 인스턴스를 시작하는 최초의 운영체제를 의미하는데, **ubuntu server 20.04 버전** 으로 설정했습니다.
<img src="https://velog.velcdn.com/images/chaerim1001/post/99a65f6a-66fa-4035-a587-9560da8b8316/image.png" alt="aws_ec2_ami">
### (2) 키페어 생성
#### (2) 키페어 생성
``` .pem ``` 파일 형식으로 키 페어를 생성합니다.
네트워크나 다른 설정은 기본 값으로 두고 진행하였습니다.

<img src="https://velog.velcdn.com/images/chaerim1001/post/2a17fe06-576f-49ee-9565-cca0093cef5a/image.png" alt="aws_key">

### (3) 보안 그룹 구성
#### (3) 보안 그룹 구성
인스턴스를 생성한 뒤에는 인스턴스 상세 화면에서 보안 그룹을 확인할 수 있습니다.
보안 그룹을 클릭하여 인바운드 규칙을 추가해 줍니다.

Expand All @@ -127,7 +127,7 @@ AMI는 인스턴스를 시작하는 최초의 운영체제를 의미하는데, *

<img src="https://velog.velcdn.com/images/chaerim1001/post/8dbf13a4-2777-4d56-8e3d-34e25502bf16/image.png" alt="security_group_2">

### (4) 고정 IP 설정
#### (4) 고정 IP 설정
인스턴스를 중지했다가 다시 시작하면 IP가 계속 바뀌기 때문에 고정적인 IP 사용을 위해 탄력적 IP (Elastic) IP를 설정해 줍니다.

<img src="https://velog.velcdn.com/images/chaerim1001/post/d79cf830-ca6f-4bdc-af69-74d1eb3ab479/image.png" alt="elastic_ip">
Expand All @@ -138,14 +138,14 @@ IP 할당 후 생성된 IP로 들어가 앞서 생성한 인스턴스를 연결

_인스턴스를 더이상 사용하지 않아 중지할 때에는 IP도 함께 릴리즈해야 합니디!!_

## (2) 인스턴스 접속하기
### (2) 인스턴스 접속하기
EC2로 인스턴스에 ssh를 사용하여 접속해 봅시다!

<img src="https://velog.velcdn.com/images/chaerim1001/post/26babcad-7ec8-4758-84f0-e008b58da87e/image.png" alt="connect">

생성한 인스턴스의 Connect 탭으로 들어가 SSH Client 부분에서 자신의 환경에 맞는 명령어를 확인할 수 있으니 그대로 진행하면 됩니다.

## (3) Docker 설치
### (3) Docker 설치
접속한 서버에 docker를 설치해 줍니다.

```console
Expand All @@ -166,9 +166,9 @@ $ sudo apt-get install docker-ce docker-ce-cli containerd.io

이후 docker 명령을 입력하면 docker 명령어들이 나오는데 그렇게 나오면 docker가 잘 설치된 것입니다.

## (4) Github actions 설정
### (4) Github actions 설정

### (1) build-and-deploy.yml 작성
#### (1) build-and-deploy.yml 작성
```yml
name: build and deploy
Expand Down Expand Up @@ -221,7 +221,7 @@ jobs:

master 브랜치에 push 이벤트가 발생했을 때 해당 작업을 수행하도록 워크플로우를 작성해 줍니다.

### (2) ssh password 생성
#### (2) ssh password 생성

ssh 배포에 [appleboy](https://github.com/appleboy/ssh-action) 를 활용하는데 private key나 password를 사용해 ssh 접속이 가능합니다. 저는 password를 사용해 접속하는 방법을 선택했기 때문에 비밀번호를 생성해준 뒤 repository의 secret 변수로 등록해 줍니다.

Expand All @@ -244,7 +244,7 @@ $ sudo vi /etc/ssh/sshd_config
$ service ssh restart
```

### (3) secret 변수 설정
#### (3) secret 변수 설정
yml에서 사용한 secret 변수들을 설정해 줍니다.
repository의 **settings/security/secrets/actions** 탭에 들어가서 변수를 추가할 수 있습니다.

Expand All @@ -256,7 +256,7 @@ ec2 인스턴스는 생성할 때 선택한 AMI에 따라 [username](https://doc
* password: 위에서 생성해준 ssh의 password
* port: ssh 접속 포트번호 (기본으로 ssh 접속을 위해 열려있는 포트 번호는 22다)

## (5. Docker 권한 문제)
### (5. Docker 권한 문제)
윗 단계까지 진행하고 push를 하면

```
Expand All @@ -266,21 +266,23 @@ err: Got permission denied while trying to connect to the Docker daemon socket
과 같은 에러가 발생할 수 있습니다.
이는 docker group에 해당 유저가 없어서 생기는 에러인데 docker group에 추가만 해주면 바로 해결됩니다.
### (1) ssh로 접속해서 docker group이 없을 경우에는 생성해준다.
#### (1) ssh로 접속해서 docker group이 없을 경우에는 생성해준다.
```console
$ sudo groupadd docker
```

### (2) docker group 해당 유저 추가
#### (2) docker group 해당 유저 추가
```console
$ sudo usermod -aG docker $USER
```

### (3) 변경사항 적용
#### (3) 변경사항 적용
```console
$ newgrp docker
```

<br>

>참고 <br>
>https://docs.docker.com/engine/install/ubuntu/ <br>
>https://github.com/appleboy/ssh-action <br>
Expand Down
Loading

0 comments on commit 7650d3d

Please sign in to comment.