13. Annotation이란 무엇이고 구체적으로 어떤 것이 있는지 예시를 들어 설명해주실 수 있을까요?
핵심 키워드 : 메타데이터, 주석(과의 차이), 리플렉션
"Annotation은 자바 코드에 추가적인 정보를 제공하는 메타데이터입니다. 이는 주석과 다르게, 컴파일 시간이나 실행 시간에 사용될 수 있으며, 리플렉션을 통해 프로그램에 의해 읽힐 수 있습니다. Annotation을 사용함으로써 코드에 대한 데이터를 정의하고, 이 정보를 실행 시간에 분석하여 동작을 변경할 수 있습니다. 예를 들어, `@Override`는 메서드가 상위 클래스의 메서드를 오버라이드한다는 것을 나타내며, `@Deprecated`는 메서드나 클래스가 더 이상 사용되지 않음을 표시합니다. `@SuppressWarnings`는 컴파일러 경고를 무시하도록 지시합니다. 또한, 스프링 프레임워크에서는 `@Autowired`와 같은 Annotation을 사용하여 의존성 주입을 자동화합니다. 이처럼 Annotation은 프로그램에 추가적인 정보를 제공하고, 코드의 가독성과 유지보수성을 향상시키며, 다양한 프로그래밍 패턴과 프레임워크에서 중요한 역할을 합니다."
꼬리 질문 > Annotation을 사용할 때, 컴파일 시간과 실행 시간에 각각 어떤 방식으로 처리되나요, 그리고 이러한 처리 방식이 실제 애플리케이션 개발에 어떤 영향을 미치나요?
"Annotation은 컴파일 시간과 실행 시간에 다르게 처리될 수 있습니다. 컴파일 시간에 처리되는 Annotation은 주로 코드 검증, 문서 생성 등의 목적으로 사용됩니다. 예를 들어, @Override Annotation은 컴파일러가 메서드가 정말로 오버라이드 되었는지 확인하는 데 사용됩니다. 이런 처리는 개발 단계에서 코드의 오류를 줄여주고, 프로그램의 안정성을 높여줍니다.
실행 시간에 처리되는 Annotation은 리플렉션을 통해 프로그램이 실행 중에 해당 정보를 읽고, 그에 따라 동작을 변경할 수 있게 합니다. 예를 들어, 스프링 프레임워크의 @Autowired는 실행 시간에 의존성 주입을 자동으로 처리합니다. 이러한 실행 시간 Annotation의 처리는 개발자가 직접적인 객체 생성 및 관리 로직을 작성하지 않아도 되게 하여, 코드의 복잡성을 줄이고, 유지보수성을 향상시킵니다.
컴파일 시간과 실행 시간에 Annotation을 사용함으로써, 개발자는 코드의 정확성을 높이고, 개발 과정을 단순화할 수 있으며, 유연하고 확장 가능한 애플리케이션을 구축할 수 있습니다."
14. Spring Security의 구조와 JWT 발급 과정에 대해 설명해주실 수 있을까요?
핵심 키워드 : 인증과 인가, 보안, 서블릿, 필터, 검증, 서명
"Spring Security는 인증과 인가를 위한 강력한 보안 프레임워크로, Spring 기반의 애플리케이션 보안을 위해 널리 사용됩니다. 이 구조는 다수의 서블릿 필터로 구성되어 있으며, 요청이 들어올 때마다 이 필터 체인을 통해 보안 검사를 수행합니다. 인증 과정에서는 사용자의 신원을 확인하고, 인가 과정에서는 해당 사용자가 리소스에 접근할 수 있는 권한이 있는지를 검증합니다.
JWT(JSON Web Token) 발급 과정은 Spring Security와 통합하여 사용자 인증 후 보안 토큰을 생성하고 발급하는 과정을 포함합니다. 사용자가 로그인 정보(예: 사용자명과 비밀번호)를 제공하면, Spring Security는 이를 검증하고 유효한 사용자임을 확인합니다. 사용자 인증이 성공하면, 서버는 JWT를 생성합니다. 이 토큰은 사용자의 신원 정보, 발급자, 만료 시간 등을 포함하며, 비밀 키로 서명됩니다. 이렇게 생성된 JWT는 클라이언트에게 반환되며, 이후 클라이언트는 서버로 요청을 보낼 때마다 이 토큰을 함께 전송하여 자신의 신원을 증명합니다. 서버는 요청을 받을 때마다 JWT의 유효성과 서명을 검증하여 사용자의 인증 상태와 권한을 확인합니다. 이 과정을 통해, 애플리케이션은 상태를 유지하지 않으면서도 안전하게 사용자 인증과 인가를 처리할 수 있습니다."
꼬리 질문 > Spring Security에서 JWT를 사용할 때, 만약 토큰이 탈취되었다면 어떻게 보안을 강화할 수 있나요?
"Spring Security와 JWT 사용 시 토큰 탈취 위험에 대응하기 위해 여러 보안 강화 방법을 적용할 수 있습니다. 첫째, HTTPS를 사용하여 데이터 전송 과정에서의 토큰 암호화를 보장하여 중간자 공격을 방지합니다. 둘째, JWT의 만료 시간을 짧게 설정하여 탈취된 토큰의 사용 가능 시간을 제한합니다. 셋째, 리프레시 토큰과 액세스 토큰의 조합을 사용하여, 액세스 토큰은 짧게, 리프레시 토큰은 비교적 길게 설정하고, 리프레시 토큰을 사용하여 액세스 토큰을 재발급 받는 방식을 사용합니다. 이는 탈취된 토큰으로 인한 피해를 최소화하는 동시에 사용자 경험을 저해하지 않는 균형을 찾는 전략입니다. 추가적으로, 토큰에 대한 접근 제어와 감사 로그를 통해 비정상적인 토큰 사용 시도를 감지하고 대응할 수 있습니다."
15. N+1 문제의 발생 이유와 해결 방법에 대해 설명해주실 수 있을까요? 해결 방법은 3가지 이상 말씀해주시면 좋습니다.
핵심 키워드 : 지연 로딩, 조인, 연관 관계
"N+1 문제는 ORM을 사용할 때, 한 번의 쿼리로 연관된 객체를 로드할 때 발생하는 지연 로딩 때문에, 연관된 객체의 수만큼 추가 쿼리가 발생하는 문제를 말합니다. 예를 들어, 한 게시글에 여러 댓글이 있을 때, 게시글을 조회하고 각 게시글의 댓글을 로드하기 위해 댓글 수만큼 추가 쿼리가 실행되는 것입니다. 이 문제를 해결하는 방법으로는:
첫번째로, 조인을 사용하여 연관된 엔티티를 한 번의 쿼리로 함께 조회합니다. 이 방법은 필요한 모든 데이터를 한 번에 가져올 수 있어 추가 쿼리를 줄일 수 있습니다.
다음은, ORM에서 제공하는 Fetch Join 기능을 사용하여 연관된 객체를 처음부터 함께 로드합니다. 이는 연관된 객체에 대한 지연 로딩을 방지합니다.
마지막으로 ORM 설정에서 batch size를 지정하여, 연관된 객체를 로드할 때 한 번에 여러 객체를 로드하는 쿼리를 실행할 수 있습니다. 이는 쿼리의 수를 줄이는 효과적인 방법입니다.
이러한 방법들을 적절히 활용함으로써, ORM을 사용하면서도 N+1 문제를 효과적으로 방지하고 애플리케이션의 성능을 유지할 수 있습니다."
꼬리 질문 > Fetch Join과 batch size 설정 중에서 성능 최적화를 위해 먼저 고려해야 할 점은 무엇인가요, 그리고 이 두 방법을 적용할 때 주의해야 할 사항은 무엇인가요?
"성능 최적화를 위해서는 먼저 Fetch Join을 고려하는 것이 좋습니다. Fetch Join은 관련된 엔티티를 단일 쿼리로 로드하여 N+1 문제를 근본적으로 해결할 수 있기 때문입니다. 특히, 필요한 데이터가 많고 복잡한 상황에서는 Fetch Join이 더 효과적일 수 있습니다. 하지만, 너무 많은 데이터를 한 번에 조인하려고 하면 메모리 사용량이 증가하고 성능이 저하될 수 있으므로, 조인하는 데이터의 양과 범위를 신중하게 결정해야 합니다.
반면, batch size 설정은 대량의 연관된 객체를 로드할 때 유용하며, 특히 조인 사용이 어려운 상황이나 조인으로 인한 성능 저하가 예상될 때 더 효과적일 수 있습니다. batch size를 적절히 설정하면 쿼리 수를 줄이면서도 메모리 사용량을 관리할 수 있습니다. 그러나 너무 큰 batch size는 메모리 부담을 증가시킬 수 있고, 너무 작은 batch size는 쿼리 수를 충분히 줄이지 못해 성능 향상에 큰 도움이 되지 않을 수 있습니다.
따라서, 두 방법을 적용할 때는 애플리케이션의 특정 상황과 요구 사항을 고려하여 최적의 전략을 선택해야 하며, 가능하면 두 방법을 적절히 조합하여 사용하는 것이 좋습니다. 이를 통해 ORM 사용 시 발생할 수 있는 성능 문제를 최소화하고 애플리케이션의 전반적인 성능을 개선할 수 있습니다."
16. 즉시로딩과 지연로딩은 각각 언제 사용하면 좋은지 설명해주실 수 있을까요?
핵심 키워드 : 프록시 객체, 조회 시점
"즉시로딩(Eager Loading)은 연관된 객체들을 처음 엔티티를 조회할 때 함께 로드하는 방식입니다. 이 방식은 연관된 데이터를 함께 자주 사용할 때 유용하며, 복잡한 연산이나 여러 연관 객체에 대한 정보가 한 번에 필요할 경우 선호됩니다. 하지만 불필요한 데이터까지 로드할 위험이 있어 성능 저하를 일으킬 수 있습니다.
반면, 지연로딩(Lazy Loading)은 연관된 객체를 실제로 사용하는 시점에 로드하는 방식입니다. 이는 프록시 객체를 활용해 구현되며, 필요할 때까지 데이터 조회를 지연시켜 불필요한 리소스 사용을 줄입니다. 지연로딩은 시스템의 초기 응답 시간을 단축시키고, 필요하지 않은 데이터는 로드하지 않아 리소스를 효율적으로 사용할 때 적합합니다.
즉시로딩은 데이터의 전체적인 조회가 필요한 경우에, 지연로딩은 최적화와 자원의 효율적 사용을 중시할 때 적합한 로딩 전략입니다. 각 상황에 맞게 적절한 로딩 방식을 선택함으로써, 애플리케이션의 성능과 효율성을 극대화할 수 있습니다."
꼬리 질문 > N+1 문제 해결 전략 중 조인 사용, Fetch Join, 배치 사이즈 설정이 각각 어떤 상황에서 가장 적합한가요? 그리고 이 방법들을 적용할 때 주의해야 할 점은 무엇인가요?
"조인 사용은 연관된 데이터를 한 번의 쿼리로 함께 가져와야 할 때 특히 유용합니다. 예를 들어, 리스트 페이지에서 여러 엔티티의 정보를 동시에 보여줘야 할 때 조인을 사용하면 성능을 크게 개선할 수 있습니다. 하지만, 너무 많은 데이터를 한 번에 로드하려고 할 때는 메모리 사용량이 급증할 수 있으므로 주의가 필요합니다.
Fetch Join은 지연 로딩으로 인해 발생할 수 있는 N+1 문제를 명확히 해결하고자 할 때 유리합니다. 특히, 연관된 데이터를 상세 페이지 등에서 전부 또는 대부분 사용할 예정일 때 적합합니다. 그러나 Fetch Join을 남용하면 예상치 못한 메모리 부하나 성능 저하를 일으킬 수 있습니다.
배치 사이즈 설정은 연관된 객체를 로드할 때 한 번에 로드하는 객체의 수를 조정하여 성능을 향상시키고 싶을 때 사용됩니다. 이는 지연 로딩을 사용하면서도 N+1 문제의 영향을 줄이고자 할 때 효과적입니다. 단, 배치 사이즈가 너무 크면 네트워크 병목 현상이나 메모리 부족 문제가 발생할 수 있으니 적절한 사이즈를 선택하는 것이 중요합니다.
각 해결 전략을 적용할 때는 애플리케이션의 특정 요구 사항과 환경을 고려하여 가장 적합한 방법을 선택해야 하며, 성능 테스트를 통해 최적의 해결책을 찾는 것이 중요합니다."
17. Spring bean container 생성부터 스프링 종료까지의 사이클에 대해 알려주실 수 있을까요? @PostConstruct, @PreDestroy 어노테이션의 역할도 함께 알려주시면 좋습니다.
핵심 키워드 : 생명 주기, 의존성 주입, 초기화, 메모리
"스프링 빈 컨테이너의 생명 주기는 빈의 생성부터 스프링 애플리케이션 종료까지의 과정을 포함합니다. 초기에 컨테이너는 빈 정의를 읽어들이고, 이를 기반으로 빈 인스턴스를 생성합니다. 이후 의존성 주입을 통해 빈 간의 관계를 설정합니다. 빈이 완전히 생성되고 나면, 컨테이너는 `@PostConstruct` 어노테이션이 붙은 메소드를 호출하여 초기화 작업을 수행합니다. 이 메소드는 빈이 생성된 후 실행되어야 하는 사용자 정의 로직을 포함할 수 있습니다. 애플리케이션이 종료될 때, 스프링 컨테이너는 `@PreDestroy` 어노테이션이 붙은 메소드를 호출하여 빈을 정리하거나 해제하는 작업을 수행합니다. 이는 리소스를 해제하거나 필요한 정리 작업을 정의하는 데 사용됩니다. 이러한 과정을 통해 스프링은 애플리케이션 내 빈의 생명 주기를 관리하며, 메모리 관리와 애플리케이션의 안정성을 보장합니다."
꼬리 질문 > @PostConstruct와 @PreDestroy 어노테이션이 붙은 메소드는 스프링 빈의 생명 주기에서 정확히 어떤 시점에 호출되나요, 그리고 이러한 메소드들을 활용할 때 어떤 종류의 작업을 처리하는 것이 일반적인가요?
"@PostConstruct 어노테이션이 붙은 메소드는 스프링 빈이 생성되고 의존성이 주입된 직후에 호출됩니다. 이 시점은 빈이 완전히 준비되어 사용할 수 있는 상태가 된 바로 그 순간이며, 주로 초기화 작업에 사용됩니다. 예를 들어, 데이터베이스 연결을 초기화하거나, 필요한 리소스를 불러오는 등의 작업을 이 메소드 내에서 처리할 수 있습니다.
@PreDestroy 어노테이션이 붙은 메소드는 스프링 컨테이너가 종료되기 직전, 즉 빈이 파괴되기 바로 전에 호출됩니다. 이는 빈이 소유한 자원을 해제하거나, 필요한 정리 작업을 수행하기에 이상적인 시점입니다. 예를 들어, 열려 있는 파일이나 데이터베이스 연결을 닫거나, 캐시를 정리하는 등의 작업을 처리할 수 있습니다.
이러한 메소드들을 통해 스프링 빈은 생성과 파괴의 생명 주기 동안 필요한 준비와 정리 작업을 적절히 수행할 수 있으며, 이는 애플리케이션의 안정성과 성능 유지에 기여합니다."
18. AOP, Interceptor, Filter 의 차이점, Request가 들어올때 거치는 순서, 각 역할들의 장점을 설명해주실 수 있을까요?
핵심 키워드 : 서블릿, 프록시, filter chain, 관점 지향, 컨트롤러
"AOP(Aspect-Oriented Programming), Interceptor, 그리고 Filter는 Java 웹 개발에서 요청 처리 과정에 있어 서로 다른 레이어에서 작동하며, 특정 작업을 수행합니다.
우선, Filter란 서블릿 필터는 서블릿 스펙에 정의되어 있으며, 요청과 응답을 서블릿이나 JSP에 도달하기 전에 처리합니다. 보통 인코딩 변환, 로깅, 인증과 같은 일을 수행하며, Filter Chain을 통해 여러 필터를 순서대로 적용할 수 있습니다.
Interceptor는 스프링 프레임워크에서 제공하는 기능으로, Controller에 도달하기 전과 후, 그리고 뷰가 렌더링된 후에 특정 작업을 수행할 수 있습니다. 데이터 변환, 로깅, 인증 등을 수행하며, AOP보다는 좁은 범위에서 작동합니다.
AOP는 관점 지향 프로그래밍은 애플리케이션의 공통 관심 사항(트랜잭션 관리, 로깅, 보안 등)을 모듈화하는 프로그래밍 기법입니다. 프록시 패턴을 사용하여, 특정 메소드 실행 전후 또는 예외 발생 시 등에 추가적인 작업을 할 수 있습니다.
요청이 들어올 때, Filter -> Interceptor -> AOP 순서로 거칩니다. Filter는 가장 먼저 요청을 처리하고, 요청이 컨트롤러로 넘어가기 전에 Interceptor가 작업을 수행합니다. 마지막으로, AOP는 메소드 호출 자체를 감싸 메소드 실행 전후에 작업을 수행할 수 있습니다.
각각의 장점으로는, Filter는 요청과 응답에 대한 가장 낮은 수준의 처리를 가능하게 하고, Interceptor는 스프링의 컨텍스트 내에서 동작하여 스프링 빈과의 통합이 용이하다는 점이 있습니다. AOP는 애플리케이션 전반에 걸친 공통 관심 사항을 효율적으로 관리할 수 있게 해줍니다."
꼬리 질문 > Filter, Interceptor, 그리고 AOP를 함께 사용할 때, 각각의 역할이 중첩되지 않도록 관리하는 방법은 무엇인가요? 또한, 이들을 효과적으로 조합하여 사용하기 위한 베스트 프랙티스는 무엇인가요?
"Filter, Interceptor, 그리고 AOP를 함께 사용할 때 중요한 것은 각 기술의 목적과 적용 범위를 명확히 이해하고 구분하는 것입니다. Filter는 주로 요청과 응답의 전처리 및 후처리, 예를 들어 인코딩 설정이나 CORS 정책 적용 등의 애플리케이션 전반에 걸친 처리에 사용됩니다. Interceptor는 스프링 MVC 컨트롤러의 실행 전후로 세밀한 로직을 추가하고자 할 때 사용되며, 주로 인증 검사, 로깅, 데이터 가공과 같은 작업에 적합합니다. AOP는 애플리케이션의 공통 관심 사항을 관리하는데 사용되며, 트랜잭션 관리나 보안, 로깅 등을 모듈화하여 여러 컴포넌트에 걸쳐 적용할 수 있습니다.
이들을 함께 사용할 때는 각 기술의 적용 범위와 목적에 맞게 구분하여 사용하는 것이 중요합니다. 예를 들어, 보안 관련 로직은 Interceptor나 AOP를 통해 처리하고, 요청의 인코딩 변경과 같은 전역적인 설정은 Filter를 사용하여 처리합니다. 또한, 중복된 로직을 피하고, 코드의 가독성과 유지보수성을 고려하여 각 기술을 적용해야 합니다. 베스트 프랙티스는 애플리케이션의 요구 사항과 구조를 충분히 분석한 후, 각 기술의 장점을 최대한 활용하여 애플리케이션의 성능과 유지보수성을 향상시키는 것입니다."
'면접 (Java) > 준비' 카테고리의 다른 글
[면접] 기초 면접 (19~24) (0) | 2024.03.28 |
---|---|
[면접] 프로젝트 면접 (9~12) (0) | 2024.03.27 |
[면접] 프로젝트 면접 (5~8) (0) | 2024.03.26 |
[면접] 기초 면접 (7~12) (0) | 2024.03.26 |
[면접] 프로젝트 면접 (1~4) (0) | 2024.03.25 |