상세 컨텐츠

본문 제목

[BACKEND] 백엔드 개발 기술면접 준비(2) 스프링프레임워크(어노테이션 포함)

취준/1. 기술면접

by ranlan 2022. 2. 1. 03:34

본문

728x90

기술면접 준비(2) 스프링 프레임워크와 헷갈리는 어노테이션들

 

 

Q. 프레임워크(Framework)와 라이브러리(Library)의 차이점은?

A. 프레임워크소프트웨어의 특정 문제를 해결하기 위해 상호 협력하는 클래스와 인터페이스의 집합이다. 애플리케이션 개발 시 필수적인 코드나 알고리즘, 데이터베이스 연동과 같은 기본적인 기능의 뼈대를 제공해주며 개발자가 이에 코드를 더하여 애플리케이션을 완성한다. 

라이브러리는 필요한 곳에서 호출하여 사용할 수 있도록 미리 작성된 코드, 변수, 함수 등의 집합으로 개발자가 개발하는데 필요한 것들을 모아놓은 도구이다. 프로그램이 사용하는 비휘발성 자원의 집합이다.

  • 정적 라이브러리
    필요한 함수를 프로그램 코드에 붙여 프로그램 자체에서 참조한다. 프로그램 실행 후 처리시간이 빠르다.
  • 동적 라이브러리
    프로그램 실행 시 필요시에만 외부 dll파일에서 함수를 참조한다. 프로그램 실행 시 로딩 시간이 단축되며 함수 업그레이드 시 해당 dll만 수정하여 배포가 가능하다.

 

 

Q. 프레임워크를 사용할 때 장점

A. 기본적으로 필요한 기능을 갖추고 있어 개발자가 비즈니스 로직에만 집중할 수 있고(개발시간 단축) 코드 재사용 및 유지보수가 용이하며 확장성이 크다.

 

 

Q. 스프링 프레임워크(Spring Framework)이란?

A. 자바 애플리케이션 개발을 위한 오픈소스 프레임워크이다. 공공기관의 웹 서비스 개발 시 권장하는 전자정부 표준 프레임워크의 기반 기술로 쓰인다. 동적인 웹 사이트를 개발하기위한 여러가지 서비스를 제공하며 개발자들이 애플리케이션을 보다 쉽게 개발할 수 있도록 도와준다.

 

 

Q. 스프링 프레임워크의 특징

A. 스프링은 경량 컨테이너로 객체 생성과 소멸과 같은 자바 객체의 라이프 사이클을 관리한다. 

  1. POJO(Plain Old Java Object) 방식의 프레임워크
    평범한 자바 객체. 객체 지향 원리에 충실하면서 특정 환경이나 규약에 종속되지 않고 필요에 따라 재활용될 수 있는 방식으로 설계된 객체를 의미한다.
    특정 클래스 상속과 인터페이스 구현, 어노테이션 포함을 강제하지 않는 자바 언어 사양 외의 어떠한 제한에도 묶이지 않는 자바 오브젝트이다.
    본래 자바의 장점을 살리는 '오래된' 방식의 '순수한' 자바 객체

    * EJB(Enterprise JavaBeans)
    기본적인 JD로는 한계가 있어 J2EE가 등장했다. 하지만 서블릿, JSP만으로는 복잡한 엔터프라이즈 서비스를 개발하기는 쉽지 않았다. 업무의 복잡도가 높아짐과 동시에 사용자의 요구 처리를 안정적이고 빠르게 처리해야했기에 이를 해결하기위한 방안으로 등장한 것이 EJB. 하지만 EJB는 현실적이지 않았고 객체지향적인 특징과 장점을 포기하는 문제까지 이르렀다. 그 결과 다시 POJO 방식으로 돌아서는 계기가 된다. POJO 방식의 개발은 객체지향적 설계와 자동화된 테스트의 편의성, 개발 생산성 등을 회복시켜주었다. 이런 POJO 기반의 프레임워크가 바로 스프링 프레임워크.

  2. DI(Dependency Injection, 의존성 주입) 지원
    객체에 속성값을 주입하는 방식으로 모듈간의 결합도를 낮춰 유현한 코드 작성을 가능하게 해준다.
    설정파일이나 어노테이션을 통해 객체 간의 의존관계를 설정 수 있으며 각각의 계층이나 서비스들간의 의존성이 존재할 경우 프레임워크가 서로 연결시켜준다(IoC).

  3. IoC(Inversion of Control, 제어의 역행) 지원
    개발자가 부품을 생성하여 조립하는 형태로 개발이 가능하게 한다. 이렇게 조립된 코드의 호출은 개발자가 결정하는 것이 아니라 프레임워크 내부에서 결정한다. 즉, 사용자가 제어의 흐름을 컨트롤하지 않고 스프링에 위임하여 스프링 내부 객체들 사이에 필요한 의존 관계들을 자동으로 연결해준다. 객체의 의존성을 역전시켜 객체간의 결합도를 줄이고 유연한 코드를 작성할 수 있게 해주며 가독성 및 코드 중복, 유지보수를 용이하게 해준다.
    스프링에서의 객체 생성 및 실행 순서는 객체 생성 -> 의존성 주입(스프링에 위임) -> 의존성 객체 메서드 호출 순으로 이뤄진다.
    * IoC Container
    Ioc Container에서 관리하는 객체의 생성과 관계 설정, 사용, 제거 등의 전체 라이프 사이클을 관리해주는 작업을 하는 컨테이너

  4. AOP(Aspect-Oriented Programming, 관점지향 프로그래밍)
    공통 관심 기능을 분리하여 반복되는 부분을 추출해 핵심 로직에 영향을 미치지 않고 소스의 중복을 줄이는 방법이다. 기존의 OOP(객체지향 프로그래밍)에서 관점 기능을 여러 모듈에서 적용하며 발생하는 중복된 코드 양산의 한계를 극복하기위해 등장했다. 즉, 핵심 로직에 집중할 수 있도록 필요하지만 중복해서 작성해야하는 핵심 로직 이외의 코드는 외부로 빼놓는 방법이다. 또한 흩어진 관점들을 모아 모듈화한다.


    AOP의 취지는 Aspect를 모듈화하고 핵심적인 비지니스 로직에서 분리하여 재사용하는 것이다.
    * 프록시 패턴(Proxy Pattern)

    프록시 객체가 원래 객체를 감싸 클라이언트의 요청을 처리하게 하는 패턴이다.
    실제 기능을 수행하는 객체 대신 가상의 객체(프록시 객체)를 사용해 로직의 흐름을 제어하는 디자인 패턴이다.

  5. PSA(Portable Service Abstraction, 서비스 추상화)
    스프링은 AOP의 프록시 패턴을 발전시켜 만들어졌다. 그리고 빈팩토리를 통해 프록시가 빈이 생성될 때 자동으로 생성된다. 추상화 계층을 사용하여 어떤 기술을 내부에 숨기고 개발자에게 편의성을 제공해주는 것이 서비스 추상화이다. 실제로는 내부적으로 서블릿 기반으로 코드가 동작하지만 서블릿 기술은 추상화 계층에 의해 숨겨져있다. 이에 더해 서비스 추상화로 제공되는 기술을 다른 기술 스택으로 간편하게 바꿀 수 있는 확장성을 갖고 있다.
    기본적으로 스프링에서는 PlatformTransactionManager라는 최상위 Manager를 사용하고 각각 사용자의 선언에 따라 JPATransactionManager, DatasourceTransactionManager, HibernateTransactionManager 등을 상황에 맞게 의존성 주입을 받아 사용하게 된다. 따라서 개발자는 내부적인 서블릿과 로직을 알 수 없다.

 

 

Q. Spring Triangle 스프링 핵심 3요소

A. IoC(제어의 역행), AOP(관점 지향 프로그래밍), PSA(서비스 추상화)

  • IoC는 객체의 의존성 관리를 스프링에 위임하여 객체간의 결합도를 줄인다.
  • AOP는 관점지향 프로그래밍으로 Ascpect를 모듈화하여 흩어진 공통 기능을 하나로 모으고 핵심적인 비지니스 로직에서 분리하여 재사용하는 것을 의미한다.
  • PSA는 추상화 계층을 사용하여 내부적으로 동작하는 기술을 숨기고 개발자에게 편의성을 제공해주는 것이다.

 

 

Q. 그렇다면 스프링 부트(Spring Boot)란?

A. 스프링을 더욱 쉽고 간편하게 사용할 수 있도록 하는 스프링 프레임워크의 서브 프로젝트이다.. 빠른 시간 안에 애플리케이션 완성을 목표로 한다. 내장 톰캣이나 제티로 웹 실행환경이나 의존성 관리 등 인프라 관련은 신경쓸 필요 없이 바로 개발 시작이 가능하다.

 

스프링부트의 특징

  1. starter 모듈을 통해 라이브러리 의존성을 자동화하였다.
  2. 스프링의 설정을 간편화하였다.
  3. 라이브러리 버전을 자동으로 관리한다.
  4. 내장 톰캣과 테스트환경(Junit)을 기본으로 포함한다.
  5. JAR 파일로 패키징이 가능하다.

* JUnit은 자바 프로그래밍 언어용 유닛 테스트 프레임워크(단위 테스트 도구)이다. 다른 언어에도 _Unit 형태로 테스트를 위한 프레임워크가 존재한다.

 

 

Q. 스프링 vs 스프링부트

A. 스프링은 환경설정이 복잡하다는 어려움이 있다. 스프링부트는 이러한 문제를 해결하여 스프링의 설정을 간편화하였다. 라이브러리 버전을 자동으로 관리하고 내장 톰캣을 지니고 있어 별다른 톰캣 설정이 필요 없다.

 

 

Q. JAR(Java Archive) / WAR(Web Application Archive)

A. jar 파일은 자바의 jar 툴을 사용하여 생성된 압축(아카이브) 파일이며 어플리케이션을 쉽게 배포하고 동작시킬 수 있도록 관련 파일(리소스, 속성파일 등)들을 패키징해주는 것이다.

jar자바 리소스와 파일, 라이브러리등을 압축한 파일이고 war웹 어플리케이션 배포를 위한 포맷으로 jar 파일의 일종이다.

 

 

  • JAR
    .jar 파일에는 클래스와 같은 자바 리소스와 속성파일, 라이브러리 등이 포함되어 있다. 자바 어플리케이션이 동작할 수 있도록 자바 프로젝트를 압축한 파일이라 볼 수 있다.

  • WAR
    .war 파일은 서블릿, jsp 컨테이너에 배치할 수 있는 웹어플리케이션 압축 파일 포맷이다. JSP, servlet, class, jar, xml, js, html 등 서블릿 컨텍스트 관련 파일들로 패키징되어있다. 웹 응용 프로그램을 위한 포맷이기 때문에 웹 관련 자원만 포함하고 있으며 이를 사용하면 웹 어플리케이션을 쉽게 배포하고 테스트할 수 있다.
    war 파일도 jar을 이용해 생성하는 jar의 일종으로 웹 어플리케이션 전체를 패키징하기 위한 jar 파일이다.
  • EAR(Enterprise Archive)
    JAVA EE(Enterprise Edition)에서 쓰이는 파일 형식으로 한 개 이상의 모듈을 단일 아카이브로 패키징하여 어플리케이션 서버에 동시에 일관적으로 올리기 위하여 사용되는 포맷

 

 

Q. Maven vs Gradle

A. 빌드 자동화 도구이다.

  • Maven은 pom.xml을 이용한 정형화된 빌드 시스템으로 Apache Ant를 대안으로 나왔다.
  • Gradle은 오픈 소스 빌드 자동화 도구로 Ant와 Maven의 장점을 모아 출시되었다. 유연한 범용 빌드 도구(gradle.build)를 이용하며 JVM 위에서 동작하는 Groovy 문법을 사용한다. 멀티 프로젝트에 사용하기 좋다.

 

 

Q. Gradle이 Maven보다 좋은 점

A. 최근 maven에서 gradle로 추세가 변하고 있다.

  1. 빌드 속도가 빠르다.
  2. 빌드라는 동적인 요소를 XML(pom.xml)로 정의하기에는 어려움이 있다.
    Maven의 설정 내용은 길고 가독성이 떨어지며 의존관계가 복잡한 프로젝트 설정에는 부적절하다.
  3. 상속 구조를 이용한 멀티 모듈 구현이 가능하다
  4. 동적인 빌드는 Groovy 스크립트로 플러그인 호출하거나 직접 코드로 작성할 수 있다.
  5. Configuration Injection 방식을 사용하여 공통 모듈을 상속해서 사용해야하는 단점을 커버했다.
  6. 설정 주입 시 프로젝트의 조건을 체크할 수 있어 프로젝트별로 주입되는 설정을 다르게할 수 있다.

 

 

Q. 스프링 MVC 패턴 

A. 스프링 프레임워크에서 제공하는 웹 모듈로 기본 시스템 모듈을 MVC로 나누어 구현한다.

 

  1. 클라이언트로부터 요청이 들어온다.
  2. 핸들러 매핑(HandlerMapping)을 통해 요청 URL에 매핑된 컨트롤러(Controller)를 조회한다.
  3. 해당 컨트롤러에서 비즈니스 로직 처리 후(Service) ModelAndView를 반환한다.
  4. ViewResolver를 호출하여 컨트롤러 실행 결과를 보여줄 View를 찾는다.
  5. 찾은 View를 처리 결과를 담아 렌더링하여 반환한다.

MVC의 구성요소

  • Model(M) 서버에서 동작하는 로직을 처리한다. 프로그램 정보(데이터)를 의미한다.
  • View(V) 결과를 출력하여 사용자에게 보여준다.
  • Controller(C) 사용자의 입력 처리와 흐름 제어를 담당한다.

 

 

Q. 그 외의 다른 패턴

A. MVC 패턴에는 MVC1, MVC2 두 가지가 있다. 둘의 차이는 클라이언트의 요청 사항을 모듈화되지 않은 하나의 파일로 처리할 지, 기능을 담당하는 모듈들이 역할을 분담하여 처리할 것인지로 결정된다.

  • MVC1
    WAS에서 모든 파일에 클라이언트가 요청한 로직을 처리하는 경우이다.
    JSP에서 View, Controller의 역할을 담당하며 그 결과를 클라이언트에 반환한다. 웹 브라우저(클라이언트)의 요청을 JSP가 받아서 처리하는 구조로 아키텍처가 간단하다.
    작은 웹어플리케이션은 상관없으나 대규모 웹 어플리케이션의 경우 유지보수에 어려움이 있다. 가독성이 떨어진다.
  • MVC2
    MVC 패턴에 맞게 Model, Controller, View 부분으로 모듈화되었고 JSP는 로직 처리 없이 단순히 클라이언트에게 보여주는 뷰만을 담당한다. 현재 웹 어플리케이션은 거의 MVC2 패턴이다.

 

 

Q. 컨테이너(Container, IoC Container)

A. 스프링 컨테이너는 자바 객체의 생명 주기를 관리하며 생성된 자바 객체들에게 추가적인 기능을 제공한다.
* 여기서 자바 객체를 스프링에서는
빈(Bean)이라고 한다.

 

 

Q. 빈(Bean)과 빈팩토리(BeanFactory), ApplicationContext

A. 빈(Bean)은 스프링에서의 자바 객체를 말한다. 스프링 컨테이너에는 두 가지가 있는데 BeanFactory와 ApplicationContext이다.

  • 빈팩토리(BeanFactory)
    빈을 등록, 생성, 조회하고 반환하는 기본적인 기능을 제공한다. 클라이언트 요청에 의해 빈 객체가 제공되는 지연 로딩 방식(Lazy Loading)을 이용한다. 
  • ApplicationContext
    빈팩토리처럼 빈은 관리할 수 있다.(ApplicationContext는 BeanFactory를 상속받는다).
    또한 트랜잭션 관리, 메시지 처리, AOP 처리 등 DI와 IoC 관련하여 추가적인 기능들을 제공한다. 컨테이너가 구동되는 시점에 객체들을 생성한다(Pre-Loading).

 

 

Q. 스프링 빈 등록 방법에는 어떤 것이 있나요?

A. 스프링 빈 등록 방법에는 크게 두 가지 방법이 있다.

  1. Component Scan과 자동 의존관계 설정
    스프링에서는 클래스에 특정 어노테이션을 부여하고 이 어노테이션을 부여한 클래스를 찾아 자동으로 등록해주는 방식을 제공한다.
    이런 방식을 '빈 스캐닝'이라 하며 @ComponentScan이 @Component를 찾아 빈으로 등록한다.
    이런 필터가 적용되는 어노테이션을 stereotype 어노테이션이라하며 @Component, @Service, @Controller, @Repository, @Configuration 등등 여러가지가 있다.
  2. 자바 코드로 직접 스프링 빈 등록하기
    @Configuration과 @Bean을 이용한다(@Configuration은 자바 설정 파일로 등록한다는 의미로 내부적으로 @Component를 포함한다).
    @Bean이 붙은 메서드 명이 각각 빈의 이름이 된다. 리턴되는 객체를 스프링 컨테이너가 빈으로 활용한다.
    * Bean이 붙은 메서드가 싱글톤 빈이 되기 위해서는 꼭 @Configuration 클래스 게층에 선언되어있어야 한다.

    @Bean
    public MemberService memberService(){
        return new MemberService();
    }​
  3. xml 설정 파일에 직접 등록
  4. 스프링 부트에서 @SpringBootAppliction 어노테이션에는 @Component와 @Configuration이 내포되어있다. 

 

 

Q. 싱글톤 패턴(Singleton Pattern)

A. 생성자가 여러번 호출되더라도 실제로 생성되는 객체는 하나이고 최초 생성 이후 호출된 생성자는 최초의 생성자가 생성한 객체를 반환한다.

장점으로는 메모리 낭비를 방지하고 다른 데이터 간에 데이터 공유가 쉽다는 점이 있다. 싱글톤 인스턴스는 전역으로 사용되는 인스턴스이기 때문이다. 하지만 멀티스레딩 환경에서 하나의 인스턴스에 여러 스레드가 접근할 경우 동시성 문제가 발생할 수 있다.

 

 

* 동시성 문제 해결 방법

  1. synchronized 키워드를 통해 동기화한다. 해당 키워드가 붙은 블럭에는 하나의 스레드만 접근 가능하다
    암시적 Lock을 거는 방법이다. 한 스레드가 접근중이면 다른 스레드가 접근하지 못하고 대기하게 된다.
  2. volatile 키워드를 이용한다. JVM에서 실행되고 있는 CPU 메모리 영역에 데이터를 캐싱한다. 따라서 멀티 코어 프로세서에서 다수의 스레드가 변수를 공유하더라도 캐싱된 시점에 따라 데이터가 다를 수 있으며 서로 다른 코어의 스레드는 데이터값이 불일치하는 문제가 발생한다. 또한 임의로 데이터를 갱신해주지 않는 이상 캐싱 된 데이터가 언제 갱신되었는지 정확히 알 수 없다.
    이런 경우 volatile 키워드를 이용하여 CPU 메모리 영역에 캐싱된 값이 아니라 항상 최신의 값을 가지도록 메인 메모리 영역에서 값을 참조하도록 한다(캐싱 방지).
    즉, 동일 시점에서 모든 스레드가 동일한 값을 가지도록 동기화한다. 하지만 ++와 같은 연산자는 동일하게 동시성 문제가 발생한다.
  3. Concurrent 패키지를 이용한다.
  4. 한번 생성되면 변하지 않는 불변 객체를 이용한다. 초기에 모든 값을 세팅하고 setter를 없애 변하지 않도록 한다.

 

 

Q. 싱글톤 패턴을 안티 패턴이라 하는 이유

A. private 생성자를 갖고 있어 상속이 불가능하다. 개방 폐쇄 원칙을 위배하여 테스트가 어렵다. 서버 환경에서 싱글톤이 1개만 생성됨을 보장하지 못한다. 전역 상태를 만들 수 있다.

 

 

Q. 반대로 스프링 빈을 주입 받는 방법에는 무엇이 있나요(DI)?

A. 빈을 주입 받는 방법에는 3가지가 있다.

  1. 필드 주입
    필드에 바로 의존관계를 주입하는 방법이다.
    @Autowired
    private MemeberService memberService;
  2. setter 주입
    인수가 없는 생성자를 호출한 후 빈에서 setter를 호출해 주입해주는 방식이다. 주입 받는 객체가 변경될 가능성이 있는 경우 사용한다.
    public class MemberController {
        private MemberService memberService;
        private BoardSevice boardService;
    
        @Autowired
        public void setMemberService(MemberService memberService) {
            this.memberService = memberService;
        }
    
        @Autowired
        public void setBoardService(BoardService boardService) {
            this.boardService = boardService;
        }
    }
  3. 생성자 주입
    생성자를 통해 의존관계를 주입하는 방식으로 생성자의 호출 시점에서 한번 호출되는 것이 보장된다.
    (스프링 4.3 이후부터는 생성자가 1개만 있을 경우 @Autowired를 생략해도 주입이 가능하다.)
    public class MemberController {
        private MemberService memberService;
        private BoardSevice boardService;
    
        @Autowired
        public void MemberController(MemberService memberService, BoardService boardService) {
            this.memberService = memberService;
            this.boardService = boardService;
        }
    }

    @RequiredArgsContructor어노테이션을 이용하면 final 필드의 생성자를 자동으로 만들어주기 때문에 쉽게 작성이 가능하다.
    @RequiredArgsContructor
    public class MemberController {
        private final MemberService memberService;
        private final BoardService boardService;
    }


** 생성자 주입 방법을 권고하는 이유 **

  1. 애플리케이션 구동 시점에서 순환참조의 의존성을 알아차릴 수 있기 때문이다.
    예) BoardService의 register함수가 MemberService의 add를 호출하고, MemberService의 add함수가 BoardService의 register 함수를 호출하는 경우 메모리에 함수의 CallStack이 계속 쌓여 Stack Overflow가 발생한다. 생성자 주입 방법을 이용하면 애플리케이션 구동 시점(객체 생성 시점)에 에러가 발생하여 이런 순환 참조 문제를 해결할 수 있다.
  2. final을 이용해 불변객체로 선언할 수 있다. 또한 이는 Lombok과 결합하여 사용할 수 있다(@RequiredArgsConstructor).
  3. 컴파일 시점에서 누락된 경우를 발견할 수 있다.
  4. 테스트 코드 작성 시 생성자를 통해 주입이 가능하다. 생성자 주입을 사용하면 컴파일 시점에 객체를 주입받아 테스트 코드를 작성할 수 있으며 주입하는 객체가 누락된 경우 컴파일 시점에서 오류를 발견할 수 있다. 
  5. 생성자의 호출 시점에 1회 호출되는 것이 보장됨으로 주입받은 객체가 변하지 않거나 반드시 객체 주입이 필요한 경우 강제하기위해 사용할 수 있다.(객체의 불변성 확보)

 

 

Q. VO vs DAO vs DTO

A. VO, DAO, DTO 모두 계층 간 데이터 교환을 위해 사용되는 패턴(객체)이다.

  • VO(Value Object)
    계층 간 데이터 교환을 위해 만든 객체로 불변한 객체를 만들 때 쓰는 패턴이다.
  • DAO(Data Access Object)
    계층 간 데이터 교환을 위해 만든 객체로 가변적인 객체를 만들 때 쓰는 패턴이다.
    로직 없이 순수한 데이터 속성과 속성에 접근하기위한 메서드(getter/setter)만 갖고 있으며 toString, equals와 같은 추가 메서드도 작성 가능하다.
  • DTO(Data Transfer Object)
    데이터베이스에 접근하기 위한 트랜잭션 객체로 비즈니스 로직에 필요한 쿼리를 실행하여 데이터 조회, 조작 기능을 전담하도록 만든 객체이다.
    저수준의 로직과 고급 비즈니스 로직을 분리하여 영속성 메커니즘을 숨기기 위해 사용한다. 효율적인 커넥션 관리와 보완성을 지닌다.

 

 

Q. JSP(Java Server Pages)

A. HTML 코드에 JAVA 코드를 넣어 동적 웹페이지를 생성하는 웹 어플리케이션 도구(자바 언어를 기반으로 하는 서버사이드 스크립트 언어). JSP가 실행되면 자바 서블릿(.java)으로 변환되며 WAS에서 필요한 기능을 수행하고 그렇게 생성된 데이터를 클라이언트에 응답한다. 자바 기능을 그대로 사용할 수 있으며 WAS가 이미 만들어놓은 객체(request, response, session 등)를 사용한다.

사용자 정의 태그(JSTL, JSP 표준 태그 라이브러리)를 사용하여 효율적으로 웹사이트를 구성할 수 있다.

 

* 자바 서블릿(Java Servlet)
서블릿이란 웹 페이지를 동적으로 생성하기 위한 서버측 프로그램이다. 이는 자바 언어 기반으로 만들어지며 WAS 위에서 컴파일되고 동작한다. 자바를 사용하여 웹을 만들기 위해 필요한 기술로 클라이언트가 어떠한 요청을 하면 그에 대한 결과를 다시 전송해주는 역할을 한다.
JSP와 비슷하지만 JSP는 HTML 안에 JAVA 코드를 포함하고 있는 반면, 서블릿은 자바 코드 안에 HTML을 포함하고 있다.

JAVA EE(Enterprise Edition) 사양의 일부분으로 다양한 웹 시스템을 구현한다.

서블릿은 자바로 구현 된 CGI(Common Gateway Interface)라고도 한다(CGI는 별도로 웹서버와 프로그램간의 교환 방식을 의미한다).

 

* 서블릿 컨테이너(Servlet Container)

서블릿을 관리해주는 컨테이너로 클라이언트의 요청을 받아 응답할 수 있도록 웹서버와 소켓으로 통신한다.웹서버와 통신하며 JSP와 서블릿이 작동하는 환경을 제공한다. 서블릿 생명주기 관리, 웹서버와의 통신 지원, 멀티 스레딩 기능을 제공 및 지원한다.

WAS별로 다양한 종류의 컨테이너를 내장하고 있는데, 이들 중 서블릿에 관련된 기능을 모아놓은 것을 서블릿 컨테이너라고 부른다(그 외 JSP 컨테이너, EJB 컨테이너 등이 있다).

 

* 컴포넌트(Component)

특정 기능이나 관련 기능이 재사용 가능한 형태로 만들어진 프로그램 블록이다.

 

* 템플릿 엔진

동적 컨텐츠를 생성하는 방법으로 스프링 MVC중 View(V)에 해당한다. JSP, thymleaf, Apache Freemarker, Mustache, Groovy Templates 등 여러 템플릿들이 존재한다. HTML 형태로 작성된다.

  • 데이터를 받아 DOM 객체에 동적으로 그려주는 클라이언트 사이드 템플릿 엔진과
  • 서버에서 가져온 데이터를 미리 정의된 템플릿에 전달하는 서버 사이드 템플릿 엔진이 있다.

 

 

Q. Filter / Interceptor

A. Filter와 Interceptor는 실행 시점이 다르며 Filter는 Web Application에 등록하고 Interceptor는 Spring Context에 등록한다.

* Filter -> Interceptor -> AOP

  • Filter
    응답과 요청을 정제하는 역할을 한다.
  • Interceptor

 


 

 

Q. 어노테이션이란?

A. 자바 소스 코드에 추가하여 사용할 수 있는 메타데이터의 일종으로 JDK1.5부터 사용 가능하다. 프로그램 코드의 일부가 아닌 프로그램에 관한 데이터를 제공, 코드에 정보를 추가하는 정형화된 방법이다.

 

Q. 다양한 어노테이션이 있는데 그 중 @Service, @Controller, @Repository의 용도는?

A. 서버에서 크게 Service/Controller/Repository 세 부분으로 나눠 구별한다.

  • @Service는 Business Layer에서 Service를 명시하기 위해 작성한다.
  • @Controller는 Presentation Layer에서 Controller를 명시하기 위해 작성한다.
  • @Repository는 Persistence Layer에서 DAO를 나타내기 위해 작성한다(* DAO 데이터베이스 접근 객체)

 

스프링에서는 3단계의 레이어(계층)를 구현하며 Presentation / Business / DataAccess(Persistence) Layer로 나뉜다.

 

  • Presentation Layer 프레젠테이션 계층
    브라우저상의 웹 클라이언트의 요청 및 응답을 처리하고 다른 계층에서 발생하는 Exception을 처리한다.
  • Business(Service) Layer 서비스 계층
    플리케이션 비즈니스 로직 처리와 비즈니스와 관련된 도메인 모델의 적합성을 검증한다. 프레젠테이션 계층과 데이터 액세스 계층 사이를 연결하며 두 계층이 직접적으로 통신하지 않게 한다.
  • Data Access Layer 데이터 접근 계층
    ORM(Object Relational Mapping)을 사용하는 계층으로 DAO 인터페이스와 레퍼지토리 클래스가 속한다. 데이터베이스에 데이터를 직접 CRUD하는 계층이다.
  • Domain 도메인 모델 계층
    데이터베이스 테이블과 매칭되는 계층이다. Entity라고 불린다.

이렇게 계층을 나눈 이유는 중복되는 코드를 모듈화하여 유지보수성을 높히기 위함이다. 비즈니스 로직을 서비스에 구현하여 확장성과 재사용성을 높힌다.

 

 

Q. @RestController와 @Controller의 차이점은?

A. @Controller는 Spring MVC의 View를 반환하기 위해 사용된다. 데이터를 반환하기 위해서는 @Responsebody 어노테이션과 함께 활용해야한다. 이렇게 하면 ViewResolver 대신 HttpMessageConverter가 동작하여 HTTP 응답 바디부분에 json 형태로 데이터를 담아 반환한다.

  1. 클라이언트 HTTP 요청
  2. DispatcherServlet이 Handler Mapping을 통해 요청에 맞는 Controller 호출 
  3. 요청 처리 후 DispatcherServlet에 반환
  4. DispatcherServlet는 해당하는 View를 클라이언트에 반환
    여기서 컨트롤러는 ViewResolver로 View를 반환하고 ViewResolver는 알맞은 View를 찾아 렌더링한다.

* @Responsebody는 자바 객체를 HTTP 응답 body에 매핑한다.

 

@RestController@Controller에 @Responsebody가 추가된 것이다. json형태로 데이터를 반환하고 주로 Restful API를 구현할 때 사용된다. 

 

 

Q. 의존성 주입과 관련된 어노테이션

A. 의존성 주입 방법에는 필드로 주입 / setter 주입 / 생성자 주입 이렇게 3가지 방법이 있으며 어노테이션과 함께 결합하여 사용 가능하다.

  • @Autowired
    스프링 프레임워크에서 지원하는 어노테이션으로 생성자나 메서드, 멤버변수 모두 사용 가능하다(대부분 멤버변수 위에 사용).
    타입  이름 순서로 비교하여 의존성을 주입한다.
    @Autowired(required=false) 옵션을 이용하면 없는 경우 예외처리를 할 수 있다.
  • @Inject
    자바에서 지원하는 어노테이션으로 @Autowired와 동일한 기능을 한다.
    @Named("ID")와 함께 사용하여 아이디를 지정할 수 있다.
    타입 이름 순서로 비교하여 의존성을 주입한다. 없을 경우 예외가 발생한다.
  • @Resource
    자바에서 지원하는 어노테이션으로 @Autowired와 @Qualifier의 기능을 결합한 어노테이션이다.
    이름 타입 순서로 비교하여 의존성을 주입한다. 없을 경우 예외가 발생한다.
  • @Qualifier
    특정 객체의 이름을 이용하여 의존성을 주입할 때 사용한다.
    의존성 주입 대상이 되는 타입의 객체가 두 개 이상일 때 컨테이너는 어떤 객체를 할당해야할지 판단할 수 없어 에러가 발생한다. @Autowired 아래에 함께 사용하여 의존성이 주입될 객체의 아이디나 이름을 지정할 수 있다.

 

 

Q. 빈 등록과 관련된 어노테이션

A4. 먼저 컴포넌트 스캔 방법은 @Component을 명시하여 해당 필드를 빈으로 등록한다. 클래스에 선언하는 대부분의 어노테이션에는 @Component가 포함되어있으며 그 예로는 @Controller, @Service, @Repository, @Configuration등이 있다.

  • @Component는 개발자가 구현한 클래스를 빈으로 등록한다.
    * @ComponentScan이 @Component 어노테이션을 찾아 빈으로 등록한다. 기본적으로 메인 함수에 있는 @SpringBootApplication에 @ComponentScan이 포함되어있다.
  • @Bean어노테이션의 경우 개발자가 직접 제어 불가능한 외부 라이브러리를 빈으로 등록하고자할 때 사용한다. @Configuration과 @Bean을 함께 사용하여 싱글톤 패턴으로 빈을 등록한다.

 

 

Q. HTTP 통신과 관련된 어노테이션

A. HTTP 요청과 관련된 어노테이션

  • @RequestMapping 요청 타입에 상관없이 URL 하나에 하나의 컨트롤러가 매핑된다.
  • @__Mapping HTTP 요청 타입에 따라 URL을 매핑한다.(GET, POST, PUT, DELETE,,)
  • @PathVariable URI 상 바인드되는 값을 파라미터 변수에 매핑시킨다 (localhost/member/{name})
  • @RequestParam URL에 포함된 쿼리 스트링 키에 포함되는 값을 가져온다. (localhost/member?name={name})
  • @RequestBody HTTP 요청 바디 부분을 받는다. name으로 DTO와 매핑된다.

HTTP 응답과 관련된 어노테이션

  • @ResponseBody VO객체를 json으로 바꿔 HTTP 응답 바디에 담는다.

 

 

Q. Configuration관련 어노테이션

A. 개발자가 직접 제어 불가능한 외부 라이브러리 또는 설정을 위한 클래스를 Bean을 등록할 때 @Bean을 활용한다.

1개 이상의 @Bean을 제공하는 클래스의 경우 @Configuration을 명시해 주어야 한다. 그 외 개발자가 직접 개발한 클래스를 Bean으로 등록하고자 하는 경우 @Component어노테이션을 활용한다.

* @Configuraiton은 설정 파일 등록을 위한 어노테이션으로 @Component가 포함되어있다.

 

 

Q. @Trasactional는 언제 쓰이는가

A. 트랜잭션이란 데이터베이스의 상태를 변경하는 작업 또는 한번에 수행되어야 하는 연산들을 의미한다. 예외 발생 시 자동 rollback 된다.

@Transcational을 메서드나 클래스에 선언하는 것을 선언적 트랜잭션이라 부르며 적용된 범위 안에서 트랜잭션 기능이 포함된 프록시 객체가 생성되고 자동으로 commit & rollback을 해준다. 메서드 레벨의 @Transaction이 우선적으로 적용되며 메서드 안의 어느 하나의 작업라도 실패하면 메서드 전체가 취소된다.

 

 

Q. @RequiredArgsConstructor, @AllArgsContructor, @NoArgsConstructor의 차이점

A. 생성자를 자동으로 생성해주는 어노테이션이다.

  • @RequiredArgsConstructor
    초기화되지 않은 final 필드, @NonNull 필드에 대한 생성자를 생성한다. @NonNull 필드들은 널체크가 추가적으로 생성되며 @NonNull이 있지만 파라미터에서 null값이 들어온다면 생성자에서 NullPointerException이 발생한다.
    @AllArgsConstructor
    public Class Test(){
    
        private String field1;
        private final Integer field2;
        @NonNull
        private String field3;
    }
    
    public Class Test(){
    
        private String field1;
        private final Integer field2;
        @NonNull
        private String field3;
       
        public Test(Integer field2, String field3){
        if (field3 == null) {
            throw new NullPointerException;
        } else {
            this.field2 = fied2;
            this.field3 = fied3;
        }
    }
  • @AllArgsContructor
    클래스에 존재하는 모든 필드에 대한 생성자를 생성해준다. @NonNull에 대해서는 자동으로 널체크를 해준다.
    @AllArgsConstructor
    public Class Test(){
    
        private String field1;
        private Integer field2;
        @NonNull
        private String field3;
    }
    
    public Class Test(){
    
        private String field1;
        private Integer field2;
        @NonNull
        private String field3;
       
        public Test(String field1, Integer field2, String field3){
        if (field3 == null) {
            throw new NullPointerException;
        } else {
            this.field1 = fied1;
            this.field2 = fied2;
            this.field3 = fied3;
        }
    }
 
  • @NoArgsConstructor
    파라미터가 없는 생성자를 생성한다.
    @NoArgsConstructor
    public Class Test(){
    
        private String field1;
        @NonNull
        private Integer field2;
    }
    
    public Class Test(){
    
        private String field1;
        private Integer field2;
       
        public Test(){}
    }

    주의해야할 점은 @NonNull에 대한 널체크가 되지 않는다. 또한 final 필드가 있는 경우 초기화할 수 없기 때문에 생성자를 만들 수 없고 에러가 발생한다. 이때 @NoArgsArgument(force=true) 옵션을 이용해 final 필드에 대해 0, false, null 등으로 강제 초기화할 수도 있다.

 

 

Q. @Getter, @Setter의 용도와 객체 지향 프로그래밍 특성

A. @Getter는 클래스 내 필드를 조회하는 getter를 만들어준다. @Setter는 클래스 내 필드를 등록, 수정하는 setter를 만들어준다.

외부에서 객체 내 접근을 막고 공개된 메서드를 통해서만 접근할 수 있도록 하는 객체지향 프로그래밍적 특성이 나타난다. 접근 정도를 따로 설정해주지 않으면 기본적으로 public으로 생성되고 @_etter(AccessLevel.PRIVATE) 옵션을 이용해 접근 제한을 할 수 있다.

 

 

Q. 순환참조를 막기 위한 어노테이션

A. 순환참조를 막기 위한 방법에는 여러가지가 있는데 그 중 json 관련 어노테이션을 이용하는 방법은 아래와 같다.

  • @JsonIgnore 클래스 내에서 무시할 필드를 지정한다.
    * @JsonIgnoreProperties 무시할 속성이나 속성 목록을 표시할 때 사용한다.
  • @JsonManagedReference & @JsonBackReference 직렬화 방향을 정해준다.
    부모클래스 필드(@ManyToOne)에는 @JsonManagedReference를, 자식 클래스 필드(@OneToMany)에는 @JsonBackReference를 추가한다.
  • @JsonIdentityInfo 순환참조될 대상의 식별키로 구분하여 더 이상 순환참조가 일어나지 않도록 한다.

 

 

Q. 어노테이션을 통한 스프링 AOP 구현

A. Aspect는 AOP를 통해 흩어진 기능들을 모은 모듈을, Advice는 모듈이 실행해야하는 일을, JoinPoint는 advice가 실행되어야할 시점이다.

  • @Aspect Aspect 모듈임을 알려준다.
  • @PoinCut을 통해 pointcut을 정의한다.
  • @Before(이전), @After(이후), @Around(메서드 실행 전후), @AfterReturning(정상적 반환 이후), @AfterThrowing(예외 발생 이후)등을 이용하여 타겟 메서드 이전과 이후 어드바이스가 수행할 시점을 지정한다.

 

728x90

관련글 더보기

댓글 영역