현재 구축한 시스템에서 로그인방식을 추가해야할 일이 있었다.

해당 시스템에서는 사용자가 입력한 아이디와 비밀번호 정보만 받아

스프링 시큐리티에서 인증처리를 하고 있어서,

시스템 상에서 어떤 방식으로 로그인을 할지

로직 분기를 판단하는데 어려움이 있었다.

이를 해결하기 위해 스프링 시큐리티에 대해 좀 더 알아보게 되었다.

 

 

스프링 시큐리티에서 로그인 인증 정보의 전달은 Authentication을 통해 이루어진다

Authentication을 살펴보면, 아래 메서드들로 구성된 인터페이스이다.

해당 메서드들이 접근하는 필드들은 아래와 같다

- Principal : 사용자 아이디 혹은 User 객체를 저장
- Credentials : 사용자 비밀번호
- authorities : 인증된 사용자의 권한 목록
- details : 인증 부가 정보
- Authenticated : 인증 여부

 

details필드에 로그인 방식에 대한 정보를 담아 전달하면 문제를 해결할 수 있다고 판단하였다.

이를 위해 우선 WebAuthenticationDetails 객체를 상속한 커스텀 클래스를 만들었다.

해당 WebAuthenticationDetails 객체는 일종의 VO역할을 하는듯 싶다.

public class 커스텀웹인증디테일즈 extends WebAuthenticationDetails {

    private final String 담고자하는_추가정보;

    public 커스텀웹인증디테일즈(HttpServletRequest request) {
        super(request);
        this.담고자하는_추가정보 = request.getParameter("Http요청에서 수신하는 추가정보");
    }

    public String getter_담고자하는_추가정보() {
        return 담고자하는_추가정보;
    }
}

 

 

선언한 WebAuthenticationDetails 객체의 인스턴스를 만들기 위해선

AuthenticationDetailsSource을 구현하는 객체가 필요하다.

해당 구현 객체를 통해, 앞서 만든 VO를 초기화한다.

public class 커스텀인증디테일즈소스 implements AuthenticationDetailsSource<HttpServletRequest, 커스텀웹인증디테일즈> {

    @Override
    public 커스텀인증디테일즈소스 buildDetails(HttpServletRequest request) {
        return new 커스텀웹인증디테일즈(request);
    }
}

 

 

"커스텀인증디테일즈소스"를 인증과정에서 호출하기 위해선,

security 설정에 해당 객체를 추가해야한다.

security 버전 5.x의 경우, xml설정파일의 form-login 설정에 "커스텀인증디테일즈소스"를 추가한다.

<sec:http auto-config="true" entry-point-ref="인증엔트리포인트" access-decision-manager-ref="인증결정매니저" >
    <sec:csrf disabled="true"/>
    <sec:form-login
        login-page="로그인페이지url"
        username-parameter="사용자아이디"
        password-parameter="사용자패스워드"
        login-processing-url="로그인url"
        authentication-success-handler-ref="인증성공핸들러"
        authentication-failure-handler-ref="인증실패핸들러"
        authentication-details-source-ref="커스텀인증디테일즈소스"
    />
    <sec:logout logout-url="로그아웃url" invalidate-session="true" logout-success-url="/" delete-cookies="JSESSIONID" />
    <sec:access-denied-handler ref="접근거부핸들러" />
</sec:http>
    
<bean id="커스텀인증디테일즈소스" class="클래스경로.커스텀인증디테일드소스" />


부가정보 전달 프로세스를 구현하고 인증과정을 테스트를 해보니,

아래 캡처와 같이 loginMethod 부가정보가 추가되었고,

해당 부가정보도 정상적으로 받아오는 것을 확인할 수 있었다.

 

 

참고


https://velog.io/@gmtmoney2357/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%8B%9C%ED%81%90%EB%A6%AC%ED%8B%B0-Authentication-SecurityContext

 

스프링 시큐리티 - Authentication, SecurityContext

본 게시물은 스스로의 공부를 위한 글입니다.잘못된 내용이 있으면 댓글로 알려주세요!사용자의 인증 정보를 저장하는 토큰 개념.2가지 용도로 사용된다. 인증 용도 또는 인증 후 세션에 담기

velog.io


https://dev-coco.tistory.com/174

 

Spring Security의 구조(Architecture) 및 처리 과정 알아보기

시작하기 앞서 스프링 시큐리티에서 어플리케이션 보안을 구성하는 두 가지 영역에 대해 간단히 알아보자. 인증(Authentication)과 인가(Authorization) 대부분의 시스템에서는 회원을 관리하고 있고,

dev-coco.tistory.com

 

- 개선전 코드

List<DataVO> sourceDataList = synchService.selectSourceData();

List<DataVO> targetDataList = synchService.selectTargetData();

sourceDataList.stream().forEach(sourceData -> sourceData.setDisplayModifyDate(
     targetDataList.stream().filter(targetData
                                    -> targetData.getCd().equals(sourceData.getCd()))
	                    .map(targetData -> targetData.getDisplayModifyDate())
                            .collect(Collectors.joining())
                            )
);

위의 코드는 소스디비에서 타겟디비로 데이터를 동기화하기 전에,
소스디비의 데이터를 select하는 예시코드이다. 
sourceDataList는 소스디비의 데이터를 가져와서 담아둔 list,  
targetDataList는 타겟디비에서 각 데이터별 최근 동기화한 시간을 가져와 담아둔 list이다.

 

- 개선 목표


sourceDataList.stream().foreach()로 반복하며 동기화시각을 매핑할 때,
반복문을 돌 때마다 stream()객체를 생성하는 것이 리소스 낭비로 생각됨.

stream() 객체 생성을 최소화하여 성능개선 및
로직을 단순화하여 가독성 개선을 목표로 하였음

 


- 개선 방법


stream.foreach() 내부에서 추가로 생성하던 targetDataList.stream()을
바깥으로 꺼내 map객체로 만들어 활용

 


- 개선후 코드

List<DataVO> sourceDataList = synchService.selectsourceData();

Map<String, String> targetModifyDtMap = synchService.selectTargetModifyDatetime()
	.stream().collect(Collectors.toMap(DataVO::getCd, DataVO::getDisplayModifyDate));

sourceDataList.stream()
    .forEach(sourceData-> sourceData.setDisplayModifyDate(targetModifyDtMap.get(sourceData.getCd())));



- 성능 측정


sourceDataList의 data 100개 select를 10번씩 반복하였을 때,
개선 전 소요시간 평균 619.2ms -> 개선 후 소요시간 평균 564.1ms
평균 소요시간이 55.1ms 감소하였음

1. 의존성(Dependency)란?

객체 A와 B가 있을 때,
A의 변화여부가 B에 영향을 미친다면
"B는 A를 의존한다(B는 A에 의존성을 갖는다)"라고 정의한다.



2. Spring 의존성 주입(Dependency Injection)이란?

스프링 컨테이너에서 객체간 의존성을 자동으로 연결, 관리하는 것.
의존관계를 개발자가 아닌 프레임워크가 관리(IoC개념 구현. DI는 Inversion of Control을 구현하는 방법 중 하나이다).
객체간 의존성(결합도)을 낮춰 코드 재사용성, 가독성 확보.

 

3. Spring 의존성 주입 방법


1) 생성자 주입(Constructor Injection)

생성자를 통해 의존관계를 주입함.
최초에 객체를 초기화할 때, 객체를 더이상 수정하지 않을 때 사용

@Service
public class BookService {

    private BookRepository bookRepository;

    @Autowired
    public BookService(BookRepository bookRepository) {
        this.bookRepository = bookRepository;
    }
}



2) 수정자 주입(Setter Injection)

Setter 메서드를 작성하고, 해당 Setter를 사용하는 방법.
객체가 변경될 가능성이 있는 경우에 사용.
객체의 불변성을 확보해야한다면 지양하는 것이 좋음

@Service
public class BookService {

    private BookRepository bookRepository;

    @Autowired
    public void setBookRepository(BookRepository bookRepository) {
        this.bookRepository = bookRepository;
    }
}

 

3) 필드 주입(Field Injection)

필드에 바로 의존 관계를 주입.
더 이상 권장되지 않는 방법이다.
아래는 권장되지 않는 이유이다.

(1) 객체가 생성된 후에도 의존성이 변경되어 불변성 보장이 어렵다.(객체의 안정성 보장이 어렵다)
(2) 테스트가 제한된다(spring 프로젝트 전체를 돌려야하기 때문에 JAVA 코드만으로 테스트가 불가능)
(3) 의존성이 명시적이지 않아 책임소재가 잘 드러나지 않는다(Controller에 Service를 주입한다는 코드가 없어도 실행됨)
(4) 순환참조 오류가 발생할 가능성이 있다(A와 B가 서로의 객체를 이용하면, 각각의 객체가 생성되지 않고 오버플로우가 발생한다)

@Service
public class BookService {

    @Autowired
    private BookRepository bookRepository;
}

 

 

참조


https://tecoble.techcourse.co.kr/post/2021-04-27-dependency-injection/

 

의존관계 주입(Dependency Injection) 쉽게 이해하기

이번 글에서는 DI(의존성 주입, 의존관계 주입)의 개념을 설명한다. DI란 용어가 주는 위압감과 부담감 때문에 이해를 미뤄뒀거나, 처음 접하는 분들이 쉽게 이해할 수 있도록 쉽게 설명하고자 한

tecoble.techcourse.co.kr

https://velog.io/@cgw981/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%9D%98%EC%A1%B4%EA%B4%80%EA%B3%84-%EC%A3%BC%EC%9E%85-%EC%A0%95%EB%A6%AC

 

스프링 의존관계 주입 정리

스프링 공부를 처음 시작할 때 이해가 잘 안되었던 의존관계 주입을 정리해봤다. 전체적인 흐름을 간략히 정리하고 싶었기 때문에 기술적으로 생략한 부분이 많다. 의존관계 주입의 틀을 잡는

velog.io

https://devlog-wjdrbs96.tistory.com/166

 

[Spring] @Autowired란 무엇인가?

저번 글에서 IoC 컨테이너와 빈(Bean)등록에 대해서 정리해보았다. 다시 정리하자면 의존성 주입과 빈 등록은 다른 것인데 일단 IoC 컨테이너에 빈으로 등록이 되어야 의존성 주입을 할 수 있다. 저

devlog-wjdrbs96.tistory.com

https://youwjune.tistory.com/43

 

[Spring] 스프링에서 빈 객체를 등록하는 방법(@Bean, @Component)

https://youwjune.tistory.com/37 [Spring] DI와 IOC에 대해서 스프링을 막 공부하기 시작하는 비기너에게 DI와 IOC에 대한 개념은 너무나도 중요한 것 같습니다! 하지만, 이를 왜 사용할까요? DI와 IOC를 활용하

youwjune.tistory.com

https://velog.io/@hanhyunsoo/Spring-%EC%A0%9C%EC%96%B4%EC%9D%98-%EC%97%AD%EC%A0%84IOC%EC%99%80-%EC%9D%98%EC%A1%B4%EC%84%B1-%EC%A3%BC%EC%9E%85DI

 

[Spring] 제어의 역전(IOC)와 의존성 주입(DI)

제어의 역전(IOC)와 의존성 주입(DI) 이론

velog.io

https://velog.io/@ohzzi/Spring-DIIoC-IoC-DI-%EA%B7%B8%EA%B2%8C-%EB%AD%94%EB%8D%B0

 

[Spring DI/IoC] IoC? DI? 그게 뭔데?

스프링을 공부하다 보면 꼭 나오는 이야기가 있다. 스프링은 IoC 컨테이너로 빈을 관리한다. 스프링은 DI를 사용한다 .DI 방법에는 생성자 주입, setter 주입, 필드 주입 등이 있다.... 아니 근데 대체

velog.io

https://mangkyu.tistory.com/125

 

[Spring] 다양한 의존성 주입 방법과 생성자 주입을 사용해야 하는 이유 - (2/2)

Spring 프레임워크의 핵심 기술 중 하나가 바로 DI(Dependency Injection, 의존성 주입)이다. Spring 프레임워크와 같은 DI 프레임워크를 이용하면 다양한 의존성 주입을 이용하는 방법이 있는데, 각각의 방

mangkyu.tistory.com

https://velog.io/@sunlake123/%EC%9D%98%EC%A1%B4%EC%84%B1-%EC%A3%BC%EC%9E%85%EC%9D%98-%EC%A2%85%EB%A5%98%EC%99%80-%ED%95%84%EB%93%9C-%EC%A3%BC%EC%9E%85%EC%9D%98-%EB%AC%B8%EC%A0%9C%EC%A0%90

 

의존성 주입의 종류와 필드 주입의 문제점

의존성 주입은 클래스 간 강한 결합을 풀어주어 조금 더 OOP스러운 개발을 할 수 있도록 만들어준다. 이는 Spring뿐만 아닌 객체지향적인 개발을 할 때 두루 사용된다.의존성 주입 방식에는 다음의

velog.io

 

 

Oracle 지원 로드맵

 

Oracle JAVA의 대표적인 LTS(Long Term Support)버전에는 8, 11, 17, 21이 있다.

IDE를 서비스하는 JetBrain의 20~23년 자바 버전별 사용 통계(복수선택)를 보면,

사용율을 기준으로  8, 11, 17버전이 대부분을 차지한다.

JAVA 8버전은 23년까지도 자바버전 중 사용율 1위를 차지하고 있으나, 꾸준히 하락하고 있다.

JAVA11은 22년까지 사용율이 점진적으로 증가했으나, JAVA17이 등장하며 23년에서는 사용률이 하락하였다.

JAVA17은 22년 등장이후로 급속도로 사용율이 증가하고 있다.

그렇다면 JAVA11과 17은 이전 버전과 차별화되는지, 그 특징을 정리해보았다.


ㅁ JAVA11 주요 업데이트


ㅇ New Garbage Collector(ZGC 추가) : “Stop-The-World”로 인한 성능저하를 개선
*GC stop the world : GC를 실행하기 위해 JVM이 모든 애플리케이션 실행을 멈추는 현상
(https://velog.io/@limsubin/GC-stop-the-world-%EB%9E%80)

ㅇ Collection Factory Method 기능 강화 : Set, List, Map 인터페이스에 Immutable 생성할 수 있는 새로운 메서드 추가(of 등), 기존보다 깔끔한 코드 스타일

ㅇ Reactive Stream API 추가 :비동기 스트림 처리의 표준 제공을 목적으로 하는 기능
*C10K : 동시 사용자 1만명(Concurrent 10K users)이 접속하는 서버를 구현하는 문제. 메모리부하, 스레드 경합문제
(https://oliveyoung.tech/blog/2023-10-02/c10-problem/)

ㅇ 로컬 변수 타입 추론 "var" 추가 : 로컬 변수 선언 시, “타입 추론”을 이용하여 명시적 타입 선언 없이도 변수 선언이 가능하도록 지원하는 신규 Keyword. 컴파일 시 변수 타입을 추론하기 때문에 성능에 영향을 주지는 않으나, 
가독성 높은 코드 작성을 위해 무분별한 “var” Keyword 이용은 지양

ㅇ 신규 문자열 Method 추가 : 문자열 내 공백 확인/제거 등 JDK 11 버전부터 String에 여러 편리한 기능을 지원
- isBlank: 문자열이 비어있거나 공백이면 True 반환
- lines: 줄 단위로 나뉘어 있는 문자를 배열로 반환
- strip: 문자열 공백 제거 (기존 “trim()”이 ‘\u0020’ 이하 공백만을 제거 하였다면, “strip()”은 유니코드의 공백들을 전부 제거)
- stripLeading: 문자열 앞의 공백을 제거
- stripTrailing: 문자열 뒤의 공백을 제거
- repeat: 문자열을 파라미터로 주어진 수 만큼 반복



ㅁ JAVA17 주요 업데이트

ㅇ 텍스트 블록 기능 추가 : “”” {String 문자열 } “”” 형식을 이용해 Java 문자열을 보다 가독성있게 작성지원.
 TextBlock 내 데이터를 동적으로 다루게 될 경우 %s 문자와 format Method를 이용하여 구현할 수 있고, 
또한 블록 내 “+” 연산자를 이용하여 구현할 수도 있습니다.

ㅇ Switch 표현식 기능 향상 : 1. Switch문 값 직접 반환, 2. yield 예약어 이용한 값 리턴 방식 추가, 3. Case문 람다식 지원.

ㅇ Record Data class 추가 : Immutable 객체를 생성하는 새로운 유형의 클래스.
Record 선언을 하게 되면 기존 toString, equals, hashCode 메소드를 자동으로 구현해주며, 
모든 인스턴스 필드를 초기화해주는 생성자가 생성.
Immutable 객체이기 때문에 모든 값은 생성자를 통해 설정.
DTO와 같은 Data Object 용도로 활용 시 보다 편리하고 간결하게 구분할 수 있음.

* 불변객체 사용시 장점
1. 쓰레드에 안전하여 멀티 쓰레드 환경에서 동기화를 고려하지 않아도 된다.
2. 불변객체를 필드로 사용할 때 방어적 복사가 필요없다.
3. 불변객체는 내부상태가 변경되지 않으므로, Map Key 와 Set 요소로 사용하기에 적합하다.
4. 불변객체를 한번 메모리에 할당하게 되면 같은 객체를 계속 호출하여도, 새롭게 할당하지 않아도 되므로 GC의 성능을 높힐 수 있다.
https://dev-cool.tistory.com/23

Thread-Safe하여 병렬 프로그래밍에 유용하며, 동기화를 고려하지 않아도 된다.
실패 원자적인(Failure Atomic) 메소드를 만들 수 있다.
Cache나 Map 또는 Set 등의 요소로 활용하기에 더욱 적합하다.
부수 효과(Side Effect)를 피해 오류가능성을 최소화할 수 있다.
다른 사람이 작성한 함수를 예측가능하며 안전하게 사용할 수 있다.
가비지 컬렉션의 성능을 높일 수 있다.
https://mangkyu.tistory.com/131

 

ㅁ 참고

https://techblog.gccompany.co.kr/%EC%9A%B0%EB%A6%AC%ED%8C%80%EC%9D%B4-jdk-17%EC%9D%84-%EB%8F%84%EC%9E%85%ED%95%9C-%EC%9D%B4%EC%9C%A0-ced2b754cd7

 

우리팀이 JDK 17을 도입한 이유

안녕하세요, T플랫폼개발실 개발3팀 제이든입니다. 이번 포스팅에서는 저희팀에서 Java 17 버전을 도입하게 된 이유와 개발자 입장에서 주요하다 생각되는 업데이트 내용 및 사용사례를 소개드리

techblog.gccompany.co.kr

 

https://www.jetbrains.com/ko-kr/lp/devecosystem-2023/java/

 

The State of Developer Ecosystem in 2023 Infographic

Learn about the latest trends in tools, technologies, AI, and programming languages.

www.jetbrains.com

 

+ Recent posts