728x90
반응형

기존

log4j.rootLogger=DEBUG,console,rolling

log4j.logger= DEBUG
log4j.logger.java.sql= DEBUG

log4j.logger.jdbc.sqltiming=DEBUG,stdout
log4j.additivity.jdbc.sqltiming=false

log4j.logger.jdbc.sqlonly=ERROR,sql
log4j.additivity.jdbc.sqlonly=false

log4j.logger.jdbc.audit=ERROR,jdbc
log4j.additivity.jdbc.audit=false

log4j.logger.jdbc.resultset=ERROR,jdbc
log4j.additivity.jdbc.resultset=false

log4j.logger.org.springframework=DEBUG
log4j.logger.org.springframework.transaction=DEBUG

log4j.logger.com.ibatis=DEBUG
log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=ERROR
log4j.logger.com.ibatis.common.jdbc.ScriptRunner=ERROR
log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=ERROR

log4j.logger.java.sql.Connection=ERROR
log4j.logger.java.sql.Statement=ERROR
log4j.logger.java.sql.PrepareStatement=ERROR
log4j.logger.java.sql.ResultSet=ERROR

log4j.appender.rolling=org.apache.log4j.DailyRollingFileAppender
log4j.appender.rolling.File=../logs/dr.log
log4j.appender.rolling.Append=true
log4j.appender.rolling.DatePattern= '.'yyyy-MM-dd
log4j.appender.rolling.layout=org.apache.log4j.PatternLayout
log4j.appender.rolling.ConversionPattern=[%d] %-5p - %m%n

log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%5p (%F[%M]:%L) [%d] - %m%n

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p (%F[%M]:%L) [%d] - %m%n

log4j.appender.jdbc=org.apache.log4j.ConsoleAppender
log4j.appender.jdbc.layout=org.apache.log4j.PatternLayout
log4j.appender.jdbc.layout.ConversionPattern=%5p (%F[%M]:%L) [%d] - %m%n

log4j.appender.sql=org.apache.log4j.ConsoleAppender
log4j.appender.sql.layout=org.apache.log4j.PatternLayout
log4j.appender.sql.layout.ConversionPattern=%5p (%F[%M]:%L) [%d] - %m%n


불편한 점

  • 콘솔창에 실행 쿼리가 2개씩 중복 출력됨
  • 설정을 보니 jdbc.sqltiming만 따로 지정했고,
    jdbc.sqlonly가 루트(DEBUG)로 살아 있어서 그런 거였음



변경

log4j.rootLogger=DEBUG,console,rolling

log4j.logger.jdbc.sqltiming=DEBUG,console
log4j.additivity.jdbc.sqltiming=false

log4j.logger.jdbc.sqlonly= ERROR
log4j.additivity.jdbc.sqlonly=false

log4j.logger.jdbc.audit=ERROR
log4j.additivity.jdbc.audit=false

log4j.logger.jdbc.resultset=ERROR
log4j.additivity.jdbc.resultset=false

log4j.logger.org.springframework=ERROR
log4j.logger.org.springframework.transaction=ERROR

log4j.logger.com.ibatis= ERROR
log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=ERROR
log4j.logger.com.ibatis.common.jdbc.ScriptRunner=ERROR
log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=ERROR

log4j.logger.java.sql.Connection=ERROR
log4j.logger.java.sql.Statement=ERROR
log4j.logger.java.sql.PreparedStatement=ERROR
log4j.logger.java.sql.ResultSet=ERROR

log4j.appender.rolling=org.apache.log4j.DailyRollingFileAppender
log4j.appender.rolling.File=../logs/dr.log
log4j.appender.rolling.Append=true
log4j.appender.rolling.DatePattern='.'yyyy-MM-dd
log4j.appender.rolling.layout=org.apache.log4j.PatternLayout
log4j.appender.rolling.ConversionPattern=[%d] %-5p - %m%n

log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{HH:mm:ss.SSS} %-5p [%c{1}] (%F:%L) - %m%n
728x90
반응형
728x90
반응형

다른 데이터베이스에 있는 테이블을
내가 접속 중인 데이터베이스에서 직접 조회하거나 사용할 수 있게 해주는 연결 통로
=> A DB에서 B DB의 테이블을 바로 SELECT/DML 작업 가능


DB 링크를 사용했던 이유

  • 운영 DB와 분석 DB가 분리되어 있을 때
  • 다른 시스템(DB)에 있는 데이터를 바로 써야 할 때
  • 데이터 복사 없이 실시간 참조가 필요할 때


DB 링크를 지양하는 이유

1. 장애 전파 및 복구 어려움
- 단일 장애가 연쇄 장애로 확산될 수 있음
예) 로컬 DB에서 원격 DB의 테이블을 조인하고 있었는데, 원격 DB에 장애 발생 → 로컬 서비스까지 먹통

- 복구가 어려움
단순한 재시도나 로컬 트랜잭션 롤백으로 끝나지 않음DB간 연결이 끊긴 상태에서 rollback조차 실패할 수 있음

2. 보안 취약점
- DB 링크는 일반적으로 고정된 계정/비밀번호로 연결되며 그 정보가 내부적으로 평문 저장되거나 공개될 수 있음 → 특히 PUBLIC DB LINK의 경우, 누구나 접근 가능한 보안 구멍이 될 수 있음

- 원격 DB 권한 통제 어려움
링크를 통해 간접적으로 원격 DB에 쓰기/삭제 등을 해버릴 수 있어서 위험

3. 성능 저하 및 튜닝 어려움
- 원격 쿼리를 조인하거나 트랜잭션으로 처리하면 네트워크 레이턴시 + 원격 옵티마이저 문제로 성능이 예측불가

- 옵티마이저가 원격 테이블의 통계를 알 수 없어서 비효율적인 실행계획을 세우는 경우가 많음

- 원격 DB의 성능 저하가 로컬 DB에도 영향을 미치므로 문제 원인 추적이 까다로움

4. 트랜잭션 일관성 보장 어려움
- DB 링크를 통한 분산 트랜잭션은 복잡한 구조를 가짐 (2PC - Two Phase Commit) → 트랜잭션 커밋/롤백 중 일부만 성공하면 데이터 불일치 발생 위험

- 특히 장애 중복 발생 시 원격 DB는 커밋됐는데 로컬은 롤백된 상황 등… 복구가 매우 어려움

5. 운영 및 배포 관리 복잡성
- 운영 중 링크 관리 어려움

  • 링크 대상 DB가 변경되면 모든 관련 DB 링크를 수정해야 함
  • DB 복제, 마이그레이션, 환경 분리(운영/스테이징/개발) 시 DB 링크 설정 때문에 작업량 증가

- TNS 설정, SID/서비스명 의존성 때문에 클라우드 전환/분산 아키텍처에 부적합

6. 현대적인 아키텍처와 어긋남
-요즘은 마이크로서비스, API 중심, 메시지 기반 아키텍처가 대세라서 DB끼리 직접 연결(link)하는 방식보다 API 호출, RESTful 서비스, 메시징 큐(Kafka 등)로 데이터 전달하는 추세임

- DB 링크는 서비스 독립성/경계를 깨뜨리고 강한 결합을 초래함


✅ 대안

1. REST API
- DB끼리 직접 연결하는 대신, 중간 API를 두고 호출로 연결

2. 메시징 큐
- Kafka, RabbitMQ 등을 활용한 비동기 데이터 전달 방식

3. DB 복제
- GoldenGate, Streams, Kafka CDC 등으로 DB 간 실시간 복제

4. ETL / ELT
- 주기적 배치/스트리밍으로 데이터를 이동시키고 각 DB에서 독립 운영



728x90
반응형
728x90
반응형

현재 유지보수 중인 시스템 내에
특정 상황에 in절 파라미터 갯수가 1000개 이상이 넘어가 에러가 발생했다.
아주 제한적인 환경이기 때문에 가장 공수가 덜 드는 방법을 고려하다가 iterate 태그를 사용해 처리했다.


<iterate>

  • iBATIS에서 반복적인 SQL 구문을 자동으로 생성하기 위해 사용되는 동적 SQL 태그(MyBatis에서는 <foreach>로 대체)
  • 주로 배열, 리스트, 컬렉션과 같은 반복 가능한 데이터 구조를 SQL 문에 바인딩할 때 사용
  • 파라미터 타입 Map의 key 또는 VO의 필드명 형태로 감싸서 넘겨야 함(단순히 List만 넘기면 <iterate>가 인식하지 못함)


Ex)

IN절에 리스트 바인딩

Map<String, Object> param = new HashMap<>();
param.put("userIdList", Arrays.asList("A001", "A002", "A003"));
<select id="getUserList" resultClass="User">
  SELECT *
  FROM USERS
  WHERE USER_ID IN
  <iterate property="userIdList" open="(" close=")" conjunction=",">
    #userIdList[]#
  </iterate>
</select>


실행 결과

SELECT *
FROM USERS
WHERE USER_ID IN ('A001','A002','A003')


<iterate>는 컬렉션(반복할 대상(배열, List 등)) 내 요소를 순회하면서 SQL 문을 반복적으로 생성

  • open/close: 반복 구문 앞뒤에 붙일 문자열 (예: (, ))
  • conjunction: 각 항목 사이에 붙일 구분자 (예: ,, OR, AND)
  • property: 각 항목의 필드명 (List일 경우 key명)


Ex)

다중 조건 OR 구문 생성

Map<String, Object> param = new HashMap<>();
param.put("names", Arrays.asList("홍길동", "이순신"));
<select id="findUserByNames" resultClass="User">
  SELECT *
  FROM USERS
  WHERE
  <iterate property="names" conjunction=" OR ">
    NAME = #names[]#
  </iterate>
</select>


실행 결과

SELECT *
FROM USERS
WHERE NAME = '홍길동' OR NAME = '이순신'



728x90
반응형

'ETC' 카테고리의 다른 글

notepad++ 꿀팁  (0) 2025.07.17
카카오 지도 API 사용법 - kakao is not defined  (0) 2025.05.10
Sublime text 꿀팁  (0) 2024.06.25
RSA 암호화 적용하기 - 키 생성 및 암•복호화  (0) 2024.06.03
Git&GitHub Desktop 설치  (0) 2023.07.14
728x90
반응형

web.xml은 웹 애플리케이션의 전역 설정 파일


• DispatcherServlet 등록 → 스프링 MVC 구동
• ContextLoaderListener 등록 → Root ApplicationContext 구동
• 필터/리스너 등록 → 인코딩, 보안, 로깅 등 공통 처리
• 서블릿 매핑 → URL과 서블릿 연결


1. 웹 애플리케이션의 시작점 설정

• 웹 애플리케이션이 Tomcat 같은 서블릿 컨테이너에 배포될 때 가장 먼저 읽히는 설정 파일
• 어떤 Servlet, Filter, Listener를 사용할지 정의

2. DispatcherServlet 등록

웹 계층 담당
• Spring MVC의 핵심인 DispatcherServlet(Front Controller)을 등록하는 곳

<!—- 모든 요청이 DispatcherServlet으로 들어가도록 연결—->
<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-name>/WEB-INF/…/dispatcher-servlet.xml</param-name>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>*.do</url-pattern>
</servlet-mapping>


3. ContextLoaderListener 등록

• Root ApplicationContext를 띄워주는 역할
비즈니스 로직 및 인프라 계층 담당(보통 서비스, DAO, DataSource 같은 Bean들은 여기서 초기화)

1. ContextLoaderListener + DispatcherServlet (정석 구조)
• Root Context (ContextLoaderListener)
• DataSource, TransactionManager, DAO, Service
• Web Context (DispatcherServlet)
• Controller, ViewResolver

2. DispatcherServlet만 사용하는 경우
• DispatcherServlet이 로딩하면서 DB 설정(iBatis Config)까지 다 들고감
• Root Context 없이 Web Context 하나로 통합 운영
• 초기 스프링/레거시 프로젝트에서 자주 보이는 방식

4. 필터(Filter) 설정

• 인코딩, 보안, 로깅 같은 기능을 전역으로 걸 수 있음

5. 서블릿 매핑

• 특정 URL 패턴을 어떤 서블릿이 처리할지 정의


728x90
반응형
728x90
반응형

✅ Spring

  • 자바 기반 애플리케이션 개발을 쉽게 해주는 프레임워크
  • 핵심은 DI(의존성 주입), AOP(관점 지향 프로그래밍) 같은 기능으로 객체 관리와 비즈니스 로직을 깔끔하게 분리할 수 있게 도움
  • 모듈형 구조라서, 프로젝트에서 필요한 기능에 따라 의존성을 선택적으로 추가하면 됨


✅ Modules

  • Core: 스프링의 기본 동작(빈 관리, DI, 표현식, 컨텍스트)
  • Web: 웹 애플리케이션 개발 지원
  • AOP: 부가 기능을 분리해주는 도구
  • Security:로그인/권한/보안 관리(인증/인가 처리)


https://docs.spring.io/spring-framework/docs/4.0.x/spring-framework-reference/html/overview.html

2. Introduction to Spring Framework

Spring Framework is a Java platform that provides comprehensive infrastructure support for developing Java applications. Spring handles the infrastructure so you can focus on your application. Spring enables you to build applications from "plain old Java o

docs.spring.io



✅ 모듈 의존성 순서도

spring-core
   ↓
spring-beans
   ↓
spring-context
   ↓
spring-expression
   ↓
spring-aop
   ↓
spring-web
   ↓
spring-webmvc
   ↓
spring-security-core
   ↓
spring-security-web
   ↓
spring-security-config
   ↓
spring-security-taglibs


✅ 주요 Spring Core 모듈


1. spring-core
• 스프링의 가장 기본이 되는 모듈
• IoC(Inversion of Control), DI(Dependency Injection)를 제공
• BeanFactory 같은 핵심 컨테이너 기능이 포함

2. spring-beans
• Bean(객체) 정의, 생성, 주입을 담당
• XML, annotation, Java config 등 다양한 설정 방식 지원

3. spring-context
• spring-core, spring-beans 위에 올라가는 모듈
• ApplicationContext를 제공 → 메시지 리소스 처리, 이벤트 발행, 국제화(i18n) 지원

4. spring-expression(SpEL, Spring Expression Language)
• #{} 같은 표현식으로 객체 그래프를 조회·조작할 수 있게 해주는 언어
• 예: @Value("#{systemProperties['java.home']}")


✅ Spring Web 관련 모듈


1. spring-web
• Servlet API 위에서 동작
• 멀티파트 파일 업로드, 웹 관련 유틸, REST 지원 등

2. spring-webmvc
• 흔히 말하는 Spring MVC
• DispatcherServlet 기반으로 Model-View-Controller 패턴 지원
• REST API, 뷰 렌더링, 핸들러 매핑/어댑터, 컨트롤러 관리 등


✅ Spring AOP


• AOP(Aspect-Oriented Programming) 지원 모듈
• 로깅, 트랜잭션, 보안 같은 **횡단 관심사(Cross-cutting concerns)**를 분리
• 예: 모든 서비스 메서드 실행 전에 로깅 실행


✅ Spring Security 관련 모듈


1. spring-security-core
• 인증(Authentication), 인가(Authorization)의 핵심 로직
• 사용자 계정, 권한(Role) 관리

2. spring-security-web
• 보안을 웹 레벨(필터 기반)에서 적용
• 로그인/로그아웃, 세션 관리, CSRF 보호, URL 기반 접근 제어

3. spring-security-config
• XML, Java Config로 보안 설정을 쉽게 할 수 있게 해주는 모듈
• 예: @EnableWebSecurity

4. spring-security-taglibs
• JSP 같은 뷰에서 보안 태그 사용 가능.
• 예: <sec:authorize access="hasRole('ADMIN')">


Spring Boot일 경우‼️

대부분의 모듈을 직접 추가하지 않고, starter 의존성으로 해결

Ex)
spring-boot-starter-web
→ spring-web, spring-webmvc, spring-core 등 자동 포함
spring-boot-starter-security
→ spring-security-* 모듈 자동 포함

즉, Boot 사용 시에는 목적별 스타터만 추가하면 끝이고,
Legacy Spring 사용 시에는 개별 모듈을 직접 추가해야 함(pom.xml)


1. 소프트웨어에서 “레거시”의 일반 개념
• 레거시 시스템/프로젝트 = 오래된 기술, 아키텍처, 코드 스타일을 기반으로 돌아가는 시스템
• 당장은 동작하지만 유지보수나 확장이 어렵고, 최신 기술 스택과는 괴리가 있는 경우가 많음

2. 스프링 맥락에서 “레거시 프로젝트”
• 스프링에서 말하는 레거시 프로젝트는 보통 Spring Boot를 쓰지 않고, 직접 XML 또는 JavaConfig로 설정한 프로젝트 뜻함

• Maven/Gradle에서 필요한 모듈을 하나씩 직접 추가해야 함(spring-core, spring-beans, spring-webmvc 등)

• 환경 설정(XML, JavaConfig)을 직접 관리
-applicationContext.xml
-web.xml + dispatcher-servlet.xml

• 서버도 내장 Tomcat이 아니라, WAR 파일 빌드 후 외부 WAS(WebSphere, Tomcat 등)에 배포

• 프로젝트 구조가 복잡하고 설정 코드 양이 많음


728x90
반응형
728x90
반응형

1. 데이터베이스>새 데이터베이스 연결
2. 연결하고자 하는 db를 선택
3. 원하는 connection type을 선택 후, 그에 따라 db 접속 경로 지정

basic 방식
• 접속 정보(Host, Port, Service/SID)를 DBeaver에 직접 입력하는 방식

TNS 방식
• 오라클 클라이언트에서 제공하는 tnsnames.ora 파일에 정의된 TNS Alias를 사용
• DBeaver는 TNS Alias 이름만 지정하고, 실제 접속 정보는 tnsnames.ora에서 불러옴


4. 계정 정보 입력
5. 우측 하단 [Edit Driver Settings] 버튼 클릭
6. 하단 ’Libraries’ 탭에 기본 설정된 것들 전부 삭제
🔥7. [Add File] 버튼 클릭 후, 각 DB에 맞는 JDBC(Java Database Connectivity) 드라이버 선택

JDBC(Java Database Connectivity) 드라이버
• Java 애플리케이션이나 DBeaver 같은 툴이 DB에 접속하기 위해 꼭 필요한 중간 연결 역할
• Java 애플리케이션 ↔ 데이터베이스 사이에서 명령과 데이터를 주고받는 번역기 역할
• 형식은 .jar(Java ARchive), 해당 파일이 없으면 Java 프로그램이 DB 종류를 인식하지 못해 연결 불가
MySQL JDBC 드라이버(mysql-connector.jar)
Oracle JDBC 드라이버(ojdbc.jar)


8. 하단 중간에 위치한 [Find Class] 클릭하면 ‘Drive class’를 선택할 수 있는데 아무거나 선택
9. [Test Connection…] 버튼 클릭해서 테스트 해보면 됨

728x90
반응형
728x90
반응형

dataset.filter(“조건식”)

  • 데이터셋에 로드된 데이터 중, 조건에 만족하는 행(row)만 보이게 필터링하는 메서드
  • 데이터셋의 값과 조건식 값의 타입이 다른 경우엔 이유는 모르겠으나 부정 조건이 안 먹힘
  • 부정조건으로 필터링하려면 타입을 맞추거나 아래 메서드를 사용하면 됨


dataset.set_filterstr(“조건식“)

  • 추측컨대 조건식에 쓰이는 데이터 타입을 무조건 스트링 타입으로 바꿔서 필터링 하는 듯




728x90
반응형
728x90
반응형


Ctrl + Shift + F: 전체 검색


스크립트 탭

  • Alt+ G: 선택한 함수 정의 위치로 이동 (스크립트 내 에서 함수를 선택한 후 사용)
  • Alt + 아래 화살표: 스크립트 내에서 함수 목록을 탐색하고 선택
  • Ctrl +/ : 주석 처리
  • Ctrl + Alt : 주석 제거
  • Ctrl + R : 바꾸기


디자인 탭

  • Ctrl + B: 바인딩된 개체 표시


728x90
반응형
728x90
반응형

1. 노트 패드 테마 변경

설정>스타일 설정…

  • 테마 선택: Twilight(내 눈엔 이게 젤 편-안)


2. Workspace 열기

파일>Workspace으로 폴더 열기
(디컴파일한 소스 볼 때 좋음)

-폴더 별로 찾기: ctrl+f 누르고 [파일에서 찾기] 이동 후, 디렉토리 설정

728x90
반응형
728x90
반응형

grep

  • global regular expression print
  • 파일이나 출력에서 특정 문자열이나 패턴을 검색할 때 사용하는 명령어

grep [옵션] ‘패턴’ [파일명]



정규식

  • ^ : 행의 시작 지시자 -> ‘^summer’
  • $ : 행의 끝 지시자 -> ‘summer$’
  • . : 하나의 문자와 대응 -> ‘su..er’
  • [0-9] : 0부터 9까지의 숫자 -> ‘10:1[0-9]’


옵션

  • -i : 대소문자 구분없이(ignore)
  • -c : 찾은 행의 총 개수(count)
  • -n : 찾은 행의 파일 내 행 번호(line number)
  • --color : 매칭된 부분을 색상으로 강조



예시

grep -i -n error xxx.log
grep -i -c error xxx.log
grep ‘2025-07-17 10:[1-2][0-9]’ xxx.log


응용 예시1

grep ‘2025-07-17 10:[1-2][0-9]’ xxx.log > was1.txt
grep -i -c error xxx.log >> was1.txt

>

  • 표준 출력을 오른쪽 파일(was1.txt)에 저장


was1.txt

  • 검색 결과가 저장될 텍스트 파일 (없으면 생성, 있으면 덮어씀)


>> was1.txt

  • 기존 파일 끝에 내용을 추가



응용 예시2

ps -ef|grep test

ps -ef

  • 현재 시스템에서 실행 중인 **모든 프로세스를 전체 포맷(-f)**으로 보여줘
  • e: 모든 사용자의 프로세스 보기 (== -A)
  • f: 풀 포맷 (UID, PID, PPID, 시작 시간, 명령어 등 전체 정보 출력)


| (파이프)

  • 앞 명령어(ps -ef)의 출력을 뒤 명령어(grep test)의 입력으로 전달


grep test

  • 입력된 문자열 중에서 ‘test’라는 문자열이 포함된 줄만 출력
  • 즉, COMMAND 컬럼에 ‘test’라는 글자가 들어간 프로세스가 표시됨




728x90
반응형

+ Recent posts