자바에서 문자열 처리를 하다 보면, 특정 패턴을 찾기 위해 **정규표현식(Regex)**을 사용하게 됩니다. 그런데 저는 **문자 그대로의 \n**을 찾으려고 할 때 예상치 못한 문제를 겪었습니다. 이 글에서는 제가 겪은 문제와 이를 어떻게 해결했는지 공유하고자 합니다.


문제 상황: \n을 찾으려는데 매칭이 되지 않음

목표: 문자열에서 문자 그대로의 \n (백슬래시와 문자 n)을 찾고 싶었습니다.


원인 분석: 이스케이프 문자의 이중 처리 필요

1. 정규표현식에서의 \n과 \\n

  • \n: 정규표현식에서 줄바꿈 문자를 의미합니다.
  • \\n: **문자 그대로의 \와 n**을 매칭합니다.
    • 첫 번째 \는 이스케이프 문자로 사용되고, 두 번째 \는 실제 백슬래시를 나타냅니다.

 

2. 자바 문자열에서도 똑같이 처리 된다

 

3. 때문에 자바 문자열 -> 정규표현식 처리

 

자바 문자열이 \\n 으로 입력되고 정규표현식에서는 \n 으로 처리되어서 문자열을 찾기 때문에 

줄바꿈 문자로 취급되기때문에

 

자바문자열을 \\\\n으로 입력되면 정규표현식으로 \\n으로 인식 -> "\n" 문자를 찾게 됩니다

 

자바 문자열 리터럴에서의 이스케이프

정규표현식 엔진에서의 해석

가 두번 처리됨을 유의해야된다는 것입니다

 

때문에 //를 두번 써줘야 합니다

 


해결 방법: 올바른 이스케이프 처리로 패턴 작성하기

1. 자바 코드에서 패턴을 작성할 때 \\\\n으로 입력

  • 자바 문자열에서 \\는 백슬래시(\)를 의미하므로, 정규표현식의 \\n을 표현하려면 \\\\n으로 작성해야 합니다.

2. 코드 예시

public class FindLiteralBackslashN {
    public static void main(String[] args) {
        // 입력 문자열: 문자 그대로의 \n 포함
        String input = "이 문자열에는 \\n 이 포함되어 있습니다.";

        // 정규표현식 패턴: \\n (자바 문자열에서는 \\\\n)
        String regexPattern = "\\\\n";

        // 패턴 컴파일
        Pattern pattern = Pattern.compile(regexPattern);
        Matcher matcher = pattern.matcher(input);

        // 매칭 확인
        if (matcher.find()) {
            System.out.println("문자 그대로의 \\n을 찾았습니다!");
            System.out.println("매칭된 부분: " + matcher.group());
        } else {
            System.out.println("문자 그대로의 \\n을 찾지 못했습니다.");
        }
    }
}​

4. 실행 결과

 
문자 그대로의 \n을 찾았습니다! 매칭된 부분: \n

왜 이렇게 해야 할까?

이스케이프 처리 단계별 이해

  1. 자바 문자열 리터럴에서의 이스케이프:
    • "\\\\n"은 자바 문자열에서 "\\n"으로 해석됩니다.
    • 각 \\는 하나의 \로 변환됩니다.
  2. 정규표현식 엔진에서의 해석:
    • "\\n"은 정규표현식에서 \n으로 인식됩니다.
    • 하지만 정규표현식에서 \n은 줄바꿈 문자가 아니라 **백슬래시와 문자 n**을 의미합니다.
  3. 매칭 과정:
    • 입력 문자열에서 **\**와 **n**이 연속으로 나타나는 부분을 찾아 매칭합니다.

요약 및 정리

  • 문자 그대로의 \n을 찾기 위해서는 정규표현식 패턴을 \\n으로 설정해야 합니다.
  • 자바 코드에서 이 패턴을 표현하려면 \\\\n으로 작성해야 합니다.
    • 자바 문자열에서 백슬래시를 표현하기 위해 \\를 사용하기 때문입니다.
  • 따라서, 자바에서 정규표현식을 사용할 때는 자바 문자열과 정규표현식의 이스케이프 처리를 모두 고려해야 합니다.

결론

자바에서 정규표현식을 사용하여 특정 문자를 찾을 때는 이스케이프 문자의 처리에 주의해야 합니다. 특히, 백슬래시(\)는 자바 문자열과 정규표현식 모두에서 특별한 의미를 가지므로, 이를 올바르게 이스케이프하지 않으면 의도한 대로 동작하지 않을 수 있습니다.

핵심 포인트:

  • 정규표현식에서 문자 그대로의 \n을 매칭하려면 \\n을 사용한다.
  • 자바 문자열에서 이 정규표현식을 표현하려면 \\\\n으로 작성한다.

이 원리를 이해하면 비슷한 문제를 해결할 때 큰 도움이 될 것입니다.


Tip: 다른 이스케이프 문자를 찾을 때도 동일한 원리가 적용됩니다. 예를 들어, 문자 그대로의 \t를 찾고 싶다면 정규표현식은 \\t, 자바 문자열에서는 "\\\\t"로 작성해야 합니다.

 

#H2 데이터베이스

 

h2 데이터 베이스는 3가지 모드가 있는데

상세한 내용이 궁금하면 

https://www.h2database.com/html/cheatSheet.html

 

H2 Database Engine

Using H2 Documentation Reference: SQL grammar, functions, data types, tools, API Features: fulltext search, encryption, read-only (zip/jar), CSV, auto-reconnect, triggers, user functions Embedded jdbc:h2:~/test 'test' in the user home directory jdbc:h2:/da

www.h2database.com

공식 문서를 참조하도록 하자

 

H2 Database의 3가지 모드

3가지 모드

Mode                                              : H2 다운로드여부   실행 주체                      DB 저장 위치

Server Mode O 외부 로컬(파일 시스템)
Embedded Mode X 스프링 로컬(파일 시스템)
In-Memory Mode X 스프링 메모리

 

#간단요약

Server Mode

  • 실행 파일 다운로드 필요: Yes
  • 서버 실행 방법: 외부 터미널에서명령어로 실행
  • Spring 설정: application.properties에 서버 주소 입력
  • 데이터 저장 위치: 로컬 파일 시스템(영속적) 

Embedded Mode

  • 실행 파일 다운로드 필요: No
  • 실행 방법: build.gradle 및 application.properties 설정
  • Spring 설정: Spring Boot 실행 시 함께 실행
  • 데이터 저장 위치: 로컬 파일 시스템 ( 영속적)

In-Memory Mode

  • 실행 파일 다운로드 필요: No
  • 실행 방법: build.gradle 및 application.properties 설정
  • Spring 설정: Spring Boot 실행 시 함께 실행
  • 데이터 저장 위치: 메모리 (휘발성)

 

 

 

 

 

Server Mode

  • 특징
    • H2 실행 파일을 다운로드해야 함.
    • 외부에서 터미널을 통해 H2 서버를 실행해야 함.
    • 서버 실행 후 스프링에서 application.properties에 서버 주소를 입력해 접속.
    • H2 DB 데이터를 로컬 파일 시스템에 저장하고 사용.
  • 장점
    • 여러 애플리케이션이 동시에 접근 가능.
    • 데이터가 영속적으로 저장됨.
    • PageStore 엔진 동기화로 데이터 정합성 유지 가능.
  • 단점
    • TCP/IP를 통해 데이터 전송하므로 상대적으로 느림.
    • 서버 설정이 필요하고 복잡함.
  • 사용법:
    • 터미널에서 H2 서버 실행 방법 (Mac):
      1. H2 다운로드 폴더로 이동
      2. bin 폴더 경로에서 터미널 실행
      3. ./h2.sh 입력

 

즉 정리하자면 서버모드는 h2 실행파일을 받아야 되고

외부에서 접근을 한다, 그렇기때문에 터미널로 h2 서버를 실행해야 되고

서버를 실행하여 application.properties 로 서버주소 입력해 접속한다.

 

JVM과 DB를 별도로 동작시키기 때문에 데이터베이스가 영속적이다.

임베디드 모드랑 비슷한데 데이터가 TCP/IP 로 처리된다는 부분이 다르다 

그리고 다중 접근이 가능하다는 점이 주요하게 다르다

그렇기때문에 더 느리다

 

Embedded Mode

  • 특징
    • H2 실행 파일 다운로드가 필요 없음.
    • build.gradle 및 application.properties 설정을 통해 실행 가능.
    • 스프링 부트 실행 시 함께 H2 실행.
    • H2 DB 데이터를 로컬 파일 시스템에 저장하고 사용.
  • 장점
    • 메모리로 직접 접근하여 빠른 데이터 처리.
    • 스프링 부트가 지원하는 SQL 파일을 통해 쉽게 DDL, DML 적용 가능.
  • 단점
    • 애플리케이션의 쓰레드와 자원을 사용하여 애플리케이션 상태에 영향을 받음.
    • 데이터베이스 손실 위험 존재 (쿼리, 연산 중 I/O 핸들러 종료 시).

 

 

In-Memory Mode

  • 특징
    • H2 실행 파일 다운로드가 필요 없음.
    • build.gradle 및 application.properties 설정을 통해 실행 가능.
    • 스프링 부트 실행 시 함께 H2 실행.
    • H2 DB 데이터를 메모리에만 저장하여 사용.
  • 장점
    • 파일 시스템이나 네트워크를 사용하지 않고 애플리케이션 내부에서만 데이터 유지.
    • 빠른 성능으로 테스트에 매우 유용.
  • 단점
    • 서버를 재시작하면 데이터가 삭제됨.
    • 데이터의 영속성이 필요할 경우 부적합.

 

인 메모리 모드는 메모리에만 가지고 있기 때문에 재시작 하게 되면 삭제되기 때문에 주의해야되고

임시적으로 빠르게 필요할때 유용하다고 할 수 있다.

 

 

H2 DB 설정 방법

1. build.gradle에 의존성 추가

gradle
dependencies {
   implementation 'org.springframework.boot:spring-boot-starter-jdbc'
   implementation 'com.h2database:h2'
   // runtimeOnly 'com.h2database:h2'
}​

2. application.properties에 H2 환경 설정

properties
# H2 데이터베이스의 웹 콘솔 기능 활성화
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console

# H2 설정
spring.datasource.driverClassName=org.h2.Driver
# spring.datasource.url=jdbc:h2:~/cafe # Embedded Mode: db 데이터 저장 위치 설정
# spring.datasource.url=jdbc:h2:mem:test # In-Memory mode
spring.datasource.username=sa
spring.datasource.password=

# DB 초기화 쿼리 필요 시 설정
# spring.sql.init.mode=always
# spring.sql.init.schema-locations=classpath:schema.sql
# spring.sql.init.data-locations=classpath:data.sql

YAML 설정 예시

Embedded Mode

yaml
spring:
  datasource:
    url: jdbc:h2:mem:testdb
    username: sa
    driver-class-name: org.h2.Driver
  h2:
    console:
      enabled: true

Server Mode

yaml
spring:
  datasource:
    url: jdbc:h2:tcp://localhost/~/test
    username: sa
    driver-class-name: org.h2.Driver

결론

  • 테스트에는 In-Memory Mode가 편리하고 성능이 좋음

하지만 데이터가 영속성 유지가 안되기 때문에 영속성을 원한다면 다른 선택이 필요

  • 데이터 영속성이 필요하다면 Embedded ModeServer Mode를 선택.

그런데 서버 모드는 설정이 귀찮고 속도가 느리기 때문에 보통은 임베디드 모드를 사용하게 된다

 

서버 모드는 여러 애플리케이션 동시접근, 원격 접근 필요 시에 서버 모드를 선택하면 될 것 같다

 

때문에 나는 주로 임베디드 모드로 h2를 사용할 듯하다

+ Recent posts