💡 WAS(Web Application Server)와 WS(Web Server)의 차이를 설명해주세요.
- 웹 서버는 이미지나 단순 HTML과 같은 정적인 컨텐츠를 제공하는 서버입니다.
- Apache
- 반면 WAS는 DB 조회나 어떤 로직을 처리해야 하는 동적인 컨텐츠를 제공하는 서버입니다.
- Tomcat
💡 Spring Framework에 대해 설명해주세요.
- 스프링 프레임워크는 자바 개발을 편리하게 해주는 오픈소스 프레임워크 입니다.
- 스프링은 경량 컨테이너로서 자바 객체를 직접 관리합니다. 즉, 객체 생성, 소멸과 같은 라이프 사이클을 관리하며 개발자는 스프링으로부터 필요한 객체를 얻어올 수 있습니다.
- 또한 제어의 역전(IoC)이라는 기술을 통해 오브젝트의 생성과 의존 관계 설정 등의 작업을 어플리케이션 코드가 아닌 스프링 컨테이너가 담당하게 함으로써 어플리케이션의 느슨한 결합을 도모하고
- 필요한 객체를 직접 생성하는 것이 아닌 외부로부터 객체를 받아서 사용하는 의존성 주입(DI, Dependency Injection)과
- 트랜잭션이나 로깅, 보안과 같이 여러 모듈에서 공통적으로 사용하는 기능의 경우 해당 기능을 분리하여 관리할 수 있도록 하는 관점 지향 프로그래밍(AOP, Aspect-Oriented Programming)을 지원합니다.
💡 @RequestBody, @RequestParam, @ModelAttribute의 차이를 설명해주세요.
- @RequestBody
- @RequestBody는 클라이언트가 전송하는 JSON 형태의 HTTP Body 내용을 MessageConverter를 통해 Java Object로 변환시켜주는 역할을 합니다.
- 값을 주입하지 않고 값을 변환시키므로(Reflection을 사용해 할당), 변수들의 생성자, Getter, Setter가 없어도 정상적으로 할당됩니다.
- @RequestParam
- @RequestParam은 1개의 HTTP 요청 파라미터를 받기 위해 사용합니다.
- @RequestParam은 필수 여부가 true이기 때문에, 기본적으로 반드시 해당 파라미터가 전송되어야 합니다.
- 전송되지 않으면 Error를 유발할 수 있으며, 반드시 필요한 변수가 아니라면 required의 값을 false로 설정해줘야 합니다.
- @ModelAttribute
- @ModelAttribute는 클라이언트가 보내는 HTTP 파라미터들을 특정 Java Object에 바인딩(맵핑)하는 역할을 수행합니다.
- 따라서 객체의 필드에 접근해 데이터를 바인딩할 수 있는 생성자 혹은 Setter 메서드가 필요합니다.
💡 Spring Boot와 Spring Framework의 차이점을 설명해주세요.
- 가장 큰 차이점은 Auto Configuration의 차이인 것 같습니다.
- Spring은 프로젝트 초기에 다양한 환경설정을 해야 하지만, Spring Boot는 설정의 많은 부분을 자동화하여 개발자가 편하게 스프링을 활용할 수 있도록 합니다.
- Spring Boot를 사용하면 spring boot starter dependency만 추가해줌으로써 설정을 마칠 수 있고, 톰캣 서버가 내장되어 있기 때문에 바로 실행할 수 있습니다.
💡 Spring MVC에 대해 설명해주세요.
- MVC는 Model, View, Controller의 약자이며, 각 레이어간 기능을 구분하는데 중점을 둔 디자인 패턴입니다.
- Model은 데이터 관리 및 비즈니스 로직을 처리하는 부분이며, (DAO, DTO, Service 등)
- View는 비즈니스 로직의 처리 결과를 통해 유저 인터페이스가 표현되는 구간입니다.
- Controller는 사용자의 요청을 처리하고 Model과 View를 중개하는 역할을 합니다. Model과 View는 서로 연결되어 있지 않기 때문에 Controller가 그 사이에서 중개자의 역할을 수행합니다.
💡 MVC는 어떠한 흐름으로 요청을 처리하는지 설명해주세요.
- 우선 클라이언트가 URL을 통해 요청을 전송합니다.
- 그럼 DispatcherServlet은 HandlerMapping을 통해 해당 요청이 어느 Controller에게 온 요청인지 찾고, HandlerAdapter에게 요청의 전달을 맡깁니다.
- HandlerAdapter는 해당 Controller에 요청을 전달하고
- Controller는 비즈니스 로직을 처리한 후에 반환할 View의 이름을 반환합니다.
- 이후 DispatcherServlet은 ViewResolver를 통해 반환할 View를 찾고, Controller에서 View에 전달할 데이터를 추가합니다.
- 마지막으로 데이터가 추가된 View를 반환함으로써 처리가 완료됩니다.
DispatcherServlet: 클라이언트에게 요청을 받아 응답까지의 MVC 처리과정을 통제한다.
HandlerMapping: 클라이언트의 요청 URL을 어떤 Controller가 처리할지 결정한다.
HandlerAdapter: HandlerMapping에서 결정된 핸들러 정보로 해당 메소드를 직접 호출해주는 역할을 한다. ViewResolver: Controller의 처리 결과(데이터)를 생성할 view를 결정한다.
💡 제어의 역전(IoC, Inversion of Control)에 대해 아는대로 설명해주세요.
- 제어의 역전(IoC)이란 모든 객체에 대한(생성, 라이프사이클 등) 제어권을 개발자가 아닌 IoC 컨테이너에게 넘기는 것을 말합니다.
- 스프링에서는 IoC 컨테이너에 객체들을 생성하면 객체끼리 의존성을 주입(DI, Dependency Injection)하는 역할을 하고, 이렇게 컨테이너에 등록한 객체들을 '빈(Bean)'이라고 합니다.
💡 스프링에서 빈(Bean)을 등록하는 방법에 대해 말해보세요.
- 빈을 등록하는 방법은 기본적으로 2가지가 있습니다.
- 첫 번째 방법은 @Component 어노테이션을 사용하는 것입니다. @Controller, @Service, @Repository 모두 @Component를 포함하고 있는 어노테이션이며, 이를 명시함으로써 간단하게 빈으로 등록할 수 있습니다.
- 두 번째 방법으로는 설정 클래스를 따로 만들어 @Configuration 어노테이션을 붙이고, 해당 클래스 안에서 빈으로 등록할 메소드를 만들어 @Bean 어노테이션을 붙여주면 자동으로 해당 타입의 빈 객체가 생성됩니다.
💡 의존성 주입(DI, Dependency Injection)에 대해 설명해주세요.
- 의존성 주입은 필요한 객체를 직접 생성하는 것이 아닌 외부로부터 객체를 받아서 사용하는 것을 말합니다.
- 이를 통해 객체 간의 결합도를 줄이고 코드의 재사용성을 높일 수 있습니다.
- 의존성 주입에는 생성자 주입, 필드 주입, Setter 주입의 3가지 방법이 있습니다.
- 이 중 Spring에서 가장 권장하는 의존성 주입 방법은 생성자를 통한 주입 방법입니다.
- 그 이유는 생성자의 호출 시점에 1회 호출 되는 것이 보장되므로 객체의 불변성을 확보할 수 있고, 테스트 코드의 작성이 용이하며, 순환 참조 에러를 어플리케이션 구동 시점에 파악할 수 있기 때문입니다.
💡 스프링 빈의 라이프사이클은 어떻게 관리되는지 설명해주세요.
- 먼저 스프링 Bean의 LifeCycle은 다음과 같습니다.
- 스프링 IoC 컨테이너 생성 → 스프링 빈 생성 → 의존관계 주입 → 초기화 콜백 메소드 호출 → 애플리케이션에서 빈 사용 → 소멸 전 콜백 메소드 호출 → 스프링 종료
- 스프링은 크게 3가지 방법으로 빈 생명주기 콜백을 관리합니다.
- 인터페이스(InitializingBean, DisposableBean)
- 설정 정보에 초기화 메소드, 종료 메소드 지정
- @PostConstruct, @PreDestroy 어노테이션 지원
💡 관점지향 프로그래밍(AOP, Aspect Oriented Programming)는 무엇이고, 언제 사용할 수 있을까요?
- 관점지향 프로그래밍은 트랜잭션이나 로깅, 보안과 같이 여러 모듈에서 공통적으로 사용하는 기능의 경우 해당 기능을 분리하여 관리할 수 있도록 해주는 기능을 말합니다.
- 즉, 핵심 비즈니스 로직에 부가기능을 하는 모듈이 중복되어 분포되어 있을 경우 사용할 수 있습니다.
- AOP의 가장 큰 특징이자 장점은 중복 코드 제거, 재활용성의 극대화, 변화수용의 용이성에 있습니다.
💡 서블릿(Servlet)에 대해 설명해주세요.
- 서블릿은 클라이언트의 요청을 처리하고, 그 결과를 반환하는 Servlet 클래스의 구현 규칙을 지킨 자바 웹 프로그래밍 기술입니다.
- Spring MVC에서 Controller로 이용되며, 사용자의 요청을 받아 처리한 후에 결과를 반환합니다.
- 요약하자면, 자바를 사용해서 웹을 만들기 위해 필요한 기술이라고 할 수 있습니다.
💡 서블릿의 동작 방식에 대해 설명해주세요.
- 사용자(Client)가 URL을 입력하면 HTTP Request가 Servlet Container로 전송됩니다.
- 요청받은 Servlet Container는 HttpServletRequest, HttpServletResponse 객체를 생성합니다.
- web.xml을 기반으로 사용자가 요청한 URL이 어느 서블릿에 대한 요청인지 찾습니다.
- 해당 서블릿에서 service 메소드를 호출한 후 GET, POST 여부에 따라 doGet() 또는 doPost()를 호출합니다.
- doGet() or doPost() 메소드는 동적 페이지를 생성한 후 HttpServletResponse 객체에 응답을 보냅니다.
- 응답이 끝나면 HttpServletRequest, HttpServletResponse 두 객체를 소멸시킵니다.
💡 VO와 BO, DAO, DTO에 대해 설명해주세요.
- DAO(Data Access Object)는 DB의 데이터에 접근하기 위한 객체를 말합니다. (Repository 또는 Mapper에 해당)
- BO(Business Object)는 여러 DAO를 활용해 비즈니스 로직을 처리하는 객체를 말합니다. (Service에 해당)
- DTO(Data Transfer Object)는 각 계층간의 데이터 교환을 위한 객체를 말합니다. (여기서 말하는 계층은 Controller, View, Business Layer, Persistent Layer)
- VO(Value Object)는 실제 데이터만을 저장하는 객체를 말합니다.
💡 대용량 트래픽에서 장애가 발생하면 어떻게 대응할 것인가요?
- 스케일 업을 통해 하드웨어 스펙을 향상시키거나 스케일 아웃을 통해 서버를 여러대 추가하여 시스템을 증가시킵니다.
💡 Spring의 싱글톤 패턴에 대해 설명해주세요.
- 스프링에서 빈 생성시 별다른 설정이 없으면 default로 싱글톤이 적용됩니다.
- 스프링은 컨테이너를 통해 직접 싱글톤 객체를 생성하고 관리하는데,
- 요청이 들어올 때마다 매번 객체를 생성하지 않고, 이미 만들어진 객체를 공유하기 때문에 효율적인 사용이 가능합니다.
💡 Spring의 스코프 프로토 타입 빈에 대해 설명해주세요.
- 프로토타입 스프링 빈은 싱글톤과는 달리 스프링 컨테이너와 생명주기를 달리하며, 소멸 메소드가 자동으로 호출되지 않기 때문에 클라이언트에서 직접 관리해주어야 합니다.
- 또한 프로토타입 빈은 싱글톤(default bean) 빈과는 달리 컨테이너에게 빈을 요청할 때마다 매번 새로운 객체를 생성하여 반환해줍니다.
💡 @Transactional에 대해 설명해주세요.
- 비즈니스 로직이 트랜잭션 처리를 필요로할 때 트랜잭션 처리 코드가 비즈니스 로직과 공존한다면 코드 중복이 발생하고 비지니스 로직에 집중하는 것이 힘들어질 수 있습니다.
- @Transactional은 이러한 문제를 해결하기 위해 Spring에서 제공하는 어노테이션으로, @Transactional을 메서드 또는 클래스에 명시하게 되면 특정 메서드 또는 클래스가 제공하는 모든 작업에 대해 내부적으로 AOP를 통해 트랜잭션 처리코드가 전/후로 수행되게 됩니다.
💡 @Transactional의 동작 원리에 대해 설명해주세요.
- @Transactional을 메소드 또는 클래스에 명시하면, AOP를 통해 Target이 상속하고 있는 인터페이스 또는 Target 객체를 상속한 Proxy 객체가 생성됩니다.
- 해당 Proxy 객체의 메소드는 Target 메소드를 포함하고 있으며, Target 메소드 호출 전/후로 트랜잭션 처리를 수행합니다.
💡 @Transactional에 readOnly 속성을 사용하는 이유에 대해서 설명해주세요.
- 트랜잭션 안에서 수정/삭제 작업이 아닌 ReadOnly 목적인 경우에 주로 사용하며,
- 영속성 컨텍스트에서 엔티티를 관리 할 필요가 없기 때문에 readOnly를 추가하는 것으로 메모리 성능을 높일 수 있고,
- 데이터 변경 불가능 로직임을 코드로 표시할 수 있어 가독성이 높아진다는 장점이 있습니다.
💡 JPA N + 1 문제와 발생하는 이유 그리고 해결하는 방법을 설명해주세요.
- N+1이란 1번의 쿼리를 날렸을 때 의도하지 않은 N번의 쿼리가 추가적으로 실행되는 것을 의미합니다.
- 해결 방법에는 여러 방법이 있지만 가장 많이 사용되는 방법은 Fetch Join을 사용해 해결하는 방법입니다.
- N+1 문제가 발생하는 이유는 연관관계를 가진 엔티티를 조회할 때 한 쪽 테이블만 조회하고 연결된 다른 테이블은 따로 조회하기 때문인데,
- Fetch Join을 사용하면 미리 두 테이블을 Join하여 한 번에 모든 데이터를 가져오기 때문에 N+1 문제를 사전에 방지할 수 있습니다.
💡 JPA와 같은 ORM을 사용하면서 쿼리가 복잡해지는 경우에는 어떻게 해결하는게 좋을까요?
- JPQL과 Querydsl을 사용하여 해결할 수 있습니다.
- JPQL
- JPQL은 JPA의 일부로 Query를 Table이 아닌 객체(=엔티티) 기준으로 작성하는 객체지향 쿼리 언어라고 정의할 수 있습니다.
- JPQL은 객체를 기준으로 모든 것이 움직이기 때문에 개발할 때 Table에 매핑되는 객체가 반드시 존재해야하며 검색할 때도 Table이 아닌 객체를 대상으로 검색해야 합니다.
- 다만 JPQL은 여전히 문자열(=String) 형태이기 때문에 개발자 의존적 형태이며, 컴파일 단계에서 Type-Check가 불가능하다는 문제가 존재합니다.
- Querydsl
- 앞서 언급한 JPQL의 문제점을 보완하기 위해 고안된 것이 Querydsl입니다.
- Querydsl은 정적 타입을 이용해서 SQL, JPQL을 코드로 작성할 수 있도록 도와주는 오픈소스 빌더 API 입니다.
- query DSL을 사용하는 목적은 뚜렷합니다.
- 기존 방식(Mybatis, JPQL, etc..)은 모두 문자열(=String) 형태로 쿼리가 작성되었고 이로 인해 컴파일 단계에서 Type-Check가 불가능 했습니다.
- 이러한 리스크를 줄이기 위해 Querydsl이 등장하였고, 이를 통해 컴파일 단계에서 Type-check가 가능해진 것입니다.
📌 References
- https://dev-coco.tistory.com/163
- https://victorydntmd.tistory.com/121
- https://mangkyu.tistory.com/125
- https://goddaehee.tistory.com/154
- https://tecoble.techcourse.co.kr/post/2021-05-11-requestbody-modelattribute/
- https://dololak.tistory.com/783
- https://catsbi.oopy.io/b2de2693-fd8c-46e3-908a-188b3dd961f3
- https://velog.io/@ann0905/AOP%EC%99%80-Transactional%EC%9D%98-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC
- https://velog.io/@cho876/JPQL-vs-query-DSL
'🎤 Tech Interview' 카테고리의 다른 글
[Tech Interview] Part 9. Project (0) | 2023.07.09 |
---|---|
[Tech Interview] Part 8. ETC (0) | 2023.06.05 |
[Tech Interview] Part 6. Operation System (0) | 2023.06.02 |
[Tech Interview] Part 5. Network (0) | 2023.05.29 |
[Tech Interview] Part 4. Algorithm (0) | 2023.05.24 |