3번 줄의 configuration status 구문은 이 설정파일이 로드될 때 발생하는 로그에 대한 레벨을 설정하는 부분이다.
말이 어렵지 실행화면을 보면 이해가 갈것이다.
log4j2.xml 의 내부 설정을 로드하면서 발생하는 DEBUG 이상의 로그들을 출력중이다.
status를 info로 설정하면 아~~~무 로그도 출력되지 않는다.
그 이유는 log4j2.xml 설정파일을 로드할 때의 정보는 내부적으로 DEBUG레벨로 찍고 있기 때문이다.
INFO 레벨은 DEBUG레벨보다 상위의 레벨이기 때문에 로그가 찍히지 않게 된다.
그렇다면 log4j2.xml 파일을 로드할 때 문제가 생기도록 코드를 바꾼 후 status를 info로 설정한다면?
내부적으로 error 로그가 발생할 것이고, 이는 info 레벨보다 높기 때문에 로그가 찍힐 것이다.
테스트로 5번줄의 Appenders 태그 명을 Appenderss로 바꾼 후 실행시켰다.
제일 아랫줄의 ERROR test.LogTest 부분이 log4j2.xml 을 로드하면서 생긴에러이다.
* configuration 부분을 설명하기 위해 먼저 MainClass와 LogTest를 구현하였다. 현재 MainClass와 LogTest 를 생성만 한 상태에서는 위처럼 테스트가 불가능하다. 이런 설정이구나 라고만 이해하고 넘어가자.
Appenders 태그 안에 실질적인 로그 설정 코드를 삽입한다.
현재 콘솔에 로그를 출력시키기 위해 <Console> 태그 관련 코드를 삽입하고 로그로 찍히는 패턴을 PatternLayout 태그를 통해 설정한다.
%d는 로그 시간에 관한 설정을 나타내는데 괄호 안의 형태로 포멧시킬 수 있다.
%p는 로그 레벨, %c는 로그가 발생한 클래스 경로, %m은 로그 메시지, %n은 개행이다.
%5p는 로그 레벨이 출력되는 기본 문자열 길이를 5로 설정한다는 의미이다.
12번 줄의 loggers 는 설정한 로그 코드를 적용하는 부분이다.
root 태그를 사용하면 현재 시스템에서 발생하는 모든 로그를 찍어낼 수 있고, level을 debug로 설정하여 debug 이상의 로그만 출력되도록 한다. Appender를 이용해서 앞서 설정한 console을 적용시키면, 결과적으로 기동하는 시스템내에서 발생하는 모든 로그 중 debug레벨 이상은 모두 찍히게 된다.
5. oracle 서비스 수동 전환(서비스가 자동 실행 되어있으면 oracle을 사용하지 않을 때에 컴퓨터가 버벅거릴 수 있음)
1) Oracle ~~ TNSListener - 수동으로 변경
2) OracleServiceORCL - 수동으로 변경
컴퓨터를 재부팅하면 해당 서비스는 자동으로 실행이 되지 않음. 때문에 오라클 프로그램에 필요한 서비스가 로드되지 않아 에러가 발생할 수 있음. 때문에 불필요한 메모리 낭비를 하기 싫다면 위의 설정을 따르고, 메모리 낭비가 상관없을 만큼 컴퓨터 사양이 좋다면 위의 설정은 하지 않아도 된다.
서비스를 재실행시키려면 서비스 탭으로 들어가 서비스를 실행시키거나, bat파일을 만들어 서비스를 실행시키면 된다.
6. cmd 실행 후 sqlplus 입력
7. 사용자 명에 sys as sysdba를 입력하고 비밀번호는 입력하지 않고 엔터키를 누르면 설치한 Oracle Database 12c에 접속됨.
9. tablespace 생성
* tablespace란 데이터를 관리하는 논리적인 저장 구조이다. 쉽게 말하면 테이블을 관리하는 공간을 의미한다. 테이블 데이터의 기본 용량을 설정할 수 있으며, 용량 초과 시 자동적으로 10 mbyte씩 증가한다.
기존의 웹 애플리케이션은 폼을 채우고 이를 제출(submit)하면 웹 서버는 요청된 내용에 따라서 데이터를 가공하여 새로운 웹 페이지를 작성하고 응답으로 되돌려준다. 이때 최초에 폼을 가지고 있던 페이지와 결과물로써 되돌려 받은 페이지는 일반적으로 유사한 내용을 가지고 있는 경우가 많다. 결과적으로 중복되는 HTML 코드를 다시 한번 전송을 받음으로써 많은 대역폭을 낭비하게 된다. 이는 금전적 손실을 야기할 수 있으며 사용자와 대화하는 서비스를 만들기 어렵게도 한다.
반면에 Ajax는 필요한 데이터만을 웹 서버에 요청해서 받은 후 클라이언트에서 데이터에 대한 처리를 할 수 있다. 웹 서버에서 전적으로 처리되던 데이터 처리의 일부분이 클라이언트 쪽에서 처리되므로 웹 브라우저와 웹 서버 사이에 교환되는 데이터량과 웹 서버의 데이터 처리량도 줄어들기 때문에 애플리케이션의 응답성이 좋아진다.
장점
- 페이지 이동없이 고속으로 화면을 전환할 수 있다.
- 서버 처리를 기다리지 않고, 비동기 요청이 가능하다.
- 수신하는 데이터 양을 줄일 수 있고, 클라이언트에게 처리를 위임할 수도 있다.
단점
- Ajax를 쓸 수 없는 브라우저에 대한 문제가 있다.
- HTTP 클라이언트의 기능이 한정되어 있다.
- 동일-출처 정책으로 인해 다른 도메인과는 통신이 불가능하다.
2. 실습 환경
- 이클립스
- jquery-3.4.1
- tomcat 7.0
프로젝트 생성 및 tomcat 서버 설정을 마쳤다는 가정 하에 ajax 통신을 하였다.
3. 웹 페이지 생성
먼저 사용자가 어떠한 입력을 수행할 수 있도록 html과 javascript를 사용하여 웹 페이지를 생성한다. 아래와 같이 ajax폴더에 파일들을 넣어줬다.
15 ~ 21 : 통신 방식과 통신할 url, 수신할때의 데이터 타입, Servlet으로 보낼 데이터 정보를 넣어준다. dataType은 서블릿에서 객체 형식이나 두개 이상의 데이터를 송신할 경우 "json"을, 하나의 문장으로 송신할 경우 "html"을 넣어준다. 필자는 out.print()로 하나만 보내기 때문에 html로 해주었다.
22 ~ 27 : Servlet과의 모든 통신이 정상적으로 끝나면 메서드의 매개변수 안에 Servlet이 response 한 데이터가 있게 된다. 이를 출력하기 위해 div태그에 응답 정보가 들어있는 textNode를 상속시키고, 이를 초기 HTML 코드로 생성했던 div 태그에 상속시킨다.
30 ~ 32 : Servlet과의 통신 실패 시 에러 코드 및 내용에 대한 세부사항을 출력시킨다. 만일 에러 코드가 200이 나올 경우 dataType에 대한 수정이 필요하다.
38 ~ 57 : type을 GET에서 POST로만 변경한 코드이다.
4. Servlet 생성
패키지를 myServlet으로 설정하고 Servlet 이름은 Serv로 하였다. web.xml에서 url과 Servlet을 매핑할 것이기 때문에 WebServlet()을 주석처리하였다.
<welcome-file>ajax/ajaxCommunication.html</welcome-file><!-- 루트경로 진입시 가장먼저 읽어오는 파일 -->
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<!-- 서블릿을 불러오기 위해 WAS에게 주는 정보 -->
<!-- 1. 배포할 Servlet 2. 해당 Servlet 매핑 URL -->
<servlet-name>ajaxCon</servlet-name>
<servlet-class>myServlet.Serv</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ajaxCon</servlet-name>
<url-pattern>/ajaxCon</url-pattern>
</servlet-mapping>
</web-app>
5 : <welcome-file> 태그는 루트 경로 진입 시 가장 먼저 읽어오는 파일이다. 읽어올 수 없을 시 순차적으로 아래 입력된 파일을 읽어온다. root경로에서 서버를 돌릴 시 ajaxCommunication.html 파일이 가장 처음 로드되도록 하였다. 그 아래는 기본적으로 입력되어 있는 파일이다.
13 ~ 18 : WAS가 Servlet을 정상적으로 로드하기 위해 WAS에게 주는 Servlet과 url 정보이다. <servlet-name>은 <servlet-mapping>에서 동일한 name을 가진 정보와 매핑시키기 위한 이름이다. 현재 myServlet.Serv(클래스명.서블릿명) 파일을 '/ajaxCon' 이라는 url과 매핑시켰다. 이로써 '~~test/ajaxCon' url로 접속할 시 Serv 파일이 로드된다.
javascript에서는 number, boolean, undefined, string, null이라는 기본 타입을 제외하고 모두 객체 타입이다. foo['name']은 객체 타입인 배열과 형식이 같은 것을 알 수 있다. (물론! 차이는 존재한다.)
쉽게 생각하면 foo['name']은 처럼 'name'이라는 key값(index)를 참조한다고 생각하면 이해가 쉽다. 객체의 key값은 String 값이기 때문에 작은 따옴표(')와 함께 입력해 준 것이다. 작은 따옴표가 없으면 name이라는 값은 String이 아닌 하나의 변수로 인식되고, name 변수 안에 있는 값을 참조하게 된다. name 변수는 호출이 된 최상위 객체인 window에 존재하지 않기 때문에 당연히 undefined가 출력된다.
추가적으로 javascript는 대괄호 안에 데이터가 문자열이 아닐 경우 자동적으로 toString() 메소드를 적용시킨다. toString() 메소드는 어떠한 데이터를 문자열로 변환해주며, 변수.toString() 형식으로 사용할 경우 해당 변수에 들어있는 데이터를 문자열로 변환해주는 역할을 한다.
즉, 대괄호 안에 있는 name이라는 데이터를 문자열이 아닌 변수로 인식하게 되면 name이라는 변수는 호출된 객체 영역 내에서 정의되지 않았기 때문에 문자열로 변환한들 당연히 값은 존재하지 않는다.
1
2
3
4
5
varname='name';
console.log(foo.name); // 'ssk'
console.log(foo['name']); // 'ssk'
console.log(foo[name]); // 'ssk'
때문에 변수에 객체의 key값을 넣어 조회할때 위의 방식을 사용한다.
간단히 name이라는 변수에 'name'이라는 key값을 넣었지만 key값이 많을 경우 반복문과 결합하여 사용할 수 있다.
foo['name']과 foo[name]의 차이를 정확히 알았으니 더이상 헷갈리는 일은 없겠지.
형식 언어를 사용하여 특정한 규칙을 가진 문자열의 패턴을 파악한다면 텍스트 편집, 포맷팅, 검색, 치환 등의 문자열 작업이 가능하게 된다. 기본적으로 패턴은 두 개의 '/(슬래시)' 사이에 작성한다.
예를 들어 '20190809'라는 문자열에서 패턴을 파악하여 '2019''08''09' 형태로 나누고, 그 사이에'-' 문자열을 삽입하여 '2019-08-09' 형태로 만들 수 있고, 저렇게 만든 날짜형 데이터에서 사용 가능한 메소드인 getDay(), getFullYear() 등을 사용할 수 있게 된다. 표현을 위한 포맷팅뿐 아니라 메소드의 사용까지도 가능하게 해주는 좋은 녀석이다.
2. 정규식 패턴
그렇다면 이 패턴은 어떻게 만들까? 패턴을 만드는 방법은 크게 두 가지이다.
첫째, 단순 패턴 사용
둘째, 특수 문자 사용
2.1 단순 패턴 사용
단순 패턴은 단순히 문자열을 대응시킬 때 사용한다. 예를 들어 /hi/라는 패턴은 문자열에서 hi라는 문자열이 그대로 나타나야 대응된다. "hi, hellow"에서 hi라는 문자열이 대응된다.
연습이 필요하다고 생각한다면 정규식을 테스트할 수 있는 사이트(https://regexr.com)를 들어가 보길 권한다. 참고로 끝에 있는 'g'는 패턴 속성으로 대상 문자열의 처음부터 끝까지 해당 패턴을 적용시키는 것이다. 이 속성이 없다면 'hi hi hi' 문자열의 대응 부분은 처음의 'hi' 하나뿐이다.
2.2 특수 문자 사용
단순 패턴을 사용하여 대응하기 힘든 것을 대응시키고자 할 경우 패턴에 특수 문자를 사용한다. 예를 들어, /^hi/ 패턴은 문자열의 시작이 'hi' 문자로 시작되는 것에 대응한다. 만약 'hi, hellow' 문자열에 이 패턴을 적용시킨다면 'hi'가 대응되며, 'oh, hi'라는 문자열에 적용시킨다면 대응되는 문자는 아무것도 없다.
특수문자의 종류와 기능이다.
특수 문자
기능
예시
^
입력의 시작 부분과 대응된다.
/^시작/→ 시작했다 시작
$
입력의 끝 부분과 대응된다.
/끝$/→ 끝났다끝
*
표현식이 0회 이상 연속으로 반복되는 부분과 대응된다.
/ab*c/→ cbbabbbbcdebc, acbd
+
표현식이 1회 이상 연속으로 반복되는 부분과 대응된다.
/ab+c/→ cbbabbbbcdebc, acbd
?
표현식이 0 또는 1회 등장하는 부분과 대응된다. {0,1} 과 같다. 있어도 ok, 없어도 ok 이라고 생각하면 편하다
서버는 클라이언트와 정보를 주고받는다. 다양한 이유로 그 과정에서 발생하는 여러 사건이나 정보들을 기록으로 남기는데 이 기록을 log라고 한다. 그리고 log를 남기는 행위를 '로깅'이라고 하는데, 모든 서버에 기본적으로 들어가는 개념이기 때문에 오늘은 이 logging에 대해 공부하는 시간을 가져보도록 하자. 구동 환경은 이클립스와 tomcat 7.0이다.
2. logging이란
로깅이란 시스템 동작 시 시스템 상태/작동 정보를 시간의 경과에 따라 기록하는 것이다. 그 기록을 '로그'라고 한다.
한마디로 '로깅 = 로그 기록'이다.
로깅은 많은 부분에서 사용되는데, 사용자의 패턴이나 시스템 동작 분석에 사용되거나 해킹 사고가 발생할 경우 비정상 동작의 기록을 통해 추적하는 데 사용한다. 백엔드 개발자들의 경우 개발 과정에 있어 디버깅에 활용할 수도 있다. 이 외에도 다방면으로 쓰인다.
그렇다면 Spring과 같은 Java환경에서 로깅을 하려면 어떻게 해야 할까? 시스템 동작에 대한 기록을 남기는 것이기 때문에 흔히 알고 있는 system.out.println()과 같은 메소드를 사용할 수 있겠다. 하지만 이는 메모리면에서 비효율적인 데다 클라이언트의 접속량이 많아질수록 안정적으로 실행되지 못하는 등 여러 문제를 안고 있다. (문제에 대해 궁금하다면 직접 구글링을 추천)
이 문제에 대한 솔루션이자 Java 환경의 logging 시스템이 바로 log4j이다. log4j에 대해 본격적으로 알아보도록 하자.
3. log4j란
Java 환경의 로깅 시스템을 제공하는 라이브러리.
Logger, Appender, Layout 등 다양한 컴포넌트가 사용되며, 로그 레벨을 분류하여 로그 정보를 출력시킬 수 있다.
3.1) 컴포넌트
컴포넌트
설명
Logger
로그의 주체, 로그 파일을 작성하는 클래스
Appender
로그를 출력하는 위치
Layout
Appender의 출력포맷(일자, 시간 등)을 설정하여 로그 내용으로 지정하는 속성.
Layout의 종류는 여러 가지가 있지만 일반적으로 디버깅에 가장 적합한 PattenLayout을 사용한다.
PattenLayout이란 출력 포맷을 정해진 일련의 패턴을 사용하여 설정하는 것인데 패턴 정보는 아래와 같다.
패턴
설명
C
클래스명 출력
d
로그 시간 출력
F
파일명 출력. 수행한 메소드와 라인번호가 함께 출력.
L
라인 번호 출력
m
로그로 전달된 메시지 출력
M
로그를 수행한 메소드명 출력
n
개행
p
로그 이벤트명 (DEBUG 등)
r
로그 처리시간(milliseconds)
t
로그 이벤트가 발생된 쓰레드 출력
위의 패턴을 잘 조합하여 로그에 대한 출력 포맷을 설정한다.
3.2) 로그 레벨
로그는 기본적으로 6개의 레벨을 갖는다. 아래로 갈수록 낮은 레벨이다.
로그 레벨
설명
fatal
시스템 문제와 같은 아주 심각한 에러가 발생한 상태를 나타냄.
error
요청을 처리하는중 문제가 발생한 상태를 나타냄.
warn
처리 가능한 문제이지만, 향후 시스템 에러의 원인이 될 수 있는 경고성 메시지를 나타냄.
info
로그인, 상태변경과 같은 정보성 메시지를 나타냄.
debug
개발시 디버그 용도로 사용한 메시지를 나타냄.
trace
디버그 레벨이 너무 광범위한것을 해결하기위해서 좀더 상세한 상태를 나타냄
debug(), warn(), error()와 같이 메소드를 사용해서 로그 정보를 얻을 수 있으며, 로그 레벨 설정을 통해 로그를 통제할 수 있다. 이는 Logger의 Level 메소드를 통해 이루어지며, 지정한 로그 레벨보다 낮은 로깅 이벤트는 무시된다. 이는 뒷부분의 예제를 보면 이해할 수 있을 것이다.
현재 servlet 파일에서 logger를 error, warn, info , debug, trace 총 5개 레벨에 대한 출력을 시도했으나 제일 낮은 레벨인 trace를 제외한 4개만 console로 출력된 상태이다. 이유는 앞서 언급했던 로그 레벨에 따른 통제와 관련이 있다. log4j2.xml 파일에서 STDOUT 로깅 데이터에 대한 level이 debug로 설정되었기 때문이다. trace를 출력시키고 싶다면 xml 파일 9번째 줄의 debug 대신 trace를 넣어주면 된다.
4) tomcat 서버 에러 발생 시
tomcat 서버 에러가 발생할 경우 tomcat에 서버에 대해서도 log4j 라이브러리를 추가시켜줘야 한다. log4j를 사용하여 얻은 로그가 기본적으로 WAS(tomcat)에 남기 때문이다.
추가 방법은 tomcat Server Overview → Open launch configuration → Classpath → UserEntries → Add JARs를 클릭하여 lib 폴더에 있는 두 라이브러리를 클릭하면 된다.