개발놀이터

여태까지 공부한 Spring 면접질문 / 답변 본문

CS 지식/면접준비

여태까지 공부한 Spring 면접질문 / 답변

마늘냄새폴폴 2023. 4. 6. 05:25

https://coding-review.tistory.com/343

 

여태까지 공부한 Java 면접질문 / 답변

4부터 시작하는 것은 넘어가주시길 바랍니다... 따로 정리하면서 공부한거라 Java 면접질문이 아닌 123번을 제외하고 4번부터 수록했습니다. 꼬리질문에 대한 답변도 수록했기 때문에 조금 길게

coding-review.tistory.com

위의 포스팅과 이어지는 내용입니다. 

 

1. 스프링이 어떻게 트랜잭션을 추상화했나요? / 왜 추상화 했나요? 
트랜잭션이 데이터 접근 기술마다 다른 현상이 발생했습니다. 예를 들어서 JDBC에서 JPA로 기술을 확장하기 위해서 그에 따른 모든 트랜잭션 코드들을 바꿔야했습니다. 이를 해결하고자 스프링에서는 플랫폼트랜잭션매니저 라는 것으로 모든 트랜잭션 코드들을 추상화 했습니다. 이를 통해 개발자는 특정 데이터베이스 접근기술에 종속적이지 않은 트랜잭션 코드를 작성할 수 있게 되었습니다. 

2. @Transactional에 대해서 설명해주세요
@Transactional은 스프링이 만든 AOP 중 하나입니다. @Transactional이 붙어있는 메서드에 한해서 트랜잭션의 원자성이 보장되고, 정상 로직일 때 커밋, 예외 상황일 때 롤백이 발생합니다. 이 어노테이션을 통해서 개발자는 비즈니스 로직과 트랜잭션 코드를 분리함으로써 좀 더 순수한 비즈니스 로직을 구현할 수 있게 되었습니다. 

3. AOP가 뭔가요?
AOP는 관점지향 프로그래밍의 약자로서 기존 OOP에서 기능별로 클래스를 분류했음에도 불구하고 로깅, 트랜잭션, 자원해제와 같은 공통관심사가 생기기 시작했습니다. 이를 해결하고자 개발자는 좀 더 비즈니스 로직에 집중하고 공통관심사를 분리하는 기술이 바로 AOP기술입니다. 

 

30. 스프링 DI에 대해서 설명해주세요.
스프링 DI는 스프링 프레임워크에서 지원하는 IoC의 형태로, 클래스 사이의 의존 관계를 빈 설정정보를 바탕으로 자동으로 주입해주는 것을 말합니다. 스프링에서는 스프링 컨테이너인 ApplicationContext를 통해 빈 설정정보를 등록, 수정할 수 있으며 원하는 객체를 생성자, setter, 필드로 주입할 수 있습니다. 

31. DI의 종류에 대해서 설명해주세요. 
DI의 종류는 생성자 주입, setter 주입, 필드 주입이 있습니다. 생성자 주입은 생성자가 생성될 때 단 한번만 호출되는 것을 보장하고 필수, 불변의 의존관계에서 사용됩니다. setter 주입은 선택, 변경 가능한 의존관계에서 사용되고 스프링 빈을 선택적으로 등록할 수 있습니다. 필드 주입은 필드에 선언된 객체에 @Autowired를 붙여서 직접 주입하는 것입니다. 하지만 이렇게 필드 주입을 하게 되면 외부에서 코드를 변경할 수 없기 때문에 테스트 코드를 작성하는데 굉장히 까다로워지고 순환 참조가 발생할 수 있으며 DI 프레임워크가 작동하지 않으면 동작하지 않기 때문에 애플리케이션 코드와 전혀 관계없는 테스트 코드에서 주로 사용됩니다. 

32. 스프링 빈에 대해서 설명해주세요. 
스프링 빈은 스프링 컨테이너에서 관리하는 자바 객체를 의미합니다. 

33. 스프링 컨테이너에 대해서 설명해주세요.
스프링 컨테이너는 스프링 빈의 생명주기를 관리하고 생성된 스프링 빈에 추가적인 기능을 제공하는 역할을 합니다. 개발자가 생성한 객체는 new 연산자나 인터페이스 호출등의 방식으로 생성, 소멸되지만 스프링 컨테이너를 사용하면 이를 자동으로 수행해줍니다. 즉, 제어의 흐름을 외부에서 관리한다는 의미입니다. 또한, 객체 또는 클래스 사이의 의존관계를 런티임시에 자동으로 주입해주는 역할도 합니다. 

34. 스프링 빈의 생성과정에 대해서 설명해주세요. 
스프링 빈은 의존설정, 객체 생성, 초기화, 사용, 소멸의 순서를 가지고 이는 스프링 컨테이너에 의해 관리됩니다. 빈 초기화는 @PostConstruct에 의해 수행될 수 있고, 빈 소멸은 @PreDestroy에 의해 수행될 수 있습니다. 이렇게 선언된 빈은 컴포넌트 스캔이나 Configuration 클래스를 빈으로 등록해서 사용할 수 있습니다. 

35. 스프링 빈 스코프에 대해서 설명해주세요. 
스코프는 스프링 빈이 존재할 수 있는 영역을 나타내고 싱글톤, 프로토타입, request, session, application이렇게 다섯가지가 있습니다. 싱글톤은 가장 기본이 되는 스코프로서 스프링 컨테이너의 생성과 소멸까지 관여하는 가장 긴 범위의 스코프입니다. 프로토타입은 빈 생성과 주입까지만 관여하고 그 이후는 관여하지 않는 가장 짧은 범위의 스코프입니다. request는 웹 요청이 들어오고 나올 때 까지 유지되는 스코프, session은 웹 세션이 생성되고 소멸될 때 까지 유지되는 스코프, application은 서블릿 컨테이너와 같은 방식으로 동작하는 스코프입니다. 

36. 스프링 MVC의 동작과정에 대해서 설명해주세요.
핸들러 매핑에서 핸들러를 조회하고 핸들러 어댑터 목록에서 사용할 핸들러 어댑터를 조회한다음 핸들러 어댑터를 실행하면서 그 때 사용할 핸들러도 같이 실행합니다. 이 때 핸들러 어댑터는 디스패처 서블릿에세 ModelAndView를 반환합니다. 그럼 viewResolver는 핸들러 어댑터에게 뷰를 반환합니다. 그렇게 되면 디스패처 서블릿이 뷰를 랜더링합니다.  

37. 필터와 인터셉터의 차이점에 대해서 설명해주세요. 
우선 둘은 스펙부터가 다릅니다. 필터는 javax.servlet에 포함된 클래스이고 인터셉터는 스프링MVC에 포함된 클래스입니다. 또한, 이 둘은 사용 시점도 다릅니다. 필터는 서블릿이 수행되기 전후로 실행됩니다. 인터셉터는 핸들러가 실행되기 전후에 실행되거나 viewResolver에 의해 호출된 Controller에서 viewName을 가진 렌더링을 담당한 실제 view 오브젝트가 렌더링 되고 수행됩니다. 마지막으로 저장 위치가 다릅니다. 필터는 Web Application에 저장되고 톰캣을 사용한다면 web.xml에 저장됩니다. 인터셉터는 스프링 컨테이너인 ApplicationContext에 저장됩니다. 

38. CORS 에러에 대해서 설명해주세요. 
CORS에러는 Cross Origin Resource Sharing의 약자로 동일한 출처가 아닌 다른 출처에서의 접근을 막는 보안 정책입니다. 

39. 스프링에서 CORS에러를 해결하기 위해서 어떻게 해야하나요? 
스프링에서 CORS 에러를 해결하기 위해서는 필터에서 Access-Control-Allow-Origin을 헤더에 담아 응답하거나 WebMvcConfigurer를 구현한 Configuration 클래스를 빈으로 등록하거나 @CrossOrigin 어노테이션을 사용하면 됩니다. 이중 가장 간단한 것은 어노테이션을 사용하는 것이지만 문제는 컨트롤러마다 어노테이션을 붙여야해서 url이 바뀌게 되면 일일히 찾아가서 바꿔야 한다는 문제가 있습니다. 

40. @Bean, @Component 어노테이션에 대해서 설명해주세요. 
둘 다 빈을 싱글톤으로 등록하기 위해 사용하는 어노테이션입니다. 이 둘의 차이는 @Bean은 메서드를 빈으로 등록할 때 사용하고, @Component는 클래스를 빈으로 등록할 때 사용합니다. 

41. POJO 클래스가 뭔가요? 
POJO 클래스는 클래스를 구현하거나, 확장하지 않은 가장 순수한 자바 클래스입니다. POJO 클래스는 자바 API외에 어떠한 것에도 종속되지 않습니다. 어떠한 것에도 종속되지 않기 때문에 코드를 작성하기 굉장히 쉽고 테스트하기 굉장히 쉽습니다. 스프링에서 POJO 클래스에 해당하는 것은 도메인 클래스나 비즈니스 로직을 담고있는 Service 클래스입니다. 

42. JPA 영속성 컨텍스트를 사용하면 좋은 이점이 뭔가요? 
JPA 영속성 컨텍스트를 사용하면 좋은 이점은 1차캐시, 동일성 보장, 쓰기 지연, 변경 감지, 지연 로딩이 있습니다. 1차 캐시는 데이터베이스에서 조회가 가능하고 JPA가 데이터를 관리하는데 사용되는 데이터베이스입니다. 동일성 보장은 ==비교가 가능하다는 의미입니다. 쓰기 지연은 트랜잭션이 제공하는 쓰기 지연을 사용할 수 있고 커밋이 되기 전에 SQL문을 모아놨다가 커밋이 될 때 이를 한번에 적용시키는 것을 의미합니다. 변경 감지는 1차캐시에 데이터를 스냅샷에 찍고 이후 커밋이 될 때 엔티티와 스냅샷을 비교해서 다르면 update 쿼리가 날라가는 것을 말합니다. 지연 로딩은 객체가 선언될 때가 아닌 호출될 때 쿼리가 날라가는 것을 의미합니다. 

43. JPA를 사용하는 이유에 대해서 설명해주세요. 
JPA를 사용하는 이유는 객체지향 프레임워크이기 때문입니다. JPA를 사용하는 비즈니스 로직은 RDBMS에 의존적이지 않고 자바코드로 작성할 수 있습니다. 자바코드로 작성하면 생산성이 올라갑니다. 또한, JPA는 SQL문을 JPQL이라는 것으로 추상화하여 RDBMS에 의존하지 않고 동일한 쿼리로 동일한 결괏값을 기대할 수 있습니다. 이는 Database dialect를 지원하기 때문에 생기는 장점입니다. 

44. 자바코드로 작성하면 왜 생산성이 올라가나요?
자바 컬렉션에 저장하듯이 데이터를 저장하고 개발자가 귀찮아할만한 DDL문을 자동으로 작성해주어 데이터베이스 설계 중심에서 객체 설계 중심으로 변경할 수도 있습니다. 

45. N + 1 문제에 대해서 설명해주세요. 
N + 1문제는 연관관계를 맺은 두 엔티티에서 데이터를 하나의 쿼리에 전부 가져오는 것이 아니라 필요할 때 그때그때 쿼리가 날아가는 것을 말합니다. N + 1문제는 즉시로딩과 지연로딩 모두에서 발생하는데 즉시로딩에서 발생하는 이유는 전체를 가져오는 쿼리를 작성하면 영속성 컨텍스트에서 데이터를 조회하는 것이 아니라 데이터베이스에서 데이터를 조회하고 즉시로딩 전략이 작동하기 때문입니다. 지연로딩에서 발생하는 이유는 지연로딩을 채택한 하위 엔티티를 로드할 때 조회에 필요한 쿼리가 추가적으로 나가기 때문에 발생합니다. 이러한 N + 1문제를 해결하기 위해서는 fetch join 이라고 불리는 JPQL의 join fetch를 사용하거나 @EntityGraph 어노테이션을 사용하거나 @BatchSize 어노테이션을 사용하면 해결할 수 있습니다. 이때 주의사항으로는 fetch join은 on절을 사용하면 에러가 발생하기 때문에 where절로 조건문을 작성해야 하고, @EntityGraph의 경우에는 너무 많은 연관관계가 맺어진 경우엔 자칫 잘못하다간 파국으로 치닫을 수 있기 때문에 조심해서 사용해야 합니다.