SMALL

SLF4J

Java에는 다양한 오픈소스 로깅 프레임워크가 존재한다.

이러한 다양한 종류의 프레임워크를 통합하기 위해서는 로깅 구현체를 추상화한 인터페이스 레이어가 필요하다.

해당 역할을 하는 것이 SLF4J이다. ( Simple Logging Facade For Java )

SLF4J는 인터페이스만 제공하고, 여러 구현체는 logback, log4j 등등이 있다.

구현체는 컴파일 시점에 지정된다.

Spring Boot 2.x 이후 버전에서는 SLF4J를 사용하고 아무 log관련 설정을 하지 않은 경우에는 default 설정으로 logback이 사용된다고 한다.

 

With Zero-Configuration Logging, the application will use underlying logging implementation Logback for logging. 

( https://www.baeldung.com/spring-boot-logging - 참고 )

 

 각 클래스마다 logger를 설정하기 위해서는 아래의 코드 선언해야 한다.

private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CLASSNAME.class);

 

lombok

이러한 코드를 모든 클래스에 선언하는 것은 비효율적 일수 있다.

lombok에서는 이러한 코드를 생성해주는 어노테이션을 제공한다.

해당 어노테이션을 원하는 클래스에 추가해 주면 된다. 

(lombok 관련 dependency 추가 필요) 

@Slf4j
public class LoggingTestService {

}

 

Custom Log Configuration

이러한 형태로 사용하면 default로 제공하는 log기능을 사용할 수 있다.

다만, 기본으로 제공하는 형태 이외에 추가적인 설정을 하고 싶은 경우에는 설정 파일 조작이 필요하다. 

spring boot config인 application.yml 설정 또는 logback-spring.xml 설정이 존재한다. 

 

application.yml

application.yml에서 제공하는 추가적인 설정은 공식 홈페이지에서 확인하면 자세하게 나와있다.

( https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.logging.custom-log-configuration )

 

logging:
  level:
    org.springframework: ERROR
    com.test.ttt: DEBUG
  pattern:
    console: "%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"
    file: "%d %p %c{1.} [%t] %m%n"
  file: apptest.log

 

해당 설정은 개발단계에서 로그를 확인하기 적당하다.

다만, 실제 production단계에서는 log파일 관리가 중요하기 때문에 file rolling 등의 디테일한 설정이 필요하다.

 

이러한 경우에는 logback-spring.xml설정 파일을 사용하게 된다. 

해당 파일에 대한 디테일한 설정은 다음 포스팅에서 알아보도록 하자. 

 

 

LIST
SMALL

You are given two integer arrays nums1 and nums2, sorted in nondecreasing order,

and two integers m and n, representing the number of elements in nums1 and nums2 respectively.

Merge nums1 and nums2 into a single array sorted in non-decreasing order.

The final sorted array should not be returned by the function, 

but instead be stored inside the array nums1. 

To accommodate this, nums1 has a length of m + n, where the first m elements denote the elements that should be merged, 

and the last n elements are set to 0 and should be ignored. 

nums2 has a length of n.

 

두 개의 integer 오름차순 배열 nums1, nums2과 m, n integer를 받는다.

m, n은 각 배열이 가지고 있는 element의 개수이다.

이 두 배열을 하나의 오름차순 배열로 통합하여라.

 

단, 리턴되는 배열은 새로 정의된 배열이 아닌 nums1 배열이어야 한다.

nums1 배열은 크기가 m+n이다. 

 

Input: nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
Output: [1,2,2,3,5,6]

정렬된 두 개의 배열을 merge 해야 한다.

단, 새로운 배열을 생성하여 merge 하는 것이 아닌 주어진 배열에서 merge가 이루어져야 한다.

 

주어진 배열의 마지막 element들을 point 하고 그중에 큰 값을 nums1 배열에 입력하는 형식으로 문제를 해결해 보자.

 

해당 순회를 마무리하는 조건으로는 각 배열의 pointer들이 0보다 작아진 경우이다. 

후에 만약 nums2의 pointer가 첫 index까지 순회를 하지 못한 경우에는 해당 값들을 nums1에 입력해주면 모든 배열을 순회한 것이다. 

 

    public void merge(int[] nums1, int m, int[] nums2, int n) {

        int nums1Idx = m - 1;
        int nums2Idx = n - 1;

        int point = nums1.length - 1;

        while (nums1Idx >= 0 && nums2Idx >= 0) {

            if (nums1[nums1Idx] >= nums2[nums2Idx]) {
                nums1[point] = nums1[nums1Idx];
                point--;
                nums1Idx--;
            } else {
                nums1[point] = nums2[nums2Idx];
                point--;
                nums2Idx--;
            }
        }

        if (nums2Idx >= 0) {
            while (nums2Idx >= 0) {
                nums1[point] = nums2[nums2Idx];
                point--;
                nums2Idx--;
            }
        }

    }

 

시간 복잡도는 각 배열을 모두 순회하므로 O( M + N )이다.

 

 

문제 출처

https://leetcode.com/problems/merge-sorted-array/

 

Merge Sorted Array - LeetCode

Level up your coding skills and quickly land a job. This is the best place to expand your knowledge and get prepared for your next interview.

leetcode.com

 

LIST
SMALL

704. Binary Search

Given an array of integers nums which is sorted in ascending order, and an integer target, 

write a function to search target in nums. 

If target exists, then return its index. Otherwise, return -1.
You must write an algorithm with O(log n) runtime complexity.

 

오름차순으로 정렬된 integer 배열과 타깃 integer가 주어진 상황에서 

타깃을 배열에서 찾는 코드를 작성하여라

타깃이 존재한다면 해당 숫자가 들어있는 배열의 인덱스를 반환하고, 없다면 -1을 반환하라

반드시 시간 복잡도가 O(log n)인 알고리즘으로 작성하라


정렬된 배열에서 값을 찾는 문제로 시간 복잡도가 O(log n)인 알고리즘을 사용해야 한다. 

Binary Search를 이용하여 문제를 해결하도록 하자.

 

    public int search(int[] nums, int target) {

        int left = 0;
        int right = nums.length - 1;
        int pivot = 0;

        while (left <= right) {
            pivot = (left + right) / 2;

            if (target == nums[pivot]) {
                return pivot;
            } else if (nums[pivot] < target) {
                left = pivot + 1;
            } else {
                right = pivot - 1;
            }
        }
        return -1;
        
    }

 

먼저 left, right 인덱스를 지정하고,

해당 인덱스들을 기반으로 while loop의 조건을 지정한다.

Binary Search의 경우에는 left 인덱스가 right 인덱스보다 큰 경우에는 타깃으로 하는 값이 없는 경우이므로 해당 조건이 while loop에 들어가게 된다. 

 

Binary Search에서는 각각의 left, right 인덱스의 중간값을 pivot으로 설정하고 

해당 값을 기준으로 다음 조건의 인덱스를 지정한다.

 

pivot 인덱스의 배열값이 타깃보다 작은 경우에는 left 인덱스를 pivot 다음 인덱스로 지정

pivot 인덱스의 배열값이 타깃보다 큰 경우에는 right 인덱스를 pivot 이전 인덱스로 지정

 


문제 출처

https://leetcode.com/problems/binary-search/

 

Binary Search - LeetCode

Level up your coding skills and quickly land a job. This is the best place to expand your knowledge and get prepared for your next interview.

leetcode.com

 

 

 

LIST
SMALL

Spring Security에서 현재 로그인한 사용자의 정보를 가져오는 방법을 알아보도록 하자.

 

SecurityContextHolder 이용

Spring Security에서 전역으로 선언된 SecurityContextHolder를 통해서 정보를 가져올 수 있다. 

SecurityContextHolder는 Spring Security Architechture에서 간단하게 알아본 적이 있는데

( https://joomn11.tistory.com/90 )

해당 클래스를 통해서 인증을 통해 발급된 Authentication을 얻을 수 있다. 

 

Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String userName = auth.getName();

 

Controller 메서드 인자 이용 

 

Controller로 선언된 클래스의 메서드에서 인자로 Authentication 객체에 접근을 할 수 있다. 

@Controller 
public class UserController { 

    @GetMapping("/user") 
    public String userName(Authentication authentication) { 
        
        String userName = authentication.getName();
        
        return userName;
    } 
}

 

추가적으로, Principal 객체도 얻을 수 있다. 

@Controller 
public class UserController { 

    @GetMapping("/user") 
    public String userName(Principal principal) { 
        
        String userName = principal.getName();
        
        return userName;
    } 
}

 

LIST

+ Recent posts