[TIL] 240415

Geehyun(장지현)·2024년 4월 15일

TIL

목록 보기
61/70
post-thumbnail

Today

  • Spring

    • 스프링이란,
      자바 언어를 기반으로 한 기술로서 대규모 자바 애플리케이션 개발을 신속하고 편리하게 해주는 오픈 소스 프레임 워크
    • 스프링을 사용하는 이유
      1) 엔터프라이즈급 개발의 복잡함을 제거하면서 엔터프라이즈급 개발을 할 수 있는 경량급 오픈소스 프레임워크
      2) 스프림은 동적 웹 사이트를 개발하기 위한 여러 가지 서비스를 제공
      3) 웹 애플리케이션을 훨씬 효율적으로 구현할 수 있어 생산성고 품질이 우수
      4) 개발 이후에는 유지보수의 해결책도 제시해줌
      + 선생님 : 우리나라만 Java가 사용량이 많음 => 이유 : 전자 정부 프레임 워크 때문
    • 스프링의 주요 특징
      1. 일반적인 자바 객체를 위한 POJO
      • 별도의 API를 갓용하여 어떠한 제한에도 묶이지 않은 자바 클래스
      • 특화된 인터페이스를 반드시 구현하거나, 의존성이 높은 클래스의 확장을 따라야할 필요가 없음
      • POJO 지원의 장점
        1) 코드가 훨씬 단순해짐
        2) 개발 후 특정 데이터베이스나 서버가 없어도 테스트를 할 수 있어서 개발 속도가 빠라짐
        3) POJO는 프레임워크의 규약이나 규제가 없어서 매우 자유롭게 객체 지향적으로 설계할 수 있음 => 단, 이게 유지보수 시에는 스파게티 코드 등으로 단점이 되어버림...!

        POJO란?
        Plain Old Java Object의 약자로, 일반적인 자바 언어와 꼭 필요한 API외에는 특정 구현 기술에 종속되지 않으며 특정 데이터 베이스나 서버에 의존하지 않는 자바 클래스만으로 구성해도 프로그래밍 가능
        참고

      1. 객체 간의 결합도를 줄이는 의존성 주입(DI) 지원
      • 객체 간의 의존 관계를 직접 생성하거나 제어하지 않아도 됨
      • 설정 파일을 통해서 스프링 컨테이너가 자동적으로 객체를 연결함
      • 의존성 주입의 장점
        1) 코드가 훨씬 간단해지고, 이해하기 쉬우며, 테스트하기 쉬워짐
        2) 프로그램을 쉽게 설계할 수 있음
        3) 이미 개발된 프로그램을 변경해야할 때도 변경 사항을 적용하기 쉬워 확장성이 좋음
        4) 각 객체간의 의존관계와 객체들의 생명주기를 간편하게 개발하거나 유지보수할 수 있음

        의존성 주입?

        • 객체 간의 관계를 관리할 때 사용하는 기법
        • 객체 또는 구성 요소 사이의 의존관계를 직접 생성하거나 제어하는 것이 아니라 외부의 Bean 설정 파일을 활용해 스프링 컨테이너가 자동으로 연결해주는 방식을 의미
        • 생성자 주입 방식 : 생성자에서 초기화 하는 것
          메서드 주입 방식 : 메서드를 만들어서 초기화 하는 것 (setter 느낌) - 이게 더 많이 쓰임.
          참고
      1. 공통 모듈을 재상하기 위한 AOP 지원
      • 반복적으로 나타나는 공통 관심사(Cross-Cutting Concerns)를 분리하여 설계 및 관리가능
      • AOP 지원의 장점
        1) 애플리케이션 전체에 사용되는 핵심 기능을 애스팩트에 담아 재사용 가능
        2) 이로 인해 개발자는 비즈니스 기능만 구현하면 되기 때문에 개발 과정이 간소화됨
        3) 공통 모듈을 각 독립된 모듈로 중복 없이 작성할 수 있음
        4) 공통 모듈을 XML 설정 파일에 설정 가능 - 요즘엔 자주 안씀 다 어노테이션 주로 씀

        AOP란..?
        AOP는 관점(Aspect)지향 프로그래밍으로, 관점을 기준으로 다양한 기능을 분리하여 보는 프로그래밍이다. 관점(Aspect)이란, 부가 기능과 그 적용처를 정의하고 합쳐서 모듈로 만든 것이다.
        => 핵심적인 기능에서 부가적인 공통 관심사를 분리하여 공통 모듈로 만들어서 설계하고 개발하는 방법
        참고

      1. 일관성 있는 모듈의 트랜잭션 지원
      • 데이터베이스 연동 기술과 트랜잭션 서비스 사이의 종속성을 제거하고 트랜잭션 처리를 위한 일관된 방법을 제공
      • 트랜잭션 지원의 장점
        1) 트랜잭션 추상 계층을 이용하면 데이터베이스 연동 기술과 상관없이, 같은 방식으로 트랜잭션 기능을 활용 가능
        2) 트랜잭션 서비스의 종류나 환경이 바뀌더라도 트랜잭션을 사용하는 코드는 그대로 유지하는 유연성도 제공

        트랜잭션 이란?

        • 쪼갤 수 없는 최소 단위의 작업
        • 어떤 작업을 하나로 묶어 실행할 때, 하나의 작업이라도 실패하면 모두 실패 처리를(RollBack), 성공하면 모두 성공처리를(Commit) 해주는 것
  • 스프링 웹 MVC

    • 스프링이 제공하는 웹 애플리케이션 개발 전용 프레임워크
    • MVC 패턴을 사용
      • 웹 애플리케이션 모델, 뷰, 컨트롤러 사이의 의존 관계를 스프링 컨테이너가 관리
      • 스프링이 제공하는 많은 기능을 자유롭게 확정하여 웹 애플리케이션 구축 가능
    • 구성
      • 모델 : 애플리케이션의 데이터가 들어있는 객체
      • 뷰 : 모델의 정보(데이터)를 특정 형식으로 보여주는 페이지 (UI)
        ex ) JSP (스프링 부트가면, 타임리프 사용)
      • 컨트롤러 : 애플리케이션의 비즈니스 로직을 포함,
        ex ) 자바 클래스, @Controller 어노테이션
      • 프런트 컨트롤러 : 애플리케이션 흐름을 관리
        ex ) DispatcherServlet 클래스
  • 스프링의 웹 MVC의 구성요소

    • DispatcherServlet
      : 웹으로부터 요청을 전달받습니다. 이 요청을 컨트롤러에 전달하고, 컨트롤러가 반환한 결과값을 뷰에 전달하여 사용자에게 보여줄 응답을 생성하는 등의 모든 연결을 담당
    • HandlerMapping
      : 클라이언트의 요청 URL에 대해 어떤 컨트롤러가 처리할지를 결정합니다.
      (스프링의 프론트 컨트롤러가 이 역할을 함)
    • HandlerAdapter
      : 핸들러 매핑 클래스에 의해 결정된 컨트롤러를 호출합니다.
    • Controller : 클라이언트의 요청을 처리한 뒤 결과를 반환합니다. 응답 결과에서 보여줄 데이터를 모델에 담아서 뷰로 전달합니다.
    • Model ANd View
      : 컨트롤러가 처리한 결과 정보 및 뷰 선택에 필요한 정보를 담습니다.
    • ViewResolver
      : 컨트롤러의 처리 결과를 사용자에게 보여줄 뷰를 결정합니다.
    • View
      : 컨트롤러의 처리 결과 화면을 생성합니다. 주로 JSP파일(또는 타임리프)을 이용해서 클라이언트에 응답 결과를 전송합니다.
  • Spring 프로젝트 생성 (InteliJ 사용)
    1) 프로젝트 생성


    2) 서버 구성 수정

    -Dfile.encoding=UTF-8 : D 접두어는 실행시점에 뒤에 있는 부분을 읽어오라는 뜻
    3) 파일 - 설정




    4) spring 관련 라이브러리 설정

    • Spring Core

    • Spring Context

    • Spring TestContext Framework

    • Project Lombok
      * 컴파일, 어노테이션 프로세서, 테스트컴파일, 테스트 어노테이션 전부 포함해서 갖고올 수 있음.

    • Apache Log4j Core

    • Apache Log4j API

    • Apache Log4j SLF4J Binding

      • log4j관련 설정파일 만들기 (위치 : src > main > resorses )
        <?xml version="1.0" encoding="UTF-8" ?>
        <configuration status="INFO">
            <Appenders>
                <Console name="CONSOLE" target="SYSTEM_OUT">
                    <PatternLayout charset="UTF-8" pattern="%d{hh:mm:ss} %5p [%c] %m%n" />
                </Console>
            </Appenders>
            <loggers>
                <logger name="org.springframework" level="INFO">
                    <append-ref ref="CONSOLE" />
                </logger>
                <logger name="org.fullstack4" level="INFO">
                    <append-ref ref="CONSOLE" />
                </logger>
                <root level="INFO" additivity="false">
                    <AppenderRef ref="CONSOLE" />
                </root>
            </loggers>
         </configuration>
    • JSTL

      위 라이브러들 다 build.gradle에 내용 넣기!

      dependencies {
          compileOnly('javax.servlet:javax.servlet-api:4.0.1')
      
          testImplementation("org.junit.jupiter:junit-jupiter-api:${junitVersion}")
          testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${junitVersion}")
          // https://mvnrepository.com/artifact/org.springframework/spring-core
          implementation group: 'org.springframework', name: 'spring-core', version: '5.3.34'
          // https://mvnrepository.com/artifact/org.springframework/spring-context
          implementation group: 'org.springframework', name: 'spring-context', version: '5.3.34'
          // https://mvnrepository.com/artifact/org.springframework/spring-test
          testImplementation group: 'org.springframework', name: 'spring-test', version: '5.3.34'
          // https://mvnrepository.com/artifact/org.projectlombok/lombok
          compileOnly 'org.projectlombok:lombok:1.18.32'
          annotationProcessor 'org.projectlombok:lombok:1.18.32'
      
          testCompileOnly 'org.projectlombok:lombok:1.18.32'
          testAnnotationProcessor 'org.projectlombok:lombok:1.18.32'
      
          // https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core
          implementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.23.1'
          // https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api
          implementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.23.1'
          // https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j-impl
          testImplementation group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: '2.23.1'
      
          // https://mvnrepository.com/artifact/jstl/jstl
          implementation group: 'jstl', name: 'jstl', version: '1.2'
      }

      혹시 build.gradle 에 열심히 넣었는데 코끼리 아이콘이 안뜬다면?

      여기서 직접 빌드/클린해서 적용할 수 있습니다.

5) 컨텍스트 루트 파일 추가해보기
* tomcat9이후부터는 web-app이 프로젝트 루트!
그 중 WEB-INF 내부의 경우 해당 경로로 직접 접근이 안되고, 컨테이너에 요청을 해서만 접근이 가능하다.

=> 만들어놓은 root_context.xml 을 이용해서 의존성 주입 연습 예정

6) 테스트해보기
1) SampleDAO 만들기

package org.fullstack4.springmvc.sample;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Repository;

@Repository
public class SampleDAO {
}

2) SampleServise 만들기

package org.fullstack4.springmvc.sample;

import lombok.ToString;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
@ToString
public class SampleService {
    @Autowired
    private SampleDAO sampleDAO;
}

3) root-context.xml(아까 만든거)에 의존성 주입하기

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context = "http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframeword.org/schema/context/spring-context.xsd">
       <bean class="org.fullstack4.springmvc.sample.SampleDAO" />
       <bean class="org.fullstack4.springmvc.sample.SampleService" />
</beans>

4) 테스트 코드 작성(경로 : test > java > 패키지명 > SampleTests)

package org.fullstack4.springmvc.sample;

import lombok.extern.log4j.Log4j2;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;

@Log4j2
@ExtendWith(SpringExtension.class)
@ContextConfiguration(locations = "file:src/main/webapp/WEB-INF/root-context.xml")
public class SampleTests {
    @Autowired
    private SampleService sampleService;
    @Test
    public void testService() {
        log.info("-----------------sampleService Test : " + sampleService);
        Assertions.assertNotNull(sampleService);
    }
}

5) 테스트 결과

03:29:10  INFO [org.fullstack4.springmvc.sample.SampleTests] -----------------sampleService Test : SampleService(sampleDAO=org.fullstack4.springmvc.sample.SampleDAO@4ee33af7)

@Autowired를 이용해서 의존성 주입

내용을 보면 만든적 없는 사용자 생성자로 SampleService가 만들어진걸 볼 수 있음 @AutoWired 어노테이션을 이용해서, 의존성을 주입한 것임
=> spring에게 @AutoWired를 통해 해당 클래스를 생성하는 시점에 생성자에 @AutoWired로 작성한 내용을 넣어서 실행해달라고 요청한 것!!
=> 만약 @AutoWired 여러개 있으면, 해당 내용을 모두 생성자에 넣어서 생성해달라고 요청하는 것임!

@Autowired를 이용해서 의존성 주입 사용방법

  1. root-context.xml 처럼 xml을 이용해서 하나씩 Bean으로 설정하는 방법
    (이렇게 사용하려면 주입할 개체 클래스에서 @Repository 추가 필요 - 스프링에서 Bean으로 관리될 수 있도록 설정)

    ApplicationContext 스프링이 Bean들을 관리하는 공간!

    ApplicationContext : 스프링의 핵심 컨테이너로서, 스프링 애플리케이션 전체에 걸쳐 스프링 빈의 생성, 관리, 라이프사이클을 담당 (BeanFactory도 유사개념 추후 학습 예정)
    따라서, @Autowired를 사용하기 위해서는 ApplicationContext(root-context.xml)에 Bean으로 설정되어있어야 함.
    참고(공부용)

    *선생님의 깨알 CS지식(?) 특강

    1. WAS 내에는 도메인 당 한개의 application이 존재하며, applicaiton에는 하나의 ApplicationContext가 존재 (application은 서버의 리소스의 범위만큰 만들 수 있다.)
    2. ApplicationContext : ServletContext => 1:1로 존재
  2. 🌟<context:component-scan>을 이용해서 한번에 빈으로 등록 (스프링 2.5부터 지원)
    <context:component-scan>을 이용해서 패키지를 지정해서 해당 패키지 내 클래스의 인스턴스들을 스프링의 빈으로 등록할 수 있음
    특정 어노테이션을 이용해서 스프링의 빈으로 관리될 객체를 표시해주면 <context:component-scan>이 알아서 스캔해가는 방식!
    - @Controller : MVC의 컨트롤러를 위한 어노테이션
    - @Servise : 서비스 계층의 객체를 위한 어노테이션
    - @Repository : DAO와 같은 객체를 위한 어노테이션 (DB에 접근하는애들 DAO일 수도 File관련일 수도)
    - @Component : 일반 객체나 유틸리티 객체를 위한 어노테이션 (공통유틸 등)

    => 위 1번 방법은 개발자가 개별로 하나하나 등록해서 관리하는 방식이고, 2번 방식은 특정 어노테이션으로 표시만 해주고 spring이 알아서 관리하도록 하는 방식!!

    📒 <context:component-scan> 사용해서 의존성 주입해보기

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context = "http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframeword.org/schema/context/spring-context.xsd">
    <!--       1. `root-context.xml` 처럼 xml을 이용해서 의존성 주입하는 방법 -->
    <!--       <bean class="org.fullstack4.springmvc.sample.SampleDAO" />-->
    <!--       <bean class="org.fullstack4.springmvc.sample.SampleService" />--> 
    
    <!--       2. `<context:component-scan>`을 이용하는 방법 -->
           <context:component-scan base-package="org.fullstack4.springmvc.sample" />
    </beans>

    이렇게만 바꿔주면 spring에서 알아서 @Controller @Servise @Repository @Component 로 설정된 것들을 알아서 Bean으로 등록해 줌.

  • 생성자 주입 방식(lombok @RequiredArgsConstructor 이용!)
    1) 주입 받아야하는 객체의 변수는 private final로 작성합니다.
    2) 생성자를 이용해서 해당 변수를 생성자의 파라미터로 지정(@RequiredArgsConstructor 로 알아서 만들어지게 설정함)

    lombok의 여러 생성자 어노테이션

    • @RequiredArgsConstructor : 초기화 되지않은 final 필드나, @NonNull 이 붙은 필드만 파라미터로 갖는 생성자를 만들어 줍니다.
    • @NoArgsConstructor : 파라미터가 없는 기본 생성자를 생성해 줍니다.
    • @AllArgsConstructor : 어노테이션은 모든 필드 값을 파라미터로 받는 생성자를 만들어줍니다

    @어노테이션 어떤건 class위에 써주고 어떤건 method위에 써주고.. 뭐가 다름?

    • class위
      : class가 생성(컴파일)되는 시점에 어노테이션이 실행 됨 => 해당 class 전체에 어노데이션에 영향을 받으며, 주로 의존성 주입으로 사용 됨
      이러한 경우 class가 컴파일 되는 시점에 작성한 어노테이션에 오류가 있을 경우 컴파일 자체에서 에러가 발생
    • method 위
      : 해당 메서드가 호출된 시점에 어노테이션이 실행 됨. => 해당 메서드에만 적용할 경우에 사용 됨
      메서드에만 적용할 경우 오류가있어도 컴파일 시점에 에러가 발생하지 않으며, 해당 메서드를 호출할 때 에러가 발생합니다.

Review

  • spring으로 슬쩍 들어오니깐 역시 이해하면서 따라간다기 보다는 일단 휩쓸려서 끌려가는 느낌이 강함 => lombok, spring 셋팅 등 따로 공부하면서 따라가야할 것 같음!
  • 정처기 실기가 4/20일인줄 알았으나... 4/27일이었다!!! => 일주일의 시간이 더 주어졌으니 진짜 열심히 준비해서 한번에 붙자!!!!
  • 5/3일까지 이력서 및 포트폴리오 1차 제출 필요 : 슬슬 준비해야함!
profile
블로그 이전 했습니다. 아래 블로그 아이콘(🏠) 눌러서 놀러오세요

0개의 댓글