Spring - Spring Framework에 대해

제훈·2024년 8월 8일

Spring

목록 보기
2/18

Spring Framework 구성 모듈

Spring Core Container

스프링에서 가장 기본적이며 중요한 모듈 중 하나
Spring Core Container 모듈은 스프링에서 객체의 생성과 관리를 담당한다.
스프링의 DI(Dependency Injection)IoC(Inversion of Control) 개념이 구현되어 있다.
이를 통해, 코드의 재사용성유지보수성을 높일 수 있다.


Context를 사용해서 개발방식에 대해 알아보자.

1. JavaConfig 방식

build.gradle

    implementation 'org.springframework:spring-context:6.1.11'
    implementation 'org.projectlombok:lombok:1.18.24'

MemberDTO

import lombok.*;

@NoArgsConstructor
@AllArgsConstructor
@Getter @Setter @ToString
public class MemberDTO {
    private int sequence;
    private String id;
    private String pwd;
    private String name;
}
  • @NoArgsConstructor : 기본 생성자를 만들어준다는 뜻의 어노테이션
  • @AllArgsConstructor : 모든 필드를 매개변수로 갖는 생성자를 만들어준다는 어노테이션
  • @Getter : 각 필드들의 get 메소드를 만들어준다는 뜻의 어노테이션
  • @Setter : 각 필드들의 set 메소드를 만들어준다는 뜻의 어노테이션
  • @ToString : toString() 메소드를 만들어준다는 뜻의 어노테이션

ContextConfiguration
아래 예제에서도 같은 이름의 클래스를 만들 것이다.

같은 이름의 클래스를 만들 때는 다른 패키지에 만들어야 한다..!

import com.jehun.common.MemberDTO;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ContextConfiguration {
    // 설정용 자바 클래스
    
    @Bean(name="member")
    public MemberDTO getMember() {
        return new MemberDTO(1, "user01", "pass01", "홍길동");
    }
}
  • @Bean : 객체를 의미하는 어노테이션
    코드에서는 member 라는 key와 1, "user01", "pass01", "홍길동" 라는 value를 갖는다.

스프링 컨테이너가 켜지는 순간 @Bean 어노테이션이 달린 객체를 생성해서 갖고 있을 것이다. (싱글톤 방식)

Application

import com.jehun.common.MemberDTO;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Application {
    public static void main(String[] args) {
        // 컨테이너라고 생각하면 된다.
        ApplicationContext context = new AnnotationConfigApplicationContext(ContextConfiguration.class);

        String[] beanNames = context.getBeanDefinitionNames();
        for (String beanName : beanNames) {
            System.out.println("beanName = " + beanName);
        }

        // bean의 id(이름)을 이용해서 bean을 가져오는 방법
        MemberDTO member = (MemberDTO) context.getBean("member");
        System.out.println("id(이름)을 이용 - member = " + member);

        // bean의 클래스 메타 정보 (bean의 타입)을 전달하여 가져오는 방법
        MemberDTO member2 = context.getBean(MemberDTO.class);
        System.out.println("클래스 메타 정보 - member = " + member2);

        // bean의 id 와 클래스 메타 정보를 전달하여 가져오는 방법
        MemberDTO member3 = context.getBean("member", MemberDTO.class);
        System.out.println("id 와 클래스 메타 정보 - member = " + member3);
    }
}

실행결과

beanName = member 를 제외한 5가지는 자동으로 생성해주는 bean들이다.


2. xml 파일에 bean 등록해두는 방법

resources/xmlconfig/spring-context.xml 을 만들고

spring-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"
       xsi:schemaLocation="
		http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- MemberDTO bean 등록-->
    <bean id ="member2" class="com.jehun.common.MemberDTO">
        <constructor-arg index="0" value="2" />
        <constructor-arg name="id" value="2" />
        <constructor-arg index="2"><value>pass01</value></constructor-arg>
        <constructor-arg name="name"><value>pass01</value></constructor-arg>
    </bean>
</beans>
import com.jehun.common.MemberDTO;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

public class Application {
    public static void main(String[] args) {
        ApplicationContext context = new GenericXmlApplicationContext("section02/xmlconfig/spring-context.xml");

        MemberDTO member2 = (MemberDTO) context.getBean("member2");
        System.out.println("member2 = " + member2);
    }
}

실행결과


3. 어노테이션 방식

@Repository 어노테이션을 이용해서 자동으로 스프링에게 객체들을 만들어달라고 할 수도 있다.

@Repository
1. @Component 계열로 스프링 컨테이너(IOC 컨테이너) 가 bean으로 등록하는 클래스에 추가하는 어노테이션이다.
2. DAO (또는 Repository) 계층에 MVC 구조에 맞춰 구분하기 위해 추가하는 어노테이션이다.
- (추가적으로 DB에서 발생한 에러를 자바의 예외타입으로 바꿔주는 부가 기능이 있다.)

한 번 보자.

Member.DAO

import org.springframework.stereotype.Repository;

import java.util.HashMap;
import java.util.Map;

@Repository
public class MemberDAO {
    // DAO : 레포지토리 계층의 또다른 표시
    private final Map<Integer, MemberDTO> memberMap;

    public MemberDAO() {
        memberMap = new HashMap<>();

        memberMap.put(1, new MemberDTO(1, "user01", "pass01", "홍길동"));
        memberMap.put(2, new MemberDTO(2, "user02", "pass02", "유관순"));
    }

    /* 설명. 회원 조회용 메소드 */
    public MemberDTO selectMember(int sequence) {
        return memberMap.get(sequence);
    }

    /* 설명. 회원 가입용 메소드 */
    public int insertMember (MemberDTO registerMember) {
        int before = memberMap.size();

        memberMap.put(registerMember.getSequence(), registerMember);

        int after = memberMap.size();

        return after - before;
    }
}

메소드들은 쓰이지는 않지만 DAO처럼 보이기 위해서 만들어보긴 했다. 추후에 DAO를 활용해서 예시를 작성해보겠다.

ContextConfiguration
위에서 말한 것과 다른 패키지에 생성한 클래스

설정용 클래스이다.

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration("configurationAnother")
@ComponentScan(basePackages = "com.jehun.common")
public class ContextConfiguration {
	
}

Application

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Application {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(ContextConfiguration.class);

        String[] beanNames = context.getBeanDefinitionNames();

        for (String beanName : beanNames) {
            System.out.println("beanName = " + beanName);
        }
    }
}

실행결과


4. xml 파일에 어노테이션 형태로 나타내는 방식

spring-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 https://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.jehun.common"/>

</beans>

Application

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

public class Application {
    public static void main(String[] args) {
        ApplicationContext context = new GenericXmlApplicationContext("section03/annotationconfig/subsection02/xml/spring-context.xml");

        String[] beanNames = context.getBeanDefinitionNames();
        for (String beanName : beanNames) {
            System.out.println("beanName = " + beanName);
        }
    }
}

패키지 구조

위 4가지 방식이 있는데 주로 3번째 방식인 어노테이션 방식을 사용할 것이다.


Lombok

  • @Getter : 해당 멤버 변수에 대한 getter를 생성한다.
  • @Setter : 해당 멤버 변수에 대한 setter를 생성한다.
  • @ToString : 해당 클래스의 toString()을 자동으로 생성한다.
  • @EqualsAndHashCode : 해당 클래스의 equals()와 hashCode()를 자동으로 생성한다.
  • @NoArgsConstructor : 파라미터가 없는 생성자를 생성한다.
  • @AllArgsConstructor : 모든 멤버 변수를 파라미터로 받는 생성자를 생성한다.
  • @RequiredArgsConstructor : final이나 @NonNull인 멤버 변수만 파라미터로 받는 생성자를 생성한다.
  • @Data : @ToString, @EqualsAndHashCode, @Getter, @Setter, @RequiredArgsConstructor을 모두 적용한 것과 같다.

@Data 를 권장하지 않는 이유

너무 많은 메소드를 담고 있어서 무겁다. 필요없는 메소드들까지 가지고 있어야 해서 좋지 않다.
그리고 @Setter 또한 권장하지 않기 때문에 매번 생성자를 만들면서 불변객체를 만드는 것이 낫다.

profile
백엔드 개발자 꿈나무

0개의 댓글