욕설 필터링 시스템을 설계할 때 다양한 방법론과 기술적인 선택지가 존재합니다. 저는 프로젝트를 진행하면서 욕설 필터링을 구현하기 위해 여러 접근 방식을 조사했고, 각각의 장단점을 비교해 보았습니다. 그 결과, 단순한 데이터베이스 기반 필터링부터 시작해, 정규 표현식을 활용한 필터링을 구현하는 방식을 선택했습니다.


1. 욕설 필터링의 일반적인 방법

욕설 필터링을 구현하는 방법은 크게 두 가지로 나눌 수 있습니다.

  1. 데이터베이스 기반 필터링
    • 욕설과 비속어를 데이터베이스에 저장하고, 입력된 텍스트를 이 데이터와 비교해 감지하는 방식입니다.
    • 구현이 간단하고 빠르게 결과를 도출할 수 있지만, 데이터베이스 크기에 따라 성능이 저하될 수 있습니다.
    • 방대한 욕설 데이터베이스가 필요하며, 새로운 욕설이나 변형된 표현에 대한 대응이 어렵습니다.
  2. 자연어 처리 기반 필터링
    • 머신러닝 또는 딥러닝 모델을 활용해 욕설을 감지하는 방식입니다.
    • 문맥을 이해하고 변형된 욕설도 감지할 수 있는 장점이 있지만, 구현이 복잡하며 모델 학습에 많은 데이터와 리소스가 필요합니다.

2. 데이터베이스 기반 필터링 적용

욕설 필터링을 가장 빠르게 구현할 수 있는 방법은 데이터베이스에 욕설 데이터를 저장하고 이를 비교하는 방식입니다.
초기에 단순한 구현을 위해 욕설 데이터베이스를 직접 만들어 활용했으며, 기본적으로 다음과 같은 과정을 통해 처리했습니다.

 

욕설 데이터 수집

  1. 기본 욕설 목록 추가:
    초기에는 간단한 욕설 단어를 데이터베이스에 직접 추가하여 테스트를 진행했습니다.
  2. 확장 가능한 욕설 데이터베이스 조사:
    이후 필터링의 정확도를 높이기 위해, 방대한 욕설 데이터베이스를 제공하는 자료들을 조사했습니다.
    대표적으로 아래와 같은 자료들이 있었습니다:
    • Technote:
      국내에서 자주 사용되는 욕설과 비속어를 포함한 방대한 데이터베이스를 제공.
    • ZDNet 기사:
      네이버가 제공하는 욕설 필터링 데이터에 대한 정보. 양이 방대하고 다양한 욕설 패턴을 포함하고 있었습니다.
      이를 통해 기존에 생각하지 못했던 다양한 욕설과 변형된 표현까지 감지할 수 있다는 점을 알게 되었습니다.
  3. 현실적 한계:
    그러나 이러한 방대한 데이터를 실제 프로젝트에 바로 적용하기에는 리소스와 성능 문제가 발생할 수 있어, 현재 프로젝트에서는 단순한 데이터베이스로 시작했습니다.

3. 정규 표현식을 활용한 욕설 필터링

욕설 데이터베이스 기반 필터링은 초기 구현 단계에서는 유용하지만, 성능 문제와 변형된 욕설(예: 띄어쓰기, 특수문자 사용)에 대한 대응이 부족하다는 한계가 있습니다. 이를 보완하기 위해 정규 표현식(Regex)을 활용한 필터링 로직을 구현해 보았습니다.

정규 표현식 적용 과정

  1. 욕설 패턴 정의:
    • 바보, 멍청이 같은 단순한 욕설을 포함한 기본 패턴 작성.
    • 욕설 단어 변형(예: 바ㅂㅗ, 멍청@이)을 감지하기 위해 다양한 정규 표현식을 작성.
  2. 구현 예시:
@Service
@Transactional
@RequiredArgsConstructor
public class ProfanityFilterService {

    private final ProfanityRepository profanityRepository;

    public List<String> getPatterns() {
        return profanityRepository.findAll().stream()
                .map(Profanity::getPattern)
                .toList();
    }


    public String filter(String text, List<String> patterns) {
        System.out.println("Original text: " + text);
        String filteredText = text;

        for (String pattern : patterns) {
            Pattern compiledPattern = Pattern.compile("(?i)" + pattern, Pattern.UNICODE_CASE);
            if (compiledPattern.matcher(text).find()) {
                filteredText = compiledPattern.matcher(filteredText).replaceAll("****");
            }
        }

        return filteredText;
    }
    
}

블러 처리 결과

 


4. 결론

욕설 필터링은 데이터베이스 기반의 간단한 구현부터 시작해 점진적으로 고도화할 수 있습니다. 초기 단계에서는 정규 표현식을 활용해 간단하게 필터링 로직을 작성했으며, 이후 확장성을 고려해 다음과 같은 방향으로 발전시킬 계획입니다.

  1. 방대한 욕설 데이터를 포함하는 데이터베이스와 결합.
  2. 사용자 경험을 고려한 실시간 필터링 로직 추가.
  • 데이터를 제한하여 필요한 부분만 조회하는 방법을 학습합니다.
  • SQL의 연산 기능과 다양한 함수 활용법을 익힙니다.
  • 데이터를 보기 좋게 표현하기 위해 별칭(Alias)을 사용하는 방법을 배웁니다.

1. LIMIT와 OFFSET

LIMIT와 OFFSET은 데이터를 조회할 때 출력 개수를 제한하거나 특정 위치에서 시작하도록 합니다.

기본 문법

SELECT 컬럼명
FROM 테이블명
LIMIT 개수 OFFSET 시작위치;
  • LIMIT: 반환할 행(Row)의 최대 개수를 지정합니다.
  • OFFSET: 데이터를 조회할 때 시작 위치를 지정합니다.

예제

  • 상위 5개의 트랙 조회
SELECT Name, UnitPrice 
FROM Track LIMIT 5;

  • 5번째부터 10번째까지 트랙 조회
SELECT Name, UnitPrice 
FROM Track 
LIMIT 5 OFFSET 5;

TIP: MySQL에서는 LIMIT 5, 5 형태로 OFFSET을 생략하고 사용 가능 (LIMIT {시작위치}, {개수}).


2. 기본 연산

SQL에서 기본 산술 연산과 문자열 연산을 사용할 수 있습니다.

1) 산술 연산

연산자 설명

+ 덧셈
- 뺄셈
* 곱셈
/ 나눗셈

예제

  • 가격에 세금을 추가하여 계산트랙 가격(UnitPrice)에 10% 세금을 추가하여 새로운 컬럼 TaxedPrice로 출력합니다.
SELECT Name, UnitPrice, UnitPrice * 1.1 AS TaxedPrice
FROM Track;

  • 두 값의 합계 계산가격에 재생 시간(초 단위)을 더한 값을 계산합니다.
SELECT UnitPrice + Milliseconds / 1000 AS AdjustedPrice
FROM Track 
WHERE UnitPrice > 1.00;


2) 문자열 연산

  • 문자열을 연결하거나 변환하는 데 사용할 수 있습니다.

주요 연산자와 함수

함수/연산자 설명

CONCAT 문자열 연결
`  
LENGTH 문자열 길이 반환
UPPER 문자열을 대문자로 변환
LOWER 문자열을 소문자로 변환

예제

  • 이름과 가격 연결트랙 이름과 가격을 결합하여 TrackInfo로 출력합니다.
SELECT CONCAT(Name, ' - $', UnitPrice) AS TrackInfo
FROM Track;

  • 문자열 길이 확인이름이 10자 이상인 트랙과 그 길이를 출력합니다.
SELECT Name, LENGTH(Name) AS NameLength 
FROM Track 
WHERE LENGTH(Name) > 10;


3. Alias (별칭)

Alias는 테이블이나 컬럼의 이름을 임시로 변경하여 가독성을 높이고, 결과 데이터를 명확히 표현할 때 유용합니다.

기본 문법

SELECT 컬럼명 AS 별칭
FROM 테이블명;
  • AS는 별칭을 지정하기 위한 키워드이며 생략 가능.

예제

  • 컬럼 이름에 별칭 지정
SELECT Name AS TrackName, UnitPrice AS Price
FROM Track;

  • 테이블 이름에 별칭 지정
SELECT T.Name, T.UnitPrice 
FROM Track AS T;


4. 기본 함수

SQL은 데이터를 변형하거나 분석하기 위해 다양한 내장 함수를 제공합니다.

1) 문자열 함수

함수 설명

LENGTH 문자열 길이를 반환
UPPER 문자열을 대문자로 변환
LOWER 문자열을 소문자로 변환
TRIM 문자열의 앞뒤 공백 제거

예제

  • 대문자로 변환
SELECT UPPER(Name) AS UpperName 
FROM Track;

  • 공백 제거
SELECT TRIM(Name) AS TrimmedName 
FROM Track 
WHERE Name LIKE ' %';


2) 수학 함수

함수 설명

ROUND 숫자를 반올림
CEIL 숫자를 올림
FLOOR 숫자를 내림

예제

  • 가격을 소수점 첫째 자리에서 반올림
SELECT Name, ROUND(UnitPrice, 1) AS RoundedPrice
FROM Track;

  • 가격을 올림
SELECT Name, CEIL(UnitPrice) AS CeilPrice 
FROM Track;

  • 가격을 내림
SELECT Name, FLOOR(UnitPrice) AS FloorPrice 
FROM Track;


요약

  • LIMIT와 OFFSET: 출력 데이터의 개수를 제한하거나 특정 위치에서 시작.
  • 산술 연산과 문자열 연산: 데이터를 계산하거나 연결.
  • Alias (별칭): 컬럼이나 테이블의 이름을 명확히 표현.
  • 기본 함수: 데이터를 분석하거나 변형하기 위한 내장 함수.

이 문법들을 활용하면 SQL을 사용하여 데이터를 더 유연하게 처리하고, 보기 좋은 형태로 출력할 수 있습니다. 다음 글에서는 SQL 집계 함수를 통해 데이터를 그룹화하고 집계하는 방법을 다뤄보겠습니다.

'SQL > 학습정리' 카테고리의 다른 글

SQL Join  (0) 2024.12.11
SQL 집계함수  (0) 2024.12.10
SQL 기본 문법 1  (0) 2024.12.09
데이터베이스 및 SQL 기본 개념 정리  (1) 2024.12.09
실습 데이터 정하기  (0) 2024.12.09

1. SELECT 기본 문법

SQL의 데이터 조회는 SELECT 문법을 사용하여 이루어집니다. 기본 구조는 다음과 같습니다.

SELECT 컬럼명
FROM 테이블명;

예제

  • 모든 컬럼 조회Track 테이블의 모든 데이터를 조회합니다.
SELECT * 
FROM Track;

 

  • 특정 컬럼만 조회트랙의 이름(Name)과 가격(UnitPrice)만 조회합니다.
SELECT Name, UnitPrice
FROM Track;


2. WHERE로 데이터 필터링

WHERE 절을 사용하여 특정 조건에 맞는 데이터를 필터링할 수 있습니다.

조건 연산자

연산자 설명

= 값이 같음
!= 값이 같지 않음
> 값이 큼
< 값이 작음
>= 값이 크거나 같음
<= 값이 작거나 같음

논리 연산자

연산자 설명

AND 여러 조건을 모두 만족
OR 여러 조건 중 하나라도 만족
NOT 조건의 반대

예제

  • 특정 조건 조회가격이 $1.00 이상인 트랙을 조회합니다.
SELECT Name, UnitPrice
FROM Track
WHERE UnitPrice > 1.00;

  • 여러 조건 필터링가격이 $1.00 이상이고 재생 시간이 5분(300,000 밀리초) 이상인 트랙을 조회합니다.
SELECT Name, UnitPrice 
FROM Track
WHERE UnitPrice > 1.00 AND Milliseconds > 300000;


3. DISTINCT로 중복 제거

DISTINCT 키워드는 중복된 데이터를 제거하고 고유한 값을 반환합니다.

예제

  • 작곡가 목록 조회트랙 테이블에서 중복되지 않은 작곡가 목록을 조회합니다.
SELECT DISTINCT Composer
FROM Track;

  • 국가 목록 조회고객 테이블에서 중복되지 않은 국가 이름을 조회합니다.
SELECT DISTINCT Country
FROM Customer;


4. ORDER BY

ORDER BY 절은 데이터를 정렬할 때 사용합니다. 기본값은 오름차순(ASC)이며, 내림차순은 DESC 키워드를 사용합니다.

예제

  • 가격 오름차순 정렬가격을 기준으로 낮은 순서대로 정렬합니다.
SELECT Name, UnitPrice 
FROM Track
ORDER BY UnitPrice ASC;

  • 가격 내림차순 정렬가격을 기준으로 높은 순서대로 정렬합니다.
SELECT Name, UnitPrice
FROM Track 
ORDER BY UnitPrice DESC;

  • 여러 컬럼 정렬가격을 기준으로 내림차순 정렬하고, 같은 가격인 경우 재생 시간을 기준으로 오름차순 정렬합니다.
SELECT Name, UnitPrice, Milliseconds 
FROM Track
ORDER BY UnitPrice DESC, Milliseconds ASC;


5. 특수 조건

1) BETWEEN

BETWEEN을 사용하여 특정 범위 내의 데이터를 조회할 수 있습니다.

  • 예제재생 시간이 200,000에서 400,000 밀리초 사이인 트랙을 조회합니다.
SELECT Name, Milliseconds
FROM Track
WHERE Milliseconds BETWEEN 200000 AND 400000;

2) LIKE

LIKE는 특정 패턴과 일치하는 데이터를 조회합니다.

와일드카드 설명

% 0개 이상의 문자
_ 단일 문자
  • 예제이름에 "Love"가 포함된 트랙을 조회합니다.
SELECT Name 
FROM Track
WHERE Name LIKE '%Love%';

3) IN

IN은 여러 값 중 하나와 일치하는 데이터를 조회합니다.

  • 예제가격이 $0.99, $1.99, $2.99 중 하나인 트랙을 조회합니다.
SELECT Name, UnitPrice
FROM Track
WHERE UnitPrice IN (0.99, 1.99, 2.99);

 


요약

  • SELECT: 데이터를 조회하는 기본 명령어입니다.
  • WHERE: 조건을 통해 데이터를 필터링합니다.
  • DISTINCT: 중복된 데이터를 제거합니다.
  • ORDER BY: 데이터를 정렬합니다.
  • BETWEEN, LIKE, IN: 특정 조건에 맞는 데이터를 조회하는 데 사용됩니다.

이 문법들을 활용하면 SQL의 기본적인 데이터 조회와 필터링 작업을 수행할 수 있습니다. 다음 글에서는 SQL 기본 문법 2로 한 단계 더 나아간 기능을 학습하겠습니다.

'SQL > 학습정리' 카테고리의 다른 글

SQL Join  (0) 2024.12.11
SQL 집계함수  (0) 2024.12.10
SQL 기본 문법 2  (0) 2024.12.09
데이터베이스 및 SQL 기본 개념 정리  (1) 2024.12.09
실습 데이터 정하기  (0) 2024.12.09

1. 데이터베이스 및 SQL 기본 개념

  • 데이터베이스와 RDBMS:
    • 주요 특징: 데이터 중복 감소, 무결성 유지, 데이터 접근 속도 향상.
  • 데이터를 효율적으로 저장, 관리, 검색하는 시스템. 관계형 데이터베이스(RDBMS)는 데이터를 테이블 형식으로 저장하며, 테이블 간 관계를 설정할 수 있음.
  • 기본 용어:
    • 테이블(Table): 데이터를 행(Row)과 열(Column)로 구성해 저장.
    • 컬럼(Column): 테이블의 속성을 정의하는 필드.
    • 행(Row): 데이터의 한 레코드.
  • 데이터베이스 스키마(Schema):
  • 데이터베이스 구조를 정의하는 설계도. 테이블, 뷰, 인덱스, 트리거 등을 포함.
  • 데이터베이스의 장단점:
    • 장점: 데이터 중복 최소화, 무결성 유지, 다중 사용자 지원.
    • 단점: 초기 설계 복잡성, 시스템 유지 관리 비용.

2. SQL(Structured Query Language)

  • DDL (Data Definition Language):
    • 예: CREATE (생성), ALTER (수정), DROP (삭제).
  • 데이터베이스 구조를 정의하거나 수정하는 데 사용.
  • DML (Data Manipulation Language):
    • CRUD 작업: SELECT, INSERT, UPDATE, DELETE.
  • 데이터를 조회하거나 조작하는 데 사용.
  • DCL (Data Control Language):
    • 예: CREATE USER, GRANT, REVOKE.
  • 데이터베이스 사용자와 권한을 관리.

'SQL > 학습정리' 카테고리의 다른 글

SQL Join  (0) 2024.12.11
SQL 집계함수  (0) 2024.12.10
SQL 기본 문법 2  (0) 2024.12.09
SQL 기본 문법 1  (0) 2024.12.09
실습 데이터 정하기  (0) 2024.12.09

실습 데이터베이스: Chinook DB

Chinook DB는 음악 판매점을 모델링한 샘플 데이터베이스로, 실제 비즈니스 시나리오와 유사한 데이터를 제공합니다. 이를 통해 SQL 문법과 데이터베이스 개념을 효과적으로 학습할 수 있습니다.

  • 주요 테이블:
    • artists: 아티스트 정보
    • albums: 앨범 정보
    • tracks: 곡 정보
    • customers: 고객 정보
    • invoices: 송장 및 주문 정보
    • invoice_items: 송장 상세 내역

Chinook DB 다운로드 및 설치 방법

  1. Chinook DB 다운로드
  2. MySQL용 스크립트 변환
  3. Chinook DB는 기본적으로 SQLite 형식이므로, MySQL에서 사용하기 위해 스크립트를 변환해야 합니다. 이미 변환된 MySQL용 스크립트를 다운로드할 수 있습니다.


저는 그냥 여기서 복사해서 바로 붙여 넣기 했습니다.

 

show tables 를 입력하면 전체 테이블을 확인할 수 있습니다.

'SQL > 학습정리' 카테고리의 다른 글

SQL Join  (0) 2024.12.11
SQL 집계함수  (0) 2024.12.10
SQL 기본 문법 2  (0) 2024.12.09
SQL 기본 문법 1  (0) 2024.12.09
데이터베이스 및 SQL 기본 개념 정리  (1) 2024.12.09

성능 테스트란?

  • 성능 테스트(Performance Testing)는 애플리케이션이 특정 조건에서 얼마나 잘 작동하는지를 평가하기 위한 테스트 방식입니다. 이는 주로 애플리케이션의 속도, 안정성, 확장성, 그리고 자원을 얼마나 효율적으로 사용하는지에 초점을 맞춥니다. 성능 테스트는 다양한 형태로 나뉩니다
  1. 부하 테스트(Load Testing): 시스템이 예상되는 최대 사용자 수에서 어떻게 작동하는지 확인합니다.
  2. 스트레스 테스트(Stress Testing): 시스템이 용량 한계를 초과할 때 어떻게 작동하는지 확인합니다.
  3. 스파이크 테스트(Spike Testing): 갑작스러운 트래픽 급증에 시스템이 어떻게 반응하는지 평가합니다.
  4. 내구성 테스트(Soak Testing): 장시간 동안 일정 부하를 주고 안정성을 점검합니다.

Artillery란?

Artillery는 성능 테스트와 부하 테스트를 수행하기 위한 강력하고 사용하기 쉬운 오픈 소스 툴입니다. Node.js 기반으로 만들어졌으며, 다음과 같은 특징이 있습니다

  • JSON/YAML 파일로 간단하게 시나리오 정의 가능
  • HTTP, WebSocket, Socket.io 등 다양한 프로토콜 지원
  • 클라우드 환경 및 CI/CD 파이프라인에 쉽게 통합 가능

Artillery 설치

Artillery를 사용하려면 Node.js가 설치되어 있어야 합니다.

npm install -g artillery

설치 후, 다음 명령어로 설치가 완료되었는지 확인하세요

artillery --version

 


Artillery 기본 사용법

Artillery는 설정 파일을 기반으로 시나리오를 정의합니다. 기본 설정 파일은 다음과 같은 구조를 가집니다:

config:
  target: "<http://your-api-endpoint.com>"
  phases:
    - duration: 60   # 테스트 실행 시간(초)
      arrivalRate: 10 # 초당 사용자 수
scenarios:
  - flow:
      - get:
          url: "/api/resource"

주요 요소 설명

  1. config: 테스트 환경 설정
    • target: 테스트 대상 URL
    • phases: 테스트 단계 설정 (시간, 사용자 수 등)
  2. scenarios: 사용자가 수행할 시나리오 정의
    • flow: 사용자가 따를 작업의 순서

간단한 HTTP 테스트 시나리오

설정 파일 생성

test.yml 파일을 생성합니다:

config:
  target: "<https://jsonplaceholder.typicode.com>"
  phases:
    - duration: 10
      arrivalRate: 5
scenarios:
  - flow:
      - get:
          url: "/posts"

테스트 실행

다음 명령어로 테스트를 실행합니다:

artillery run test.yml

결과 확인

결과는 실행 후 콘솔에 출력됩니다. 결과 요약에는 다음과 같은 정보가 포함됩니다:

  • 요청 성공/실패 수
  • 응답 시간 통계 (평균, 95th 퍼센타일 등)
  • 초당 처리량(*RPS)

 

용어 정리

RPS (Requests Per Second)

  • 초당 서버로 보내지는 요청(Request)의 수를 의미합니다.
  • HTTP 요청 단위로 측정되며, GET, POST, PUT 등 모든 요청이 포함됩니다.
  • Artillery는 HTTP 요청 단위를 기준으로 결과를 계산하므로, 결과로 나온 초당 처리량은 RPS입니다.

TPS (Transactions Per Second)

  • 초당 처리되는 트랜잭션(Transaction)의 수를 의미합니다.
  • 트랜잭션은 하나의 사용자 작업 단위로, 여러 요청(Request)을 포함할 수 있습니다.
  • 예를 들어, "사용자가 로그인하고 데이터를 조회하는 과정"을 하나의 트랜잭션으로 본다면, 이는 여러 RPS로 구성될 수 있습니다.

 

Artillery 공식 문서: https://www.artillery.io/docs/

욕설 필터링 시스템(Clean Bot)을 설계하면서 가장 큰 고민은 "필터링이 실시간으로 이루어져야 하는가?" 였습니다. 이를 결정하기 위해 다양한 요소를 고려했으며, 각각의 장단점을 아래와 같이 정리해보았습니다.


1. 실시간 필터링의 장단점

장점

  • 사용자 경험 개선: 욕설이 즉시 차단되어 플랫폼의 건전성을 유지하고 사용자 만족도를 높일 수 있습니다.
  • 문제 확산 방지: 부적절한 콘텐츠가 다른 사용자에게 노출되기 전에 차단됩니다.

단점

  • 성능 이슈: 대규모 트래픽 환경에서는 높은 처리 성능이 요구되며, 지연(Latency)이 발생할 가능성이 있습니다.
  • 비용 증가: 실시간 처리를 위해 추가적인 서버 자원과 기술적 구현이 필요합니다.
  • 오탐(False Positive): 과도한 필터링으로 부적절하지 않은 콘텐츠까지 차단될 위험이 있습니다.

2. 비실시간(배치) 필터링의 장단점

장점

  • 성능 최적화: 배치 처리로 서버 부하를 줄이고, 전체 시스템의 안정성을 유지할 수 있습니다.
  • 비용 절감: 실시간이 아니기 때문에 상대적으로 적은 자원으로 구현이 가능합니다.

단점

  • 지연된 대응: 욕설이 일정 시간 동안 노출될 가능성이 있습니다.
  • 사용자 불만: 부적절한 언어가 즉시 차단되지 않으면 관리 부족으로 느껴질 수 있습니다.

결론

일단 욕설 필터링은 배치 처리 방식으로 구현하여 기본적인 기능을 완성한 뒤, 이후 실시간성을 어떻게 도입할지 고민하는 방향으로 진행하고 있습니다.


배치 처리 코드 구현

아래는 욕설 필터링 시스템을 배치 처리로 구현한 코드입니다. Spring Batch를 활용하여 데이터베이스의 Posting 엔티티 중 필터링이 필요한 데이터를 주기적으로 처리합니다.

 
@Configuration
@RequiredArgsConstructor
public class ProfanityBatch {
	private final JobRepository jobRepository;
    private final PlatformTransactionManager platformTransactionManager;
    private final PostingRepository postingRepository;
    private final ProfanityFilterService profanityFilterService;
    
    @Bean
    public Job profanityJob() {
    	return new JobBuilder("profanityJob", jobRepository)
        	.start(profanityStep()) .build(); 
    }
    
    @Bean
    public Step profanityStep() { 
    	return new StepBuilder("profanityStep", jobRepository)
        	.<Posting, Posting>chunk(10, platformTransactionManager)
            .reader(profanityReader()) .processor(profanityProcessor())
            .writer(profanityWriter()) .build();
    }
    
    @Bean
    public RepositoryItemReader<Posting> profanityReader() {
    	return new RepositoryItemReaderBuilder<Posting>()
        	.name("profanityReader")
            .pageSize(10)
            .repository(postingRepository) 
            .methodName("findByIsCleanedFalse")
            .arguments(Collections.emptyList())
            .sorts(Map.of("id", Sort.Direction.ASC))
            .build(); 
    }
    
    @Bean
    public ItemProcessor<Posting, Posting> profanityProcessor() {
    	return posting -> {
			List<String> patterns = profanityFilterService.getPatterns();
            String filteredContent = profanityFilterService.filter(posting.getContent(), patterns);
            posting.updateCleanPosting(filteredContent);
            return posting;
        };
    }
            
    @Bean 
    public RepositoryItemWriter<Posting> profanityWriter() {
    	return new RepositoryItemWriterBuilder<Posting>() 
        .repository(postingRepository)
        .methodName("save")
        .build();
    } 
}

코드 설명

  1. Job과 Step 구성:
    • profanityJob: 배치 작업을 시작하는 엔트리포인트.
    • profanityStep: 필터링 작업의 단위, 데이터 읽기-처리-쓰기 구성.
  2. Reader:
    • 데이터베이스에서 필터링이 필요한 데이터(isCleaned = false)를 읽어옵니다.
  3. Processor:
    • ProfanityFilterService를 활용하여 콘텐츠에서 욕설을 필터링하고, 필터링된 콘텐츠로 업데이트합니다.
  4. Writer:
    • 필터링이 완료된 데이터를 다시 저장합니다.

2편에서는 ACM 인증서 연결, EC2 보안 그룹설정, 로드 밸런싱 설정, Route 53 레코드 생성, 결과 순으로 진행하겠습니다.

1. HTTPS 설정

1-1. ACM 인증서 연결

  1. AWS 로드 밸런싱 페이지 접속
    • AWS Management Console에서 로드 밸런싱 > 로드 밸런서로 이동합니다.
  2. 로드 밸런서 생성
    • 로드 밸런서 유형: Application Load Balancer 선택.
    • 리스너 추가: HTTPS(포트 443)를 선택하고, 1편에서 발급받은 ACM 인증서를 연결합니다.
      • ACM 인증서를 선택할 수 없는 경우, 인증서 발급이 완료되었는지 확인하세요.
    • 가용 영역:
      • EC2 인스턴스가 위치한 VPC와 서브넷을 선택합니다.
      • 여러 서브넷을 선택해 가용성을 높일 수 있습니다.
  3. 로드 밸런서 생성 완료
    • 생성 후, 로드 밸런서는 HTTPS 요청을 처리할 준비가 완료됩니다.
    • 로드 밸런서의 DNS 이름을 기록해둡니다 (예: my-loadbalancer-1234567890.us-east-1.elb.amazonaws.com).

2. 배포

2-1. EC2 보안 그룹 설정

HTTPS 요청을 허용하기 위해 EC2 인스턴스의 보안 그룹을 적절히 설정해야 합니다:

  1. EC2 콘솔 접속
    • AWS Management Console에서 EC2 인스턴스를 선택합니다.
  2. 보안 그룹 확인
    • 보안 > 보안 그룹 메뉴로 이동하여 EC2 인스턴스에 연결된 보안 그룹을 확인합니다.
  3. 인바운드 규칙 추가
    • 규칙 편집을 클릭하고 아래 항목을 추가합니다:
      • HTTPS (443): 0.0.0.0/0 (모든 IP 허용) 또는 제한된 IP 대역.
      • 기존 HTTP(80) 규칙도 유지하여 HTTP 요청도 처리 가능.
  4. 규칙 저장


2-2. 로드 밸런싱 설정

로드 밸런서를 EC2와 연결하기 위해 대상 그룹을 생성하고, 로드 밸런서 리스너를 설정합니다.

  1. 대상 그룹 생성
    • AWS Management Console에서 로드 밸런싱 > 대상 그룹으로 이동합니다.
    • 대상 그룹 생성 버튼을 클릭:
      • 대상 유형: 인스턴스.
      • 프로토콜: HTTP.
      • 포트: 8080 (Spring Boot 기본 포트).
      • VPC: EC2 인스턴스가 속한 VPC 선택.
  2. 대상 그룹에 EC2 추가
    • 생성된 대상 그룹에 EC2 인스턴스를 추가합니다:
      • 대상 등록을 클릭.
      • 대상 목록에서 EC2 인스턴스를 선택하고, 포트 8080으로 등록합니다.
  3. 로드 밸런서와 대상 그룹 연결
    • 로드 밸런서 > 리스너 탭으로 이동합니다.
    • HTTPS 리스너를 선택한 뒤, 대상 그룹을 새로 생성한 그룹으로 연결합니다.
    • 요청이 HTTPS(443) → 대상 그룹(HTTP 8080)으로 전달됩니다.

2-3. Route53에서 레코드 생성 (도메인 연결)

  1. Route53 콘솔 접속
    • AWS Management Console에서 Route53 서비스로 이동합니다.
  2. 호스팅 영역 선택
    • 1편에서 생성한 도메인의 호스팅 영역으로 이동합니다.
  3. 레코드 생성
    • 레코드 생성 버튼을 클릭하고 아래 항목을 입력합니다:
      • 레코드 이름: 기본적으로 비워 두면 도메인의 루트(https://yourdomain.com)로 설정됩니다.
      • 레코드 유형: A (IPv4 주소).
      • : 로드 밸런서의 DNS 이름 입력 (예: my-loadbalancer-1234567890.us-east-1.elb.amazonaws.com).
        • 로드 밸런서의 DNS 이름은 로드 밸런서 콘솔에서 확인할 수 있습니다.
      • Alias: 활성화된 상태로 설정.
        • Alias 대상: 로드 밸런서를 선택.
  4. 저장 및 확인
    • 레코드를 저장하고, Route53에서 DNS 전파가 완료될 때까지 기다립니다 (최대 24시간 소요 가능).

 

3. 결과

 

'AWS > 서버 배포' 카테고리의 다른 글

도메인 구매부터 HTTPS 배포까지 1편  (0) 2024.12.05

1편에서는 도메인 구매 방법, Route53 등록, Gabia 네임 서버 등록, ACM 인증서 발급을 말씀드리겠습니다.

1. Gabia에서 도메인 구매

  1. Gabia 사이트 접속
  2. Gabia 도메인 구매 페이지로 이동합니다.
  3. 도메인 검색 및 구매
    • 원하는 도메인을 검색창에 입력하여 사용 가능 여부를 확인합니다.
    • 사용 가능한 도메인을 선택한 뒤, 구매를 진행합니다.


2. Route53에 도메인 등록

  1. Route53 접속
    • AWS Management Console에서 Route53 서비스로 이동합니다.
  2. 호스팅 영역 생성
    • "호스팅 영역" 메뉴를 클릭한 뒤, "호스팅 영역 생성" 버튼을 누릅니다.
    • 도메인 이름에 Gabia에서 구매한 도메인을 입력하고, 퍼블릭 호스팅 영역을 선택합니다.
  3. 네임 서버 확인
    • 호스팅 영역 생성이 완료되면, AWS가 자동으로 네임 서버(NS) 목록을 생성합니다.
    • 생성된 네임 서버 목록을 기록해 둡니다. (예: ns-123.awsdns-45.com. 등)


3. Gabia 네임 서버 등록

  1. Gabia 네임 서버 설정
    • Gabia 계정에 로그인한 뒤, 구매한 도메인의 DNS 관리로 이동합니다.
    • 네임 서버 변경 메뉴를 선택합니다.
  2. AWS 네임 서버 등록
    • Route53에서 생성된 네임 서버 목록을 하나씩 입력합니다.
    • 주의: 네임 서버 입력 시, 마지막.(점)은 제외해야 합니다. 예: ns-123.awsdns-45.com. → ns-123.awsdns-45.com
  3. 저장 및 확인
    • 모든 네임 서버를 등록한 뒤 저장합니다. 네임 서버 변경 사항이 반영되는 데 약간의 시간이 소요될 수 있습니다.


4. ACM 인증서 발급

  1. AWS ACM 서비스 접속
    • AWS Management Console에서 Certificate Manager (ACM) 서비스로 이동합니다.
  2. 인증서 요청
    • "인증서 요청" 버튼을 클릭합니다.
    • 공용 인증서를 선택하고, 구매한 도메인을 입력합니다.예: yourdomain.com, www.yourdomain.com.
  3. 도메인 확인
    • AWS가 제공하는 DNS 값을 Route53에 추가하여 도메인 소유권을 확인합니다.
    • Route53에서 레코드 생성을 클릭합니다.
  4. 인증서 발급 완료
    • 도메인 소유권 확인이 완료되면, ACM 콘솔에서 상태가 "발급됨"으로 변경됩니다. 인증서 발급에는 약 30분 정도 소요됩니다.
    • 저는 기존에 1개 있어서 저렇게 뜨는데 처음 만드시는 분들은 무시하시면 됩니다.
     

 

 

 

'AWS > 서버 배포' 카테고리의 다른 글

도메인 구매부터 HTTPS 배포까지 2편  (0) 2024.12.07

이번 포스팅에서는 AWS EC2를 사용해 간단한 스프링 부트 API를 배포하고, 브라우저에서 결과를 확인하는 과정을 단계별로 안내합니다.


1. EC2 인스턴스 생성

1. AWS 접속

2. EC2 검색

  • AWS 검색창에서 "EC2"를 입력하여 EC2 대시보드로 이동합니다.

 

3. 인스턴스 시작

  • 인스턴스 시작 버튼을 클릭하고 아래와 같이 설정합니다
    • 이름: 원하는 이름 설정 (예: my-ec2-instance).
    • OS 선택: Ubuntu (최신 LTS 버전 선택).
    • 인스턴스 유형: 프리티어를 위해 t2.micro 선택.
    • 키 페어: 이번 프로젝트는 바로 삭제할 예정이므로 키 페어 없이 계속 진행 선택.
    • 네트워크 설정: 보안 그룹 생성을 선택하고 HTTP(80), HTTPS(443), SSH(22) 포트를 열어줍니다.
  • 설정 완료 후 인스턴스 시작 버튼을 클릭합니다.

 


2. 간단한 스프링 부트 프로젝트 생성

1. 스프링 부트 프로젝트 생성

  • Spring Initializr에서 새로운 프로젝트를 생성합니다.
    • Dependencies: Spring Web.
    • Build Tool: Maven 또는 Gradle.
  • 생성된 프로젝트에서 간단한 API를 작성합니다
@RestController
public class MainController {
    @GetMapping("/test")
    public String test() {
        return "EC2 quick test";
    }
}

 

2. GitHub에 프로젝트 업로드

  • 생성된 프로젝트를 로컬에서 GitHub에 업로드합니다.

3. EC2 인스턴스 연결

1. EC2 인스턴스 연결

  • AWS 관리 콘솔에서 생성된 인스턴스를 선택하고, 연결 버튼을 클릭합니다.

2. 필수 소프트웨어 설치

sudo apt update
sudo apt install openjdk-17-jdk git -y
  • EC2 인스턴스에 접속한 뒤, Java와 Git을 설치합니다

3. GitHub에서 프로젝트 클론

  • HTTPS 방식을 사용하는 경우, Personal Access Token을 생성하여 클론합니다:
  • git clone <https://github.com/>/.git


4. 보안 그룹 설정: 포트 8080 열기

  1. 보안 그룹 설정 확인
    • AWS EC2 대시보드에서 인스턴스를 선택하고 보안 그룹으로 이동합니다.
    • 인바운드 규칙 편집을 클릭하고 아래와 같은 규칙을 추가합니다:
      • Custom TCP Rule: 포트 8080.
      • Source: 0.0.0.0/0 (모든 IP 허용).
       


5. 스프링 부트 애플리케이션 실행

  1. 프로젝트 빌드 및 실행
    • 클론한 프로젝트 디렉토리로 이동한 뒤, Gradle을 사용해 애플리케이션을 실행합니다:
    • cd <your-repository> ./gradlew bootRun
  2. 애플리케이션 테스트
    • 브라우저에서 아래 URL로 접속하여 API 응답을 확인합니다:
    • http://<EC2_PUBLIC_IP>:8080/test


6. 결과

이제 간단한 스프링 부트 API가 EC2에서 성공적으로 실행되었습니다.

여기까지 따라오셨다면 EC2 서버와 스프링 부트를 연동하는 기본적인 과정을 이해하셨을 겁니다.

🎉 완성된 URL

  • 테스트 URL: http://<EC2_PUBLIC_IP>:8080/test

7. 학습하면 좋을 내용

 

  • 탄력적 IP (Elastic IP)
    • EC2 인스턴스의 공인 IP 주소를 고정하여 인스턴스 재시작 후에도 동일한 IP를 유지하는 방법.
  • EC2 인스턴스 완전 삭제
    • 사용하지 않는 EC2 인스턴스를 안전하게 종료하고, 스토리지와 연결된 리소스를 삭제하는 방법.
  • GitHub SSH 연동 방법
    • SSH 키를 사용해 GitHub에 인증하고, 더 간단하고 안전하게 프로젝트를 관리하는 방법.
  • Docker를 사용한 배포
    • Docker를 활용해 애플리케이션을 컨테이너화하고, EC2에서 손쉽게 배포하는 방법.

 

 

추가 참고사항

  • HTTPS 설정: HTTPS를 적용하려면 Spring Boot에서 SSL 인증서를 설정해야 합니다.
  • 보안: 실제 서비스에서는 보안 그룹의 0.0.0.0/0 설정을 사용하지 말고, 허용할 IP를 제한하는 것을 권장합니다.

'AWS > 학습정리' 카테고리의 다른 글

gabia 도메인 구매방법  (0) 2024.12.04
Route53  (1) 2024.12.03
ACM  (0) 2024.12.02
ELB  (0) 2024.12.02

+ Recent posts