컴퓨터공학 💻 도서관📚

Part2. 6-11 오류의 로그를 남기기 - java.util.logging.Logger 활용 (이해 잘 안 됨...) 본문

✅🌲강의 복습 노트/패캠 JavaSpring 강의,코드 복습

Part2. 6-11 오류의 로그를 남기기 - java.util.logging.Logger 활용 (이해 잘 안 됨...)

들판속초록풀 2025. 8. 15. 14:03

logging

  • 시스템 운영에 대한 기록
  • 오류가 발생 했을 때 그 오류에 대한 기록을 남겨 디버깅을 용이하게 함
  • 로그 파일에 기록하는 코드를 추가하여 필요한 정보가 로그로 남을 수 있도록 한다
  • 디버깅, 시스템 에러 추적, 성능, 문제점 향상들을 위해 사용
  • 어느정도까지 로그를 남길 것인가?
    너무 많은 로그 : 빈번한 file I/O의 오버헤드와 로그 파일의 백업 문제등...
    너무 적은 로그 : 정확한 시스템의 상황을 파악하기 어려움

java.util.logging

  • 자바에서 기본적으로 제공되는 log package
  • 파일이나 콘솔에 로그 내용을 출력할 수 있음
  • jre/lib/logging.properties 파일을 편집하여 로그의 출력방식 로그 레벨을 변경 할 수 있음
  • logging 패키지에서 제공하는 로그 레벨은 severe, warning, info, config, fine, finer, finest
    (로그에는 레벨이 있는데 info 단계부터는 정보를 남겨주고
    익셉션 상황인 경우에는 warning, severe 단계로 넘어간다.)
  • 오픈소스로는 log4j를 많이 사용하고 있음

java.util.logging.Logger
logger 안에  Handler 라는걸 가지고 있는데 그중 중요한게 2가지이다


1. 화면에 로그를 찍어주는 콘솔 핸들러 (콘솔 핸들러는 우리가 핸들링 하지 않는다)
2. 파일에 로그를 찍어주는 파일 핸들러
    파일 핸들러를 생성을 해서 생성된 로고에 추가를 해주면 된다.
    그러면 나중에 로고를 찍을 때,  예시로 3개의 파일에 찍으라고 했으면
    3개의 파일 핸들러를 돌아가면서 찍게끔 구현이 되어 있다.

Logger 만들기

  • 시나리오
    학생 정보 시스템에 로그를 기록하도록 한다.
    학생의 이름에 오류가 있는 경우 예외 처리를 하고 예외 상황을 로그로 남긴다.
    학생의 이름은 null 이거나 중간에 space가 3개 이상인 경우 오류가 발생한다.
  • 구현하기
    Logger 인스턴스를 생성한다.
    로그를 남기기 위한 FileHandler를 생성한다.
    FileHandler의 level을 지정하고
    Logger에 생성된 addHandler()메서드로 FileHandler를 추가한다.

MyLogger.java

public class MyLogger {   // MyLogger도 싱글톤 패턴이다. 생성자를 private로 선언
	
	Logger logger = Logger.getLogger("mylogger");    // 밑에 설명 있음
	private static MyLogger instance = new MyLogger();   // private static --> 싱글톤 패턴(유일한 인스턴스 만들기)
	
	public static final String errorLog = "log.txt";    // 3개의 파일
	public static final String warningLog = "warning.txt";
	public static final String fineLog = "fine.txt";
	
	private FileHandler logFile = null;   // 3개의 파일 핸들러
	private FileHandler warningFile = null;
	private FileHandler fineFile = null;

	private MyLogger(){   // 생성자를 private로 선언 --> 싱글톤 패턴(외부에서 생성자를 못 만듦)
	
			try {
				logFile = new FileHandler(errorLog, true);    // 밑에 설명 있음
				warningFile = new FileHandler(warningLog, true);
				fineFile = new FileHandler(fineLog, true);
				
			} catch (SecurityException e) {    // file handler여서 IOException, Security 예외처리를 하게끔 만듦
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	
			logFile.setFormatter(new SimpleFormatter());   // 로그를 찍는 포멧은 간단한 SimpleFormatter 로 찍어라
			warningFile.setFormatter(new SimpleFormatter());
			fineFile.setFormatter(new SimpleFormatter());
			
			logger.setLevel(Level.ALL);   // 로고 레벨 세팅 --> 밑에 설명 있음
			fineFile.setLevel(Level.FINE);
			warningFile.setLevel(Level.WARNING);
			
			logger.addHandler(logFile);  // addHandler로 지금 만든 FileHandler를 추가
			logger.addHandler(warningFile);
			logger.addHandler(fineFile);
	}	
	
	
	public static MyLogger getLogger(){
		return instance;
	}

	
	public void log(String msg){  // 각 레벨에 로그 입력 (정보를 주기 위한 로그, 에러 로그 아님)
		
		logger.finest(msg);
		logger.finer(msg);
		logger.fine(msg);
		logger.config(msg);
		logger.info(msg);
		logger.warning(msg);
		logger.severe(msg);
		
	}
	
	public void fine(String msg){
		logger.fine(msg);
	}
	
	public void warning(String msg){
		logger.warning(msg);
	}
}

  

Logger logger = Logger.getLogger("mylogger");

위 코드 설명:  식별자(변수 이름)와 같은 의미로  String인 "mylogger" 를 주고 

getLogger를 하면 항상 똑같은 인스턴스가 반환된다.

일종의 싱글톤 패턴인데 내부적으로 하나만 가지고 있는게 아니라

식별자에 해당되는 놈을 mapping 해서 반환해준다

예로 배열 요소가 10개라고 하면 그 중에서 식별자들을 보고 반환하는 느낌이다.

외부에서 new 할 수 는 없고  "mylogger" 라는 이름으로 주고 가져오는 것이다.

 


logFile = new FileHandler(errorLog, true);

파일 핸들러의 1번째 매개변수는 파일이름(String)이고,  

logFile은 전체 다 찍을 거고, warningFile은 warning레벨 위로 찍을 거고,  fineFile은 fine레벨 위로 찍는다는 것이다.

true라고 2번째 매개변수에 쓰면 append해서 찍으라는 뜻이다.
override(재정의) 이 아니라  찍고 그 뒤에 쭉 연결해서 찍으라는 뜻이다.

 


1. logger.setLevel(Level.ALL);   // 로고 레벨 세팅
2. fineFile.setLevel(Level.FINE);  // fineLog 는 fine 레벨부터 시작한다.

3. warningFile.setLevel(Level.WARNING);  // warningLog 는 warning 레벨부터 시작한다.

 

Level.ALL 은  finest 부터 severe 까지 다 찍으라는 뜻이다.

FileHandler 마다 다른 레벨을 줄 수 있다.

1. logger 에다 준 거는 전체 logger에 대한 레벨이고,  

2. fineFile은 fine 레벨부터 찍고,  3.warningFile은 warning 레벨부터 찍어라 라는 뜻이다.

레벨 지정 안한 파일들은 더 높 상위 레벨을 따른다.(FINE,  ALL  2개가 있으면  ALL을 따른다)

 


LoggerTest.java

public class LoggerTest {

	public static void main(String[] args) {

		MyLogger myLogger = MyLogger.getLogger();
		
		myLogger.log("test");
	}

}

StudentNameFormatException.java

public class StudentNameFormatException extends IllegalArgumentException{  // 밑에 설명 있음

	public StudentNameFormatException(String message){
		super(message);
	}
}

Student.java

public class Student {

	private String studentName;
	MyLogger myLogger = MyLogger.getLogger();  // logger 가져오기
	
	public Student(String studentName){   // 밑에 설명 있음

		if(studentName == null){    // 이름이 입력 안 된 경우
		
			throw new StudentNameFormatException("name must not be null");
		}
		if( studentName.split(" ").length > 3)     // 이름이 너무 긴 경우
			throw new StudentNameFormatException("이름이 너무 길어요");    // 예외처리
		
		this.studentName = studentName;  // 정상인 경우
	}

	
	public String getStudentName() {
		
		myLogger.fine("begin getStudentName()");  // 로그 찍기
		
		return studentName;
	}
}

public Student(String studentName){    //  exception이 발생할 수 있는데 여기에서 throws 를 안 함

생성자에서는 throws를 하지 않는다.

그래도 exception은 발생할 수 있기 때문에

사용자 정의 예외 클래스(StudentNameFormatException) 에서 extends 뒤에 그냥 exception 으로 하지 않고

IllegalArgumentException 으로 하면 throws 를 하지 않아도 exception Handling 을 할 수 있다.

 

 

StudentTest.java

public class StudentTest {
	
	public static void main(String[] args) {
	
		MyLogger myLogger = MyLogger.getLogger();
		
		String name = null;
		try{
			Student student = new Student(name);
			
		}catch( StudentNameFormatException e ){
			myLogger.warning(e.getMessage());
		}
		
		try{
			Student student = new Student("Edward Jon Kim Test");
		}catch ( StudentNameFormatException e){
			myLogger.warning(e.getMessage());
		}
		
		Student student = new Student("James");
	}
	
}

정리

로고를 분리를 하고  로고를 레벨에 따라서 쓸 수 있다.

중요한 것은 exception 상황에서는 반드시 로고를 남겨야 하고

로고를 레벨별로 알 수 있게  파일을 잘 구별해야 한다.

 

이거는 fine인 경우 fine 이상을 다 찍는데

log4j 는  fine 만 따로 warning 만 따로 error 만 따로 debug 만 따로 찍을 수가 있다. 파일을 분리할 수 있다.

 

 

 

 

 

 

 

 

Comments