반응형

개요

실제 개발 현장에서는 다양한 편의 기능을 위해 데이터를 파싱해야 하는 요구가 자주 발생합니다. 그러나 하드웨어 자원, 특히 메모리의 용량이 한정되어 있어, 대용량 JSON 파일을 ObjectMapper로 한 번에 읽어들일 경우 OutOfMemoryError가 발생할 수 있습니다.

이러한 문제를 해결하는 방법 중 하나는 Jackson의 Streaming API, 특히 JsonParser를 활용하는 것입니다. 본 글에서는 JsonParser를 이용해 대용량 JSON 파일을 스트리밍 방식으로 파싱하고, 필요한 데이터만 추출하여 텍스트(.txt) 파일로 저장하는 과정을 정리합니다.

Jackson Streaming API란?

  • Tree Model (JsonNode)
  • Data Binding (ObjectMapper)
  • Streaming API ✅ (JsonParser, JsonGenerator)

Streaming 방식은 이벤트 기반으로 JSON 데이터를 토큰 단위로 읽고 처리합니다. 대용량 JSON을 빠르고 메모리 효율적으로 처리할 수 있습니다.

 

구분  ObjectMapper JsonParser
방식 데이터 전체를 메모리에 로딩 후 파싱 한 줄씩 토큰 단위로 스트리밍 처리
메모리 사용량 크고 예측하기 어려움 매우 적고 안정적
속도 작은 데이터에 유리 대용량에서 효율적
구조 내부 객체 매핑 (DTO 필요) 직접 토큰 단위 파싱 필요
사용 예 REST API 응답 파싱, 간단한 JSON 변환 로그 분석, 빅데이터 전처리 등

예제 상황

  • 입력: data.json (대용량 JSON 배열)
  • 출력: output.txt (필요한 필드만 추출하여 텍스트 파일 저장)
{
  "result": [
    { "id": 1, "name": "test" },
    { "id": 2, "name": "test2" },
    ...
  ]
}

예제 코드

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;

import java.io.File;
import java.io.IOException;

public class JsonResultParser {
    public static void main(String[] args) {
        JsonFactory factory = new JsonFactory();

        try (JsonParser parser = factory.createParser(new File("input.json"))) {

            while (!parser.isClosed()) {
                JsonToken token = parser.nextToken();

                if (JsonToken.FIELD_NAME.equals(token) && "result".equals(parser.getCurrentName())) {
                    // "result": [ ... ] 까지 왔음
                    token = parser.nextToken(); // START_ARRAY

                    while (parser.nextToken() == JsonToken.START_OBJECT) {
                        // 배열 내부 객체 파싱
                        String name = null;
                        int id = -1;

                        while (parser.nextToken() != JsonToken.END_OBJECT) {
                            String fieldName = parser.getCurrentName();
                            parser.nextToken(); // move to value

                            switch (fieldName) {
                                case "name":
                                    name = parser.getText();
                                    break;
                                case "id":
                                    id = parser.getIntValue();
                                    break;
                                default:
                                    parser.skipChildren(); // 예외 필드는 무시
                            }
                        }

                        System.out.println("Parsed name: " + name + ", id: " + id);
                    }
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

주요 메서드 설명

  • parser.nextToken(): 다음 JSON 토큰으로 이동
  • parser.getCurrentName(): 현재 필드 이름 가져오기
  • parser.getText(): 현재 값 텍스트로 가져오기
  • parser.skipChildren(): 객체/배열 건너뛰기

주의사항

  • 필요한 필드만 추출하면 훨씬 빠르고 효율적입니다.
  • 파일 인코딩이 필요하면 OutputStreamWriter로 처리할 수 있습니다.

실제 적용 예

  • 로그 데이터를 날짜별로 분리하여 저장
  • 대용량 API 응답을 실시간으로 분석 및 요약
  • IoT 디바이스 JSON 로그 정제

마무리

ObjectMapper 대신 JsonParser를 활용하면, 대용량 데이터를 처리할 때 메모리 효율성과 속도를 모두 잡을 수 있습니다. 대용량 Json을 파싱하는데 효율적이며 

 

반응형
반응형

Java에서는 변수나 메서드, 클래스의 동작 방식을 제어하는 다양한 키워드가 존재합니다. 이 중에서도 volatile, transient, synchronized는 각각 메모리 동기화, 직렬화, 그리고 스레드 동기화와 관련된 중요한 역할을 합니다.


volatile 키워드

volatile은 멀티스레드 환경에서 변수의 값을 메인 메모리에 직접 저장하고, 모든 스레드가 항상 최신 값을 읽도록 보장하는 역할을 합니다.

적용 대상 변수
주요 기능 캐시된 값을 사용하지 않고 항상 메인 메모리의 최신값을 읽음
주로 사용하는 경우 스레드 간 변수 값 공유 시 데이터 일관성 유지
public class SharedData {
    private volatile boolean flag = false;

    public void writer() {
        flag = true; // 값 변경 시 바로 메인 메모리에 반영
    }

    public void reader() {
        if (flag) {
            // flag가 true로 바뀌면 반드시 이 코드가 실행됨
        }
    }
}

 

단, volatile원자적 연산(atomic operation)을 보장하지 않으므로, 복합 연산이 필요하면 synchronized를 함께 사용해야 합니다.


transient 키워드

transient 키워드는 Java 기본 직렬화(ObjectOutputStream 등) 과정에서 특정 필드를 직렬화 대상에서 제외하고자 할 때 사용합니다.
즉, 직렬화 시점에 해당 필드는 저장되지 않으며, 역직렬화 후에는 기본값으로 초기화됩니다.

적용 대상 변수
주요 역할 Java 기본 직렬화 시 필드 제외

 

class User implements Serializable {
    String username;
    transient String password; // Java 직렬화 시 제외
}

transient 키워드 vs @JsonIgnore 어노테이션

구분 transient @JsonIgnore
적용 대상 변수 변수, 메서드
직렬화 대상 Java 기본 직렬화 (ObjectOutputStream) JSON 직렬화/역직렬화 (Jackson, Gson 등)
주요 역할 직렬화 시 필드 제외 JSON 변환 시 필드 제외
사용 시점 Java 직렬화를 직접 사용하는 경우 REST API JSON 응답/요청 시 민감 데이터 숨길 때
사용 예시
transient String password;
@JsonIgnore
private String password;
비고 Java 기본 직렬화에 한함 JSON 변환 제어에 특화

 

실무에서는 REST API 응답 시 민감 정보를 숨기기 위해 @JsonIgnore를 많이 사용하며, Java 기본 직렬화 목적이라면 transient를 사용합니다.


synchronized 키워드

synchronized는 멀티스레드 환경에서 임계 영역(critical section)을 보호하여, 동시에 한 스레드만 접근 가능하도록 하는 동기화 기능을 제공합니다.

적용 대상 메서드, 코드 블록
주요 기능 스레드 간 동시 접근 방지 및 데이터 일관성 유지
사용 목적 공유 자원 접근 시 레이스 컨디션 예방

 

public class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++; // 이 메서드는 한번에 한 스레드만 접근 가능
    }

    public int getCount() {
        return count;
    }
}

또는 특정 코드 블록만 동기화할 수도 있습니다.

public void add(int value) {
    synchronized(this) {
        count += value;
    }
}

주의할 점은 동기화 과도 사용 시 성능 저하가 발생할 수 있으므로, 필요한 부분에만 최소한으로 적용하는 것이 좋습니다.


요약 비교표

키워드 적용 대상 주요 역할 사용 시기
volatile 변수 메인 메모리와 변수 값 동기화, 최신 값 보장 멀티스레드 변수 값 공유 시
transient 변수 Java 기본 직렬화 시 필드 제외 객체 직렬화 시 제외 필드 지정
synchronized 메서드, 블록 임계 영역 보호, 동시 접근 방지 멀티스레드 환경에서 데이터 무결성 필요할 때

 


실무 팁

  • volatile는 원자적 연산이 아닌 단순 값 변경 공유에 적합하며, 복합 연산은 synchronized를 병행 사용하세요.
  • transient@JsonIgnore는 각각 직렬화 환경(Java 기본 직렬화 vs JSON)에서 필드 제외를 위해 사용하므로, 목적에 맞게 선택해야 합니다.
  • synchronized는 꼭 필요한 부분에 최소한으로 사용해 성능 저하를 방지하세요.

마무리

Java의 volatile, transient, synchronized 키워드는 모두 멀티스레드 처리, 직렬화, 데이터 일관성 유지 등에서 매우 중요한 역할을 합니다.
각 키워드가 가진 특징과 차이점을 이해하고, 상황에 맞게 적절히 활용하는 것이 안정적이고 효율적인 Java 프로그래밍의 핵심입니다.

반응형
반응형

Java에서는 특정한 예약어(keywords)들을 사용해 클래스/메서드/변수의 속성을 제한하거나 제어할 수 있습니다.
이 글에서는 가장 많이 사용되는 final, static, this, super 키워드에 대해 정리하고, 언제 어떻게 사용하는지 코드 예제와 함께 비교해보겠습니다.


final 키워드

final수정 불가(변경 불가능)를 의미합니다. 변수, 메서드, 클래스 등 다양한 곳에 사용됩니다.

적용 대상 의미
변수 값이 한 번만 할당 가능 (상수처럼 사용)
메서드 오버라이딩 불가
클래스 상속 불가

 

final int MAX_COUNT = 10;
MAX_COUNT = 20; // 컴파일 에러

final class Animal {}
class Dog extends Animal {} // 컴파일 에러 (상속 불가)

class Parent {
    final void speak() {}
}
class Child extends Parent {
    void speak() {} // 에러: final 메서드는 오버라이드 불가
}

static 키워드

static공용(클래스 단위) 개념입니다. 인스턴스 생성 없이 사용 가능하고, 메모리 효율성을 높입니다.

적용 대상 의미
변수 모든 객체가 공유하는 클래스 변수
메서드 객체 없이 클래스명으로 호출 가능
블록 클래스 초기화 시 자동 실행되는 정적 블록

 

class Counter {
    static int count = 0;

    Counter() {
        count++;
        System.out.println(count);
    }
}

Counter c1 = new Counter(); // 1
Counter c2 = new Counter(); // 2

this 키워드

this현재 인스턴스 자신을 참조합니다. 주로 변수 이름 충돌 해결이나 코드의 가독성을 높이기 위해 명시적으로 사용합니다.

class Person {
    String name;

    Person(String name) {
        this.name = name; // 왼쪽: 인스턴스 변수, 오른쪽: 매개변수
    }

    void print() {
        System.out.println(this.name); // 현재 인스턴스의 name
    }
}

super 키워드

super부모 클래스 요소에 접근할 때 사용합니다. 생성자 호출이나 오버라이드 메서드 안에서 사용됩니다.

class Parent {
    String name = "부모";
    void greet() {
        System.out.println("안녕 from 부모");
    }
}

class Child extends Parent {
    String name = "자식";

    void greet() {
        super.greet(); // 부모 메서드 호출
        System.out.println(super.name); // 부모 변수 접근
    }
}

요약 비교표

키워드 사용 위치 주요 기능
final 변수/메서드/클래스 값/상속/오버라이드 불가로 제한
static 변수/메서드/블록 클래스 단위로 공유, 인스턴스 없이 접근
this 인스턴스 내부 현재 객체 참조, 변수 충돌 해결, 코드 가독성을 위한 명시적 사용
super 상속 구조 내부 부모 클래스 요소 참조 (메서드, 변수 등)

 


실무 팁

  • final 변수는 상수처럼 사용하며, static final 조합으로 전역 상수를 선언할 수 있습니다.
  • static 메서드는 공용 기능을 제공하는 유틸성 클래스에서 많이 사용됩니다.
  • this는 주로 생성자 파라미터 명과 멤버변수 이름이 같을 때 사용하거나, 코드 가독성을 위해 명시적으로 사용할 때 사용합니다.
  • super는 오버라이딩한 메서드에서 부모의 로직을 확장할 때 유용합니다.

마무리

Java의 핵심 키워드인 final, static, this, super는 객체 지향 프로그래밍에서 매우 자주 사용됩니다.
각각의 의미와 쓰임을 정확히 이해하고, 상황에 맞게 사용하는 것이 중요합니다.

반응형
반응형

자바 변수의 종류

변수는 크게 네 종류로 변수의 선언된 위치에 따라서 클래스변수, 인스턴스변수, 지역변수, 매개변수로 나뉜다.

public class Main {
	public static void main(String[] args) { // 매개변수
    	int num = 0; // 지역변수
    }
}

public class Page {

	private int state = 0; // 인스턴스 변수
    public static int page = 10; // 클래스 변수
    public int get() {
    	return state;
    }
}
변수명 선언위치 설명 저장 메모리
클래스 변수
(class variable)
= static 변수
클래스 영역 클래스 영역에서 타입 앞에 static이 붙는 변
객체를 공유하는 변수로 여러 객체에서 공통으로 사용하고 싶을 때 정의
Method
인스턴스 변수
(instance variable)
클래스 영역에서 static이 아닌 변수
개별적인 저장 공간으로 객체/인스턴스마다 다른 값 저장 가능

* 객체/인스턴스 생성만하고 참조 변수가 없는 경우 가비지 컬렉터에 의해 자동 제거됨
Heap
지역 변수
(local variable)
메서드 영역 메서드 내에서 선언되고 메서드 수행이 끝나면 소멸되는 변수
초기값을 지정한 후 사용할 수 있음
Stack
매개 변수
(parameter)
메서드 호출 시 '전달하는 값'을 가지고 있는 인수
(지역 변수처럼 선언된 곳부터 수행이 끝날 때까지 유효함)

 

자바의 메모리 영역

자바 프로그램을 실행하게되면, JVM은 OS로 부터 메모리를 할당 받고 Method, Stack, Heap 각 세 영역에 맞춰서 할당하게 된다.

 - 메소드 (Method) 영역 : 전역변수와 static 변수를 저장하며, Method 영역은 프로그램의 시작부터 종료까지 메모리에 남아있음

 - 스택 (Stack) 영역 : 지역변수와 매개변수 데이터 값이 저장되는 공간이며, 메소드가 호출될 때 메모리에 할당되고 종료되면 메모리가 해제. LIFO (Last In First Out) 구조를 갖고 변수에 새로운 데이터가 할당되면 이전 데이터는 지워짐

 - 힙 (Heap) 영역 : new 키워드로 생성되는 객체 (인스턴스), 배열 등이 Heap 영역에 저장되며, 가비지 컬렉션에 의해 메모리가 관리

 - PC Register : JVM이 실행하고 잇는 현재 위치를 저장하며, 스레드가 생성되면서 생기는 공간

 - Native Method Stack : Java가 아닌 다른 언어로 구성된 메소드 실행이 필요할 때 사용되는 공간

 

자바의 각 메모리 영역이 할당되는 시점?

 - Method : JVM 동작 후 클래스가 로딩 될 때 생성

 - Stack : 메소드가 호출될 때 할당

 - Heap : 런타임시 할당

 

원시 타입 vs 참조 타입의 메모리 영역

원시 타입 : Stack에 값이 그대로 저장되는 타입 / 참조가 없어서, 빠르게 값에 접근 가능

참조 타입 : Stack에 Heap의 어딘가를 가리키는 주소가 저장

 

반응형
반응형

인터페이스 vs 추상클래스 비교

인터페이스 (implements) : 인터페이스에 정의된 메서드를 각 클래스 목적에 맞게 기능을 구현

추상클래스 (extends) : 자신의 기능들을 하위 클래스로 확장

  추상 클래스 인터페이스
사용 키워드 abstract interface
사용 가능 변수 제한 없음 static final (상수)
사용 가능 접근 제어자 제한 없음 (public, private, protected, default) public
사용 가능 메소드 제한 없음 abstract method, default method, static method, private method
상속 키워드 extends implements
다중 상속 가능 여부 불가능 가능 (클래스에 다중 구현, 인터페이스 끼리 다중 상속)
공통점 1. 추상 메소드를 가지고 있어야한다.
2. 인스턴스화 할 수 없다. (new 생성자 사용 x)
3. 인터페이스 혹은 추상 클래스를 상속받아 구현한 구현체의 인스턴스를 사용해야 한다.
4. 인터페이스와 추상클래스를 구현, 상속한 클래스는 추상 메소드를 반드시 구현하여야한다.

 

사용 시기 및 목적

추상클래스 : 상속 관계 시, 부모나 조상클래스를 상속하는데 기능까지 같은 경우 추상클래스 사용

                     (상속, 확장하여 사용)

인터페이스 : 상속 관계 시, 부모나 조상클래스를 상속하는데 다른 기능이 필요할 경우 인터페이스 사용

                     (동일한 사용방법과 동작을 보장하기 위해 사용)

반응형
반응형

SQL Injection이란?

웹 애플리케이션과 데이터베이스 간의 연동으로 발생하는 취약점으로, 공격자가 입력 폼에 악의적으로 조작된 쿼리를 삽입하여 데이터베이스 정보를 불법적으로 열람하거나 조작할 수 있는 방식

 

SQL Injection 공격 유형

Error based SQL injection (논리적 에러를 활용한 SQL 인젝션) 

  - 가장 대중적인 기법으로, 인증 우회를 위해 논리적 에러를 유도하는 방식의 공격 기법

-- 정상적인 input
SELECT * FROM user WHERE id = 'id' AND pwd = 'pwd'

-- 비정상적인 input
'OR 1=1 --'

-- 인증 우회를 통한 비정상적 input
SELECT * FROM user WHERE id = '' OR 1=1 --
==> SELECT * FROM user 결과값 도출

 

Union SQL Injection (UNION 명령어를 활용한 SQL 인젝션)

  - 공격자가 추가적인 쿼리를 삽입하여 정보를 획득하는 기법으로, UNION 명령어를 이용하여 여러 쿼리를 합치는 방식을 이용, UNION을 하려는 두 테이블의 컬럼 수와 데이터 형식이 같아야 하므로 ORDER BY 절이나 HAVING을 이용한 오류 메시지를 통해 컬럼의 수를 유추

-- 정상적인 input
SELECT * FROM board WHERE title = 'title' and contents = 'contents'

-- 비정상적인 input
'UNION SELECT id, pwd FORM user --'

-- UNION을 통한 비정상적 input
SELECT * FROM board WHERE title LIKE '' UNION SELECT id, pwd FORM user --

==> SELECT * FROM board 컬럼에 user 정보 합계되서 결과값 도출


Blind SQL Injection (Boolean based SQL)

  - 서버의 반응을 통해 정보를 얻는 SQL 공격 기법으로, 단순히 참과 거짓의 정보한 알 수 있을 때 사용하는 공격 기법. 조건이 참이면 페이지가 정상적으로 출력되고 그렇지 않은 경우 출력되지 않음으로 구분이 가능

-- Boolean 기반 공격 예시
-- 정상적인 input
SELECT * FROM user WHERE id = 'id' and pwd = 'pwd'

-- 비정상적인 input
'abc123' and ASCII(SUBSTR((SELECT name FROM information_schema.tables WHERE table_type='base table' limit 0,1),1,1)) > 100 --'

-- Boolean 통한 비정상적 input
SELECT * FROM user WHERE id = 'abc123' and ASCII(SUBSTR((SELECT name FROM information_schema.tables WHERE table_type='base table' limit 0,1),1,1)) > 100 --

-- Time 기반 공격 예시
-- 정상적인 input
SELECT * FROM user WHERE id = 'id' and pwd = 'pwd'

-- 비정상적인 input
'abc123' OR (LENGTH(DATABASE())=1 AND SLEEP(2)) --

-- Time을 통한 비정상적 input
SELECT * FROM user WHERE id = 'abc123' OR (LENGTH(DATABASE())=1 AND SLEEP(2)) --

 

Stored Procedure based SQL Injection

  - 웹에서 저장 프로시저에 대한 접근 권한을 가짐으로써 정보를 탈취할 수 있는 공격 기법

 

Mass SQL Injection

  - 한 번의 공격으로 다량의 DB를 조작해 큰 피해를 입히는 공격 기법

 

SQL Injection 대응 방안

입력값 검증

  - 사용자의 입력을 받을 때 검증 로직을 추가하여 값이 유효한지 검증하는 방법
     (데이터 길이 제한, 특수문자와 명령어 필터링 등)

 

Prepared Statement 구문 사용

  - 사용자의 입력 값이 데이터베이스의 파라미터로 들어가기 전에 DBMS가 미리 컴파일하여 실행하지 않고 대기. 그 후 사용자의 입력 값을 문자열로 인식하여 공격 쿼리가 들어간다고 하더라도, 단순 문자열로 인식하여 공격을 무효화하는 방법

 

Error Message 노출 금지

  - SQL Injection을 수행하기 위해서는 데이터베이스의 정보가 필요하기 때문에, 오류 발생 시 사용자에게 보여주는 로그를 별도로 작업하여 데이터베이스 정보 유출 방지하여 공격을 무효화 하는 방법

 

웹 방화벽 사용

  - 웹 공격 방어에 특화되어있는 웹 방화벽을 사용하는 방법

반응형

'개발새발 > 기타' 카테고리의 다른 글

코딩 스타일 괄호 및 표기법  (1) 2021.05.27
반응형

에러 메시지

 

Database "C:/Users/kai/test" not found, either pre-create it or allow remote database creation [90149-214] 90149/90149

 

원인

H2 Database를 처음 연동할 시 주로 볼 수 있는 에러이다.

주로 연동 이후 웹 H2 Console로 연결 테스트를 진행할 때 볼 수 있는 에러인데, 해당 에러의 경우 보안 정책상 데이터베이스를 생성할 수 없어서 데이터베이스를 별도로 생성해 주거나, 원격 데이터베이스 생성을 허용해야 한다.

 

해결방법

보안상으로 추천되지 않으니, 직접 데이터베이스를 생성하려면 에러 메시지 상의 위치 C:/User/kai [사용자명]/test [데이터베이스명]로 이동하여서 test.mv.db 파일을 생성하면 해당 문제를 해결할 수 있다.
test의 경우 데이터베이스명이므로, jdbc:h2:~/errortest 같은 경우에는 errortest.mb.db로 데이터베이스 파일을 생성하여야 한다.

데이터베이스를 생성한 뒤, 다시 Test Connection을 실행하면 아래와 같은 성공 메시지를 볼 수 있다.

반응형

'개발새발 > 이슈' 카테고리의 다른 글

Connection NetworkTimeout 에러 (HikariCP)  (2) 2021.06.01
반응형

Spring Boot에서 JS(Javascript) 사용?

자바에서 제공하는 API인 Java Scripting API를 통해서, 자바에서 자바스크립트 함수 호출이 가능하다.

js 파일 및 설정

js를 사용하기 위해선, 우선 해당 스크립트가 적용된 js파일을 적용할 필요가 있다.
resources 하단에 사용할 js 파일을 정리하여 resources/js/aes.js 와 비슷한 형태로 적용하면 된다.
해당 부분은 css, image 파일 또한 동일하게 적용 가능하다.

 

application.yml 설정

local.yml
prod.yml

js 파일을 설치하여, 적용하였으면 해당 부분의 경로를 불러오기 위해 설정을 진행하여야 하는데

local, dev, prod 각 설정에 맞게 절대 경로를 지정하여 사용하면 된다. (build 이후 경로의 차이가 존재)

 

Java Scripting API 사용

JavaScripting API의 ScriptEngine을 통해 스크립트 엔진을 호출하여 aes.js 자바 스크립트 파일을 불러오는 소스이다.
간략하게 decrypt 함수를 호출하는 방식으로, JavaScripting의 인터페이스를 활용하여 작업이 가능하다.

// 스크립트 엔진 호출
ScriptEngineManager sem = new ScriptEngineManager();
ScriptEngine se = sem.getEngineByName("JavaScript");

// js 파일 호출
URL resourceUrl = this.getClass().getClassLoader().getResource("js/aes.js");
String fileLocation = resourceUrl.getFile();

// evel 메소드를 사용하여 컴파일
try {
	se.eval(new FileReader(fileLocation));
} catch (FileNotFoundException | ScriptException e) {
	e.printStackTrace();
}

String aesKey = "test";
String ob = null;
// 자바스크립트의 함수를 실행하게 해주는 Invocable
Invocable inv = (Invocable) se;

// invokeFunction을 통한 특정 함수 호출
try {
	ob = (String) inv.invokeFunction("decrypt", input, aesKey, 256);
} catch (NoSuchMethodException | ScriptException e) {
	e.printStackTrace();
}

 

반응형

'개발새발 > Spring Boot' 카테고리의 다른 글

Lombok 설치 및 STS 연동  (0) 2021.05.22
Spring Boot 프로젝트 설정 방법  (0) 2021.05.19
반응형

UF (Universal Forwarder) 란 ?
Splunk Enterprise로 데이터를 보내기 위해 로그 등의 데이터를 수집할 서버 설치하는 간소화된 Splunk이다.

리소스 사용량은 3% 내외지만, 데이터 전송량이 늘어날 경우 늘어나며 데이터 전송 속도의 제한이 기본적으로 존재하기 때문에 리소스 사용량을 마냥 신뢰할 수 없다는 것이 함정이다.

 

UF 설치 방법

U/F는 기존 Splunk 설치 파일과 별도의 설치 파일을 해당 OS에 알맞게 Splunk 사이트에서 다운로드하여 설치하면 된다.

https://www.splunk.com/en_us/download/previous-releases/universalforwarder.html

 

universalforwarder

 

www.splunk.com

사이트 주소에 접속하여 파일을 다운로드 한 뒤, 

https://kairuen.tistory.com/9

 

Splunk 설치 및 설정

Splunk란? 스플렁크(Splunk)는 웹 기반 인터페이스를 통해 데이터 수집, 검색, 분석 및 모니터링을 위한 비정형 데이터 분석 솔루션이다. 현업에서는 주로, 보안 혹은 관제를 위한 빅데이터 솔루션으

kairuen.tistory.com

기존 Splunk 설치 방법과 동일하게 설치 및 설정을 진행하면 된다.

 

U/F 설정

기본적으로 U/F에서는 conf 파일을 수정하여, 데이터 수집 및 전달, 속도 제한 등의 설정이 가능하다.

경로는 $SPLUNK_HOME/etc/system/local 으로 들어가서 해당 파일명으로 생성한 뒤 아래 내용을 필요에 맞게 설정하면 된다.

 

outputs.conf (데이터 전송 설정)

[tcpout]

defaultGroup = <target_group> : 인덱스로 보낼 그룹명 지정

[tcpout:<target_group>]

server = [<ip>|<servername>]:<port> : 인덱스로 보낼 IP 및 포트 지정

[tcpout-server://<ip address>:<port>] : 인덱스로 전송

 

inputs.conf (데이터 수집 설정)

[default]

host = <string> : 데이터 전송 시, 호스트명

index = <string> : 데이터 전송 시, 저장할 인덱스

source = <string> : 데이터 전송 시, 소스 설정

sourcetype = <string> : 데이터 전송 시, 소스 타입 설정

[monitor://<path>] : 모니터링할 폴더 및 파일 지정

_TCP_ROUTING = <tcpout_group_name> : 모니터링 후 데이터 전송할 그룹

 

limit.conf (U/F 제한 설정)

[thruput]

maxKBps = <integer> : 데이터 전송 속도 설정 (기본 256 Kbps) - 대부분 빅데이터를 구축하기 위함이므로 설정 변경 필요

 

등의 파일을 기본적으로 설정해주면 된다.

이러한 설정 이외에도 여러 가지 conf가 존재하며 각 설정 하위에도 추가적인 설정은 존재하지만, 기본적인 데이터 전송은 위의 설정만 추가하여도 가능하다.

반응형

'개발새발 > Splunk' 카테고리의 다른 글

Splunk 설치 및 설정  (0) 2021.05.26
반응형

Spring Boot를 작업하다보면, 간혹 해당 에러에 대해서 확인할 수 있다.

별도의 설정을 하지 않는다면, Spring Boot에서는 Hikari가 기본적으로 제공되는데, 해당 기본 세팅이 연결한 DBMS 세팅과 차이가 존재하여, Connection 에러가 뜨는 것이라고 볼 수 있다.

 

java.sql.SQLException: Connection.setNetworkTimeout cannot be called on a closed connection
        at org.mariadb.jdbc.internal.util.exceptions.ExceptionMapper.getSqlException(ExceptionMapper.java:277) ~[mariadb-java-client-2.4.4.jar!/:na]
        at org.mariadb.jdbc.MariaDbConnection.setNetworkTimeout(MariaDbConnection.java:1700) ~[mariadb-java-client-2.4.4.jar!/:na]
        at net.sf.log4jdbc.sql.jdbcapi.ConnectionSpy.setNetworkTimeout(ConnectionSpy.java:1120) ~[log4jdbc-log4j2-jdbc4.1-1.16.jar!/:na]
        at com.zaxxer.hikari.pool.PoolBase.setNetworkTimeout(PoolBase.java:556) [HikariCP-3.4.2.jar!/:na]
        at com.zaxxer.hikari.pool.PoolBase.quietlyCloseConnection(PoolBase.java:133) [HikariCP-3.4.2.jar!/:na]
        at com.zaxxer.hikari.pool.HikariPool.lambda$closeConnection$1(HikariPool.java:447) [HikariCP-3.4.2.jar!/:na]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_252]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_252]
        at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_252]

 

우선, 설정을 변경하기 전에 DB에 설정된 값을 확인하여야하는데, 해당 SQL을 통해 확인할 수 있다.

 

SHOW variables LIKE '%time%'

 

 

해당 SQL을 사용시, 아래와 같은 결과 값을 볼 수 있으며 여기서 두 가지의 데이터를 매핑 시키면 된다.

 

DB HikariCP
wait_timeout max-lifetime
connect_timeout connection-timeout
  • max-lifetime : 커넨션의 최대 유지 시간 설정. 사용중인 커넥션은 maxLifetime에 상관없이 제거되지않고, 사용중이지 않을 때만 제거된다. 0으로 설정하면 무한 lifetime이 적용되지만, idle-timeout 설정되어 있는 경우에는 적용되지 않는다. (default: 1800000 (30분))
  • connection-timeout : pool에서 커넥션을 얻어오기전까지 기다리는 최대 시간. 허용가능한 시간을 초과하면 SQLException이 발생하며, 설정가능한 가장 작은 시간은 250ms 이다. (default: 30000 (30초))

해당 데이터의 시간을 확인하고, DB의 경우는 초(seconds) 단위 HikariCP의 경우 밀리세컨드(millisecond) 단위를 사용하기 때문에 변환기를 사용하거나 혹은 계산하여 HikariCP에 설정할 시간을 계산한 뒤에 1~2초 정도 적게 설정하면 된다

계산이 다 끝난 경우에는 properties 파일에 해당 데이터를 입력하면 해당 에러를 해결할 수 있다.

 

spring.datasource.hikari.connection-timeout=58000
spring.datasource.hikari.max-lifetime=580000
반응형

+ Recent posts