728x90

싱글톤 방식의 주의점

싱글톤 패턴이든 , 스프링 같은 싱글톤 컨테이너를 사용하든, 객체 인스턴스를 하나만 생성해서 공유하는 싱글톤 방식은 여러 클라이언트가 하나의 같은 객체 인스턴스를 공유하기 때문에 싱글톤 객체는 상태를 유지(stateful)하는 설계를 지양합니다.

 

👉 무상태(stateless)로 설계해야 함!

싱글톤 패턴을 사용하는 방식에는 몇 가지 주의해야 할 점이 있습니다. 이러한 주의점을 알고 사용함으로써 문제를 예방하고 싱글톤의 장점을 최대한 활용할 수 있습니다. 주요한 주의점은 다음과 같습니다:

  1. 멀티스레딩 환경에서의 동시성 문제: 싱글톤은 전역 상태를 유지하므로, 멀티스레드 환경에서 여러 스레드가 동시에 접근할 경우 동기화 문제가 발생할 수 있습니다. 따라서 동시성 문제를 방지하기 위해 스레드 안전(Thread-Safe)한 싱글톤 구현 방식을 선택하거나 동기화 메커니즘을 적절히 사용해야 합니다.

  2. 의존성 관리의 어려움: 특정 클라이언트에 의존적인 필드가 있으면 안됩니다. 가급적 값을 수정하면 안되고, 읽기 기능만 가능하도록 해야합니다. 싱글톤은 전역적인 상태를 가지고 있기 때문에 의존성이 복잡한 경우 다른 객체에 대한 의존성을 주입하는 것이 어려울 수 있습니다.

스프링 빈의 필드에 공유 값을 설정하면 정말 큰 장애가 발생할 수 있습니다.

 

	ㅡㅡㅡㅡㅡㅡㅡㅡ주문 정보를 입력받아 출력하는 파일ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

        public class StateFulService {

            private int price; //상태를 유지하는 필드 10000->20000으로 바꿔치기 됨

            public void order(String name, int price) {
                System.out.println("name = " + name + " " +"price = " +  price);
                this.price = price;
            }

            public int getPrice() {
                return price;
            }
        }

        ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡTest 코드가 작성된 파일ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

        class StateFulServiceTest {

            //해당 스프링 컨테이너는 하단에 생성된 TestConfig안의 1개의 Bean만 생성해서 사용


            @Test
            void statefulServiceSingleton() {

                AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(TestConfig.class);
                StateFulService stateFulService1 = ac.getBean(StateFulService.class);
                StateFulService stateFulService2 = ac.getBean(StateFulService.class);

                //ThreadA : userA사용자는 10000원어치 주문
                stateFulService1.order("userA", 10000);
                //ThreadB : B 사용자는 20000원을 주문
                stateFulService2.order("userB", 20000);

                //ThreadA : 사용자  A가 주문 금액을 조회하고 싶을때 사용하는 메서드 작성
                //A가 주문을 하고, 금액을 조회하는 사이에 B의 주문이 들어온 상황
                int price = stateFulService1.getPrice();
                System.out.println("price = " + price); 
                        //출력 price=20000(중간에 B의 주문이 들어오게 되며 price의 값이 변경)


                //A사용자는 10000원을 주문했는데, 중간의 가격 변경으로 price가 20000으로 변경되었는데도 Test는 통과됨
                assertThat(stateFulService1.getPrice()).isEqualTo(20000);
            }


        ㅡㅡㅡ해당코드에서 임시로 사용할 Bean 생성ㅡㅡㅡ
            static class TestConfig {

                @Bean
                public StateFulService stateFulService() {
                    return new StateFulService();
                }
            }
        }

 

ThreadA가 사용자 A의 코드를 출력하고, ThreadB가 사용자 B의 코드를 출력한다고 가정하에 StateFulService의 price 필드는 공유되는 필드인데, 특정 클라이언트가 중간에 값을 변경하는 상황이 발생하게 됩니다.
이 때, 공유된 필드값을 같이 사용하게되면서 사용자 A의 주문 금액은 10000원이 되어야 하는데, 20000원이라는 결과가 나오게 되었습니다. 공유필드의 사용은 주의해서 사용해야 하며 스프링 빈은 항상 무상태(stateless)로 설계해야 합니다.


👉 @Configuration과 싱글톤의 관계

 

@Configuration은 스프링 프레임워크에서 사용되는 어노테이션으로, 스프링 빈(Bean) 구성 클래스를 나타냅니다. @Configuration 어노테이션이 지정된 클래스는 스프링 컨테이너에서 빈으로 인식되고, 해당 클래스 내의 @Bean 어노테이션이 지정된 메서드들이 스프링 빈으로 등록됩니다.

@Configuration을 사용하는 이유는 다음과 같습니다:

  1. 스프링 빈 등록: @Configuration 어노테이션이 지정된 클래스에서 @Bean 어노테이션이 지정된 메서드들은 스프링 컨테이너에 의해 관리되는 빈으로 등록됩니다. 이를 통해 객체의 인스턴스화, 의존성 주입, 라이프사이클 관리 등을 스프링이 담당하게 됩니다.

  2. 컨테이너 설정: @Configuration 어노테이션이 지정된 클래스는 스프링 컨테이너의 설정 파일 역할을 수행합니다. 스프링은 @Configuration 어노테이션이 지정된 클래스를 스캔하여 컨테이너의 설정 정보로 활용하며, 이를 통해 스프링 빈들의 관계와 동작 방식을 구성할 수 있습니다.

@Configuration 어노테이션을 사용하여 스프링 빈을 등록할 때 주의해야 할 점은, 기본적으로 스프링은 등록된 빈들을 싱글톤(Singleton)으로 관리한다는 것입니다.
즉, @Configuration 어노테이션이 지정된 클래스 내의 @Bean 어노테이션이 지정된 메서드들이 반환하는 객체들은 스프링 컨테이너 내에서 단 하나의 인스턴스만 생성되고 공유됩니다.

따라서, @Configuration 어노테이션을 사용하여 빈을 등록하면 해당 빈들은 싱글톤 패턴으로 동작하게 됩니다.
이는 애플리케이션 전체에서 객체를 공유하고 메모리 사용을 최적화하는 장점을 가지지만, 주의해야 할 점도 있습니다. 싱글톤으로 등록된 빈은
멀티스레드 환경에서 동시에 접근할 경우 동기화 문제가 발생할 수 있으므로, 동시성에 대한 주의가 필요합니다.

 

 

728x90
반응형
728x90

스프링은 대부분 기업용 온라인 서비스 기술을 지원하기 위해 만들어졌습니다. 스프링 애플리케이션의 대부분은 웹 애플리케이션이며, 웹 애플리케이션은 보통 여러 고객이 동시에 요청하는 경우가 많습니다.

웹 애플리케이션의 특징은 고객의 요청이 많고 빈번합니다.

웹 애플리케이션과 싱글톤은 서로 다른 개념입니다. 각각에 대해 간단히 설명해드리겠습니다.

  1. 웹 애플리케이션(Web Application) 웹 애플리케이션은 인터넷 브라우저를 통해 접근할 수 있는 애플리케이션입니다. 일반적으로 웹 애플리케이션은 클라이언트-서버 아키텍처를 따르며, 웹 브라우저에서 요청을 보내고 서버에서 처리한 결과를 다시 브라우저로 응답하는 방식으로 동작합니다. 웹 애플리케이션은 주로 HTML, CSS, JavaScript 등을 사용하여 사용자 인터페이스를 제공하고, 서버 측에서는 서버 사이드 프레임워크를 사용하여 비즈니스 로직을 처리합니다.
  2. 싱글톤(Singleton) 싱글톤은 디자인 패턴 중 하나로, 애플리케이션에서 특정 클래스의 인스턴스를 오직 하나만 생성하고 사용하는 것을 의미합니다. 이렇게 하면 여러 곳에서 동일한 인스턴스에 접근하여 상태를 공유하고 객체 간의 일관성을 유지할 수 있습니다. 싱글톤은 주로 자원의 공유나 중복 생성을 피하기 위해 사용됩니다. 스프링 프레임워크에서는 빈(Bean)의 기본 스코프로 싱글톤을 사용하며, 컨테이너 내에서 하나의 빈 인스턴스를 생성하고 관리합니다.

따라서 웹 애플리케이션은 웹 환경에서 동작하는 애플리케이션을 의미하고, 싱글톤은 객체의 인스턴스 생성과 관리 방식 중 하나로 애플리케이션에서 공유되는 유일한 인스턴스를 생성하는 패턴입니다. 웹 애플리케이션에서도 싱글톤 패턴을 활용하여 객체를 생성하고 관리할 수 있습니다.

      
      public class SingletonTest {
            @Test
            @DisplayName("스프링 없는 순수한 DI 컨테이너")
            void pureContainer() {
                //DI컨테이너에 있는 Bean객체의 사용이 필요하여 AppConfig 객체를 생성
                AppConfig appConfig = new AppConfig();

                //1. 조회: 호출할 때마다 객체를 생성하는지 조회
                MemberService memberService1 = appConfig.memberService();

                //2. 조회: 호출할 때마다 객체를 생성하는지 조회
                MemberService memberService2 = appConfig.memberService();

                //참조 값이 다른 것을 확인해 보도록 합니다.
                //AppcConfig한테서 memberService를 호출을 힐 때마다 참조값(주소가) 다르게 호출
                System.out.println("memberService1 = " + memberService1);
                System.out.println("memberService2 = " + memberService2);
            }
        }
        

        출력 : memberService1 = Spring.core.member.MemberServiceImpl@5dda768f
               memberService2 = Spring.core.member.MemberServiceImpl@7a8c8dcf







ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

스프링 없는 순수한 DI 컨테이너인 AppConfig는 요청을 할 때마다 객체를 새로 생성합니다. 고객 트래픽이 초당 100이 나오면 100개의 객체가 생성되고 소멸됩니다. 메모리 낭비가 심하게 발생합니다. 해결 방안으로는 해당 객체가 딱 1개만 생성되고, 공유하도록 설계하기 위해 싱글톤 패턴이 등장하였습니다.


 

👉 싱글톤 패턴

싱글톤 패턴(Singleton Pattern)소프트웨어 디자인 패턴 중 하나로, 클래스의 인스턴스가 단 하나만 생성되도록 보장하는 패턴입니다. 즉, 해당 클래스의 인스턴스를 전역적으로 접근 가능하고 재사용할 수 있습니다. 객체 인스턴스를 2개 이상 생성하지 못하도록 막아야 하며, private 생성자를 사용해서 외부에서 임의로 new 키워드를 사용하지 못하도록 막아야 합니다.

 

 

🎈 Singleton객체를 생성해보고, Test를 진행해보자

      
      public class SingletonService {

            //1. static 영역에 객체를 딱 1개만 생성해둔다.
            //자기 자신을 내부에 static private으로 선언하고 가지고 있게 됨
            //(클래스 레벨에 올라가게 되면서 딱 하나만 존재)
            
            private static final SingletonService instance = new SingletonService();

            //JVM이 실행될 때, 바로 싱글톤 서비스의 스태틱 영역에 자기 자신의 객체를 생성하여 인스턴스를 담음
            //2. public으로 열어서 객체 인스턴스가 필요하면 이 static 메서드를 통해서만 조회하도록 허용한다.
            public static SingletonService getInstance() {
                return instance;
            }

            //3. 생성자를 private로 선언해서 외부에서 new 키워드를 사용한 객체 생성을 못하게 음
            private SingletonService() {
            }
            

            public void logic() {
                System.out.println("싱글톤 객체 로직 호출");
            }
        }




  ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡSingleTon 객체 생성 Test 코드ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
  

            @Test
            @DisplayName("싱글톤 패턴을 적용한 객체 사용")
            void singletonServiceTest() {
                SingletonService singletonService1 = SingletonService.getInstance();
                System.out.println("singletonService1 = " + singletonService1);

                SingletonService singletonService2 = SingletonService.getInstance();
                System.out.println("singletonService2 = " + singletonService2);

                assertThat(singletonService1).isSameAs(singletonService2);
                
          // same == : 두 객체가 정확히 동일한 객체인지를 확인 / 두 객체가 메모리에서 같은 위치를 참조하는지를 비교
          // equal : 두 객체의 값이 동등한지를 확인 / 객체의 실제 값을 비교하여 동등성을 판단
            }
            

        출력 : singletonService1 = Spring.core.singleton.SingletonService@55fe41ea
               singletonService2 = Spring.core.singleton.SingletonService@55fe41ea

 

  1. static 영역에 객체 instance를 미리 하나 생성해서 올려둡니다. 이 객체 인스턴스가 필요하면 오직 getInstance() 메서드를 통해서만 조회할 수 있습니다.
  2. getInstance() 메서드를 호출하면 항상 같은 인스턴스를 반환합니다. 딱 1개의 객체 인스턴스만 존재해야 하므로, 생성자를 private으로 막아서 혹시라도 외부에서 new 키워드로 객체 인스턴스가 생성되는 것을 막습니다.

싱글톤 패턴은 다음과 같은 특징을 가집니다:

  1. 단일 인스턴스: 싱글톤 패턴은 클래스의 인스턴스를 하나만 생성합니다. 이 인스턴스는 애플리케이션 전체에서 공유되어 사용됩니다.
  2. 전역 접근: 싱글톤 인스턴스는 어디서든 전역적으로 접근할 수 있습니다. 다른 객체들은 해당 인스턴스를 사용하여 데이터를 공유하거나 해당 인스턴스의 메서드를 호출할 수 있습니다.
  3. 지연 로딩: 일반적으로 싱글톤 인스턴스는 처음 필요할 때 생성됩니다. 이를 지연 로딩(Lazy Loading)이라고 합니다. 따라서 인스턴스 생성 비용을 줄이고 필요할 때만 생성하여 자원을 효율적으로 관리할 수 있습니다.

싱글톤 패턴은 다양한 상황에서 활용될 수 있습니다. 예를 들어, 데이터베이스 연결, 로깅, 캐시 등과 같이 애플리케이션 전체에서 공유되어야 하는 객체들을 관리하기 위해 싱글톤 패턴이 사용될 수 있습니다.

싱글톤 패턴을 구현하기 위해서는 다양한 방법이 있지만, 대표적으로는 다음과 같은 방식을 사용합니다:

  1. 정적 멤버 변수: 클래스 내부에 정적 멤버 변수를 선언하고, 해당 변수에 인스턴스를 생성하여 저장합니다.
  2. 지연 초기화: 인스턴스 생성을 처음 요청받을 때까지 지연시키고, 해당 요청 시에만 인스턴스를 생성합니다.
  3. 스레드 안전성: 멀티스레드 환경에서의 동시 접근 문제를 해결하기 위해 동기화 처리를 추가합니다.

싱글톤 패턴의 단점으로는
1. 싱글톤 패턴을 구현하는 코드가 길어지게 됩니다.
2. 의존 관계상 클라이언트가 구체 클래스에 의존합니다. (DIP를 위반하게 됩니다.)
3. 클라이언트가 구체 클레스에 의존해서 OCP 원칙을 위반할 가능성이 높고, 테스트 하기가 어렵습니다.
4. 내부 속성을 변경하거나 초기화 하기 어렵고, private 생성자로서 자식 클래스를 만들기 어렵습니다. 그 결과 유연성이 떨어지며, 안티 패턴으로 불리기도 합니다.


📄 싱글톤 컨테이너

 

스프링 컨테이너는 싱글톤 패턴의 문제점을 해결하면서 객체 인스턴스를 싱글톤(1개만 생성)으로 관리합니다. 스프링 빈이 바로 싱글톤으로 관리되는 빈을 의미합니다.

싱글톤 컨테이너(Singleton Container)는 객체를 싱글톤 패턴으로 관리하는 디자인 패턴과 관련된 개념입니다. 싱글톤 패턴은 애플리케이션 전체에서 단 하나의 인스턴스만 생성하여 공유하고, 이를 통해 객체 생성과 메모리 사용을 최적화하는 패턴입니다. 싱글톤 객체를 생성하고 관리하는 기능을 싱글톤 레지스트리라고 합니다.

싱글톤 컨테이너는 이러한 싱글톤 패턴을 구현하는데 사용되는 컨테이너입니다. 스프링 컨테이너는 싱글톤 컨테이너의 역할을 합니다. 주로 의존성 주입(Dependency Injection)을 사용하는 프레임워크나 라이브러리에서 제공되며, 객체의 인스턴스를 관리하고 필요한 곳에서 공유할 수 있도록 지원합니다.

싱글톤 컨테이너의 주요 특징은 다음과 같습니다:

  1. 객체 인스턴스의 단일성: 싱글톤 컨테이너는 애플리케이션 전체에서 단 하나의 인스턴스만 생성하여 사용합니다. 이를 통해 여러 곳에서 동일한 객체를 공유하고, 객체 생성과 소멸에 따른 오버헤드를 줄일 수 있습니다.

  2. 라이프사이클 관리: 싱글톤 컨테이너는 객체의 라이프사이클을 관리합니다. 객체의 생성, 초기화, 소멸 등의 작업을 컨테이너가 담당하므로, 개발자는 객체의 라이프사이클에 대해 직접 관리할 필요가 없습니다.

  3. 의존성 주입: 싱글톤 컨테이너는 의존성 주입(Dependency Injection)을 통해 객체 간의 의존성을 관리합니다. 다른 객체에 대한 의존성을 주입받을 수 있으며, 이를 통해 코드의 유연성과 테스트 용이성을 개선할 수 있습니다.

싱글톤 컨테이너는 대표적으로 스프링(Spring) 프레임워크에서 제공하는 스프링 컨테이너가 있습니다. 스프링 컨테이너는 객체의 싱글톤 패턴을 지원하며, @Component, @Service, @Repository 등의 어노테이션을 사용하여 싱글톤 빈을 등록하고 관리할 수 있습니다. 이를 통해 스프링은 객체의 라이프사이클을 관리하고, 필요한 곳에서 싱글톤 빈을 주입하여 사용할 수 있도록 지원합니다.

728x90
반응형
728x90

 

빈 팩토리(Bean Factory)와 애플리케이션 컨텍스트(Application Context)는 스프링 프레임워크에서 빈(Bean)을 생성하고 관리하는 기능을 제공하는 핵심 컨테이너입니다. 하지만 두 개의 용어는 약간의 차이점이 있습니다.

  1. 빈 팩토리(Bean Factory):
    • 빈 팩토리는 스프링의 핵심 컨테이너로서 빈(Bean)의 생성, 관리, 의존성 주입(Dependency Injection), 라이프사이클 관리 등의 기능을 제공합니다.
    • 주요 인터페이스로는 BeanFactory가 있으며, DefaultListableBeanFactory와 같은 구현체가 사용됩니다.
    • 빈 팩토리는 스프링의 가장 기본적인 컨테이너로서, 간단한 빈 관리 기능을 제공합니다.

  2. 애플리케이션 컨텍스트(Application Context):
    • 애플리케이션 컨텍스트는 빈 팩토리의 기능을 확장한 컨테이너로서, 빈 팩토리의 모든 기능을 포함하며 추가적인 기능을 제공합니다.
    • 주요 인터페이스로는 ApplicationContext가 있으며, AnnotationConfigApplicationContext, ClassPathXmlApplicationContext, WebApplicationContext 등이 사용됩니다.
    • 메세지 소스를 활용한 국제화 기능 - 한국에서 들어오면 한국어, 영어권에서 들어오면 영어로 출력해주는 기능입니다. ( 국제화(i18n) 지원 )
    • 환경변수 - 로컬, 개발, 운영등을 구분해서처리합니다.
    • 애플리케이션 이벤트 - 이벤트 발행 및 구독하는 모델을 편리하게 지원합니다.
    • 편리한 리소스 조회 - 파일이나 클래스 패스같은 외부 url 같은 곳에서 파일을 불러와서 쓸 때, 편하게 사용할 수 있는 기능을 제공합니다.
    • 또한, 애플리케이션 컨텍스트는 빈을 지연 로딩(lazy-loading)하거나 프로토타입 스코프의 빈을 여러 번 생성하는 등의 더 복잡한 빈 관리 기능을 제공합니다.

즉, 빈 팩토리는 스프링의 가장 기본적인 빈 관리 기능을 제공하는 컨테이너이며, 애플리케이션 컨텍스트는 빈 팩토리의 모든 기능을 포함하고 추가적인 기능을 제공하는 확장된 형태의 컨테이너입니다. 애플리케이션 개발 시 일반적으로 애플리케이션 컨텍스트를 사용하는 것이 더 편리하며, 빈 팩토리는 특별한 상황에서나 좀 더 가볍게 사용될 수 있습니다.'


XML로 만드는 Bean

 

xml기반의 appconfig.xml 스프링 설정정보와 코드로 된 Appconfig.java 설정 정보를 비교해보면 유사하다는 걸 알 수 있습니다. xml 기반으로 설정하는 것은 최근에 잘 사용하지 않으므로 필요하면 공식 문서를 확인해보시면 좋습니다. https://spring.io/projects/spring-framework

        👉 XML로 bean 생성하는 코드 (.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 http://www.springframework.org/schema/beans/spring-beans.xsd">

        <bean id="memberService" class="Spring.core.member.MemberServiceImpl">
            <constructor-arg name ="memberRepository" ref="memberRepository" />

        </bean>
        <bean id="memberRepository" class="Spring.core.member.MemoryMemberRepository"/>
        <bean id="orderService" class="Spring.core.order.OrderServiceImpl" >
            <constructor-arg name="memberRepository" ref="memberRepository" />
            <constructor-arg name="discountPolicy" ref="discountPolicy"/>
        </bean>
        <bean id="discountPolicy" class="Spring.core.discount.RateDiscountPolicy"/>
</beans>



        👉 xml 형식의 bean을 소환하여 작성한 TEST 코드 test 실행

        public class XmlAppContext {

            @Test
            void XmlAppContext() {
                ApplicationContext ac = new GenericXmlApplicationContext("appconfig.xml");
                MemberService memberService = ac.getBean("memberService", MemberService.class);
                assertThat(memberService).isInstanceOf(MemberService.class);
            }
        }

테스트코드가 실행이 완료되며, xml로 입력된 bean이 생성됨을 확인할 수 있습니다. 스프링의 싱글톤 빈으로 생성이 완료되었습니다

 

스프링 빈 메타 정보 - BeanDefinition

스프링에서 빈 메타 정보는 BeanDefinition이라는 개념을 통해 표현됩니다. BeanDefinition스프링 컨테이너가 빈(Bean)을 생성하고 관리하기 위해 필요한 정보를 담고 있는 객체입니다. 앞서 설명한 역할과 구현을 개념적으로 나눈 것입니다. BeanDefinition을 설정 메타 정보라 하고, @Bean 또는 <Bean> 당 각각 하나씩 메타정보가 생성됩니다. 스프링 컨테이너는 이 메타정보를 기반으로 스프링 빈을 생성합니다.

다음은 BeanDefinition에 대해 알아보는데 도움이 될 수 있는 설명입니다

  1. 빈의 클래스 타입: BeanDefinition은 빈으로 생성될 클래스의 타입 정보를 가지고 있습니다. 이는 스프링 컨테이너가 해당 클래스를 인스턴스화하고 빈으로 등록할 때 사용됩니다.
  2. 빈의 범위(Scope): BeanDefinition은 빈의 범위를 지정하는 정보를 가지고 있습니다. 스프링은 다양한 범위를 지원하는데, 주로 싱글톤(Singleton)과 프로토타입(Prototype)이 가장 많이 사용됩니다.
  3. 빈의 의존성(Dependency): BeanDefinition은 빈이 의존하는 다른 빈들과의 관계를 나타내는 정보를 가지고 있습니다. 이를 통해 스프링 컨테이너는 의존성 주입(Dependency Injection)을 수행하여 빈들 간의 관계를 자동으로 설정할 수 있습니다.
  4. 초기화 메서드와 소멸 메서드: BeanDefinition은 빈의 초기화와 소멸에 관련된 메서드 정보를 가지고 있습니다. 이를 통해 스프링 컨테이너는 빈의 라이프사이클을 관리하며, 빈이 생성될 때 초기화 메서드를 호출하고 소멸될 때 소멸 메서드를 호출할 수 있습니다.
  5. 추가 속성과 설정 정보: **BeanDefinition**은 다양한 추가 속성과 설정 정보를 포함할 수 있습니다. 예를 들어, 빈의 이름, 별칭, 프로파일, 지연 로딩 여부 등의 정보를 포함할 수 있습니다.

BeanDefinition은 스프링 컨테이너가 빈을 생성하고 관리하는 중요한 메타 정보를 담고 있습니다. 이를 통해 스프링은 빈의 생성, 초기화, 의존성 주입 등을 자동으로 처리할 수 있고, 개발자는 빈의 구체적인 설정과 관계를 중심으로 애플리케이션을 개발할 수 있습니다.

        👉 **스프링 빈 메타 정보를 확인해 보는 코드 작성**

        public class BeanDefinitionTest {

            AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig .class);

            @Test
            @DisplayName("빈 설정 메타 정보 확인")
            void findApplicationBean() {
                String[] beanDefinitionNames = ac.getBeanDefinitionNames();
                for (String beanDefinitionName : beanDefinitionNames) {
                    BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);

                    if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
                        System.out.println("beanDefinition = " + beanDefinition + "beanDefinition = " + beanDefinition);
                    }
                }
            }    
            }

 

 

해당 TEST 코드를 실행하면 AppConfig.class에 등록 되어 있는 bean들의 메타 정보를 확인할 수 있습니다.

728x90
반응형
728x90

🎈 스프링 빈 조회 - 동일한 타입이 둘 이상

타입으로 조회 시 같은 타입의 스프링 빈이 둘 이상이면 오류가 발생합니다.빈 이름을 지정해줌으로써 오류를 방지할 수 있습니다. 스프링 빈의 타입을 조회하는 문법은 ac.getBeansOfType();을 사용하면 해당 타입의 모든 빈을 조회할 수 있습니다.

👉 동일한 타입의 스프링 Bean의 DI 컨테이너에서 Bean을 조회했을 때의 예시

        public class ApplicationContextSameBeanFindTest {

            AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SameBeanConfig.class);

            @Test
            @DisplayName("타입으로 조회 시 같은 타입이 둘 이상 있으면, 중복 오류가 발생합니다.")
            void findBeanByTypeDuplicate() {

                //DiscountPolicy bean = ac.getBean(DiscountPolicy.class);
                //아래와 같이 코드를 작성한다면 예외가 발생하게 되는데, 지금 @Bean(하단에 작성한) 조회는 하단의 Bean을 조회
                /*MemberRepository bean = ac.getBean(MemberRepository.class);*/
                assertThrows(NoUniqueBeanDefinitionException.class, () -> ac.getBean(MemberRepository.class));

            }

            @Configuration
            //static를 사용 시 지역(scope)설정을 하기 위해 해당 클래스 안에서만 쓰겠다는 의미로 작성
            static class SameBeanConfig {

                //Bean의 이름은 다르나 반환되는 리턴값의 객체는 동일할 수 있음
                @Bean
                public MemberRepository memberRepository1() {
                    return new MemoryMemberRepository();
                }

                @Bean
                public MemberRepository memberRepository2() {
                    return new MemoryMemberRepository();
                }

            }

        }

해당 TEST 코드를 실행하게 되면 NoUniqueBeanDefinitionException 예외가 발생하게 됩니다.

 

먼저 두 개의 @Bean 메서드가 동일한 타입인 경우는 메서드의 반환 타입을 기반으로 알 수 있습니다. 위의 코드에서 memberRepository1()과 memberRepository2() 메서드는 모두 MemoryMemberRepository 타입의 객체를 반환하고 있으므로, 이 두 @Bean 메서드의 타입은 MemoryMemberRepository입니다.

 

스프링 프레임워크는 @Bean 메서드의 반환 타입을 기준으로 해당 메서드가 생성하는 빈(Bean)의 타입을 결정합니다. 따라서 같은 타입의 빈을 여러 개 정의하려면, 메서드의 반환 타입을 동일한 타입으로 지정해야 합니다.

이러한 상황에서 스프링은 빈의 식별을 위해 메서드 이름을 사용합니다. 즉, memberRepository1()과 memberRepository2() 메서드는 동일한 타입의 빈을 생성하지만, 스프링은 메서드 이름으로 구분하여 각각의 빈을 생성합니다. 따라서, 위의 코드에서 memberRepository1()과 memberRepository2() 메서드는 동일한 타입인 MemoryMemberRepository를 반환하지만, 스프링은 메서드 이름에 따라 각각의 빈을 구분합니다.


 

💡 스프링 빈 조회 - 상속관계

스프링 빈 상속 관계스프링 프레임워크에서 빈(Bean) 설정 시 사용되는 개념입니다.

부모타입으로 조회하면 본인을 포함하여 자식 타입도 함께 조회됩니다. 그래서 모든 자바 객체의 최상위 Object 타입으로 조회하면 모든 스프링 빈을 조회합니다. 스프링에서는 빈을 정의하고 구성하기 위해 XML 또는 어노테이션 기반의 설정을 사용합니다.

빈 상속은 한 빈을 기반으로 다른 빈을 정의하는 것을 의미합니다. 기본 빈(부모 빈)을 정의하고, 이를 상속하는 빈(자식 빈)을 생성할 수 있습니다. 자식 빈은 부모 빈의 설정을 상속하면서 추가적인 설정이나 오버라이딩을 할 수 있습니다.

빈 상속을 사용하면 다음과 같은 장점을 얻을 수 있습니다:

  1. 코드 중복 감소: 공통적인 설정을 부모 빈에서 정의하고, 자식 빈에서 추가적인 설정만 정의하여 중복을 줄일 수 있습니다.
  2. 유지보수성 향상: 공통된 설정을 부모 빈에서 관리하므로, 변경이 필요한 경우 부모 빈만 수정하면 모든 자식 빈에 반영됩니다.
  3. 가독성과 일관성: 빈 상속을 통해 관련 빈들을 계층 구조로 표현할 수 있으며, 코드의 가독성과 일관성을 높일 수 있습니다.

빈 상속은 스프링의 설정 파일(XML 또는 어노테이션)에서 parent 속성을 사용하여 부모 빈을 지정하는 방식으로 사용됩니다. 자식 빈은 부모 빈의 설정을 상속하며, 필요한 경우 추가적인 설정을 오버라이딩하여 사용할 수 있습니다.

 



        public class ApplicationContextExtendsFindTest {

            AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(TestConfig.class);

            @Test
            @DisplayName("부모 타입으로 조회 시 자식이 둘 이상 있으면 중복 오류가 발생합니다.")
            void findBeanByParentTypeDuplicate() {
            
                //아래와 같이 작성한 후 bean을 조회한다면 현재 2개의 @Bean이 생성되어 있어 두개 다 조회되며
                //NoUniqueBeanDefinitionException 예외가 발생
                //DiscountPolicy bean = ac.getBean(DiscountPolicy.class);
                assertThrows(NoUniqueBeanDefinitionException.class, () -> ac.getBean(DiscountPolicy.class));
            
			}

            @Test
            @DisplayName("부모 타입으로 조회 시 자식이 둘 이상 있으면 빈 이름을 지정하면 됩니다.")
            void findBeanByParentTypeBeanName() {
                DiscountPolicy ratediscountPolicy = ac.getBean("rateDiscountPolicy", DiscountPolicy.class);
                assertThat(ratediscountPolicy).isInstanceOf(RateDiscountPolicy.class);
            }


            @Test
            @DisplayName("특정 하위 타입으로 조회하면 됩니다.(좋지 않은 방법)")
            void findBeanBySubType() {
                RateDiscountPolicy bean = ac.getBean(RateDiscountPolicy.class);
                assertThat(bean).isInstanceOf(RateDiscountPolicy.class);
            }


            @Test
            @DisplayName("부모 타입으로 모두 조회하기")
            void findAllBeanByParentType() {
                Map<String, DiscountPolicy> beansOfType = ac.getBeansOfType(DiscountPolicy.class);
                assertThat(beansOfType.size()).isEqualTo(2);

                for (String key : beansOfType.keySet()) {
                    System.out.println("key = " + key +" " + "value = " + beansOfType.get(key)  );

                }
            }

            @Test
            @DisplayName("부모 타입으로 모두 조회하기 - Object")
            void findAllBeanByObjectType() {
             Map<String, Object> beansOfType = ac.getBeansOfType(Object.class);
                for (String key : beansOfType.keySet()) {
                    System.out.println("key = " + key + "value = " + beansOfType.get(key));

                }

            }


            @Configuration
            static class TestConfig {

                @Bean
                public DiscountPolicy rateDiscountPolicy() {
                    return new RateDiscountPolicy();
                }

                @Bean
                public DiscountPolicy fixDiscountPolicy() {
                    return new FixDiscountPolicy();
                }
            }
        }
728x90
반응형
728x90

@Configuration & @Bean

@Configuration과 @Bean은 Spring Framework에서 사용되는 애노테이션입니다. 이들은 Spring IoC 컨테이너에게 빈(Bean) 객체의 생성 및 구성 방법을 알려주는 역할을 합니다.

@Configuration 애노테이션은 클래스를 Spring의 설정 클래스로 지정합니다. 설정 클래스는 Spring IoC 컨테이너에게 해당 애플리케이션의 구성 정보를 제공하는 역할을 합니다. @Configuration 애노테이션이 적용된 클래스는 하나 이상의 빈을 생성하기 위해 @Bean 애노테이션과 함께 사용됩니다.

@Bean 애노테이션은 메서드를 통해 Spring IoC 컨테이너에게 빈 객체의 생성 및 구성 방법을 알려줍니다. @Bean 애노테이션이 적용된 메서드는 빈 객체를 반환하며, 이러한 빈 객체는 Spring IoC 컨테이너에 의해 관리됩니다. @Bean 애노테이션이 적용된 메서드의 이름은 빈의 이름이 되고, 반환되는 객체는 해당 빈의 인스턴스가 됩니다.

예를 들어, @Configuration과 @Bean을 사용하여 빈을 정의하는 예시입니다

            @Configuration
            public class AppConfig {

            @Bean
            public MyBean myBean() {
                return new MyBean();
            }

            @Bean
            public AnotherBean anotherBean() {
                return new AnotherBean(myBean());
            }

            // 다른 빈 정의 메서드...
            }

위의 예시에서 AppConfig 클래스는 @Configuration 애노테이션이 적용되었으며, myBean()과 anotherBean() 메서드는 @Bean 애노테이션이 적용되어 각각 MyBean과 AnotherBean 빈을 정의합니다. anotherBean() 메서드에서는 myBean()을 참조하여 AnotherBean의 의존성 주입을 수행합니다.

이렇게 @Configuration과 @Bean을 함께 사용하여 설정 클래스에서 빈을 정의하면 Spring IoC 컨테이너가 해당 빈을 인스턴스화하고 관리합니다. 이를 통해 의존성 주입, 빈의 스코프 지정, 초기화 메서드 등을 구성할 수 있습니다.


ApplicationContext

ApplicationContextSpring Framework에서 IoC 컨테이너의 인터페이스입니다. IoC 컨테이너는 애플리케이션의 구성 정보를 로드하고, 빈 객체의 생성과 관리, 의존성 주입 등을 수행합니다. ApplicationContext 인터페이스는 이러한 기능을 정의하고 제공합니다.

빈(Bean) 관리: ApplicationContext는 설정된 빈 정의를 바탕으로 빈 객체의 생성과 관리를 수행니다. 빈 객체는 @Bean 애노테이션이나 XML 설정 파일에서 정의될 수 있습니다. ApplicationContext는 빈의 스코프(싱글톤, 프로토타입 등) 및 라이프사이클 콜백(초기화, 소멸 등)을 관리합니다.

ApplicationContext 인터페이스를 사용하여 기존 자바코드로 작성하여 DI 컨테이너에 담아두었던 빈(Bean) 정의 메서드들을 ApplicationContext에 등록하여 applicationContext.getBean(”Bean의 이름”, Bean의 타입) 해당 문법을 사용하여 선택한 Bean을 호출할 수 있습니다.
→ ApplicationContext ac = new AnnotationConfigApplicationContext(설정 클래스);
ex) ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
⇒ applicationContext.getBean("memberService", MemberService.class);

 

   
   		public class MemberApp {

            public static void main(String[] args) {

        //      AppConfig appConfig = new AppConfig();
        //      MemberService memberService = appConfig.memberService();


                //AppConfig 클래스를 설정으로 사용하여, AnnotationConfigApplicationContext를 생성하고,
                //애플리케이션에서 필요한 빈을 applicationContext를 통해 가져와서 사용이 가능합니다.
                ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
                MemberService memberService = applicationContext.getBean("memberService", MemberService.class);



                Member member = new Member(1L, "memberA", Grade.VIP);
                memberService.join(member);


                Member findMember = memberService.findMember(1L);
                System.out.println("new member = " + member.getName());
                System.out.println("findMember = " + findMember.getName());
            }

 

위 코드와 같이 기존에 AppConfig 객체를 생성하여 AppConfig에 생성된 객체들을 직접 호출하는 것이 아니라 applicationContext를 이용하여 Bean을 호출하였습니다. 해당 코드를 실행하게 되면 콘솔창에 DI 컨테이너에 @Bean으로 설정된 메서드들의 객체가 등록되어 출력되는 것을 확인할 수 있습니다. 출력시에는 해당 Bean의 이름(ex.memberServie).(도트연산자)를 이용하여 출력이 가능합니다.

ApplicationContext를 스프링 컨테이너라고 합니다. 기존에는 개발자가 AppConfig를 사용해서 직접 객체를 생성하고 DI를 했지만, 이제부터는 스프링 컨테이너를 통해서 사용합니다. 스프링 컨테이너는 @Configuration이 붙은 AppConfig를 설정(구성)정보로 사용하고, 여기서 @Bean이라고 적힌 메서드를 모두 호출해서 반환된 객체를 스프링 컨테이너에 등록합니다. 이렇게 스프링 컨테이너에 등록된 객체를 스프링 빈 (Spring Bean)이라고 합니다.

Spring Bean은 Spring Framework에서 관리되는 객체를 의미합니다. 의존성 주입(Dependency Injection, DI)객체 간의 의존 관계를 개발자가 직접 관리하지 않고, 외부에서 의존하는 객체를 주입하여 사용하는 디자인 패턴입니다. DI는 객체 간의 결합도를 낮추고 유연하고 재사용 가능한 코드를 작성할 수 있도록 도와줍니다. Spring Framework은 의존성 주입(Dependency Injection)을 통해 객체들을 생성, 관리, 연결하는데, 이러한 객체들을 “Spring Bean”이라고 합니다.

tmvmfld qlsdms @Bean이 붙은 메서드 명을 스프링 빈의 이름으로 사용합니다. 이전에는 개발자가 필요한 객체를 AppConfig를 사용해서 직접 조회했지만, 이제부터는 스프링 컨테이너를 통해서 필요한 스프링 빈(객체)를 찾아야 합니다. applicationContext.getBean() 메서드를 사용해서 찾을 수 있습니다.


💡 스프링 컨테이너와 빈

스프링 컨테이너를 부를 때, “BeanFactory”와 “ApplicationContext”로 구분해서 이야기합니다.

  • 스프링 컨테이너의 생성과정
    • new AnnotationConfigApplicationContext(AppConfig.class); 를 선언함과 동시에 스프링 컨테이너가 생성됩니다. 컨테이너가 생성되면서, 빈 이름(key), 빈 객체(value)로 만들어지는 스프링 빈 저장소가 만들어집니다. 스프링 컨테이너가 생성될 때는 구성 정보를 지정해주어야 하는데 여기선 AppConfig.class로 지정되었습니다. @Bean의 이름은 직접 부여할 수도 있습니다. ex) @Bean(name=”NewBeanName”)

    • 스프링 빈 등록 AppConfig.class가 구성정보로 등록 되어있기 때문에 해당 구성 정보에서 @Bean이 붙은 메서드들을 전부 호출해줍니다 .이 때 메서드의 이름은 Bean 이름으로 해당 메서드가 반환하는 값(객체)는 Bean 객체로 등록을 해줍니다. 빈 이름은 항상 다른이름을 부여해야 합니다. 같은 이름을 부여하면, 다른 빈이 무시되거나, 기존 빈을 덮어버리는 등의 설정에 따라 오류가 발생합니다.
    1. 스프링 설정 파일 작성: 먼저, 스프링 컨테이너를 생성하기 위해 스프링 설정 파일을 작성합니다. 스프링 설정 파일은 일반적으로 XML, Java Config 또는 어노테이션 기반으로 작성될 수 있습니다. 설정 파일에는 애플리케이션의 구성 정보와 빈(Bean) 정의, 의존성 설정 등이 포함됩니다.

    2. 스프링 컨테이너 생성: 설정 파일을 기반으로 스프링 컨테이너를 생성합니다. 스프링은 다양한 종류의 컨테이너를 제공합니다. 가장 일반적인 컨테이너는 ApplicationContext 인터페이스를 구현한 클래스들입니다. ApplicationContext의 구현체는 설정 파일의 종류에 따라 다르게 선택할 수 있습니다.
    • XML 기반 설정: ClassPathXmlApplicationContext, FileSystemXmlApplicationContext, XmlWebApplicationContext 등이 사용됩니다.
    • Java Config 기반 설정: AnnotationConfigApplicationContext, GenericApplicationContext 등이 사용됩니다.
    • Spring Boot: Spring Boot에서는 SpringApplication 클래스의 run() 메서드를 사용하여 자동으로 스프링 컨테이너를 생성합니다.
    1. 빈 생성과 의존성 주입: 스프링 컨테이너는 설정 파일을 기반으로 빈 객체를 생성하고 관리합니다. 설정 파일에 정의된 빈들은 컨테이너에 의해 인스턴스화되고, 의존성 주입(Dependency Injection)을 통해 서로간의 의존성이 해결됩니다. 빈 객체는 컨테이너에 의해 스코프(싱글톤, 프로토타입 등)에 따라 관리되며, 필요한 경우 라이프사이클 콜백을 수행합니다.

    2. 컨테이너 사용: 스프링 컨테이너가 생성되고 빈이 초기화되면, 개발자는 컨테이너에서 필요한 빈을 가져와 사용할 수 있습니다. 컨테이너는 빈들을 관리하고, 필요에 따라 의존성 주입을 수행하여 객체 간의 결합도를 낮추고 유연한 애플리케이션을 개발할 수 있도록 도와줍니다.

스프링 빈은 생성하고, 의존관계를 주입하는 단계가 나누어져 있습니다. 자바코드로 스프링 빈을 등록하면 생성자를 호출하면서 의존관계 주입도 한번에 처리가 됩니다.

👉 빈 이름 조회하기

        class ApplicationContextInfoTest {

            AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

            @Test
            @DisplayName("모든 Bean 출력하기")
            void findAllBean() {
                String[] beanDefinitionNames = ac.getBeanDefinitionNames();
                for (String beanDefinitionName : beanDefinitionNames) {
                    Object bean = ac.getBean(beanDefinitionName);
                    System.out.println("bean = " + bean);
                }
            }


            @Test
            @DisplayName("애플리케이션 Bean 출력하기")        
            void findApplicationBean() {
                String [] beanDefinitionNames = ac.getBeanDefinitionNames();
                for (String beanDefinitionName : beanDefinitionNames) {
                    BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);


                    //Role ROLE_APPLICATION : 직접 등록한 애플리케이션 빈
                    //Role ROLE_INFRASTRUCTURE : 스프링이 내부에서 사용하는 빈
                    if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
                        Object bean = ac.getBean(beanDefinitionName);
                        System.out.println("beanDefinitionName  = " + beanDefinitionName + "object" + bean);
                    }

                }
            }
        }

 

빈에 대한 정보 출력하기 위해서 사용 가능한 메서드들이 있습니다. 실행하면 스프링에 등록된 모든 빈 정보를 출력할 수 있습니다.
모든 빈 출력하기 getBeanDefinitionNames() : 스프링에 등록된 모든 빈 이름을 조회
getBean() : 빈 이름으로 빈 객체(인스턴스)를 조회
애플리케이션 빈 출력하기 스프링이 내부에서 사용하는 빈은 제외하고, 내가 등록한 빈만 출력 가능 / 스프링이 내부에서 사용하는 빈은 getRole()로 구분이 가능합니다.
ROLE_APPLICATION :
일반적으로 사용자가 정의한 빈 ROLE_INFRASTRUCTURE : 스프링이 내부에서 사용하는 빈

728x90
반응형
728x90

 

🎈 Where 절

SQL의 WHERE 절은 데이터베이스에서 특정 조건을 충족하는 행만을 선택하기 위해 사용됩니다. WHERE 절은 SELECT, UPDATE, DELETE 문에서 사용될 수 있습니다.

  • 가져올 데이터의 조건(filter)을 컴퓨터에게 알려주는 라인입니다. ( 데이터가 너무 많아, 다 불러오려면 과부하가 될 수 있기 때문입니다.)
  • 한 개 이상의 조건을 작성할 수 있으며, And와 Or 조건들을 구분하여 조건을 설정할 수 있습니다. 작성하는 방식은 , “WHERE 컬럼명 연산자 조건”의 순서로 적어줍니다. (데이터는 ‘ ‘ 안에 작성! ) Ex) - 도시가 'Seoul'이고 직업이 'Developer'인 사용자를 선택하는 예시
    SELECT * FROM users WHERE city = 'Seoul' AND occupation = 'Developer';

 

        --문제 6. Customers 테이블에서 Mexico에 사는 사람들 정보를 추출해주세요.
        select * 
            from Customers
            where Country != 'Mexico';
        --column에 들어있는 값들은 전부 문자열로 저장되어 있기 때문에, 찾고자하는 데이터도 ' ' 로 감싸서 작성해야합니다.

        --문제 7. Customers 테이블에서 Mexico에 살지 않는 회원들의 정보를 추출하세요.
        select * 
            from Customers
            where Country != 'Mexico';

        --문제 8. 국가이름이 "S"로 시작하는 국가에 거주하는 사람들 정보를 모두 추출해주세요
        select * 
            from Customers
            where country like "s%";

        --문제 8-2. "S"로 시작하지 않는 국가에 거주하는 사람들 정보 (like와 반대!)
        select * 
            from Customers
            where country not like "s%";

        --문제 8-3. 회원 중 나라 이름의 마지막 알파벳이 A로 끝나는 국가에 거주 중인 사람 정보를 모두 추출해주세요

            like 연산자 사용 예제
            -- 이름이 'John'으로 시작하는 사용자를 선택하는 예시
            SELECT * FROM users WHERE name LIKE 'John%';

            -- 이메일이 '@gmail.com'으로 끝나는 사용자를 선택하는 예시
            SELECT * FROM users WHERE email LIKE '%@gmail.com';

            -- 이름이 'J_n'과 같은 형식의 사용자를 선택하는 예시 (J 다음에 한 글자와 n으로 끝나는 경우)
            SELECT * FROM users WHERE name LIKE 'J_n';

 

  • LIKE 연산자는 특정 문자열 패턴 매칭을 위해 사용됩니다. LIKE 연산자는 특정 패턴과 일치하는 값을 선택하기 위해 WHERE 절과 함께 사용됩니다.%: 0개 이상의 문자와 일치합니다. _: 단일 문자와 일치합니다. []: 지정된 범위 내의 문자와 일치합니다. 예를 들어 **[abc]**는 'a', 'b', 'c' 중 하나와 일치합니다. [^]: 지정된 범위 외의 문자와 일치합니다. 예를 들어 [^abc]는 'a', 'b', 'c' 이외의 문자와 일치합니다.
  • **pattern**에는 와일드카드 문자를 사용할 수 있습니다. 정규표현식이라는 문자를 다룰 수 있는 사항이 입력됩니다. 주요 와일드카드 문자는 다음과 같습니다

 

🎈 Order by절 - order by ‘key(컬럼명)’ (asc/desc)

ORDER BY 구문은 SQL에서 사용되는 명령문으로, 가져온 데이터의 결과를 순서대로 정렬해주는 명령을 작성해주는 라인이며, 정렬 기준을 지정하는데 사용됩니다.
결과 집합을 특정 열(또는 열들)의 값에 따라 오름차순(ASC) 또는 내림차순(DESC)으로 정렬할 수 있습니다. 디폴트 값이 오름차순(asc)이기때문에, 조건부에 아무것도 안 적을 시 자동으로 오름차순 정렬을 수행합니다.
다중조건 , 즉 두 가지 이상의 컬럼에 조건을 줄 수 있습니다. ex) order by colum1 asc, coulm2 desc

ORDER BY 구문은 SELECT 문에서 마지막에 추가되며, 쿼리 결과의 정렬된 순서로 데이터를 반환합니다. 컴퓨터는 A,B,C.. 등을 출력할 때 문자를 숫자로 인식하여(아스키코드) 크기를 비교할 수 있습니다.

 

        SELECT *
            FROM customers
            order by country asc -> 오름차순 A-Z순서로 나라이름이 정렬됩니다.
            limit 10
            ;
            order by 7 desc -> 7번째 컬럼인 country를 기준으로 내림차순으로 정렬하였습니다.
        컬럼을 가지고 정렬을 하지만 컬럼의 이름은 모르고 위치만 알 때 사용하는 방법도 있습니다. 컬럼의 위치에 따라서 숫자를 입력하여 해당 컬럼을 지정할 수 있습니다.

 

 

728x90
반응형

'[ DATABASE]' 카테고리의 다른 글

[SQL] SQL이란?  (0) 2023.06.27

+ Recent posts