** IoC(Inversion of Control)가 무엇인지 설명해주세요. 그리고 이를 사용하는 이유는 무엇인가요?

IoC(Inversion of Control)는 일반적으로 프로그램의 제어 흐름을 직접 제어하지 않고 외부에서 관리하는 것을 말합니다. 이는 프로그램의 유연성을 증가시키고 결합도를 낮추는데 도움이 됩니다.

전통적인 프로그래밍에서는 우리가 작성하는 프로그램이 전체적인 제어 흐름을 가지고 있습니다. 우리가 작성한 클래스가 필요로 하는 다른 클래스를 직접 생성하고, 호출하며, 관리합니다. 이 방식의 문제점은 모든 컴포넌트가 강하게 결합되어 있어서 변경에 대한 유연성이 낮다는 점입니다.

IoC 이런 제어 흐름을 '뒤집어' 외부(: 프레임워크, 컨테이너)에서 객체의 생성과 생명주기를 관리하며 필요한 의존성을 주입합니다. 이렇게 하면  컴포넌트는 서로를 직접적으로  필요가 없으므로 결합도가 낮아지고, 교체나 수정이 용이해집니다. 이는 유지보수와 테스트 작성을 쉽게 만들며, 개발 과정에서의 유연성을 증가시킵니다.

 

** Dependency Injection(DI)가 무엇인지 설명해주실 수 있나요? 그리고 왜 이를 사용하나요?

DI 의존성 주입이라고 불리며, 객체의 생성과 의존 관계를 외부에서 정의하는 디자인 패턴입니다. DI 사용하면  클래스 사이에 있는 의존 관계를 느슨하게 만들어서 결합도를 낮출 수 있고, 코드의 유지 보수성을 향상시키고, 테스트를 용이하게 만듭니다. DI IoC(Inversion of Control)  형태로, 제어의 역전을 통해 객체의 생명주기를 개발자가 아닌 프레임워크에게 맡기는 것을 가능하게 합니다.

어플리케이션의 다른 부분에서 사용되는 객체를 생성하고 관리하는 방법입니다. 코드의 재사용성, 유지보수성을 향상시키고, 모듈 간의 결합도를 낮추는 데 도움이 됩니다.

 

**Spring Framework에서는 어떻게 DI를 구현하나요?

Spring Framework에서는 주로  가지 방법을 통해 의존성 주입(Dependency Injection, DI) 구현합니다
1. 생성자 주입 : 
객체 생성  생성자를 통해 필요한 의존성을 주입하는 방법입니다. 객체는 생성되는 시점에 모든 필요한 의존성을 갖게 되며, 객체의 불변성을 보장할  있습니다. 생성자 주입은 필수적인 의존성을 주입하는 경우에 주로 사용됩니다.
ex. 

객체가 만들어질 때 필요한 '재료'를 생성자에 전달하여 객체를 만드는 방법입니다. 예를 들어, 자동차를 만들 때 엔진, 타이어, 핸들 등이 필요한데, 이것들이 바로 '의존성'입니다. 자동차를 만드는 사람은 이 '재료'들을 미리 준비하고, 자동차 생성자에게 전달하여 자동차를 만듭니다.

2. 세터 메서드 주입: 세터 메서드를 통해 의존성을 주입하는 방법입니다. 세터 메서드 주입은 선택적인 의존성을 주입할  주로 사용됩니다.  방식을 사용하면 객체가 생성된 후에 의존성을 변경할  있지만, 잘못 사용하면 불변성이 깨질  있습니다.

ex. 

객체가 만들어진 후 필요한 '재료'를 세팅하는 방법입니다. 여기서도 자동차 예시를 들어보겠습니다. 자동차를 만든 후에 나중에 라디오를 추가하려면 세터 메서드를 사용하여 라디오를 추가할 수 있습니다.

 외에도 필드 주입(Field Injection) 방법도 제공하지만,  방법은 테스트와 다른 상황에서 의존성을 변경하기 어려워 사용을 권장하지 않습니다.

즉, 생성자 주입은 주로 필수적인 '재료'를 주입할 때 사용되고, 세터 주입은 선택적인 '재료'를 주입할 때 사용됩니다.


** Constructor Injection과 Setter Injection의 차이점은 무엇인가요? 어떤 상황에서 어떤 것을 사용하는 것이 좋은가요?

주요 차이점은 객체 생성 시점에 의존성이 주입되는 시점이 다르다는 것

Constructor Injection:

  1. Constructor Injection은 객체 생성과 동시에 모든 의존성이 주입됩니다. 따라서, 주입받는 객체가 생성되는 시점에 필요한 모든 의존성을 갖게 됩니다.
  2. 이 방식을 사용하면 객체가 변하지 않는 불변성(Immutability)을 보장할 수 있습니다. 한 번 객체가 생성되면 그 상태를 변경할 수 없습니다.
  3. 또한 순환 의존성(Circular Dependency) 문제를 컴파일 시점에 쉽게 발견할 수 있습니다.

Setter Injection:

  1. Setter Injection 객체 생성  필요할  의존성을 주입  있습니다. 객체가 생성된 후에도 상태를 변경할  있습니다.
  2.  방식은 선택적인 의존성이 있는 경우 유용합니다. , 특정 조건 하에서만 필요한 의존성을 주입할  있습니다.
  3. 하지만  방식을 사용하면 객체의 상태가 변할  있으며, 순환 의존성 문제를 런타임 시점에야 발견  있습니다.

** DI를 사용하면 어떤 문제점이 발생할 수 있나요? 이런 문제를 어떻게 해결하나요?

  1. 복잡성 증가: DI는 각 클래스와 객체들 사이의 의존성을 관리하기 위해 추가적인 구성 요소와 코드가 필요합니다. 이로 인해 코드의 복잡성이 증가할 수 있으며, 초기에는 이해하기 어려울 수 있습니다. 이를 해결하기 위해, DI 프레임워크(Spring 등)를 사용하여 복잡성을 줄일 수 있습니다. 또한, 잘 정리된 코드와 문서를 유지하여 복잡성을 관리할 수 있습니다.
  2. 코드 추적의 어려움: DI를 사용하면 객체 생성 로직이 분산되므로, 어떤 객체가 어떻게 생성되고 어디에서 사용되는지 추적하기가 어려울 수 있습니다. 이 문제는 IDE의 도구나, DI 프레임워크가 제공하는 디버깅 도구를 사용하여 해결할 수 있습니다.
  3. Over-engineering: 많은 개발자들이 DI가 항상 필요한 것이라고 생각할 수 있지만, 작은 프로젝트나 단순한 코드에서는 DI를 사용하지 않는 것이 더 효과적일 수 있습니다. 너무 복잡하게 생각하지 않고, 실제 필요한 상황에서만 DI를 적용하는 것이 중요합니다.

이런 문제점들에도 불구하고, DI는 객체 간의 의존성을 줄이고, 테스트 용이성을 높이며, 코드의 재사용성을 증가시키는 등 많은 장점을 제공합니다. 따라서, DI의 장점과 단점을 잘 이해하고 적절하게 활용하는 것이 중요합니다.

 

** DI를 통해 단위 테스트를 작성하고 실행하는 방법에 대해 설명해주세요.

DI 사용하면 실제 의존성 대신 mock 객체를 주입할  있어 테스트를 쉽게 작성하고 실행할  있습니다. 

이는 코드의 결합도를 낮추고, 테스트의 격리를 보장합니다.

 

** IoC 컨테이너가 무엇인지, 그리고 그 기능에 대해 설명해주세요.

IoC(Inversion of Control) 컨테이너는 프레임워크나 라이브러리에서 제공하는 컴포넌트를 관리하고 조율하는 역할을 합니다. IoC라는 용어는 컴포넌트의 제어 권한이 사용자가 아니라 프레임워크에게 있음을 의미합니다.

IoC 컨테이너의 주요 기능은 다음과 같습니다:

  1. 객체의 생명 주기 관리: IoC 컨테이너는 프로그램에서 사용되는 객체의 생성과 소멸, 그리고 그 생명 주기를 관리합니다. 이를 통해 개발자는 객체의 생명 주기를 직접 관리하는 데 신경 쓰지 않고 비즈니스 로직에 집중할 수 있습니다.
  2. 의존성 주입(Dependency Injection): IoC 컨테이너는 객체가 필요로 하는 의존성을 자동으로 주입합니다. 이를 통해 객체간의 강한 결합도를 줄이고, 코드의 재사용성과 테스트 용이성을 증가시킬 수 있습니다.
  3. 구성 관리(Configuration Management): IoC 컨테이너는 애플리케이션의 환경 설정과 같은 구성 정보를 관리합니다. 예를 들어, 데이터베이스 연결 정보나 외부 서비스의 URL 같은 정보를 애플리케이션 코드에서 분리하여 IoC 컨테이너에서 관리하게 되면, 이런 설정 정보를 바꿀  코드를 바꾸지 않고도 설정만 변경하면 됩니다. 이를 통해 개발 환경, 테스트 환경, 실제 서비스 환경 등에서 각기 다른 설정을 사용할  있어 편리합니다.
  4. 서비스 제공(Service Provisioning): IoC 컨테이너는 필요한 서비스를 제공하는 역할도 합니다.예를 들어, 보안 관련 처리(인증, 권한 체크 ), 트랜잭션 관리, 로깅 등의 서비스를 제공합니다. 이런 기능들은 많은 애플리케이션에서 공통적으로 필요한 기능인데, 이런 것들을 각각의 애플리케이션 코드에서 직접 구현하는 것은 비효율적입니다. 이런 공통 기능들을 IoC 컨테이너가 제공하면 애플리케이션 코드는 이런 기능들을 직접 구현할 필요 없이 IoC 컨테이너가 제공하는 기능을 사용하기만 하면 됩니다. 이로써 개발이 단순화되고 효율이 높아집니다.

Spring Framework IoC 컨테이너는 'ApplicationContext'라는 이름으로 제공됩니다.  컨테이너는 BeanFactory 인터페이스를 상속받아 구현되며, Bean 객체의 생성, 초기화, 관리 등을 책임지고 있습니다.

 

** Bean이란 무엇인가요? Spring에서 Bean의 라이프사이클은 어떻게 관리되나요?

Bean이란 Spring Framework에서 관리하는 객체를 뜻합니다. 이 객체들은 Spring IoC(Inversion of Control) 컨테이너에 의해 생성되고, 관리됩니다. 보통 application-context.xml 파일 또는 어노테이션을 통해 Bean을 등록하고, 이들은 컨테이너가 시작될 때 생성되고 컨테이너가 종료될 때 소멸합니다.

Spring에서 Bean의 라이프사이클은 다음과 같이 관리됩니다.

  1. Bean 객체 생성: Spring 컨테이너가 Bean의 정의를 읽어들이고, Bean 객체를 생성합니다.
  2. Bean 속성 설정: Spring 컨테이너는 Bean 정의에 따라 속성(Property)을 설정합니다.
  3. Bean 초기화: Spring 컨테이너는 Bean이 초기화되는 시점에 @PostConstruct 어노테이션이 붙은 메서드를 호출하거나, 설정 파일에 등록된 초기화 메서드를 호출합니다.
  4. Bean 사용: 응용프로그램은 이제 Bean을 사용하게 됩니다.
  5. Bean 소멸: Spring 컨테이너는 @PreDestroy 어노테이션이 붙은 메서드를 호출하거나, 설정 파일에 등록된 소멸 메서드를 호출하여 Bean을 소멸시킵니다.

이렇게 Spring Bean 전체 생명주기를 관리함으로써 개발자가 객체 생성과 소멸, 속성 설정 등과 같은 보일러플레이트 코드를 작성할 필요가 없게 해줍니다. 이를 통해 개발자는 핵심 비즈니스 로직에만 집중할  있습니다.

 

** Spring에서는 어떻게 싱글톤 Bean을 관리하나요? 다른 Bean 범위는 무엇이 있나요?

Spring에서는 기본적으로 모든 Bean을 싱글톤(Singleton)으로 관리합니다. 즉, Spring IoC(Inversion of Control) 컨테이너가 Bean을 생성할 때, 각 Bean에 대해 하나의 인스턴스만을 생성하고 이를 컨테이너 전체에서 공유합니다. 이렇게 함으로써 Spring은 애플리케이션 전체에서 공유되는 객체들의 생명주기를 관리하고, 애플리케이션의 효율성과 확장성을 증가시킵니다.

하지만 모든 상황에서 싱글톤 Bean이 적합하지는 않습니다. 따라서 Spring은 다음과 같은 다양한 범위의 Bean을 지원합니다:

  1. 싱글톤(Singleton): Spring IoC 컨테이너 당 하나의 인스턴스만 생성. 이것은 Spring의 기본 범위입니다.
  2. 프로토타입(Prototype): 요청할 때마다 새로운 인스턴스를 생성합니다.
  3. 요청(Request): HTTP 요청당 하나의 Bean 인스턴스를 생성합니다. 이 범위는 웹 어플리케이션 컨텍스트에서만 유효합니다.
  4. 세션(Session): HTTP 세션당 하나의 Bean 인스턴스를 생성합니다. 이 범위도 웹 어플리케이션 컨텍스트에서만 유효합니다.
  5. 애플리케이션(Application): ServletContext당 하나의 Bean 인스턴스를 생성합니다. 이 범위는 웹 어플리케이션 컨텍스트에서만 유효합니다.

이러한 범위를 통해 Spring 다양한 상황에 맞는 객체의 생명주기를 관리할  있습니다.

더보기

먼저, Spring에서 'Bean'이란 것은 간단히 말해서 우리가 만드는 프로그램의 일부분을 담당하는 객체입니다. 예를 들어, 사용자 정보를 관리하는 'UserService', 상품 정보를 관리하는 'ProductService' 같은 것들이 Bean이 될 수 있습니다.

Spring은 이런 Bean들을 관리하는데, 이때 Bean들을 어떻게 만들고 사용할지에 대한 규칙을 정하는 것을 'Bean의 라이프사이클 관리'라고 합니다.

이제 '싱글톤(Singleton)'에 대해 알아봅시다. '싱글톤'이란 한 번 만들어진 Bean을 계속해서 재사용하는 것을 말합니다. 예를 들어, 'UserService'라는 Bean이 싱글톤으로 설정되어 있다면, 'UserService'가 필요할 때마다 새로 만들지 않고 처음에 만든 하나를 계속해서 쓰게 됩니다.

하지만 모든 경우에 싱글톤이 좋은 것은 아닙니다. 때때로, 요청이 올 때마다 새로운 Bean을 만들어야 할 경우도 있습니다. 예를 들어, 사용자마다 다른 정보를 담고 있는 'UserSession'과 같은 Bean은 싱글톤으로 만들면 안 됩니다. 이럴 때는 '프로토타입(Prototype)'으로 설정해서, 요청이 올 때마다 새로운 Bean을 만들도록 합니다.

마지막으로, '요청(Request)', '세션(Session)', '애플리케이션(Application)' 범위는 웹 어플리케이션에서 사용됩니다. '요청' 범위는 한 번의 웹 요청이 들어올 때마다 새로운 Bean을 만듭니다. '세션' 범위는 웹 브라우저의 한 세션 동안 유지되는 Bean을 만듭니다. '애플리케이션' 범위는 웹 애플리케이션 전체에서 공유하는 하나의 Bean을 만듭니다.

이렇게 Spring 다양한 상황에 맞게 Bean 만들고 관리할  있도록 도와줍니다.

 

**  싱글톤 패턴이 무엇인지 설명해주실 수 있나요? 그리고 이를 어떻게 구현하나요?

싱글톤 패턴(Singleton Pattern)은 객체 지향 프로그래밍에서 사용하는 디자인 패턴 중 하나로, 클래스의 인스턴스가 하나만 만들어지고, 어디서든지 그 인스턴스에 접근할 수 있도록 하는 것을 목적으로 합니다. 이 패턴은 전역 변수를 사용하지 않고 객체를 전역적으로 액세스할 수 있게 해줍니다.

싱글톤 패턴은 주로 공유 리소스에 대한 동시 접근을 제어하거나, 한 시스템에서 사용되는 환경 설정과 같은 상황에서 사용됩니다.

자바에서는 주로 private 생성자를 가진 클래스를 만들고, 클래스 내부에 해당 클래스의 static 변수를 만듭니다. 이후 외부에서 접근할 수 있는 public static 메서드를 제공하여 이 메서드가 클래스의 유일한 인스턴스를 반환하도록 합니다.

public class Singleton {
    // 자신의 타입인 정적 필드를 가지고 있습니다. 이 필드가 유일한 인스턴스를 저장합니다.
    private static Singleton uniqueInstance;

    // 생성자를 private로 선언해, 외부에서 인스턴스를 직접 생성할 수 없게 합니다.
    private Singleton() {}

    // 유일한 인스턴스를 얻는 메서드를 제공합니다.
    public static Singleton getInstance() {
        // 인스턴스가 없을 때만 생성합니다. 이를 "Lazy Initialization"라고 합니다.
        if (uniqueInstance == null) {
            uniqueInstance = new Singleton();
        }
        return uniqueInstance;
    }
    // 다른 메서드들...
}

위 예제에서 볼 수 있듯이, 싱글톤 패턴은 private 생성자와 자신의 타입을 반환하는 정적 메서드를 사용하여 구현합니다. 싱글톤 객체가 아직 생성되지 않았을 때에만 객체를 생성하고, 이미 생성된 경우에는 해당 객체를 반환합니다.

,  방식은 멀티스레딩 환경에서 동기화 문제 야기할  있습니다. 따라서 멀티스레딩 환경에서는 추가적인 동기화 처리가 필요할  있습니다. 이를 위해 getInstance() 메서드를 synchronized 선언하거나, "Initialization-on-demand holder idiom" 같은 다른 방법을 사용할  있습니다.

 

멀티스레딩 환경에서 싱글톤 패턴을 사용하면 동기화 문제가 발생할 수 있습니다. 즉, 동시에 두 개 이상의 스레드가 getInstance() 메소드를 호출하면, 유일해야 하는 인스턴스가 두 개 이상 생성될 수 있습니다.

이를 해결하기 위한 여러 가지 방법이 있습니다. 먼저 getInstance() 메소드를 synchronized 선언하는 방법이 있습니다. synchronized 키워드를 사용하면 메소드가 번에 스레드만 접근할 있도록 동기화를 보장합니다.

public class Singleton {
    private static Singleton uniqueInstance;

    private Singleton() {}

    // synchronized 키워드를 추가했습니다.
    public static synchronized Singleton getInstance() {
        if (uniqueInstance == null) {
            uniqueInstance = new Singleton();
        }
        return uniqueInstance;
    }
    // 다른 메서드들...
}

그러나 이 방법은 getInstance() 메소드에 대한 동시 접근을 막아 성능 저하를 일으킬 수 있습니다. 그래서 더 효율적인 방법이 필요한데, 그 중 하나가 "Initialization-on-demand holder idiom"입니다.

public class Singleton {
    private Singleton() {}

    // 이 내부 클래스는 getInstance() 메서드가 처음 호출될 때 로드됩니다.
    private static class Holder {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return Holder.INSTANCE;
    }
    // 다른 메서드들...
}

이 방법은 JVM의 클래스 로딩 메커니즘과 클래스가 로딩될 때 한 번만 초기화된다는 점을 이용합니다. Holder 내부 클래스는 getInstance() 메서드가 처음 호출될 때 로드되며, 그 때 Singleton 인스턴스가 생성됩니다. 이후 getInstance() 호출에서는 이미 생성된 인스턴스를 반환하므로 동기화가 필요 없고, "lazy initialization"도 가능합니다.

더보기

"Initialization-on-demand holder idiom"은 Singleton 패턴을 구현하는 방법 중 하나입니다. 이 패턴은 Java의 언어 스펙을 최대한 활용하여 thread-safe한 Singleton을 만들고, 동시에 lazy initialization도 가능하게 합니다.

Java의 클래스 로딩 방식과 클래스 초기화에 대한 스펙 때문에 이 방법이 가능합니다. Java는 클래스가 처음으로 참조될 때 해당 클래스를 로딩하고 초기화합니다. 그리고 클래스 초기화는 여러 스레드에 의해 동시에 실행될 수 없습니다. 즉, 클래스 초기화는 내부적으로 동기화가 보장되어 있습니다.

이런 특성을 이용하여, Initialization-on-demand holder idiom Singleton 객체를 가지고 있는 private static 내부 클래스(Holder 클래스) 정의합니다. Holder 클래스는 Singleton 클래스의 getInstance() 메소드가 호출될 처음으로 참조되므로, 그때 클래스가 로딩되고 Singleton 인스턴스가 생성됩니다.

위의 코드에서 보면, Holder 클래스는 getInstance() 메소드가 호출될 처음으로 참조되므로, 시점에서 Singleton 인스턴스가 생성됩니다. 이후 getInstance() 메소드가 호출되면, 이미 생성된 Singleton 인스턴스를 반환합니다. 이렇게 하면 불필요한 동기화 없이 thread-safe하게 Singleton 인스턴스를 생성하고, 동시에 lazy initialization 가능하게 있습니다.

 

2023.05.18 - [Mockterview] - DI와 IoC, Bean pt.1

26. 코드 처리하기 ⭐️ ⭐️

문제...너무 길어서..이해하는데.... 한나절...걸림.....접근방법은 하나씩 입출력하면서 값 체크 ! 사고력과 관찰력의 문제이다 !! 

 String answer = "";

        int temp = 0;
        for(int i=0; i<code.length(); i++){

            if(code.charAt(i) == '1'){
                temp++;
            }else if(temp%2==0&&i%2==0||temp%2==1&&i%2==1){
                answer+=code.charAt(i);
            } 
        }
        if(answer.equals("")){
            answer = "EMPTY";
        }
        return answer;

27. 등차수열의 특정한 항만 더하기 

더보기

등차수열의 합 : S = n/2 * (a + l)

  • S는 등차수열의 합
  • n은 등차수열의 항의 수
  • a는 등차수열의 첫 번째 항
  • l은 등차수열의 마지막 항

28. 주사위 게임2 

29. 원소들의 곱과 합 

진짜 길게도 풀었네...

      int answer = 0;

        int temp = 1;
        int temp1 = 0;
        for(int i=0; i<num_list.length; i++){
            temp *= num_list[i];
            temp1 += num_list[i];
        }

        answer = temp1*temp1 > temp ? 1 : 0;
        return answer;

30. 이어 붙인 수 

  int answer = 0;
        String even = "";
        String odd= "";
        for(int i : num_list) {
            if(i%2==0) even += i + "";
            else odd += i + "";
        }
        answer = Integer.parseInt(even) + Integer.parseInt(odd);
        return answer;
     int answer = 0;

        int even = 0;
        int odd = 0;

        for(int num : num_list) {
            if(num % 2 == 0) {
                even *= 10;
                even += num;
            } else {
                odd *= 10;
                odd += num;
            }
        }
        answer = even + odd;

        return answer;

31. 머쓱이보다 키 큰 사람 

 int answer = 0;
        for(int i: array){
            answer += (i>height) ? 1 : 0;
        }
        return answer;
 int answer = 0;
        for(int i : array) {
            if(i > height) answer++;
        }
        return answer;

32. 중복된 숫자 개수 

 return (int) Arrays.stream(array).filter(i -> i == n).count();

'Algorithm' 카테고리의 다른 글

프로그래머스 Lv.0  (0) 2023.05.27
프로그래머스 Lv.0  (0) 2023.05.25
프로그래머스 Lv.0  (0) 2023.05.20
프로그래머스 Lv.0  (2) 2023.05.19
프로그래머스 Lv.0  (0) 2023.05.19

영속성 컨텍스트(Persistence Context)는 JPA에서 매우 중요한 개념입니다. '엔티티를 영구 저장하는 환경'이라는 뜻입니다.

JPA를 통해서 엔티티를 생성하고, 이를 데이터베이스에 저장하는 작업을 수행할 때, 이 엔티티는 영속성 컨텍스트에 저장되며, 이 상태를 '영속 상태'라고 합니다. 이렇게 영속성 컨텍스트에 저장된 엔티티는 데이터베이스와 일치하는 상태를 유지합니다. 이때 영속성 컨텍스트는 해당 엔티티를 관리하면서 발생하는 모든 변경사항을 데이터베이스에 동기화하게 됩니다.

1차 캐시는 영속성 컨텍스트 내부에 있는 캐시로서, 엔티티의 조회와 관련한 동작을 수행합니다. 영속성 컨텍스트는 엔티티를 저장하거나 조회할 때 먼저 1차 캐시에서 해당 엔티티를 찾아보고, 있다면 데이터베이스에 접근하지 않고 해당 엔티티를 반환합니다. 이런 방식으로 1차 캐시는 데이터베이스와의 불필요한 접근을 줄여 성능을 향상시킵니다.

하지만, 1 캐시는 해당 트랜잭션 범위에서만 유효하며, 트랜잭션이 종료되면 1 캐시의 엔티티들도 모두 사라지게 됩니다. 따라서, 1 캐시는 트랜잭션 범위에서의 재조회를 최적화하거나, 동일 트랜잭션 내에서의 엔티티 동일성을 보장하는 역할을 수행하게 됩니다.

 

1. 영속성 컨텍스트(Persistence Context)는 무엇인가요? 이를 사용하는 이유는 무엇인가요?

 

영속성 컨텍스트는 JPA에서 핵심적인 역할을 하는 개념으로, Entity를 영구 저장하는 환경을 의미합니다.

이 영속성 컨텍스트는 Entity Manager에 의해 관리되며, Entity Manager는 Entity를 저장, 수정, 삭제, 조회하는 기능을 제공합니다. 영속성 컨텍스트는 Entity의 생명주기를 관리하며, 해당 Entity에 대한 1차 캐시, 쓰기 지연, 변경 감지(Dirty Checking), 지연 로딩(Lazy Loading) 등의 역할을 수행합니다.

영속성 컨텍스트를 사용하는 이유는 아래와 같습니다:

  1. 1차 캐시: 영속성 컨텍스트는 조회한 Entity를 1차 캐시에 보관하므로, 같은 트랜잭션 내에서는 같은 Entity를 반환하도록 보장하며, 이를 통해 트랜잭션 내에서 데이터 일관성을 유지할 수 있습니다.
  2. 쓰기 지연: 영속성 컨텍스트는 트랜잭션을 커밋할 때까지 쓰기 지연 SQL 저장소에 저장된 쿼리를 데이터베이스에 보낼 것입니다. 이를 통해 네트워크 비용을 줄일 수 있고, 필요한 시점에만 데이터베이스에 접근할 수 있습니다.
  3. 변경 감지: 영속성 컨텍스트는 트랜잭션을 커밋하는 시점에 1차 캐시에 있는 Entity와 스냅샷을 비교하여 변경사항을 감지(Dirty Checking)하고, 이를 데이터베이스에 반영합니다. 이를 통해 개발자가 별도로 업데이트 쿼리를 작성할 필요 없이 Entity의 상태 변경만으로 데이터베이스와 동기화를 수행할 수 있습니다.
  4. 지연 로딩: 영속성 컨텍스트는 필요한 시점에 데이터를 로딩하는 지연 로딩을 지원합니다. 이를 통해 성능 최적화를 할 수 있습니다.

따라서 영속성 컨텍스트는 JPA 핵심 기능을 수행하며, 이를 사용함으로써 개발자는 객체 지향 프로그래밍에 집중하고, JPA 데이터 접근과 트랜잭션 관리를 대신해주기 때문에 생산성을 향상시킬 있습니다.

 

2. JPA에서 1차 캐시와 2차 캐시의 차이는 무엇인가요?

 

1차 캐시:

  • 1차 캐시는 영속성 컨텍스트 내부에 존재하는 캐시로서, Entity Manager가 관리하는 영역입니다. 한 개의 트랜잭션 범위에서만 동작하며, 트랜잭션을 시작하고 커밋하기까지의 범위에서 Entity를 관리합니다.
    Entity Manager에서 조회한 Entity는 1차 캐시에 저장되고, 이후 같은 Entity를 조회하려 하면 1차 캐시에서 우선적으로 조회하므로 데이터베이스 접근을 줄일 수 있습니다. 또한, 트랜잭션 커밋 시점에 변경 감지(Dirty Checking)를 통해 데이터베이스에 적절한 쿼리를 전송합니다.

2차 캐시:

  • 2차 캐시는 여러 트랜잭션과 여러 세션, 즉 여러 영속성 컨텍스트 간에 공유되는 캐시입니다. 이는 애플리케이션의 성능을 향상시키기 위한 전략으로, 자주 접근되는 데이터를 메모리에 보관하여 데이터베이스 접근을 최소화합니다.
    2차 캐시는 Entity Manager 간에 공유되므로, 다른 트랜잭션에서 이미 로딩된 Entity에 대한 정보를 재사용할 수 있습니다. 그러나 모든 Entity가 2차 캐시에 적합한 것은 아니며, 주로 읽기가 많고 변경이 잘 일어나지 않는 데이터에 대해 사용됩니다.
    2차 캐시는 JPA 표준 스펙에는 포함되어 있지 않지만, 대부분의 JPA 구현체(하이버네이트, EclipseLink 등)에서 지원하는 기능입니다.

따라서, 1 캐시와 2 캐시는 공통적으로 데이터베이스 접근을 최소화하여 애플리케이션의 성능을 향상시키는 역할을 하지만, 범위와 사용되는 상황에 있어서 차이가 있습니다.

 

더보기

1차 캐시는 사장님이 하루 동안 팔린 상품의 정보를 기록하는 메모장과 같습니다. 즉, 그날그날의 거래 내용을 잠시 기록해두는 곳입니다. 만약 오후에 같은 상품이 다시 팔리면, 아침에 기록해둔 정보를 참고하여 판매 수량을 늘리거나 재고를 확인할 수 있겠죠. 하지만 이 메모장은 하루가 끝나면 초기화되고 다음 날을 위해 새롭게 시작합니다.

이와 달리, 2차 캐시는 사장님이 매일의 판매 내역을 정리하여 1년 동안 쌓아두는 대형 서랍장과 같습니다. 이 서랍장에서는 지난 1년 동안 어떤 상품이 얼마나 팔렸는지, 어느 시즌에 어떤 상품이 잘 팔렸는지 등의 정보를 찾을 수 있습니다. 이런 정보는 상품 주문이나 마케팅 전략 등에 도움이 됩니다. 이 서랍장의 정보는 오래 보관되어 언제든 참고할 수 있습니다.

여기서 중요한 점은, 가지 캐시 모두 상품 판매 정보를 저장하고 있지만, 사용 목적과 저장 범위, 지속 시간이 다르다는 것입니다. 이처럼 JPA에서 1 캐시는 트랜잭션(하루의 거래) 동안 일시적으로 정보를 저장하고, 2 캐시는 여러 트랜잭션(1 동안의 거래) 걸친 정보를 보관합니다.

 

3. JPA의 트랜잭션 관리에 대해 설명해주세요.

 

 

JPA(Java Persistence API)는 자바에서 데이터베이스와의 상호작용을 단순화하고 객체 지향적으로 관리할 수 있는 API입니다. JPA의 트랜잭션 관리는 데이터의 일관성을 보장하며, 작업의 원자성(Atomicity)을 유지하는데 중요한 역할을 합니다.

트랜잭션은 하나의 작업 단위로, 이 작업들은 모두 성공하거나 모두 실패해야 합니다. 즉, 트랜잭션 내의 모든 변경은 모두 커밋되거나 롤백되어야 합니다.

ex. JPA에서 트랜잭션의 시작과 종료는 EntityTransaction 인터페이스의 begin() 및 commit() 메서드를 통해 수행됩니다. 롤백은 rollback() 메서드를 사용하여 수행합니다.

JPA 트랜잭션 관리는 이처럼 작업의 원자성을 보장하며, 이를 통해 데이터의 무결성과 일관성을 유지합니다. 또한, Spring Framework 함께 사용할 경우 @Transactional 어노테이션을 통해 선언적 트랜잭션 관리를 있습니다. 이를 통해 코드의 가독성을 높이고, 안전하게 트랜잭션을 관리할 있습니다.

 

더보기

JPA에서 트랜잭션이란, 여러 데이터베이스 작업들이 모두 성공하거나 모두 실패하도록 보장하는 하나의 작업 단위를 말합니다. 이런 트랜잭션을 사용하면 데이터의 정확성을 보장할 수 있어요.

예를 들어, 당신이 은행에서 돈을 송금한다고 생각해봅시다. 송금 과정은 크게 두 단계로 나눠집니다. 첫째, 당신의 계좌에서 돈을 빼는 것. 둘째, 받는 사람의 계좌에 돈을 더하는 것. 이 두 단계 중 하나라도 실패하면 큰 문제가 발생하겠죠. 따라서 이 두 단계는 하나의 트랜잭션으로 묶여야 합니다.

JPA는 이런 트랜잭션을 관리해줍니다. 코드로 보면, begin()을 통해 트랜잭션을 시작하고, 모든 작업이 성공적으로 끝나면 commit()을 통해 변경 사항을 데이터베이스에 반영합니다. 만약 중간에 어떤 문제가 발생하면 rollback()을 통해 모든 작업을 원래 상태로 돌려놓습니다.

이렇게 JPA 트랜잭션 관리를 통해 여러 작업을 하나로 묶고, 작업들이 모두 성공하거나 모두 실패하도록 보장할 있습니다. 이는 데이터의 정확성을 유지하는데 매우 중요합니다.

 

2023.05.19 - [Mockterview] - 더티체킹 (Dirty Checking)

1. ORM(Object-Relational Mapping) :

객체 지향 프로그래밍 언어와 관계형 데이터베이스 간에 호환되지 않는 데이터를 변환하는 프로그래밍 기법입니다. 이는 객체 지향 프로그래밍 언어에서 사용하는 "객체"와 관계형 데이터베이스에서 사용하는 "테이블" 간의 차이를 극복하려는 것입니다. 이 둘 사이에는 패러다임의 불일치 문제가 발생하는데, 다음과 같은 몇 가지 주요 이슈가 있습니다:

더보기
  1. 상속: 객체 지향 프로그래밍에서는 클래스 간의 상속이 가능하며 이를 통해 코드 재사용과 다형성을 구현합니다. 그러나 관계형 데이터베이스에서는 이러한 상속 개념이 존재하지 않습니다.
  2. 연관성: 객체 지향 프로그래밍에서는 객체 간에 다양한 관계가 있을  있습니다(1:1, 1:N, N:M ). 하지만 관계형 데이터베이스에서는 이러한 관계를 직관적으로 표현하기 어렵습니다.
  3. 데이터 타입: 객체 지향 프로그래밍에서는 사용자 정의 데이터 타입을 만들  있지만, 관계형 데이터베이스에서는 제한된 데이터 타입만 제공합니다.
  4. 동일성과 동등성: 객체 지향 프로그래밍에서는  객체의 동일성(identity) 동등성(equality) 다르지만, 관계형 데이터베이스에서는  둘을 구분하지 않습니다.

** 동일성(Identity): 두 객체가 동일하다는 것은, 그들이 메모리 상에서 동일한 위치에 있음을 의미합니다. 즉, 두 참조가 실제로 동일한 객체를 가리키고 있을 때, 이들은 동일하다고 말합니다. Java에서는 == 연산자를 이용해 두 객체의 동일성을 확인할 수 있습니다.

** 동등성(Equality): 반면에 두 객체가 동등하다는 것은, 그들이 서로 다른 메모리 위치에 있을 수 있지만, 그들의 속성이나 상태가 같음을 의미합니다. Java에서는 .equals() 메서드를 이용해 두 객체의 동등성을 확인할 수 있습니다.

 

하지만 관계형 데이터베이스에서는 이러한 개념이 없습니다. 데이터베이스 테이블의 행은 고유한 식별자(보통 "Primary Key"라고 부릅니다) 가지며, 식별자는 행의 동일성과 동등성을 모두 보장합니다. , 식별자가 같다면 행은 동일하며 동등하다고 봅니다. 이는 객체 지향 프로그래밍과 데이터베이스 사이의 중요한 패러다임 불일치 하나입니다.

밀도(Granularity) 문제:

  • 객체 지향: 객체는 다양한 크기와 복잡도를 가질 수 있습니다. 커스텀 데이터 타입을 쉽게 만들 수 있습니다.
  • 관계형 데이터베이스: 테이블은 주로 기본 데이터 타입을 사용합니다. 사용자 정의 타입(User Defined Type, UDT)도 가능하지만, 일반적으로 추천하지 않습니다.

서브타입(Subtype) 문제:

  • 객체 지향: 상속 구조를 쉽게 만들 수 있으며, 이로 인해 다형성이 가능합니다.
  • 관계형 데이터베이스: 테이블에는 상속이라는 개념이 없습니다. 표준 SQL에서는 다형적인 관계를 표현할 수 있는 방법이 없습니다.

식별성(Identity) 문제:

  • 객체 지향: 레퍼런스 동일성(==)과 인스턴스 동일성(equals() 메서드)을 통해 객체의 동일성을 판단합니다.
  • 관계형 데이터베이스: 주키(Primary Key)를 통해 행의 동일성을 판단합니다.

관계(Association) 문제:

  • 객체 지향: 객체는 레퍼런스를 통해 다른 객체와 관계를 맺을 수 있습니다. 다대다 관계도 가능하며, 이 관계에는 '방향'이 존재합니다.
  • 관계형 데이터베이스: 외래키(Foreign Key)를 사용하여 관계를 표현합니다. '방향'이라는 개념이 없으며, 다대다 관계를 직접 표현할 수 없습니다. 대신, 조인 테이블을 사용해 두 개의 1대다 관계로 변환해야 합니다.

데이터 내비게이션(Navigation) 문제:

  • 객체 지향: 객체는 레퍼런스를 이용해 다른 객체로 이동할 수 있으며, 컬렉션을 순회할 수 있습니다.
  • 관계형 데이터베이스: 데이터베이스에서 릴레이션을 조회할 때 객체 지향처럼 순차적으로 접근하는 것은 매우 비효율적입니다. 따라서 SQL의 JOIN 연산을 사용하여 한 번에 여러 테이블을 조회합니다.

https://knoc-story.tistory.com/m/90

 

이러한 패러다임 불일치는 객체-관계 매핑(Object-Relational Mapping, ORM) 프레임워크가 해결하려는 문제입니다.
JPA(Java Persistence API)와 같은 ORM 프레임워크는 이러한 차이점을 최소화하고, 객체 지향적인 코드를 작성하면서도 관계형 데이터베이스의 기능을 효율적으로 사용할 수 있도록 도와줍니다.

ORM이 이 패러다임 불일치 문제를 어떻게 해결하는지

  1. 밀도(Granularity) 문제: ORM 복잡한 객체를 여러 테이블에 나눠 저장하거나, 반대로 여러 테이블의 데이터를 하나의 객체에 매핑하는 기능을 제공합니다.
  2. 서브타입(Subtype) 문제: ORM 상속 관계를 데이터베이스 스키마에 매핑하는 전략을 제공합니다. 예를 들어, 각각의 클래스를 별도의 테이블로 매핑하거나, 테이블에 모든 클래스를 매핑하는 등의 전략이 있습니다.
  3. 식별성(Identity) 문제: ORM 같은 주키를 가진 엔티티가 같은 Java 객체를 참조하도록 관리해주며, 이를 Identity Map 패턴이라고 부릅니다.
  4. 관계(Association) 문제: ORM 객체 간의 관계를 테이블 간의 관계로 매핑해줍니다. 그리고 다대다 관계를 관리하기 위해 내부적으로 조인 테이블을 사용합니다.
  5. 데이터 내비게이션(Navigation) 문제: ORM 필요한 데이터만 효율적으로 로드하는 여러 전략을 제공합니다. 예를 들어, 지연 로딩(Lazy Loading) 전략을 사용하면 실제 데이터가 필요한 시점까지 데이터 로드를 미룰 있습니다. 이를 통해 데이터베이스의 부하를 줄이고 성능을 향상시킬 있습니다.

즉, 패러다임 불일치에서 기인한 문제들과, 반복적이고 번거로운 어플리케이션 단에서의 쿼리 작업을 줄여주기 위해서 ORM(객체 관계 매핑)기술들이 등장

 

2. JPA(Java Persistence API) :

Java Persistence API (JPA)는 자바 개발자들이 데이터를 관리하는 방법을 표준화한 인터페이스입니다. JPA는 관계형 데이터베이스의 데이터를 쉽게 사용하게 해주는 기술 중 하나이며, 자바 애플리케이션에서 객체와 관계형 데이터베이스 테이블 간의 매핑을 처리해줍니다.

JPA의 주요 특징은 다음과 같습니다:

  1. ORM (Object-Relational Mapping): JPA 자바 애플리케이션에서 사용하는 객체와 관계형 데이터베이스의 테이블 간의 매핑을 처리합니다. 이로 인해 개발자는 데이터베이스의 구조나 SQL 쿼리에 대해 신경 필요가 적어집니다.
  1. 추상화와 Loose Coupling: JPA는데이터베이스와애플리케이션사이의결합도를낮춥니다. 이로인해개발자는특정데이터베이스에종속되지않고, 다양한데이터베이스시스템과상호작용할수있습니다.
  2. 표준화: JPA Java EE 표준의 일부이며, 이에 따라 다양한 JPA 구현체(Hibernate, EclipseLink, OpenJPA ) 있습니다. 구현체들은 JPA 표준 인터페이스를 준수하므로, 개발자는 구현체를 쉽게 교체할 있습니다.
  3. 자동화된 CRUD 연산: JPA 데이터베이스의 Create, Read, Update, Delete (CRUD) 연산을 자동화합니다. Entity 클래스를 만들고, 해당 Entity 어노테이션을 추가함으로써 데이터베이스 테이블과 객체를 매핑할 있습니다.
  4. JPQL (Java Persistence Query Language): SQL과비슷한구문을가진 JPQL을제공합니다. JPQL은객체지향적인쿼리언어이며, SQL 쿼리를직접작성하는것보다효과적인쿼리를작성할수있게돕습니다.
  5. Caching: JPA는일차캐시와이차캐시를지원합니다. 이러한캐싱메커니즘을통해애플리케이션의성능을향상시킬수있습니다.
  • JPA를 사용하면 개발자는 비즈니스 로직에 집중하면서도, 객체-관계형 매핑의 복잡성을 추상화 시킬 수 있습니다. 그러나 JPA의 동작 방식과 한계를 이해하고 있지 않다면, JPA는 예상치 못한 문제를 야기할 수 있습니다.
  • 예를 들어, 즉시 로딩(Eager Loading)과 지연 로딩(Lazy Loading) 간의 차이를 이해하지 못하면, 성능 문제를 일으킬 수 있습니다. 또한, JPA는 SQL을 직접 다루는 것보다 유연성이 떨어질 수 있으며, 복잡한 쿼리를 작성하기 어렵다는 단점도 있습니다.
  • 이런 이유로, JPA를 사용할 때에는 이러한 특성과 한계를 잘 이해하고, 필요한 경우에는 JPA를 사용하지 않고 직접 SQL을 사용하는 등의 대안을 고려해야 합니다. 또한, JPA는 자동화된 동작을 수행하기 때문에, 그 동작 원리를 잘 이해하고 사용하는 것이 중요합니다.
  • 이런 한계를 이해하고 적절히 대응하는 것이 중요하지만, 그럼에도 불구하고 JPA는 객체 지향 프로그래밍과 관계형 데이터베이스 사이의 간극을 줄여줄 수 있는 강력한 도구입니다. JPA를 통해 개발자는 복잡한 데이터베이스 연산을 간소화하고, 유지보수를 용이하게 할 수 있습니다.

Spring Data JPA 의 Query Methods : 

https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods

 

 

2023.05.25 - [Spring] - JPA(Java Persistence API), ORM(Object-Relational Mapping) pt.2

트리(tree)와 그래프(graph)는 노드들을 연결하는 간선을 이용하여 데이터를 구성하는 방식입니다. 

 

1. 트리(Tree) : 

트리는 비선형 자료구조로서 노드들이 계층적으로 연결되어 있습니다. 트리의 특징은 다음과 같습니다:

  1. 트리는 루트(root) 노드에서 시작하여 자식 노드를 통해 연결되는 구조를 가집니다.
  2. 각 노드는 자식 노드를 가질 수 있으며, 하나의 부모 노드에 연결됩니다. 즉, 트리는 순환 구조(cycle)를 가질 수 없습니다.
  3. 트리는 이진 트리, AVL 트리, B-트리 등 다양한 형태를 가질 수 있습니다.
  4. 트리는 계층적인 데이터를 표현하는 데 유용하게 사용됩니다. 예를 들어, 파일 시스템, 조직도 등이 트리 구조로 표현될 수 있습니다.

이진 트리(Binary Tree)

이진 트리는 각 노드가 최대 두 개의 자식 노드를 가질 수 있는 트리 구조입니다. 이진 트리의 자식 노드들은 각각 왼쪽 자식과 오른쪽 자식이라고 불립니다. 이진 트리의 중요한 특성 중 하나는 이진 트리의 높이(height)가 작을수록 효율적인 연산이 가능하다는 것입니다.

AVL 트리

AVL 트리는 균형 이진 탐색 트리의 한 종류입니다. AVL 트리는 모든 노드에서 왼쪽 서브트리와 오른쪽 서브트리의 높이 차이가 최대 1이라는 특징을 가집니다. 이 특성 덕분에 트리가 한쪽으로 치우쳐 자라는 것을 방지하고, 트리의 높이를 최소화하여 검색, 삽입, 삭제 등의 연산이 빠르게 수행되도록 합니다.

B-트리

B-트리는 이진 트리를 일반화한 자료구조로, 각 노드가 두 개 이상의 자식을 가질 수 있습니다. B-트리는 특히 디스크에 데이터를 저장하는 시스템에서 유용하게 사용됩니다. B-트리는 모든 잎 노드가 같은 깊이를 가지는 특성과 노드 내부의 키가 정렬된 상태를 유지하는 특성을 가지며, 디스크 접근을 최소화함으로써 큰 데이터 집합에 대한 검색, 삽입, 삭제를 효율적으로 수행할 수 있습니다.

 

B-트리의 변형 하나로 B+ 트리 있는데, 이는 데이터베이스 시스템이나 파일 시스템에서 자주 사용됩니다. B+ 트리는 모든 값들이 노드에만 존재하며, 내부 노드들은 값과 자식 노드를 가리키는 포인터만을 저장합니다. 구조 덕분에 B+ 트리는 데이터 집합에 대한 순차적인 접근을 더욱 효율적으로 처리할 있습니다.

 

잎 노드(Leaf Node)는 트리 구조에서 자식 노드가 없는 노드를 말합니다. 다른 말로 말하면, 잎 노드는 트리의 가장 끝에 위치한 노드들로서 부모 노드에게서 자식 노드를 가지지 않습니다.

잎 노드는 트리의 가장 하위에 위치하며, 더 이상의 자식 노드를 가질 수 없는 노드입니다. 이러한 특성으로 인해 잎 노드는 트리의 종단 노드라고도 불립니다.

이진 트리의 경우, 잎 노드는 왼쪽 자식과 오른쪽 자식이 모두 없는 노드입니다. AVL 트리, B-트리 등 다른 트리 구조에서도 잎 노드는 동일한 개념으로 적용됩니다.

잎 노드는 트리의 마지막 단계에 위치하여 트리의 가장 끝에 있는 데이터를 나타내는 역할을 합니다. 일반적으로 잎 노드에는 실제 데이터가 저장되며, 트리 구조에서 검색 작업을 수행할 때 이 잎 노드를 통해 실제 데이터를 찾아갈 수 있습니다.

트리의 구조는 루트 노드에서부터 노드까지의 경로로 이동하며 데이터를 탐색하는데, 이때 노드가 트리의 종단을 나타내므로 검색 작업이 완료되는 지점입니다.

B 트리와 B+ 트리는 데이터베이스와 파일 시스템에서 사용되는 데이터 구조로서, 특히 검색과 정렬 작업을 효율적으로 수행하기 위해 설계되었습니다. B 트리와 B+ 트리는 유사한 구조를 가지지만 몇 가지 중요한 차이점이 있습니다.

B 트리:

  • B 트리는 자식 노드를 가리키는 포인터를 내부 노드와 리프 노드에 모두 가지고 있습니다.
  • 각 노드는 키-값 쌍을 저장할 수 있습니다.
  • 리프 노드에는 키 값과 관련된 데이터가 직접 저장됩니다.
  • B 트리는 키 값에 대한 정렬된 구조를 유지하며, 특정 키를 검색하거나 범위 검색을 수행하는 데 효율적입니다.
  • 데이터의 삽입과 삭제에 대한 재배치 작업이 필요할 수 있습니다.

B+ 트리:

  • B+ 트리는 리프 노드에만 키 값과 관련된 데이터를 저장합니다.
  • 내부 노드는 키 값만을 저장하고, 자식 노드를 가리키는 포인터만을 갖습니다.
  • 리프 노드는 연결 리스트로 구성되어 있어 범위 검색에 용이합니다.
  • 키 값은 정렬된 상태를 유지하며, 리프 노드를 순차적으로 접근할 수 있습니다.
  • B+ 트리는 범위 검색과 정렬 작업에 효율적이며, 데이터베이스 인덱스와 같은 용도로 널리 사용됩니다.
  • 데이터의 삽입과 삭제에 대한 재배치 작업이 필요할 수 있습니다.

요약하면, B 트리와 B+ 트리는 키-값 쌍을 저장하고 검색 작업을 효율적으로 수행하기 위한 트리 기반의 데이터 구조입니다. B 트리는 내부 노드와 리프 노드 모두 키-값 쌍을 저장하고, B+ 트리는 리프 노드에만 값을 저장합니다. B+ 트리는 범위 검색과 정렬 작업에 특히 유용하며, 데이터베이스와 파일 시스템에서 널리 사용됩니다.

 

2. 그래프(Graph) : 

그래프는 노드(node) 또는 정점(vertex)와 이들을 연결하는 간선(edge)으로 구성된 자료구조입니다. 그래프의 특징은 다음과 같습니다:

  1. 그래프에서 노드들은 서로 독립적일 수 있으며, 간선을 통해 서로 다른 노드와 연결될 수 있습니다.
  2. 그래프는 순환 구조를 가질 수 있습니다. 즉, 트리와 달리, 그래프에서는 한 노드에서 시작하여 다른 노드들을 거쳐 자신으로 다시 돌아오는 경로가 있을 수 있습니다.
  3. 그래프는 방향성(directed)을 가질 수도, 가지지 않을 수도 있습니다. 방향성을 가지는 그래프를 '방향 그래프(directed graph)'라고 하며, 간선에 방향이 있습니다. 방향성을 가지지 않는 그래프를 '무방향 그래프(undirected graph)'라고 하며, 간선에 방향이 없습니다.
  4. 그래프는 네트워크, 웹 페이지의 하이퍼링크, 소셜 네트워크 등 다양한 분야에서 사용됩니다.

요약하면, 트리는 그래프의 종류입니다. 트리는 순환이 없는 연결된 무방향 그래프 또는 방향 그래프로 볼 수 있습니다. 트리의 특징 중 하나는 모든 노드 사이에 하나의 경로만 존재한다는 것입니다. 이는 트리가 순환구조를 갖지 않음을 의미합니다.

반면에 그래프는 노드와 노드를 연결하는 간선으로 구성되며, 이 간선은 방향을 가질 수도, 가지지 않을 수도 있습니다. 또한 그래프는 순환 구조를 가질 수 있으며, 서로 다른 두 노드 사이에 여러 경로가 존재할 수 있습니다.

따라서 트리는 계층적이며 순서와 구조가 중요한 데이터를 표현하는 사용되며, 그래프는 복잡한 네트워크나 시스템을 표현하는 사용됩니다.

더보기

트리(Tree)에 대한 예시

가족 관계도를 생각해보시면 도움이 될 것입니다. 한 가족의 가계도를 그릴 때, 보통 가장 위에 부모님을 두고 그 아래에 그들의 자녀들을 배치하죠. 그 자녀들 중에도 다시 자신의 자녀가 있다면 그 아래에 그리게 됩니다. 이처럼 부모-자녀간의 관계를 계층적으로 나타낼 때 트리 구조를 사용합니다. 이 구조에서 자식들은 각각의 부모로부터 분기하고, 부모로부터 자식으로 가는 경로는 딱 하나입니다.

그래프(Graph)에 대한 예시

그래프의 경우에는 도시 간의 비행 경로를 생각해보시면 좋습니다. 각 도시를 노드로, 그리고 두 도시 간의 비행 경로를 간선으로 생각해 볼 수 있습니다. 이런 경우, 한 도시에서 다른 도시로 가는 방법은 여러 가지가 있을 수 있고, 도시 간의 비행 경로는 순환할 수도 있습니다. 이러한 관계를 나타낼 때 그래프 구조를 사용합니다.

트리와 그래프의 주요 차이점은, 트리는 계층적이고 노드 간에 하나의 경로만 존재하는 반면, 그래프에서는 노드 간에 여러 경로가 존재할 있고 순환이 있을 있다는 입니다. 구조는 각자의 특성에 맞게 서로 다른 문제를 해결하는 사용됩니다.

'Mockterview' 카테고리의 다른 글

인덱스(Index), Composite(복합)인덱스 pt.2  (0) 2023.05.24
DI와 IoC, Bean pt.2  (0) 2023.05.23
이분탐색(Binary Search)의 시간복잡도 = O(log n)  (0) 2023.05.23
Index(인덱스), B-tree, Hash pt.1  (0) 2023.05.19
Annotation(@)  (0) 2023.05.19

이분 탐색(Binary Search)은 정렬된 리스트에서 특정한 값을 빠르게 찾아내는 탐색 알고리즘입니다. 이 방법은 리스트의 중간값을 선택하고, 찾고자 하는 값과 중간값을 비교해서 대상을 찾습니다.

이분 탐색의 기본 원리는 다음과 같습니다:

  1. 정렬된 리스트의 중간에 위치한 원소를 선택합니다.
  2. 만약 선택한 원소가 찾고자 하는 값과 같다면, 탐색을 종료합니다.
  3. 선택한 원소가 찾고자 하는 값보다 크다면, 중간 원소의 왼쪽 하위 리스트에서 탐색을 계속합니다.
  4. 선택한 원소가 찾고자 하는 값보다 작다면, 중간 원소의 오른쪽 하위 리스트에서 탐색을 계속합니다.
  5. 리스트에 더 이상 탐색할 원소가 없다면, 탐색을 종료합니다.

이분 탐색의 시간 복잡도는 O(log n)입니다. 그 이유는 이분 탐색에서는 매번 탐색 범위를 절반으로 줄이기 때문입니다. 이 때문에 이분 탐색은 정렬된 리스트에서 특정 값을 찾는 데 매우 효율적인 방법이며, 큰 데이터 집합에서도 빠르게 동작합니다.

다만, 이분 탐색을 사용하려면 리스트가 미리 정렬되어 있어야 하며, 이렇게 정렬하는 데는 시간이 필요하다는 점을 주의해야 합니다. 때문에 이분 탐색은 정렬된 데이터에 대해 특정 값을 반복적으로 찾아야 하는 상황에서 가장 유용합니다.

더보기

이분 탐색의 원리를 이해하기 위한 간단한 예시 : 

정렬된 숫자 배열 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]에서 숫자 8을 찾는 상황을 생각해 보겠습니다.

  1. 우선, 리스트의 중간 값인 5를 확인합니다.
  2. 찾고자 하는 숫자 8은 중간 값 5보다 크므로, 이제 우리는 5보다 큰 숫자들만 있는 오른쪽 하위 리스트 [6, 7, 8, 9, 10]를 탐색하면 됩니다.
  3. 이 하위 리스트에서도 중간 값 8을 확인합니다. 이번에는 찾고자 하는 숫자와 중간 값이 일치하므로, 탐색을 여기서 종료하고 8의 위치를 반환합니다.

이처럼 이분 탐색은 단계에서 리스트의 절반씩 불필요한 부분을 제거함으로써 탐색 범위를 빠르게 줄여나갑니다. 따라서 데이터의 양이 많아져도 빠르게 원하는 값을 찾을 있습니다. 이를테면, 위의 예제에서 리스트의 크기가 1,000개든 1,000,000개든 원하는 숫자를 찾기까지는 로그 시간만큼이 걸리게 됩니다.

 

이분 탐색(binary search)을 사용하려면 데이터가 미리 정렬되어 있어야 합니다. 이는 이분 탐색의 원리가 "중간 요소를 기준으로 검색 대상을 반으로 줄여나간다"는 데 있어서, 이 '중간' 요소를 정확히 선택하기 위해서는 데이터가 정렬되어야 한다는 점에서 비롯됩니다.

그러나 데이터를 정렬하는 것 역시 시간과 리소스를 필요로 하기 때문에 다음과 같은 상황을 고려해볼 수 있습니다:

  1. 데이터의 변경 빈도 : 데이터가 자주 변경되는 경우, 데이터를 매번 정렬하면 시간이 많이 소요될 수 있습니다. 따라서 이 경우에는 정렬된 구조를 유지하는 것이 효율적일 수 있습니다. 예를 들어, 트리 기반의 자료구조(예: 이진 탐색 트리, AVL 트리, 레드-블랙 트리 등)는 데이터의 삽입, 삭제가 일어날 때 자동으로 재배열되어 정렬된 상태를 유지합니다.
  2. 검색이 자주 일어나는지 : 검색이 자주 일어나고, 검색 대상의 데이터가 매우 크다면, 이분 탐색은 큰 이점을 가져다 줄 수 있습니다. 이 경우에는 데이터를 한 번 정렬한 뒤에 이분 탐색을 사용하여 검색하는 것이 효율적일 것입니다.
  3. 메모리 사용량 : 정렬된 복사본을 유지하는 것은 추가적인 메모리를 필요로 합니다. 메모리가 제한적인 경우, 이것이 문제가 될 수 있습니다.
  4. 대안적인 탐색 방법의 사용 : 해시 테이블 등의 다른 자료구조를 사용하면, 정렬 없이도 빠른 검색이 가능할 수 있습니다. 하지만 이러한 방법도 데이터의 특성에 따라 장단점이 있습니다.

즉, 이분 탐색의 사용 여부는 데이터의 특성, 애플리케이션의 요구 사항, 사용 가능한 리소스 등을 고려해 결정해야 합니다.

더보기

* 트리 기반의 자료구조 : 

 데이터를 트리(tree)라는 구조로 저장하고 관리하는 방식을 말합니다. 여기서 '트리'는 노드(node)와 그 노드들을 연결하는 간선(edge)로 이루어진 그래프의 한 종류를 말하는데, 이는 일반적으로 우리가 '나무'라고 생각하는 구조와 비슷하게 생겼습니다.

트리 기반 자료구조의 몇 가지 종류를 살펴보겠습니다:

  1. 이진 탐색 트리(Binary Search Tree, BST): BST는 각 노드의 왼쪽 하위 트리에는 해당 노드의 값보다 작은 값들을, 오른쪽 하위 트리에는 해당 노드의 값보다 큰 값들을 가지는 이진 트리를 말합니다. 이 특성은 탐색, 삽입, 삭제 연산을 효율적으로 수행할 수 있게 합니다.
  2. AVL 트리: AVL 트리는 이진 탐색 트리의 한 종류로, 트리의 균형을 유지하도록 설계되었습니다. AVL 트리에서는 각 노드의 두 하위 트리의 높이 차이가 최대 1이 되도록 합니다. 이렇게 함으로써 트리가 한 쪽으로 치우쳐 자라는 것을 방지하고, 탐색 시간을 최적화합니다.
  3. 레드-블랙 트리(Red-Black Tree): 레드-블랙 트리 역시 이진 탐색 트리의 한 종류이며, 트리의 균형을 유지하도록 설계되었습니다. 레드-블랙 트리는 노드에 색깔(레드 혹은 블랙)을 부여함으로써 특정 규칙을 만족시키고, 이 규칙을 통해 트리의 균형을 유지합니다. 이 규칙을 통해 삽입, 삭제 시에도 트리의 균형이 유지되도록 하고, 따라서 탐색 시간을 최적화합니다.

이런 트리 기반의 자료구조들은 모두 탐색, 삽입, 삭제 연산을 로그 시간 복잡도로 처리할 있도록 돕습니다. 

* 해시 테이블(hash table), 혹은 해시 맵(hash map) : 

키(key)를 값(value)에 매핑하는 자료 구조 중 하나입니다. 해시 테이블은 '해시 함수(hash function)'라는 특별한 함수를 사용하여 키를 해시(hash)로 변환하며, 이 해시를 배열의 인덱스로 사용하여 값을 저장하거나 검색합니다.

이런 방식은 데이터를 빠르게 검색할 수 있게 해줍니다. 즉, 주어진 키에 대응하는 값을 찾을 때, 전체 데이터를 순회할 필요 없이, 해시 함수를 사용해 바로 해당 값을 찾을 수 있습니다. 따라서 해시 테이블의 검색, 삽입, 삭제 연산의 시간 복잡도는 평균적으로 O(1)입니다.

하지만 해시 테이블도 몇 가지 주의할 점이 있습니다:

  1. 해시 충돌(hash collision): 서로 다른 키가 같은 해시를 가지게 되는 경우, 즉 해시 함수가 같은 출력을 내는 경우를 말합니다. 이런 상황은 해시 테이블의 효율성을 저하시킬 수 있습니다. 이를 해결하기 위한 여러 가지 방법(예: 개방 해싱, 폐쇄 해싱 등)이 있습니다.
  2. 메모리 사용: 해시 테이블은 효율적인 검색을 위해 추가적인 메모리를 사용합니다. 따라서 메모리가 제한적인 환경에서는 이 부분을 고려해야 합니다.
  3. 순서 보장: 해시 테이블은 키의 순서를 보장하지 않습니다. 즉, 데이터를 순서대로 순회할 필요가 있는 경우에는 다른 자료 구조를 고려해야 합니다.

이런 특성 때문에, 해시 테이블은 키를 통해 빠르게 데이터를 검색하거나 수정해야 하는 경우에 매우 유용합니다.

 

'Mockterview' 카테고리의 다른 글

DI와 IoC, Bean pt.2  (0) 2023.05.23
트리(tree)와 그래프(graph)  (0) 2023.05.23
Index(인덱스), B-tree, Hash pt.1  (0) 2023.05.19
Annotation(@)  (0) 2023.05.19
더티체킹 (Dirty Checking)  (0) 2023.05.19

데이터베이스는 데이터를 “효율적으로 성능 좋게” 다루기 위해 존재합니다.

즉 더 많이 저장하기 위해서가 아니라, 저장 조회 수정 삭제등을 더 빠르고 효율적으로 처리하기 위해서, “성능상의 이점”을 얻기 위해서 사용한다고 생각하면 좋을 것 같습니다.

DBMS (Database Management System) : 데이터베이스를 관리하는 소프트웨어

RDBMS (Relational DBMS) : 데이터를 테이블 형태로 표현,  데이터의 중복을 최소화, SQL 언어를 사용하여 데이터를 쉽게 조작가능 

ex.  MySQL, Oracle, MariaDB

 

  • RDBMS는 ‘Relational DBMS’의 약자로 관계형 데이터베이스라고 불립니다.
  • RDBMS는 테이블(table)이라는 최소 단위로 구성되며, 이 테이블은 열(column)과 행(row)으로 이루어져 있습니다.
  • RDBMS의 종류 : MySQL, PostgreSQL, Oracle Database, H2(In-memory DB, 서버가 작동하는 동안에만 내용을 저장하고, 서버가 작동을 멈추면 데이터가 모두 삭제되는 데이터베이스)

SQL(Structured Query Language) :  관계형 데이터베이스에서 데이터를 정의하고 조작하고 제어할 수 있는 표준 언어

** SQL의 분류 

  1. DDL (Data Definition Language) : 카테고리의 SQL 명령어는 데이터베이스의 구조를 생성, 변경, 제거하는데 사용됩니다. 주요 DDL 명령어에는 CREATE (테이블, 인덱스 생성), ALTER (테이블 구조 변경), DROP (테이블, 인덱스 삭제), TRUNCATE (테이블 데이터 삭제) 포함됩니다.
  2. DCL (Data Control Language) : DCL 데이터베이스에 대한 액세스를 제어하는 사용되는 SQL 명령어입니다. 명령어에는 주로 GRANT (권한 부여) REVOKE (권한 회수) 포함됩니다.
  3. DML (Data Manipulation Language) : DML 명령어는 데이터를 추가, 검색, 수정, 삭제하는데 사용됩니다. 주요 DML 명령어에는 INSERT (데이터 삽입), SELECT (데이터 검색), UPDATE (데이터 수정), DELETE (데이터 삭제) 포함됩니다.

** 데이터의 무결성을 보장 (제약조건) 

  1. PRIMARY KEY : 기본 키는 테이블에서 각 레코드를 고유하게 식별하는 역할을 합니다. 이것은 테이블의 각 레코드가 고유해야 함을 보장하며, 따라서 NOT NULL (값이 NULL일 수 없음)과 UNIQUE (값이 중복될 수 없음) 제약조건을 모두 만족합니다. 이 기능은 데이터의 중복을 방지하고, 특정 데이터를 빠르게 찾는 데 도움이 됩니다.
  2. FOREIGN KEY : 외래 키는 다른 테이블에 있는 데이터를 참조하는 데 사용됩니다. 외래 키를 가지는 테이블의 해당 필드는 참조되는 테이블의 기본 키 값을 가지게 됩니다. 이 기능은 데이터 무결성을 보장하며, 관련 데이터가 한 테이블에서 다른 테이블로 일관성있게 이동하도록 합니다. 외래 키가 참조하는 기본 키 값이 변경되거나 삭제될 경우, CASCADE 옵션은 그 변경을 외래 키를 가진 모든 레코드에 자동으로 반영하게 해 줍니다.

** JOIN :

  • ON이라는 키워드를 통  해 기준이 되는 컬럼을 선택하여 2개의 테이블을 합쳐 줍니다.
  • JOIN을 할 때에는 적어도 하나의 컬럼을 서로 공유하고 있어야 하기 때문에 테이블에 외래키가 설정 되어 있다면 해당 컬럼을 통해 JOIN을 하면 해당 조건을 충족할 수 있습니다.
  • JOIN 대개 공유되는 (일반적으로 하나의 테이블의 PRIMARY KEY 다른 테이블의 FOREIGN KEY) 기반하여 이루어집니다. JOIN 사용하면 여러 테이블에 분산된 정보를 번에 가져올 있으므로 데이터 분석이나 보고서 작성 등에 편리합니다.

외래 (FK) 설정하여 JOIN 하는 것이 항상 최선의 선택은 아닙니다. 외래 키는 데이터 무결성을 보장하기 위해 추가적인 연산을 필요로 하며, 이는 시스템의 성능을 저하시키거나, 데이터를 삽입, 수정, 삭제하는 등의 작업을 제약하는 등의 부작용을 가져올 있습니다.

 

  • RDBMS vs NoSql
    • RDBMS
      1. 엑셀과 같은 표의 형태로 데이터가 저장됩니다. 테이블을 만들때 컬럼이 고정되어 있기때문에 데이터가 실제로 저장되면 컬럼을 수정하기가 쉽지 않습니다.
      2. 테이블을 여러개 만들어서 테이블끼리 연결됩니다. 그래서 네이밍에 R(Relation)이 붙습니다.
      3. 제품에는 Oracle, MySql, postgreSQL, Mssql 이 있습니다.
    • NoSql(Not Only sql)
      1. JSON 형태로 데이터가 저장됩니다. 도큐먼트라는 RDBMS의 테이블과 비슷한 곳에 저장됩니다.
      2. 도큐먼트는 생성될때 컬럼이 고정되지 않기 때문에 변경이 용이합니다. 그렇기 때문에 정형화된 데이터 보다는 비정형화된 데이터를 저장하는 용도로 사용합니다.

 

 

 

참고 문헌 : https://inpa.tistory.com/category/DBMS/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4%20%EC%9D%B4%EB%A1%A0

API(application programming interface)란? 

서버의 창구, 웹 API는 클라이언트와 웹 리소스 사이의 게이트웨이라고 생각할 수 있습니다.

다른 소프트웨어 시스템과 통신하기 위해 따라야 하는 규칙을 정의합니다. 개발자는 다른 애플리케이션이 프로그래밍 방식으로 애플리케이션과 통신할 수 있도록 API를 표시하거나 생성합니다.

하나의 "약속" 이자, 서로 다른 어플리케이션 간에 약속한 방식으로 요청을 하면 정해진 결과물, 즉 요청을 받아 응답을 돌려주는 식당의 점원

더보기

인터페이스(interface)는 서로 다른 두 개의 시스템, 장치 사이에서 정보나 신호를 주고받는 경우의 접점이나 경계면이다. 즉, 사용자가 기기를 쉽게 동작시키는데 도움을 주는 시스템을 의미한다. 컴퓨팅에서 컴퓨팅 시스템끼리 정보를 교환하는 공유 경계이다. 이러한 교환은 소프트웨어, 컴퓨터 하드웨어, 주변기기, 사람간에 이루어질 수 있으며, 서로 복합적으로 이루어질 수도 있다.

 한 소프트웨어 애플리케이션(또는 시스템)에서 다른 애플리케이션과 상호작용하는데 사용하는 규약 또는 메커니즘을 의미합니다.

API는 애플리케이션과 서비스 간에 데이터를 교환하고 상호 작용하게 할 수 있는 일련의 함수, 메서드, 규약, 프로토콜을 정의합니다. API를 통해, 개발자들은 다른 애플리케이션의 기능을 활용하거나 운영체제, 데이터베이스, 하드웨어와 같은 저수준 자원에 접근할 수 있습니다.

API는 다양한 종류와 형태로 존재합니다:

  1. 웹 API: HTTP 프로토콜을 통해 서버와 클라이언트 간의 통신을 가능하게 하는 API입니다. RESTful API, GraphQL API 등이 이에 속합니다.
  2. 운영체제 API: 운영체제에서 제공하는 기능에 접근하는데 사용되는 API입니다. 예를 들어, 파일 시스템에 접근하거나 새 프로세스를 생성하는 등의 작업을 수행합니다.
  3. 라이브러리/프레임워크 API: 특정 프로그래밍 언어나 소프트웨어 프레임워크가 제공하는 기능에 접근하는 API입니다. 예를 들어, Java의 Swing API는 그래픽 사용자 인터페이스 구성 요소를 만들기 위해 사용됩니다.
  4. 하드웨어 API: 특정 하드웨어 장치의 기능에 접근하는데 사용되는 API입니다. 예를 들어, GPU의 기능을 활용하기 위한 API인 OpenGL이 있습니다.

이처럼, API 다양한 소프트웨어 구성 요소들이 서로 상호 작용하고 통신하는데 있어 중요한 역할을 합니다. API 없이는 각각의 소프트웨어가 어떻게 통신하고 상호 작용해야 하는지를 개발자가 직접 구현해야 하므로 개발 과정이 복잡해지고 시간이 많이 소요될 있습니다.

 

RESTful API(Representational State Transfer)란? 

웹 서비스의 아키텍처 스타일 중 하나입니다. REST는 자원(resource)을 이름(자원의 표현)으로 구분하여 해당 자원의 상태(정보)를 주고 받는 모든 것을 의미하며, 이는 웹의 장점을 최대한 활용할 수 있는 아키텍처 스타일입니다.

RESTful API는 HTTP 기반으로 필요한 자원에 접근하는 방식을 정의한 인터페이스를 의미합니다. 이 방식은 HTTP의 메소드인 GET, POST, PUT, DELETE 등을 이용하여 CRUD(Create, Read, Update, Delete) 연산을 수행합니다.
RESTful API는 웹 서비스를 구축하는 데 널리 사용되며, 주로 HTTP 메서드(GET, POST, PUT, DELETE 등)를 사용하여 리소스에 접근합니다. 이러한 API는 JSON, XML 등의 형식으로 데이터를 교환

RESTful API의 주요 특징은 다음과 같습니다:

  1. Stateless: 각 요청 간 클라이언트의 컨텍스트가 서버에 저장되지 않습니다. 즉, 각 요청은 독립적이며 서버는 이전 요청을 기억하지 않습니다.
    각 요청은 서버에서 클라이언트의 상태를 변경하는 데 필요한 모든 정보를 포함해야 합니다. 이는 서버가 클라이언트의 상태를 기억할 필요가 없다는 것을 의미하며, 이로 인해 서버의 확장성이 향상
  2. Client-Server: 클라이언트와 서버는 서로 독립적이며 서로의 구현 내용을 알 필요가 없습니다.
    인터페이스가 일관되게 유지되는 한 클라이언트와 서버의 구현이 독립적으로 변경될 수 있다는 것을 의미
  3. Cacheable: 클라이언트는 응답을 캐싱할 수 있어야 합니다. 즉, 재사용 가능한 응답은 캐시 가능함을 명시해야 합니다.
  4. Uniform Interface: API는 일관적인 인터페이스를 가져야 합니다. 이를 통해 API의 단순성과 사용성이 증가하고, 코드의 가독성도 높아집니다.
  5. Layered System: 클라이언트는 실제 서버가 직접 연결된 서버인지, 중간 서버인지 알 수 없습니다. 중간 서버를 사용할 경우 보안, 로드 밸런싱, 공유 캐시 등을 제공할 수 있습니다.
  6. Code-On-Demand (optional): 서버는 클라이언트에게 스크립트를 보내서 기능을 확장할 수 있습니다. 이는 선택적 특성입니다.
더보기

RESTful API는 웹사이트들이 서로 '대화'하는 방법 중 하나입니다. 예를 들어, 웹사이트에 로그인하거나 새로운 게시물을 올릴 때, 그 웹사이트는 보통 RESTful API를 통해 서버와 정보를 주고받습니다.

RESTful API는 우편 배달부와 비슷하게 작동합니다. 웹사이트(또는 다른 종류의 애플리케이션)는 특정 정보를 요청하거나 전달하려면 '편지'(즉, 데이터)를 작성하고, RESTful API는 그 '편지'를 목적지인 서버에 전달합니다. 그런 다음 서버는 요청을 처리하고 필요한 정보가 담긴 '편지'를 다시 API를 통해 웹사이트에 전달합니다.

이런 방식으로, 웹사이트와 서버는 서로 정보를 주고받을 있으며, 과정을 통해 웹사이트는 최신 정보를 유지하고 사용자가 원하는 작업을 수행할 있게 됩니다.

 

"API"는 보통 "Application Programming Interface"의 약자로, 소프트웨어에서 다른 소프트웨어와 통신하도록 설계된 규약이나 도구 모음을 일반적으로 가리킵니다. API는 매우 광범위하며, 다양한 유형과 형태가 있습니다.

한편, "RESTful API"는 특정한 종류의 API입니다. RESTful API는 "REST"(Representational State Transfer)라는 아키텍처 스타일을 따르며, 이는 상태를 가지지 않는(stateless) 통신과 클라이언트-서버 모델, 그리고 일관된 인터페이스 등의 원칙에 기반을 둡니다.

RESTful API는 일반적으로 웹 서비스에서 데이터를 주고받는데 사용되며, 이는 대개 HTTP(Hypertext Transfer Protocol)를 통해 이루어집니다.

요약하면, "API" 일반적인 개념이며, "RESTful API" 그것의 특정한 형태 또는 예시입니다. 따라서 모든 RESTful API API이지만, 모든 API RESTful 것은 아닙니다. RESTful 이외의 API로는 SOAP, GraphQL 등이 있습니다.

 

https://aws.amazon.com/ko/what-is/restful-api/