1. 객체지향 프로그래밍이란 무엇인가요? 그리고 그 주요 특징은 무엇인가요?

객체지향 프로그래밍(Object-Oriented Programming, OOP)은 프로그래밍의 패러다임 중 하나로, 프로그램을 '객체'라는 기본 단위로 구성하고 이러한 객체들이 상호 작용하도록 하는 방식입니다. 각 객체는 데이터(속성)와 그 데이터를 조작하는 방법(메서드)를 포함하고 있습니다. 패러다임의 주요 특징은 다음과 같습니다:

  1. 캡슐화(Encapsulation): 객체의 데이터와 메서드를 함께 묶는 것을 의미하며, 객체의 상태를 직접 변경하지 못하게 하고 메서드를 통해서만 접근을 허용하는 방식입니다. 이를 통해 데이터의 안전성을 보장하며, 구현 내용을 숨기고 사용자에게는 필요한 기능만을 제공하는 인터페이스를 제공합니다.
  2. 상속(Inheritance): 상속은 클래스 간에 코드를 재사용하고 계층 구조를 형성하는 데 사용됩니다. 기존 클래스의 속성과 메서드를 새 클래스가 상속받아 사용할 수 있으며, 이를 통해 코드 중복을 줄이고 유지 관리를 용이하게 할 수 있습니다.
  3. 다형성(Polymorphism): 하나의 메서드나 클래스가 있을 때 이를 여러 방법으로 동작시키는 기능을 의미합니다. 오버라이딩(상속 받은 메서드를 재정의) 및 오버로딩(동일한 이름의 메서드를 다른 파라미터로 사용)이 다형성에 포함됩니다.
  4. 추상화(Abstraction): 복잡한 시스템을 단순화하는 기법으로, 필요한 기능만을 표현하고 불필요한 정보는 숨깁니다. 이를 통해 사용자는 간단한 인터페이스를 통해 복잡한 시스템을 다룰 수 있게 됩니다.

이러한 특징들은 코드의 재사용성을 높이고, 모듈성을 증가시키며, 유지 관리를 용이하게 하여 소프트웨어 개발을 효율적으로 만드는 크게 기여합니다.

 

2. 절차지향 프로그래밍과 객체지향 프로그래밍의 주요 차이점을 설명해주실 수 있나요?

절차지향 프로그래밍과 객체지향 프로그래밍은 프로그래밍 방식에 있어서 근본적으로 다른 접근 방식을 가지고 있습니다.

절차지향 프로그래밍은 프로그램이 순차적으로 실행되도록 설계하며, 데이터를 입력 받아서 처리하고 결과를 출력하는 일련의 과정을 순서대로 기술하는 방식입니다. 이런 방식은 컴퓨터의 처리 방식과 유사하여 초기의 프로그래밍 언어에서 주로 사용되었습니다. 대표적인 절차지향 언어로는 C언어가 있습니다.

절차지향 프로그래밍의 주요 특징과 단점은 다음과 같습니다:

  • 코드의 순서가 프로그램의 흐름과 일치하므로 이해하기 쉽습니다.
  • 일반적으로 빠른 실행 속도를 가집니다.
  • 하지만 프로그램이 커지고 복잡해질수록 유지보수와 코드의 재사용이 어렵습니다.
  • 또한 함수 내부에서 데이터를 직접 변경하므로 코드의 추적이 어렵고 디버깅이 어려울 수 있습니다.

반면, 객체지향 프로그래밍은 프로그램을 여러 개의 독립된 '객체'로 구성하고, 이들 객체 간의 상호작용으로 프로그램을 설계하는 방식입니다. 각 객체는 상태(데이터)와 행동(메서드)을 가지며, 이를 통해 실세계의 사물이나 개념을 추상화하여 프로그램에 반영하는 것이 가능합니다. 대표적인 객체지향 언어로는 Java, C++, Python 등이 있습니다.

객체지향 프로그래밍의 주요 특징과 장점은 다음과 같습니다:

    • 코드의 재사용이 용이하며, 유지보수가 쉽습니다.
    • 객체 간의 정보은닉(캡슐화)이 가능하여 데이터의 보안성이 높습니다.
    • 실세계의 개념을 직관적으로 코드에 반영할 수 있어 설계 과정이 자연스럽습니다.
    • 다형성, 상속 등의 개념을 통해 유연성과 확장성이 높은 프로그램을 작성할 수 있습니다.
    • 하지만 객체 간의 상호작용이 복잡해질수록 전체 시스템을 이해하기 어렵고, 실행 속도가 절차지향 프로그래밍에 비해 상대적으로 느릴 있지만, 이는 대형 시스템에서는 큰 문제가 되지 않습니다. 오늘날의 컴퓨터는 충분히 빠르기 때문에, 대부분의 경우에서 객체지향 프로그래밍의 여러 가지 이점이 속도 저하를 상쇄합니다.
    • 객체지향 프로그래밍의 주요 원칙 중 하나는 DRY(Don't Repeat Yourself) 원칙입니다. 이 원칙은 코드 중복을 최소화하고 코드의 재사용을 극대화하도록 권장합니다. 이는 메서드와 클래스를 잘 설계하여 여러 위치에서 재사용할 수 있게 함으로써 달성할 수 있습니다.
    • 마지막으로, 객체지향 프로그래밍은 테스트와 디버깅을 용이하게 합니다. 객체는 상대적으로 독립적이므로 개별적으로 테스트하고 디버깅할 있습니다. 이는 유닛 테스트 작성을 쉽게 하며, 코드의 품질을 향상시키는 도움이 됩니다.
    • 객체지향 프로그래밍의 또 다른 특징은 코드의 모듈성입니다. 이는 객체 간의 통신이 메서드 호출을 통해 이루어진다는 사실에서 기인합니다. 각 객체는 독립적인 엔티티로, 다른 객체와 상호작용하기 위해 정의된 인터페이스를 통해 통신합니다. 이 접근 방식은 코드의 재사용을 쉽게 만들며, 시스템의 다른 부분에 영향을 미치지 않고 개별 객체를 업데이트하거나 수정할 수 있습니다.

3. 관점지향 프로그래밍(AOP)에 대해 알고 있나요? 그리고 어떤 상황에서 AOP를 사용하면 좋을까요?

  • 관점지향 프로그래밍(Aspect-Oriented Programming, AOP)은 특정 로직을 기존 코드 전반에 걸쳐 재사용하도록 설계된 프로그래밍 기법입니다. 이는 로직의 분산(Distributed Logic)을 방지하며, 관련 없는 코드가 섞이는 것을 피할 수 있습니다. 이를 통해 코딩의 복잡성을 줄이고, 가독성을 향상시킬 수 있습니다.
  • AOP는 '관심사(Cross-cutting Concerns)'의 분리를 통해 이를 달성합니다. 관심사는 프로그램의 다양한 부분에 걸쳐 나타나는 특정 기능이나 규칙을 의미합니다. 로깅, 보안, 트랜잭션 관리 등이 그 예입니다. 이러한 관심사를 별도의 모듈('관점')으로 분리하고, 핵심 로직에서는 이를 참조하지 않도록 합니다. 이렇게 함으로써 핵심 로직의 순수성과 재사용성을 보장할 수 있습니다.
  • AOP를 사용하면 좋은 상황은 주로 다음과 같습니다:
  1. 로깅: 여러 메소드나 클래스에 걸쳐 반복적으로 사용되는 로깅 기능을 AOP를 이용해 한 곳에서 관리할 수 있습니다.
  2. 트랜잭션 관리: 특정 조건에 따라 트랜잭션을 시작하거나 커밋, 롤백하는 등의 기능을 AOP를 통해 캡슐화할 수 있습니다.
  3. 보안: 특정 메소드 호출 전에 권한을 체크하는 등의 보안 검사 로직을 AOP를 통해 적용할 수 있습니다.
  4. 에러 처리: 공통적인 에러 처리 패턴을 AOP를 이용해 한 곳에서 관리하고 재사용할 수 있습니다.

Java Spring 프레임워크에서는 AOP 지원하며, 관련 기능을 구현하는데 많이 사용됩니다.

 

4. AOP를 사용함으로써 어떤 장점을 얻을 수 있나요? 구체적인 예를 들어 설명해주세요.

AOP (Aspect-Oriented Programming)는 관점지향 프로그래밍으로서 코드의 중복을 줄이고, 모듈화를 통해 각 기능을 분리하여 관리할 수 있는 프로그래밍 패러다임입니다. AOP를 사용함으로써 얻을 수 있는 주요 장점과 구체적인 예시는 다음과 같습니다:

  1. 중복 코드 제거: AOP를 이용하면 공통 기능을 한 곳에 모듈화하여 여러 위치에서 재사용할 수 있습니다. 이는 코드의 중복을 줄여주고 코드의 가독성을 높여줍니다. 예를 들어, 서비스의 여러 메서드에서 동일한 로깅 또는 에러 핸들링 로직이 필요한 경우, 이를 별도의 '관점'으로 분리하여 코드 중복을 줄일 수 있습니다.
  2. 모듈화 및 코드의 유지 보수성 향상: AOP는 관심사의 분리(SoC, Separation of Concerns)를 통해 모듈화를 지원합니다. 이는 각 기능을 독립적으로 개발하고 유지 보수할 수 있도록 해주며, 따라서 코드의 유지 보수성이 향상됩니다. 예를 들어, 보안, 트랜잭션 관리, 로깅과 같은 공통 기능을 별도의 '관점'으로 분리하여 각 기능을 독립적으로 개발하고 유지 보수할 수 있습니다.
  3. 추가 기능 적용 용이: AOP는 비즈니스 로직과는 별개의 공통 기능을 쉽게 추가할 수 있도록 합니다. 이는 프로그램의 기능 확장을 용이하게 합니다. 예를 들어, 특정 메서드 호출 시에 성능 측정 로직을 추가하고 싶을 경우, AOP를 통해 성능 측정 관점을 만들고 이를 적용할 메서드에 적용함으로써 쉽게 성능 측정 기능을 추가할 수 있습니다.
  4. 프로그램의 가독성 향상: 각 기능이 모듈화되어 분리되므로, 개별 기능에 대한 이해가 용이해지고 프로그램의 전체적인 가독성이 향상됩니다.

이런 장점들 덕분에 AOP Spring 같은 프레임워크에서 흔히 사용되며, 비즈니스 로직의 효율적인 관리와 기능 확장성 제공 등에 크게 기여합니다.

 

5. 절차지향, 객체지향, 관점지향 각 프로그래밍 패러다임이 적합한 사례나 상황에 대해 설명해주실 수 있나요?

  1. 절차지향 프로그래밍(Procedural Programming):
  • 절차지향 프로그래밍은 프로그램을 일련의 절차나 단계로 보는 프로그래밍 방식입니다. 이 방식은 간단하고 직관적이며, 상대적으로 빠른 실행 속도를 가집니다. 하지만 코드가 복잡해질수록 유지보수와 확장이 어려울 수 있습니다.
  • 절차지향 프로그래밍은 프로그램이 순차적으로 명령을 수행하는 문제나, 간단하고 명확한 절차를 가지는 문제를 해결하는 데 적합합니다. 예를 들어, 순차적인 단계를 거치는 데이터 분석이나, 간단한 계산기나 문자열 처리 등의 애플리케이션을 만드는데 적합합니다.
  1. 객체지향 프로그래밍(Object-Oriented Programming):
  • 객체지향 프로그래밍은 실세계의 사물이나 개념을 추상화하여 클래스와 객체로 나타내는 프로그래밍 방식입니다. 코드의 재사용성과 유지보수가 용이하며, 다형성, 상속 등을 통해 유연성과 확장성이 높은 프로그램을 작성할 수 있습니다.
  • 객체지향 프로그래밍은 복잡하고 대형의 소프트웨어 시스템을 개발하거나, 여러 사람이 협업해야 하는 프로젝트, 또는 유지보수와 확장이 필요한 시스템을 개발하는 데 적합합니다. 예를 들어, GUI 애플리케이션, 웹 애플리케이션, 데이터베이스 시스템, 분산 시스템 등에 적합합니다.
  1. 관점지향 프로그래밍(Aspect-Oriented Programming):
  • 관점지향 프로그래밍은 여러 모듈이 공통으로 사용하는 기능(로그 기록, 보안 확인 등)을 분리하여 관리하는 프로그래밍 방식입니다. 이 방식은 코드의 재사용성을 높이고 중복을 줄일 수 있습니다.
  • 관점지향 프로그래밍은 프로그램의 다양한 부분에 걸쳐 있는 공통 기능을 모듈화하고 재사용하는 데 적합합니다. 예를 들어, 로깅, 트랜잭션 관리, 보안 등의 공통 기능을 분리, 관리할 수 있습니다. 이런 공통 기능들은 프로그램의 여러 위치에서 반복적으로 발생하며, 이를 횡단 관심사(cross-cutting concern)라고 부릅니다. 이런 횡단 관심사를 별도의 코드로 분리함으로써 기능 간의 결합도를 낮추고, 유지보수와 재사용성을 높일 수 있습니다.
  • AOP는 로깅, 보안, 트랜잭션 관리 등과 같이 여러 객체나 함수, 클래스에 걸쳐 공통적으로 필요한 기능을 분리하여 개발하고 싶을 때 유용합니다. 예를 들어, 서비스의 모든 메소드 호출 시간을 로깅하고자 한다면, 각 메소드마다 로깅 코드를 삽입하는 것이 아니라 AOP를 사용하여 해당 기능을 분리하고 중앙에서 관리할 수 있습니다. 이는 코드의 중복을 줄이고, 가독성과 유지보수성을 향상시키는 데 도움이 됩니다.
  • AOP 스프링 프레임워크와 같은 엔터프라이즈급 애플리케이션에서 흔히 사용되며, 이를 통해 서비스의 일관성을 유지하고 코드의 품질을 향상시킬 있습니다.

6. 특정 프로젝트에 적절한 프로그래밍 패러다임을 선택하는 기준은 무엇이라고 생각하나요?

  1. 프로젝트의 복잡성과 크기: 규모의 프로젝트에서는 코드 재사용성, 모듈성, 유지보수성 등이 중요해질 있습니다. 경우, 객체지향 프로그래밍이나 함수형 프로그래밍 같은 패러다임을 사용하면 좋습니다. 반면, 작은 프로젝트에서는 절차지향 프로그래밍이 충분할 있습니다.
  2. 동시에 많은 사용자가 접속하는 서비스: 많은 사용자가 동시에 서비스를 이용하면서 병렬로 처리되어야 하는 작업이 많은 경우, 함수형 프로그래밍이 유리할 있습니다. 함수형 프로그래밍은 상태를 변경하지 않고 데이터를 처리하는 방식으로, 병렬 처리와 동시성에 강점을 가지고 있습니다.
  3. 로깅, 보안, 트랜잭션 처리와 같은 공통적인 기능이 필요한 경우: 이런 경우에는 관점지향 프로그래밍(AOP) 유용합니다. AOP 특정 기능을 모듈화하고 해당 기능이 필요한 다양한 지점에서 재사용할 있게 해줍니다.

7. 스프링 프레임워크에서의 AOP 구현에 대해 설명해주실 수 있나요? 해당 기술을 사용한 경험이 있다면 구체적으로 어떤 프로젝트에서 어떻게 사용했는지 말씀해주세요

 Spring Security 처리나 Custom Error Handling 등은 관점지향 프로그래밍(AOP) 통해 구현될 있습니다. 예를 들어, Spring Security 메소드 호출 전에 권한 검사를 수행하는 등의 보안 관련 기능을 AOP 통해 적용합니다. 또한, 에러 처리 로직 역시 AOP 통해 공통 로직을 분리하고 재사용할 있습니다. 이런 방식은 코드의 중복을 줄이고 가독성을 높이며, 유지보수를 용이하게 합니다.

더보기

AOP(관점지향 프로그래밍)는 거시적인 관점에서 코드의 특정 부분에 공통적으로 적용되는 기능을 모듈화하는 프로그래밍 패러다임입니다. 로깅, 트랜잭션 관리, 보안 등과 같은 기능이 AOP의 대표적인 예시입니다.

프로그램의 핵심 비즈니스 로직과는 별개이지만, 프로그램 전반에 걸쳐 필요로 하는 기능들입니다. 이런 기능들을 AOP를 통해 분리하면, 비즈니스 로직에 집중할 수 있게 되고 코드의 재사용성과 가독성이 높아집니다.

 

엔티티 분리는 주로 도메인 주도 설계 (Domain-Driven Design, DDD)에서 사용되는 설계 패턴 하나로, 엔티티가 자신의 비즈니스 로직을 캡슐화하도록 유지하는 것을 목표로 합니다.

 

AOP (Aspect-Oriented Programming)은 관점 지향 프로그래밍의 약어입니다. AOP는 객체지향 프로그래밍(OOP)의 보완적인 기술로 개발되었습니다.

AOP는 애플리케이션의 로직에서 핵심 비즈니스 로직과 관련 없는 부가적인 기능, 즉 "관심사(Concern)"를 분리하여 개발하는 방법론입니다.

AOP는 이러한 관심사를 "어드바이스(Advice)"라는 단위로 분리합니다. 이 어드바이스는 애플리케이션의 핵심 비즈니스 로직과 분리되어 실행되며, 일반적으로 로깅, 보안, 트랜잭션 처리 등과 같은 부가적인 기능을 수행합니다.

또한, AOP는 "포인트컷(Pointcut)"이라는 개념을 사용하여, 어떤 메소드에 어떤 어드바이스를 적용할지를 결정할 수 있습니다. 포인트컷은 메소드의 이름, 인자, 리턴값 등을 이용하여 메소드를 필터링하여 지정할 수 있습니다.

AOP의 장점은 다음과 같습니다.

  1. 핵심 비즈니스 로직과 부가적인 기능을 분리하여 코드를 유연하고 재사용 가능하게 만듭니다.
  2. 어드바이스를 중앙 집중화하여 적용하므로, 코드의 중복을 제거하고 유지보수를 용이하게 합니다.
  3. 애플리케이션의 모든 메소드에 일관된 부가적인 기능을 적용할 수 있습니다.

하지만 AOP를 사용하면 코드의 가독성이 떨어지고, 디버깅이 어려워질 수 있기 때문에, AOP는 적절한 경우에만 사용해야 합니다.

 

* "포인트컷(Pointcut)"은 "어드바이스(Advice)"가 적용될 메소드를 결정하는 역할을 합니다. 여기서 어드바이스는 "메소드 실행 전/후나 예외 발생 등 특정 지점에서 실행되어야 하는 코드"를 말합니다.

포인트컷은 표현식을 사용하여 어떤 메소드에 어드바이스가 적용될지 결정합니다. 이 표현식은 일반적으로 메소드의 패턴, 매개변수 타입, 예외 타입 등을 기반으로 합니다.

execution(* com.example.service.*.*(..))

이 표현식은 com.example.service 패키지의 모든 클래스의 모든 메소드를 선택하게 됩니다.

  • execution은 메소드 실행 조인 포인트를 선택하는 가장 일반적인 포인트컷 디자인에이터입니다.
  • * com.example.service.*.*(..)는 com.example.service 패키지의 모든 클래스의 모든 메소드를 대상으로 합니다.
  • 첫 번째 *는 메소드의 리턴 타입에 관계없이 모든 메소드를 의미합니다.
  • 두 번째 *는 com.example.service 패키지 내의 모든 클래스를 의미합니다.
  • 세 번째 *는 모든 메소드를 의미합니다.
  • (..)는 어떠한 매개변수가 오든 상관 없음을 의미합니다.

따라서 이 포인트컷 표현식은 "com.example.service 패키지의 모든 클래스의 모든 메소드가 실행될 때" 어드바이스를 적용하겠다는 의미입니다.

이렇게 포인트컷을 통해 어드바이스를 적용할 메소드를 정확하게 지정함으로써, 코드의 중복을 줄이고 관심사를 분리하여 코드의 가독성과 유지보수성을 향상시킬 있습니다.

 

2023.05.25 - [Spring] - 절차지향(Procedural), 객체지향(Object-Oriented), 관점지향(Aspect-Oriented) 프로그래밍 pt.1

1. 절차지향 프로그래밍(Procedural Programming) :

    • 초기의 프로그래밍 방식으로, 컴퓨터가 수행해야 할 작업들을 순차적으로 나열하는 코딩 방식입니다.
    • 코드가 하나의 파일에 많이 존재하는 경우, 해당 방식을 사용하여 작업을 나열하게 됩니다.
    • 절차지향 프로그래밍은 프로그램을 명령어의 순서대로 구성하는 방식입니다. 방법은 일련의 동작으로 프로그램을 작성하고, 데이터와 상태를 조작하는 집중합니다. (알고리즘과 데이터 구조에 중점을 둔다)
    • 예를 들어, 클래스의 각 API 처리를 나열하는 방식등 이 있습니다. 
    • 주요 언어: C언어

2. 객체지향 프로그래밍(Object-Oriented Programming) :

  • 소프트웨어의 규모가 커짐에 따라 부각된 프로그래밍 방식입니다. 대부분의 사람들은 한 번에 여러 가지 생각을 하기 어려우므로, 객체지향 프로그래밍은 하나의 사물 (객체)에 하나의 의미를 부여하게 만듭니다.
  • 객체지향 프로그래밍은 프로그램을 객체들의 집합으로 바라보는 방식입니다. 객체는 데이터와 이를 조작하는 메소드로 구성되어 있습니다. 방법은 실제 세계의 객체를 모델링하여 코드 재사용, 모듈성, 캡슐화를 증가시키는 중점을 둡니다.
  • 예를 들어, 무언가를 자를 필요가 있을 때 'Scissors' 클래스를 생각하거나, 종이에 쓸 필요가 있을 때 'Pen' 클래스를 생각하는 것과 같습니다. 여기서 'Scissors', 'Pen' 등이 객체가 되며, 각각에는 '자르는 일', '쓰는 일' 등의 역할이 부여됩니다.
  • 주요 언어: Java, C++, Python, Ruby 등

3. 프로그래밍 방식의 추천 순서 :

  • 처음에는 '절차적 프로그래밍'을 사용하여, 하나의 파일에 너무 많은 코드가 들어가지 않도록 관리합니다.
  • 코드를 역할별로 분리하여 가독성을 높입니다.
  • 시간이 지나고 코드가 복잡해지면, '객체지향 프로그래밍'으로 리팩토링을 진행합니다.

4. 리팩토링 :

  • 기능의 변경 없이 프로그램의 구조를 개선하는 작업을 의미합니다.
  • 따라서, 처음 프로그래밍을 시작할 때는 절차적 프로그래밍을 사용하되, 프로그램이 커지고 복잡해질수록 객체지향 프로그래밍으로 전환하여 가독성과 유지보수성을 높이는 것이 일반적인 추천 사항입니다.

5. AOP(Aspect-Oriented Programming, 관점 지향 프로그래밍) :

  • 소프트웨어 개발 패러다임 중 하나로, 흩어진 관심사(Cross-cutting Concerns)를 모듈화하는 것에 중점을 둡니다.
  • 프로그램에서 공통적으로 사용되는 기능을 재사용하기 쉽게 모듈화하는 것이 AOP의 주된 목표입니다. 예를 들어, 로깅, 보안, 트랜잭션 관리 등과 같은 서비스를 특정 비즈니스 로직과 분리하여 관리할 수 있습니다.
  • 이러한 방법은 코드의 가독성을 높이고, 유지 보수를 용이하게 합니다. 여러 비즈니스 로직에서 공통적으로 사용되는 기능을 한 곳에서 관리하므로 코드의 중복을 줄일 수 있고, 수정이 필요할 경우 해당 기능을 관리하는 한 곳만 수정하면 되므로 유지보수의 효율성을 높일 수 있습니다.
  • 스프링 프레임워크에서는 AOP를 지원하며, 이를 통해 트랜잭션 관리, 로깅, 보안 등의 기능을 비즈니스 로직으로부터 분리하여 개발할 수 있습니다. 이는 객체 지향 프로그래밍(OOP)의 주요 원칙인 단일 책임 원칙(Single Responsibility Principle)을 준수하는 데 도움을 줍니다.
  • 관점지향 프로그래밍은 프로그램을 관심사의 집합으로 바라보는 방식입니다. 관심사란 프로그램의 다양한 부분(로깅, 보안 등)을 뜻하며, 이를 모듈화하는 것이 관점지향 프로그래밍의 주요 목표입니다.
  • 방법은 크로스 커팅 관심사(Cross-cutting Concerns) 공통 모듈로 분리하여 코드의 재사용성을 증가시키고, 유지 보수를 용이하게 하는 중점을 둡니다.

프로그래밍 패러다임은 서로 배타적이지 않으며, 실제 개발에서는 이들을 혼합하여 사용하는 경우가 많습니다. 예를 들어, 객체지향 프로그래밍을 사용하면서 관점지향 프로그래밍을 활용하여 공통 기능을 분리할 있습니다.

 

더보기

절차지향 프로그래밍 :

프로그래밍의 흐름대로 순서대로 진행되는 것을 말한다. (알고리즘과 데이터 구조에 중점을 둔다)

순차적으로 실행되는 단계별 절차를 중심으로 코드를 작성, 대표적으로 C언어
객체지향 프로그래밍 :

프로그래밍은 객채 개념을 기반으로 한다. 데이터와 기능이 하나의 객체에 묶여있다. (객체 간의 상호작용에 중점을 둔다)

객체를 중심으로 코드를 작성, 캡슐화 상속 다형성개념 사용 코드의 재사용성과 확장성을 높힌다, 대표적으로 우리가 쓰는 Java언어
관점지향 프로그래밍 :

로깅, 보안 성능과 같은 문제를 기본 프로그램 논리에서 분리하는데 중점을 둔다.

코드를 작성하는 것보다는 프로그램의 관점을 중심으로 코드를 작성, 관심사의 분리를 통해 비즈니스 로직과 시스템 로직 등을 분리하여 코드를 유연하고 확장 가능하게 만듬, 대표적으로 스프링 프레임워크, AOP(Aspect-Oriented Programming)

 

2023.05.25 - [Spring] - 절차지향(Procedural), 객체지향(Object-Oriented), 관점지향(Aspect-Oriented) 프로그래밍 pt.2

영속성 컨텍스트(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

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

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

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/

 

 

 

 

 

 

1. IP 주소란 ? 

거대한 네트워크망에서 사용자의 컴퓨터를 식별하기 위한 위치 주소, 네트워크라는 공간에서 컴퓨터의 집주소

네트워크상에서의 데이터 송/수신의 기준 

 

2. 브라우저란 ? 

크롬, 사파리, 엣지와 같이 웹페이지, 이미지, 비디오등의 컨텐츠를 송/수신하고 표현해주는 소프트웨어

 

3. DNS 란 ? 

Domain Name Server, 서버의 IP주소와 도메인 이름을 중개해주는 전화번호부와 같은 서버

 

4. HTTP(HyperText Transfer Protocol)란?

메세지 송신자와 수신자가 공유하고 있는 “약속(Protocol)”, 웹 상에서는 HTTP 라는 프로토콜을 통해서 데이터를 송/수신

  1. 데이터를 주고 받는 양식을 정의한 "통신 규약"중 하나
  2. 범용적인 양식을 가지고 있어 전 세계에서 제일 널리 쓰이는 통신 규약(컴퓨터끼리 데이터를 주고 받을때 정해둔 약속)
  3. HTTP에서는 언제나 Request, Response라는 개념이 존재
    • 브라우저는 서버에게 자신이 원하는 페이지(URL 등의 정보)를 요구(Request)합니다.
    • 서버는 브라우저가 원하는 페이지가 있는지 확인하고, 있다면 해당 페이지에 대한 데이터를 실어 응답(Response)해줍니다. 없다면 없는 페이지에 대한 데이터를 반환합니다.
    • 브라우저는 서버에게 전달 받은 데이터를 기반으로 브라우저에 그려줍니다.
  4. HTTP의 구성 요소
    • Method (호출/요청 방식)
      • GET: 이름 그대로 어떤 리소스를 얻을 때 사용됩니다. 브라우저의 주소창에 URL을 입력하면 GET 메서드를 사용해서 서버에 요청을 보냅니다.
      • POST: 웹 서버에 데이터를 게시할 때 사용하는게 일반적입니다. (ex. 회원가입, 게시글 작성, 댓글 작성)
    • Header (추가 데이터. 메타 데이터)
      • 브라우저가 어떤 페이지를 원하는지
      • 요청 받은 페이지를 찾았는지
      • 요청 받은 데이터를 성공적으로 찾았는지
      • 어떤 형식으로 데이터를 보낼지
    • Payload (데이터. 실제 데이터)
      • 서버가 응답을 보낼 때에는 항상 Payload를 보낼 수 있습니다.
      • 클라이언트(브라우저)가 요청을 할 때에도 Payload를 보낼 수 있습니다. 그리고 "GET method를 제외하곤 모두 Payload를 보낼 수 있다" 는게 HTTP에서의 약속입니다.

웹 서버란 ? 

  1. 인터넷을 통해 HTTP를 이용하여 웹상의 클라이언트의 요청을 응답해주는 통신을 하는 일종의 컴퓨터
  2. 오늘날 우리가 자주 사용하는 이메일이나 SNS 등 대부분의 서비스
  3. 웹 서버의 기본 동작 원리
    • 브라우저를 통해 HTTP request로 웹사이트를 웹서버에 요청합니다. 이후 웹서버는 요청을 승인하고 HTTP response를 통해 웹사이트 데이터를 브라우저에 전송합니다. 마지막으로 브라우저는 서버에서 받아온 데이터를 이용해 웹사이트를 브라우저에 그려내는 일을 합니다.
    • 기본적으로 브라우저가 웹서버에 요청을 할때는 항상 GET method로 요청하게 됩니다.

🧩 Quiz

사용자가 브라우저에 주소(URL)를 입력하면 해당 동작에 맞게 HTTP 데이터를 만들어 서버로 보내고 서버는 알맞는 응답 데이터를 브라우저(클라이언트)로 보내 이 데이터가 브라우저에 표현됩니다.

 

1. 웹 서버 (Web Server)는 무엇일까요?

  • 웹 서버(Web Server)는 HTTP를 통해 웹 브라우저에서 요청하는 HTML 문서나 각종 리소스를 전달하는 서버입니다. 대표적인 웹 서버 소프트웨어로는 Apache, Nginx, IIS 등이 있습니다.

2. 웹 서버 (Web Server)와 웹 어플리케이션 서버(WAS)는 어떤 차이점이 있을까요?

  • 웹 어플리케이션 서버(WAS, Web Application Server)는 웹 서버의 기능과 함께 동적인 서비스를 제공하기 위한 어플리케이션 서버의 기능을 모두 가지고 있는 서버입니다. 이는 DB 조회, 다양한 로직 처리 등 비즈니스 로직을 수행할 수 있습니다. 대표적으로 Tomcat, JBoss, WebSphere 등이 있습니다.
  • 웹 서버와 WAS의 가장 큰 차이는 동적인 데이터 처리 여부입니다. 웹 서버는 주로 정적인 컨텐츠를 처리하는데 최적화되어 있고, WAS는 동적인 컨텐츠를 처리하는데 적합합니다.
    더보기

    WAS Web Application Server 약어로, 애플리케이션을 실행하는 필요한 기능을 제공하는 소프트웨어입니다. WAS JSP, Servlet, EJB 등의 기술을 사용하여 동적인 페이지를 생성하고, 데이터베이스 연동, 보안, 트랜잭션 관리, 스레드 관리, 세션 관리 등의 기능을 제공합니다.
    WAS Web Server 가장 차이점은 기능적인 측면입니다. Web Server 정적인 콘텐츠(HTML, 이미지, CSS ) 제공하는 특화된 소프트웨어이며, WAS 동적인 콘텐츠( 애플리케이션) 제공하는 특화된 소프트웨어입니다.
    또한, WAS 보통 Web Server 기능을 내장하고 있으며, 대부분의 WAS 자체적으로 Web Server 기능을 처리합니다. 이러한 이유로, WAS 보다 복잡한 구성을 필요로 하며, Web Server보다 높은 성능과 안정성을 제공할 있습니다.

    따라서, Web Server WAS 기능적인 측면에서 차이가 있으며, 각각의 용도에 따라 적절한 소프트웨어를 선택하여 사용해야 합니다.

웹 서버와 WAS(Web Application Server)는 모두 클라이언트의 요청에 따라 응답을 하는 서버지만, 그들이 처리하는 작업의 유형과 복잡성에서 차이가 있습니다.

  • 웹 서버:
  • HTTP 프로토콜을 통해 클라이언트(일반적으로 웹 브라우저)로부터 요청을 받아, 정적인 컨텐츠(예: HTML 문서, 이미지, CSS, JavaScript 파일 등)를 제공합니다. 웹 서버의 주요 목표는 가능한 빠르고 효율적으로 이러한 정적 컨텐츠를 전달하는 것입니다. Apache, Nginx 등이 대표적인 웹 서버 소프트웨어입니다.
  • WAS(Web Application Server):
  • 동적 컨텐츠를 처리하고 제공하는 역할을 합니다. 클라이언트로부터 요청을 받으면, 해당 요청에 따라 비즈니스 로직을 실행하고, 결과를 생성하여 응답합니다. 이 과정은 데이터베이스 조회, 데이터 처리, 비즈니스 로직 수행 등 복잡한 작업을 포함할 수 있습니다. Java EE, ASP.NET, PHP 등의 플랫폼에서 동작하는 서버를 예로 들 수 있습니다.

기능적으로 , WAS 서버의 기능을 모두 포함하며 추가로 동적인 데이터 처리 비즈니스 로직을 수행하는 기능까지 포함하고 있습니다. 하지만 무조건 WAS 사용하는 것이 좋은 것은 아닙니다. 처리해야 요청이 정적 컨텐츠 위주인 경우, 서버가 효율적일 있습니다. 반면에, 동적 컨텐츠 처리가 많은 경우에는 WAS 사용하는 것이 적합할 있습니다. 많은 경우에 서버와 WAS 함께 사용되며, 각각의 장점을 최대한 활용하는 아키텍처를 구성합니다.

 

3. HTTP Method에서 Get과 Post의 차이점은 무엇이 있을까요?

  • GET: 클라이언트에서 서버로 데이터를 요청할 때 사용합니다. 데이터를 URL에 포함하여 전달하며, 캐싱이 가능합니다. 주로 조회를 할 때 사용합니다.
  • POST: 클라이언트에서 서버의 리소스를 생성하거나 수정하기 위해 데이터를 전송할 사용합니다. 데이터는 HTTP 메시지의 body 포함되어 전송되며, GET 비해 상대적으로 안전합니다.

4. HTTP와 HTTPS의 차이점은 무엇일까요?

  • HTTP와 HTTPS의 가장 큰 차이점은 '보안'입니다. HTTP는 HyperText Transfer Protocol의 약자로, 인터넷에서 정보를 주고받는 프로토콜입니다. 반면, HTTPS는 HTTP에 Secure Socket Layer(SSL)이라는 보안 프로토콜을 추가한 것입니다. HTTPS는 데이터를 암호화하여 전송함으로써, 데이터가 도중에 탈취되더라도 암호를 해독하지 않는 한 원본 데이터를 알 수 없도록 보호합니다.

5. WAS가 필요한 이유는 무엇인가요?

WAS는 Web Application Server의 약자로, 사용자가 웹을 통해 응용 프로그램을 실행하는 데 필요한 환경을 제공하는 미들웨어입니다. WAS는 다음과 같은 이유로 필요합니다:

  1. 동적 콘텐츠 처리: WAS는 클라이언트의 요청에 따라 동적으로 데이터를 처리하고 응답을 생성합니다. 이는 정적 웹 서버가 할 수 없는 기능으로, 사용자의 요청에 따라 콘텐츠를 실시간으로 변경하거나 사용자마다 다른 콘텐츠를 제공할 수 있습니다.
  2. 비즈니스 로직 수행: WAS는 일반적으로 데이터베이스와 연동되어 웹 응용 프로그램의 비즈니스 로직을 수행합니다. 예를 들어, 사용자가 상품을 구매하는 웹 사이트에서 WAS는 사용자의 주문 정보를 데이터베이스에 저장하고, 상품 재고를 업데이트하며, 결제를 처리하는 등의 업무를 수행할 수 있습니다.
  3. 트랜잭션 관리: WAS는 트랜잭션을 관리하여 데이터의 일관성을 유지합니다. 예를 들어, 여러 데이터베이스 작업이 하나의 트랜잭션으로 묶여야 하는 경우 WAS는 이러한 작업이 모두 성공적으로 완료되거나, 실패할 경우 모든 작업을 취소(롤백)하여 데이터의 일관성을 유지합니다.
  4. 보안 기능: WAS는 웹 응용 프로그램의 보안을 관리하는 기능을 제공합니다. 사용자 인증, 권한 부여, 데이터 암호화 등의 기능을 통해 사용자의 정보와 데이터를 보호합니다.
  5. 스케일링 및 로드 밸런싱: WAS는 응용 프로그램의 확장성을 지원하며, 다수의 클라이언트 요청을 효과적으로 처리할 수 있습니다. 또한, 여러 서버에 작업을 분산시키는 로드 밸런싱 기능도 제공합니다.
  6. 세션 관리: WAS는 사용자마다 세션을 생성하고 관리하여, 사용자별 상태 정보를 유지할 수 있습니다. 이를 통해 사용자마다 개인화된 서비스를 제공하거나 로그인 세션을 유지하는 등의 기능을 수행할 수 있습니다.

따라서, WAS는 사용자에게 동적이고, 개인화된 웹 서비스를 제공하며, 응용 프로그램의 비즈니스 로직을 수행하고, 데이터의 일관성을 유지하며, 보안을 관리하는 등의 중요한 역할을 합니다.

  1. 서비스 통합: WAS는 여러 서비스를 통합하는 데 사용될 수 있습니다. 예를 들어, 여러 웹 서비스를 하나의 플랫폼에서 실행하거나 다양한 종류의 데이터베이스 시스템과 연동할 수 있습니다.
  2. API 관리: 웹 애플리케이션 서버는 API를 통해 다른 소프트웨어와 통신하는 기능을 제공할 수 있습니다. 이는 모바일 앱, 데스크톱 앱, 또는 다른 웹 서비스와 통신하는 데 필요합니다.
  3. 장애 복구 및 백업: WAS는 장애 복구와 백업 기능을 제공하여 시스템 장애나 데이터 손실 시 복구할 수 있게 돕습니다.

이처럼 WAS 기반 애플리케이션의 효과적인 운영과 관리에 있어 필수적인 역할을 수행하며, 이러한 다양한 기능을 통해 애플리케이션의 안정성, 확장성, 그리고 효율성을 보장합니다.

 

6. 웹 서버와 WAS를 어떻게 결합하여 사용하나요? 이렇게 하는 이유는 무엇인가요?

웹 서버와 WAS(Web Application Server)를 결합하여 사용하는 구조는 보통 '웹 서버 - WAS 아키텍처'라고 부릅니다. 웹 서버는 보통 정적인 콘텐츠를 처리하고, WAS는 동적인 콘텐츠를 처리하는 역할을 담당합니다.

웹 서버와 WAS를 결합하는 과정은 대략적으로 다음과 같습니다:

  1. 사용자의 요청이 웹 서버에 먼저 도착합니다.
  2. 웹 서버는 요청을 분석하여, 정적인 콘텐츠 요청인 경우 해당 콘텐츠를 반환합니다.
  3. 만약 동적인 콘텐츠 요청인 경우, 웹 서버는 해당 요청을 WAS에 전달합니다.
  4. WAS는 요청을 처리한 후 그 결과를 웹 서버에 반환합니다.
  5. 웹 서버는 WAS로부터 받은 응답을 사용자에게 전달합니다.

이런 구조를 사용하는 이유는 아래와 같습니다:

  1. 성능 향상: 정적 콘텐츠와 동적 콘텐츠를 별도의 서버에서 처리하면 각 서버는 자신의 역할에 최적화되어 있기 때문에 전반적인 성능이 향상됩니다.
  2. 보안 강화: 웹 서버가 외부에서의 직접적인 WAS 접근을 차단함으로써 보안을 강화할 수 있습니다. 또한, 서버 간 통신에서도 보안을 적용할 수 있습니다.
  3. 유연성: 웹 서버와 WAS를 분리하면 각각을 독립적으로 업그레이드하거나 교체하는 등의 유연성을 갖게 됩니다. 서비스의 요구 사항이 변화할 때마다 적절한 서버 환경을 조성할 수 있습니다.
  4. 로드 밸런싱: 여러 대의 WAS를 사용하면 웹 서버가 로드 밸런싱을 수행하여 각 서버에 균등하게 요청을 분산시킬 수 있습니다. 이를 통해 시스템의 과부하를 방지하고 가용성을 높일 수 있습니다.

따라서, 서버와 WAS 결합하여 사용하는 것은 성능, 보안, 유연성, 그리고 로드 밸런싱 여러 가지 이점을 제공합니다.

 

7. 웹 서버만 사용하는 경우와 WAS를 추가로 사용하는 경우, 각각의 장단점은 무엇인가요?

웹 서버와 웹 서버 + WAS를 사용하는 경우는 각각 장단점이 있습니다. 여기서는 가장 일반적인 케이스에 대한 장단점을 다루겠습니다.

웹 서버만 사용하는 경우:

장점:

  1. 간단함: 웹 서버만 사용하는 경우, 시스템 구성이 단순하고 관리가 비교적 쉽습니다.
  2. 빠른 응답 시간: 웹 서버는 정적 콘텐츠를 빠르게 제공할 수 있습니다. 이는 웹 서버가 이미 생성된 콘텐츠를 곧바로 클라이언트에게 전송하기 때문입니다.
  3. 리소스 효율: 웹 서버는 동적 콘텐츠 처리에 필요한 CPU나 메모리 등의 리소스를 적게 사용합니다.

단점:

  1. 동적 콘텐츠 처리 불가: 웹 서버는 동적인 콘텐츠를 처리하는 데 제한이 있습니다. 즉, 사용자의 입력에 따라 변하는 콘텐츠를 웹 서버만으로 처리하기 어렵습니다.
  2. 비즈니스 로직 처리 불가: 웹 서버는 복잡한 비즈니스 로직을 처리하는 데 한계가 있습니다. 이를 처리하려면 추가적인 프로그래밍이 필요합니다.

웹 서버 + WAS를 사용하는 경우:

장점:

  1. 동적 콘텐츠 처리: WAS는 사용자의 요청에 따라 동적으로 웹 페이지를 생성하고, 웹 서비스에 필요한 다양한 기능을 수행할 수 있습니다.
  2. 비즈니스 로직 처리: WAS는 복잡한 비즈니스 로직을 처리하며, 데이터베이스와의 연동, 트랜잭션 관리 등을 할 수 있습니다.
  3. 세션 관리: WAS는 사용자별 세션 정보를 유지하고 관리할 수 있어 사용자에게 맞춤화된 서비스를 제공할 수 있습니다.

단점:

  1. 복잡함: 서버와 WAS 결합하여 사용하는 경우, 시스템 구성이 복잡하고, 관리와 유지보수가 어려울 있습니다.
  2. 성능 이슈: WAS 동적인 콘텐츠를 처리하면서 많은 리소스를 사용할 있습니다. 이에 따라 대량의 동적 콘텐츠 처리 성능 저하가 일어날 있습니다. 이를 위해 최적화가 필요합니다.
  3. 리소스사용량: WAS 애플리케이션 로직을 처리하는데 필요한 많은 컴퓨팅 리소스를 사용합니다. 따라서 높은 수준의 리소스 관리가 필요하며, 이는 하드웨어 비용 증가로 이어질 있습니다.

8. 정적 컨텐츠와 동적 컨텐츠의 차이점에 대해 설명해 주세요.

정적 컨텐츠(Static Content)

: 서버에 미리 저장되어 있는 파일로, 사용자의 요청에 따라 변경되지 않는 컨텐츠입니다. 예를 들어, HTML 파일, CSS 파일, 이미지 파일, JavaScript 파일 등이 정적 컨텐츠에 해당합니다. 이러한 파일들은 웹 서버에 저장되어 있고, 사용자가 웹 페이지를 요청하면 웹 서버는 해당 파일들을 그대로 반환합니다. 사용자마다 다르게 변화하지 않으며, 서버의 로직에 의해 변화하지도 않습니다.

동적 컨텐츠(Dynamic Content) 

: 사용자의 요청, 입력, 세션, 서버의 로직 등에 따라 실시간으로 변화하는 컨텐츠를 말합니다. 예를 들어, 사용자의 로그인 상태에 따라 보이는 화면이 달라지거나, 사용자가 입력한 정보에 따라 생성되는 결과 페이지, 서버의 처리 로직에 따라 생성되는 HTML 등이 동적 컨텐츠에 해당합니다. 이러한 컨텐츠는 웹 애플리케이션 서버(WAS)와 같은 서버 사이드 로직에 의해 처리되며, 데이터베이스와의 상호작용을 필요로 할 수도 있습니다.

따라서, 정적 컨텐츠는 페이지의 고정된 부분(레이아웃, 스타일 ) 담당하고, 동적 컨텐츠는 페이지의 변화하는 부분(사용자 정보, 실시간 데이터 ) 담당하는 것으로 있습니다. 둘을 적절히 조합함으로써 사용자에게 원활하고 맞춤화된 서비스를 제공할 있습니다.

 

9. 웹 서버와 WAS에서 보안은 어떻게 관리되나요?

웹 서버와 웹 애플리케이션 서버(WAS)에서의 보안 관리는 매우 중요한 이슈입니다. 다양한 보안 위협으로부터 서버와 사용자의 정보를 보호해야 하기 때문입니다. 웹 서버와 WAS에서의 보안 관리는 아래와 같은 방법들이 존재합니다:

  1. 인증 권한 관리: 사용자 인증과 권한 관리는 WAS 주요 보안 기능 하나입니다. WAS 로그인 메커니즘을 제공하여 사용자를 식별하고, 해당 사용자가 접근할 있는 자원과 기능을 제한합니다.
  2. 데이터 암호화: 서버와 WAS 데이터를 암호화하여 네트워크를 통한 정보 유출을 방지합니다. 이는 특히 민감한 정보(: 패스워드, 신용카드 정보 ) 전송할 중요합니다. 가장 대표적인 방법은 HTTPS 사용하는 것으로, 이는 SSL/TLS 프로토콜을 통해 암호화된 연결을 제공합니다.
  3. 방화벽 설정: 서버는 보안을 강화하기 위해 특정 IP 주소, 포트, 도메인 등으로부터의 접근을 제한하는 방화벽 설정을 있습니다.
  4. 입력 데이터 검증: WAS 사용자로부터의 입력을 검증하여 SQL Injection, Cross-site Scripting(XSS) 등의 공격을 방지합니다.
  5. 세션 관리: WAS 사용자의 세션 정보를 안전하게 관리하며, 이를 통해 사용자의 요청을 식별하고 접근 권한을 제어합니다. 이를 통해 세션 하이재킹 공격을 방지할 있습니다.
  6. 서버 보안 패치 업데이트: 서버와 WAS 지속적으로 발견되는 새로운 보안 취약점에 대응하기 위해 최신 상태로 유지되어야 합니다. 이를 위해 제공되는 보안 패치와 업데이트를 정기적으로 적용하는 것이 중요합니다.
  7. 오류 예외 처리: 잘못된 요청이나 예상치 못한 오류에 대한 적절한 처리도 중요한 보안 이슈입니다. 특히 에러 메시지가 너무 많은 정보를 제공하면 이를 이용한 공격의 기회를 제공할 있습니다.

10. 복잡한 웹 애플리케이션에서의 웹 서버와 WAS의 역할에 대해 어떻게 이해하고 있나요?

웹 서버의 주요 역할은 다음과 같습니다:

  1. HTTP 프로토콜 지원: 웹 서버는 HTTP 요청을 받아들이고 적절한 HTTP 응답을 반환하는 역할을 합니다. 이 과정에서 요청을 분석하고, 적절한 리소스를 찾아 응답을 구성하며, 필요에 따라 클라이언트로부터의 추가 정보를 요청하는 등의 작업을 수행합니다.
  2. 정적 컨텐츠 제공: 웹 서버는 HTML, CSS, JavaScript, 이미지 등의 정적 파일을 클라이언트에게 제공합니다. 이러한 파일은 서버에 미리 저장되어 있으며, 서버는 요청에 따라 이를 그대로 반환합니다.
  3. 로드 밸런싱: 여러 대의 WAS가 동작하는 환경에서 웹 서버는 로드 밸런서의 역할을 하여 트래픽을 균등하게 분산시킵니다. 이를 통해 서버 부하를 관리하고 전체 시스템의 성능을 최적화합니다.

**웹 애플리케이션 서버(WAS)**의 주요 역할은 다음과 같습니다:

  1. 동적 컨텐츠 제공: WAS는 사용자의 요청, 입력, 세션, 서버의 로직 등에 따라 실시간으로 변화하는 동적 컨텐츠를 제공합니다. WAS는 웹 애플리케이션의 로직을 처리하며, 이를 통해 동적으로 웹 페이지를 생성하거나 데이터를 처리합니다.
  2. 비즈니스 로직 처리: WAS는 웹 애플리케이션의 복잡한 비즈니스 로직을 처리하는 역할을 합니다. 데이터베이스와의 연동, 트랜잭션 관리, 세션 관리 등의 기능을 수행합니다.
  3. 보안 기능: WAS는 사용자 인증, 권한 관리, 데이터 암호화 등의 보안 기능을 제공합니다.

복잡한 웹 애플리케이션에서는 웹 서버와 WAS가 협력하여 사용자에게 원활하고 풍부한 웹 서비스를 제공합니다. 웹 서버는 사용자로부터의 요청을 받아들이고 기본적인 처리를 수행하며, WAS는 복잡한 웹 애플리케이션 로직과 안정적인 보안 기능을 처리하여 사용자에게 최종 결과를 반환하는 역할을 수행합니다.

웹 서버와 WAS가 협력하는 구체적인 과정은 다음과 같습니다:

  1. 사용자는 웹 브라우저를 통해 특정 URL에 접속 요청을 합니다.
  2. 웹 서버는 이 요청을 받아 분석합니다. 만약 요청이 정적 파일에 대한 것이라면, 웹 서버는 해당 파일을 찾아 바로 반환합니다.
  3. 하지만 요청이 동적 컨텐츠, 즉 서버 로직의 처리가 필요한 경우, 웹 서버는 이 요청을 WAS에게 전달합니다.
  4. WAS는 요청을 분석하고 필요한 비즈니스 로직을 처리합니다. 이 과정에서 데이터베이스와의 상호작용이 필요할 수도 있습니다.
  5. WAS는 처리 결과를 바탕으로 동적으로 웹 페이지를 생성하거나 데이터를 반환하고, 이를 웹 서버에게 전달합니다.
  6. 웹 서버는 WAS로부터 받은 응답을 사용자에게 전달합니다.

이러한 방식으로 웹 서버와 WAS는 각자의 역할을 수행하면서 웹 애플리케이션의 요구사항을 충족시키고, 사용자에게 원활하고 안전한 웹 서비스를 제공합니다.

 

11. 로드 밸런싱과 스케일링에 대해 알고 있나요? 웹 서버와 WAS에서 어떻게 적용되나요?

로드 밸런싱은 여러 대의 서버가 트래픽을 공유하도록 분산하는 기술입니다. 이는 서버에 가해지는 부하를 고르게 분산시킴으로써 시스템의 안정성을 유지하고 성능을 향상시키는 역할을 합니다. 웹 서버는 자주 로드 밸런서로서의 역할을 수행하며, 들어오는 요청을 여러 WAS에 고르게 분배합니다. 이를 통해 단일 WAS에 과도한 부하가 집중되는 것을 방지하고, 전체 시스템의 효율을 최적화합니다.

스케일링은 시스템의 처리 능력을 증가시키는 방법을 말하며, 크게 수평 스케일링(Horizontal Scaling, Scale Out)과 수직 스케일링(Vertical Scaling, Scale Up)으로 구분할 수 있습니다.

  1. 수평 스케일링: 시스템의 처리 능력을 증가시키기 위해 동일한 구성의 서버를 추가로 배치하는 방법입니다. 예를 들어, 웹 서버나 WAS를 추가하여 시스템을 확장할 수 있습니다. 이는 로드 밸런싱과 밀접한 관련이 있습니다. 추가된 서버 간의 트래픽 분산이 필요하기 때문에, 이때 로드 밸런서가 중요한 역할을 합니다.
  2. 수직 스케일링: 시스템의 처리 능력을 증가시키기 위해 기존 서버의 하드웨어 성능(예: CPU, RAM 등)을 향상시키는 방법입니다. 이는 간단하게 시스템의 처리 능력을 향상시킬 수 있지만, 하드웨어의 향상에는 한계가 있으며, 비용이 많이 들 수도 있습니다.

웹 서버와 WAS에서는 이러한 스케일링 방법을 적절히 조합하여 사용합니다. 예를 들어, 일정 수준까지는 수직 스케일링을 통해 서버의 성능을 향상시킬 수 있지만, 이후에는 수평 스케일링을 통해 여러 서버에 트래픽을 분산시키는 방법을 선택할 수 있습니다. 이를 통해 시스템의 안정성을 유지하면서도 효율적으로 처리 능력을 확장할수 있습니다.

특히, 클라우드 환경에서는 이러한 스케일링과 로드 밸런싱이 더욱 중요합니다. 클라우드 서비스는 일반적으로 자원을 유연하게 할당하고 조정할 수 있어, 시스템의 부하에 따라 동적으로 서버를 추가하거나 제거하는 오토 스케일링 기능을 제공합니다. 또한, 클라우드 서비스 제공자는 고급 로드 밸런싱 기능을 제공하여, 복잡한 분산 환경에서도 트래픽을 효과적으로 관리할 수 있게 합니다.

한편, 이러한 로드 밸런싱과 스케일링 기술을 적용할 때는 세션 관리, 데이터 일관성, 서버 간의 상태 동기화 등의 추가적인 고려사항이 생길 수 있습니다. 예를 들어, 여러 WAS가 동시에 동작하는 환경에서는 세션 정보를 공유하거나 동기화해야 하는 경우가 있을 수 있습니다. 이를 위해 세션 클러스터링, 스티키 세션, 세션 스토어 등의 기술을 사용할 수 있습니다.

결과적으로, 웹 서버와 WAS에서 로드 밸런싱과 스케일링은 시스템의 성능, 안정성, 확장성을 보장하는 핵심적인 역할을 수행합니다. 이를 통해 웹 애플리케이션은 다양한 환경과 요구 사항에 유연하게 대응하고, 사용자에게 안정적이고 빠른 서비스를 제공할 수 있습니다.

 

12. Nginx나 Apache 같은 웹 서버 소프트웨어에 대해 알고 있나요? 이들의 특징은 무엇인가요?

Nginx와 Apache는 가장 널리 사용되는 웹 서버 소프트웨어입니다.

Apache HTTP Server (이하 Apache)는 세계에서 가장 널리 사용되는 웹 서버 소프트웨어 중 하나로, Apache 소프트웨어 재단에서 개발하고 관리하고 있습니다. 아파치의 주요 특징은 다음과 같습니다:

  1. 확장성: Apache는 모듈화 된 설계를 가지고 있습니다. 이는 사용자가 필요에 따라 다양한 기능을 추가하거나 제거할 수 있음을 의미합니다. 예를 들어, PHP, Perl, Python 등 다양한 프로그래밍 언어를 지원하기 위한 모듈을 설치할 수 있습니다.
  2. 풍부한 기능: Apache는 매우 풍부한 기능을 제공합니다. 가상 호스팅, URL 리라이팅, 액세스 제어, 인증 등 다양한 기능을 지원합니다.
  3. 포트 이동성: Apache는 거의 모든 운영체제에서 실행될 수 있습니다. Windows, Linux, macOS 등 다양한 환경에서 Apache를 사용할 수 있습니다.

Nginx는 또 다른 인기 있는 웹 서버 소프트웨어로, 고성능, 높은 동시성, 낮은 메모리 사용량 등을 목표로 설계되었습니다. Nginx의 주요 특징은 다음과 같습니다:

  1. 성능: Nginx는 이벤트 기반 모델을 사용하여 동시에 많은 수의 연결을 처리할 수 있습니다. 이는 Nginx가 고프로 성능의 웹 서버와 리버스 프록시로서 뛰어난 선택이 될 수 있게 합니다.
  2. 리버스 프록시 및 로드 밸런싱: Nginx는 강력한 리버스 프록시 및 로드 밸런서로서의 기능을 제공합니다. 이를 통해 Nginx는 웹 애플리케이션 서버의 앞단에서 트래픽을 분산하고, 캐싱, SSL 종료 등의 기능을 수행할 수 있습니다.
  3. 정적 컨텐츠 처리: Nginx는 정적 컨텐츠를 효과적으로 제공할 수 있습니다. 이는 Nginx가 정적 파일의 서비스에 있어서 매우 빠른 성능을 보일 수 있게 합니다.
  4. 다양한 프로토콜 지원: Nginx는 HTTP, HTTPS, SMTP, POP3, IMAP 등의 다양한 프로토콜을 지원합니다.

그럼에도 불구하고, Apache와 Nginx에는 각각의 장단점이 있으므로, 사용 사례에 따라 적절한 선택을 해야합니다.

Apache는 다양한 모듈을 통해 유연하게 구성할 수 있으며, .htaccess 파일을 사용한 세부적인 설정 제어, 뛰어난 문서 지원 등이 가능하다는 이점이 있습니다. 하지만 동시 연결 수가 많아질수록 메모리 사용량이 증가하는 문제가 있을 수 있습니다.

반면에, Nginx는 이벤트 기반 모델 덕분에 많은 수의 동시 연결을 효과적으로 처리할 수 있습니다. 이는 고성능이 요구되는 사이트나 정적 컨텐츠가 많은 사이트에서 효과적입니다. 또한, Nginx는 로드 밸런서나 리버스 프록시로서의 역할도 잘 수행할 수 있습니다. 하지만 Apache에 비해 모듈 지원이 상대적으로 떨어지며, .htaccess와 같은 세부적인 디렉토리 단위의 설정이 제한적입니다.

최근에는 Apache와 Nginx를 함께 사용하는 방식도 자주 볼 수 있습니다. 예를 들어, Nginx를 리버스 프록시 및 정적 파일 서버로 사용하고, Apache를 동적 컨텐츠를 처리하는 서버로 사용하는 방식입니다. 이렇게 하면 각각의 장점을 취하면서 전체 시스템의 성능과 효율성을 향상시킬 수 있습니다.

 

** SOLID : 좋은 객체 지향 설계의 5가지 원칙 , 로버트마틴 클린코드 **

1. 단일 책임 원칙 (single responsibility principle,  SRP) :

하나의 클래스는 하나의 책임만 가져야 한다 

이때, 중요한 기준은 변경이다. 즉 변경이 있을 때 파급효과가 적은 경우 단일 책임 원칙을 잘 따른 것

 

2. 개방 폐쇄 원칙(Open closed principle, OCP)

확장에는 열려있으나 변경에는 닫혀있어야 한다, 다형성을 활용(인터페이스를 활용하여 새로운 클래스를 통한 새로운 기능을 구현)

문제점 : 구현객체를 변경하려면 클라이언트 코드를 변경해야한다

> 해당 문제점을 해결하기 위해 IoC 와 DI 같은 컨테이너가 필요하다 (객체를 생성하고 연관관계를 맺어주는 별도의 조립/설정자)

기능의 변경이나 추가가 발생해도 기존 코드는 수정되지 않고, 새로운 코드를 통해 기능이 확장되는 것이 이상적입니다.

 코드의 재사용성을 높이고유지 보수를 용이하게 만듭니다.

 

3. 리스코프 치환 원칙(Liskov substitution principle, LSP) : 

프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위타입의 인스턴스로 바꿀 수 있어야 한다

즉, 다형성에서 하위클래스는 인터페이스의 규약을 다 지켜야 한다는 것 (컴파일 성공을 넘어서는 이야기이다)
서브타입은 언제나 기반 타입으로 대체될 수 있어야 한다는 원칙입니다. 즉, 자식 클래스는 부모 클래스의 역할을 완전히 대체할 수 있어야 합니다.

 

4. 인터페이스 분리 원칙(Interface segregation principle, ISP) : 

특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다,

분리하면 인터페이스 자체가 변해도 클라이언트에 영향을 주지 않음, 인터페이스도 명확하고 대체가능성이 높아진다. 
클라이언트는 자신이 사용하지 않는 인터페이스에 의존하게 만들어서는 안 된다는 원칙입니다. 이는 "작고 구체적인 인터페이스가 낫다"라는 원칙을 의미하며, 클래스는 자신이 필요로 하는 메서드만을 가진 인터페이스에 의존해야 함을 나타냅니다.

 

5. 의존관계 역전 원칙(Dependency inversion principle, DIP)

추상화에 의존하는 것이지 구체화에 의존하면 안된다, 구현클래스가 아닌 인터페이스에 의존한다는 뜻이다. 

클라이언트가 인터페이스에 의존해야 유연하게 구현체를 변경할 수 있다

정리 :

의존한다는 것은 내가 해당 클래스의 코드를 알고 있다는 뜻이다 . 

객체지향의 핵심은 다형성으로 다형성 만으로는 OCP,DIP를 지킬 수 없다. 

 

스프링은 DI(의존성 주입) + DI컨테이너의 제공(자바객체들을 컨테이너안에 넣어두고 연결,스프링 프레임워크)을 통해

다형성 + OCP<DIP를 가능하게 지원해준다 !! (클라이언트 코드의 변경 없이 기능확장)

 

하지만 실무에서는 인터페이스를 도입하면 "추상화"라는 비용이 발생한다

기능을 확장할 가능성이 없다면 구체 클래스를 직접 사용하고 향후 인터페이스를 도입(리팩터링)

언제나 장점이 단점을 넘어설때 선택하는 것이 중요

 

* 단일 책임 원칙에 대해 설명하고, 이 원칙을 지키지 않을 때 어떤 문제가 발생할 수 있는지 설명해주세요.

단일 책임 원칙(Single Responsibility Principle, SRP)은 객체 지향 프로그래밍에서 가장 기본적인 원칙 중 하나로, 한 클래스는 한 가지 책임만 가져야 함을 의미합니다. 이는 "변경의 이유는 한 가지만 있어야 한다"라는 원칙으로 이해될 수 있습니다.

단일 책임 원칙을 지키면 코드의 응집도를 높이고 결합도를 낮출 수 있어, 유지 보수성이 향상되고 테스트하기가 더 쉬워집니다. 또한, 각 클래스의 역할이 명확해지므로 코드를 이해하고 사용하는데 도움이 됩니다.

반면에 이 원칙을 지키지 않으면 다음과 같은 문제가 발생할 수 있습니다:

  1. 유지 보수성 감소: 한 클래스가 너무 많은 책임을 지게 되면, 한 책임에 대한 변경이 다른 책임에 미치는 영향을 예측하기 어렵게 됩니다. 결과적으로 코드 변경이 어렵고 위험해집니다.
  2. 테스트 어려움: 여러 책임을 가진 클래스는 테스트하기가 어려워집니다. 한 책임에 대한 테스트를 하려면 다른 책임과 관련된 코드도 함께 실행되기 때문입니다.
  3. 코드 이해도 낮아짐: 클래스의 책임이 많아지면 클래스의 역할을 이해하고 사용하기가 어려워집니다. 이는 특히 다른 개발자가 코드를 이해하고 수정하는 데 문제가 될 수 있습니다.

따라서, 클래스가 단일 책임을 가지도록 설계하는 것은 좋은 객체 지향 설계를 위한 중요한 원칙입니다.

 

* 개방-폐쇄 원칙의 의미와 이 원칙을 따르는 설계의 장점에 대해 설명해주세요.

개방-폐쇄 원칙(Open-Closed Principle, OCP)은 소프트웨어 개체(클래스, 모듈, 함수 등)는 확장에는 열려 있어야 하고, 수정에는 닫혀 있어야 한다는 원칙입니다. 즉, 기능을 변경하거나 확장해야 할 때 기존의 코드는 수정하지 않고, 새로운 코드를 추가함으로써 기능의 변경이나 확장이 이루어져야 합니다.

이 원칙을 따르는 설계의 장점은 다음과 같습니다:

  1. 유지 보수성 향상: 기존 코드를 수정하지 않으므로, 기존 코드가 잘 작동하는 한 새로운 기능 추가나 변경이 기존 기능에 부정적인 영향을 미치지 않습니다. 따라서 버그의 발생 가능성이 줄어들고, 코드의 안정성이 높아집니다.
  2. 확장성 향상: 새로운 기능을 추가하거나 기존 기능을 변경해야 할 때, 기존 코드는 그대로 두고 새로운 코드를 추가하는 방식이므로, 시스템의 확장성이 좋아집니다. 이는 빠르게 변하는 요구사항에 효과적으로 대응할 수 있게 해줍니다.
  3. 재사용성 증가: 기존의 코드를 변경하지 않고도 새로운 기능을 추가할 수 있으므로, 기존 코드나 모듈을 재사용하기 쉽습니다. 이는 개발 시간을 단축시키고, 코드의 중복을 줄여주며, 개발 생산성을 향상시킵니다.

개방-폐쇄 원칙은 추상화와 다형성을 활용하여 구현할 수 있습니다. 예를 들어, 추상 클래스나 인터페이스를 정의하고, 이를 구현한 구체 클래스를 확장하여 새로운 기능을 추가하는 방식입니다. 이렇게 하면 기존 코드를 변경하지 않고도 새로운 기능을 추가하거나 기존 기능을 변경할 수 있습니다.

 

* 리스코프 치환 원칙을 위반했을 때 어떤 문제가 발생하는지 예를 들어 설명해주세요.

리스코프 치환 원칙(Liskov Substitution Principle, LSP)은 서브타입은 언제나 기반 타입으로 대체될 수 있어야 함을 의미합니다. 즉, 부모 클래스의 인스턴스를 자식 클래스의 인스턴스로 대체해도 프로그램이 제대로 작동해야 합니다.

이 원칙을 위반하면 다음과 같은 문제가 발생할 수 있습니다:

예를 들어, "사각형" 클래스가 "너비"와 "높이"라는 속성을 가지고, "넓이를 계산하는 메서드"를 가지고 있다고 생각해봅시다. 이 클래스를 상속받아 "정사각형" 클래스를 만든다면, "정사각형"은 "너비"와 "높이"가 항상 같아야 하므로, "너비"나 "높이"를 설정하는 메서드가 호출될 때 다른 하나의 속성도 같이 변경되어야 합니다.

그런데 만약 "사각형" 클래스의 인스턴스를 "정사각형" 클래스의 인스턴스로 대체해 사용하려고 하면 문제가 발생합니다. 예를 들어, "너비"와 "높이"를 각각 설정한 후 "넓이를 계산하는 메서드"를 호출하면, "사각형"에서는 기대한 결과를 얻을 수 있지만, "정사각형"에서는 기대한 결과를 얻지 못하게 됩니다.

, 리스코프 치환 원칙을 위반하면, 부모 클래스와 자식 클래스가 제대로 대체관계를 가지지 못하게 되어, 코드의 예측 가능성과 재사용성이 떨어지며, 버그의 발생 가능성이 높아집니다. 이런 문제를 피하기 위해, 상속을 사용할 때는 리스코프 치환 원칙을 항상 고려해야 합니다.

 

* "Liskov Substitution Principle"은 Method Overriding과 어떤 관련이 있나요?

메서드 오버라이딩은 자식 클래스에서 부모 클래스의 메서드를 재정의하는 것입니다. 만약 리스코프 치환 원칙을 위반하게 되면, 메서드 오버라이딩이 문제를 일으킬 수 있습니다. 예를 들어, 부모 클래스의 메서드와 동일한 이름과 시그니처를 가진 메서드를 자식 클래스에서 오버라이딩하되, 그 기능이나 동작 방식, 반환 값 등이 부모 클래스의 메서드와 많이 다르다면, 부모 클래스의 인스턴스가 들어갈 자리에 자식 클래스의 인스턴스가 들어가게 되면 프로그램이 예상대로 동작하지 않게 됩니다.

따라서, 메서드를 오버라이딩할 때는 리스코프 치환 원칙을 항상 염두에 두고, 부모 클래스의 메서드를 자식 클래스에서 재정의하더라도 프로그램의 동작에 문제가 없도록 해야 합니다.

 

* 인터페이스 분리 원칙을 위반하면 어떤 문제가 생길 수 있는지 설명해주세요.

인터페이스 분리 원칙(Interface Segregation Principle, ISP)은 클라이언트가 사용하지 않는 메서드에 의존하지 않도록, 즉 "클라이언트는 자신이 사용하지 않는 인터페이스에 의존하면 안 된다"는 원칙입니다. 이는 클라이언트 관점에서 필요한 메서드만을 제공하는 것이 중요하다는 의미입니다.

이 원칙을 위반하면 다음과 같은 문제가 발생할 수 있습니다:

  1. 낮은 응집력: 클라이언트가 사용하지 않는 메서드에도 의존하게 되므로 클래스나 모듈의 응집력이 낮아집니다. 응집력이 낮아지면 코드의 이해도가 떨어지고, 유지보수가 어려워집니다.
  2. 불필요한 의존성: 클라이언트는 필요하지 않은 메서드에 대해서도 의존성을 가지게 됩니다. 이로 인해 클라이언트는 자신이 사용하지 않는 메서드에 대한 변경사항에도 영향을 받게 될 수 있습니다.
  3. 낮은 재사용성: 인터페이스가 과도하게 크고 복잡해지면 재사용성이 떨어집니다. 특정 클라이언트에 맞춰진 크고 복잡한 인터페이스는 다른 클라이언트에서는 필요하지 않은 메서드들을 포함하게 될 수 있습니다.

따라서 인터페이스는 최대한 작게 나누고, 특정 목적에 맞게 분리하는 것이 좋습니다. 이렇게 하면 클라이언트는 자신이 필요로 하는 메서드만을 제공하는 인터페이스에 의존하게 되므로, 불필요한 의존성을 줄이고 코드의 유지보수성과 재사용성을 높일 수 있습니다.

 

* 의존성 역전 원칙에 대해 설명하고, 이 원칙이 설계에 어떤 영향을 미치는지 설명해주세요.

의존성 역전 원칙(Dependency Inversion Principle, DIP)은 고수준 모듈이 저수준 모듈에 의존하면 안 되며, 둘 다 추상화에 의존해야 한다는 원칙입니다. 또한, 추상화는 구체적인 사항에 의존하면 안 되며, 구체적인 사항이 추상화에 의존해야 합니다.

즉, 소프트웨어 컴포넌트 간의 의존관계가 하위 레벨에서 상위 레벨로 가는 것이 아니라, 상위 레벨의 추상화된 인터페이스를 향해 가야 함을 의미합니다.

이 원칙이 설계에 미치는 영향은 다음과 같습니다:

  1. 모듈 간의 느슨한 결합: DIP를 따르면 고수준 모듈과 저수준 모듈 사이의 의존성이 줄어들고, 이들은 추상화된 인터페이스에 의존하게 됩니다. 이로 인해 시스템의 각 부분 사이의 결합이 느슨해지며, 변경에 대한 영향이 줄어듭니다.
  2. 유지 보수성과 확장성 향상: 추상화에 의존함으로써 코드 변경이나 기능 추가가 상대적으로 용이해집니다. 하위 모듈이 변경되거나 새로운 하위 모듈이 추가되더라도, 상위 모듈은 변경되지 않거나 최소한의 변경만으로도 대응할 수 있습니다.
  3. 재사용성 증가: 고수준 모듈과 저수준 모듈이 추상화에 의존하게 되므로, 각 모듈이 독립적이고 재사용 가능해집니다. 따라서 코드의 재사용성이 증가하게 됩니다.

DIP 지키지 않으면, 하위 레벨의 모듈 변경이 상위 레벨의 모듈까지 영향을 미칠 있어 시스템이 불안정해질 있으며, 유지보수와 확장이 어려워질 있습니다. 원칙은 특히 대규모 시스템에서 중요한데, 이를 지키면 시스템의 다른 부분에 영향을 주지 않고 특정 부분을 변경하거나 확장할 있기 때문입니다.

 

* 실제 작업에서 SOLID 원칙을 어떻게 적용하고 있나요?

실제 작업에서 SOLID 원칙은 코드의 품질을 높이고 유지 보수를 쉽게 만드는 데에 도움을 줍니다. 각 원칙은 다음과 같이 적용될 수 있습니다:

  1. 단일 책임 원칙 (Single Responsibility Principle, SRP): 하나의 클래스나 함수는 하나의 책임만을 가져야 합니다. 원칙을 적용함으로써, 하나의 변경이 다른 기능에 영향을 미치는 것을 최소화하고 코드를 이해하고 유지 관리하기 쉽게 만들 있습니다.
  2. 개방-폐쇄 원칙 (Open-Closed Principle, OCP): 기존의 코드를 변경하지 않고 기능을 추가하거나 변경할 있도록 설계해야 합니다. 원칙은 주로 상속과 인터페이스를 통해 구현됩니다. 원칙을 지키면 기존 코드에 영향을 미치지 않고 새로운 기능을 추가할 있으므로 유지 보수가 용이해집니다.
  3. 리스코프 치환 원칙 (Liskov Substitution Principle, LSP): 하위 클래스는 상위 클래스를 대체할 있어야 합니다. 원칙은 주로 메서드 오버라이딩과 관련이 있습니다. 원칙을 지키면 클래스의 일관성이 유지되고 코드의 예측 가능성이 높아집니다.
  4. 인터페이스 분리 원칙 (Interface Segregation Principle, ISP): 클래스는 자신이 사용하지 않는 인터페이스에 의존하지 않아야 합니다. 원칙을 지키면 필요 없는 의존성을 줄이고 모듈 간의 결합도를 낮출 있습니다.
  5. 의존성 역전 원칙 (Dependency Inversion Principle, DIP): 고수준 모듈은 저수준 모듈에 직접 의존하는 대신 추상화에 의존해야 합니다. 원칙을 지키면 코드의 유연성과 재사용성이 증가하고 모듈 간의 결합도가 낮아집니다.

* SOLID 원칙을 지키는 것이 중요하다고 생각하는 이유는 무엇인가요?

SOLID 원칙을 지키는 것이 중요한 이유는 크게 세 가지로 요약할 수 있습니다:

  1. 유지 보수성: SOLID 원칙을 따르면 코드의 유지 보수가 용이해집니다. 각 원칙이 코드의 결합도를 낮추고 응집력을 높여서, 변경이나 추가 기능이 필요할 때 그 영향을 최소화하게 합니다. 이는 유지 보수 비용을 줄이는 데 도움이 됩니다.
  2. 확장성: 개방-폐쇄 원칙과 의존성 역전 원칙 같은 SOLID 원칙은 코드의 확장성을 높입니다. 새로운 요구 사항이나 기능 추가가 필요할 때, 기존 코드를 크게 변경하지 않고도 새로운 기능을 추가하거나 기존 기능을 수정할 수 있게 됩니다.
  3. 재사용성: SOLID 원칙을 따르면 코드의 재사용성이 높아집니다. 각각의 클래스와 모듈이 잘 정의된 책임을 갖게 되어, 필요할 때 다른 곳에서 재사용할 수 있게 됩니다.

위와 같이, SOLID 원칙은 개발자가 효율적이고 유지 보수가 쉬운, 확장 가능하며 재사용 가능한 코드를 작성하는 도움이 됩니다. 그러나 모든 상황에 SOLID 원칙을 무조건 적용하는 것이 아니라, 상황에 맞게 적절하게 적용해야 합니다.

 

* SOLID 원칙을 준수하면서 겪었던 어려움은 무엇이었나요?

  1. 설계 복잡성: SOLID 원칙을 준수하려면 종종 추가적인 추상화 레벨이나 디자인 패턴이 필요합니다. 이로 인해 설계가 복잡해질 있습니다. 예를 들어, 의존성 역전 원칙을 준수하기 위해 인터페이스나 추상 클래스를 도입하면, 코드의 복잡성이 증가할 있습니다.
  2. 이해도와 학습 곡선: SOLID 원칙을 처음 배우고 이해하는 것은 쉽지 않을 있습니다. 원칙이 의미하는 바와 원칙을 지키기 위한 방법을 이해하는 데는 시간이 필요하며, 이는 개발 과정에 추가적인 시간을 요구합니다.
  3. 과도한 적용: 때로는 SOLID 원칙을 과도하게 적용하는 경향이 있을 있습니다. 모든 클래스나 모듈이 단일 책임 원칙을 완벽하게 지키려다 보면, 과도한 클래스 분리가 일어나서 오히려 코드를 이해하고 유지 보수하는 어려움을 초래할 있습니다.
  4. 성능 문제: SOLID 원칙의 적용은 때때로 성능에 부정적인 영향을 미칠 있습니다. 예를 들어, 인터페이스를 통한 의존성 역전은 런타임에 객체 생성과 가비지 컬렉션 비용을 증가시킬 있습니다.

* SOLID 원칙과 디자인 패턴 사이의 관계에 대해 설명해주세요.

SOLID 원칙과 디자인 패턴은 모두 좋은 소프트웨어 설계를 위한 지침입니다. 그러나 그들은 다른 목적과 적용 범위를 가지고 있습니다.

SOLID 원칙은 객체 지향 프로그래밍의 핵심 원칙들을 총체적으로 설명한 것입니다. 이 원칙들은 클래스와 객체, 그리고 이들 간의 관계를 어떻게 설계해야 하는지에 대한 가이드라인을 제공합니다. SOLID 원칙을 따르면 느슨한 결합, 높은 응집력, 재사용 가능성, 유지 보수성 등을 달성할 수 있습니다.

한편, 디자인 패턴은 특정 문제에 대한 해결책을 제공합니다. 이는 재사용 가능한 설계를 만드는 데 도움이 됩니다. 디자인 패턴은 일반적으로 소프트웨어 개발에서 반복적으로 발생하는 문제를 해결하는 방법을 제공합니다.

SOLID 원칙과 디자인 패턴은 서로 상호 보완적인 관계에 있습니다. 디자인 패턴은 대부분 SOLID 원칙을 따르며, SOLID 원칙을 이해하고 적용하면 디자인 패턴을 더 잘 이해하고 적용할 수 있습니다. 예를 들어, "전략 패턴"은 개방-폐쇄 원칙을 따르며, "팩토리 패턴"은 의존성 역전 원칙을 따릅니다.

따라서 SOLID 원칙과 디자인 패턴은 각각 다른 측면에서 소프트웨어 설계의 품질을 향상시키는 도구로 볼 수 있으며, 이 두 가지를 함께 사용하면 더욱 견고하고 유지 보수가 용이한 코드를 작성하는 데 도움이 될 수 있습니다.

 

더보기
  1. 전략 패턴과 개방-폐쇄 원칙(OCP)
    전략 패턴은 알고리즘 또는 정책을 캡슐화하는 행위 디자인 패턴입니다. 패턴은 알고리즘을 별도의 클래스로 정의하고, 공통 인터페이스를 갖게 하여 상호 교환 가능하게 만듭니다. 이로 인해 알고리즘을 독립적으로 변경하거나 확장할 있게 되며, 이는 바로 개방-폐쇄 원칙(OCP) 표현입니다.
    개방-폐쇄 원칙은 "소프트웨어 구성요소(클래스, 모듈, 함수 등등) 확장에는 열려 있고, 변경에는 닫혀 있어야 한다."라는 원칙입니다. 이를 통해 새로운 기능을 추가하더라도 기존 시스템의 수정 없이 확장이 가능하게 됩니다. 전략 패턴은 원칙을 구현하며, 알고리즘의 변화에 따라 기존 클래스를 수정하지 않고, 새로운 알고리즘을 추가하여 확장할 있게 합니다.
  2. 팩토리 패턴과 의존성 역전 원칙(DIP)
    팩토리 패턴은 객체 생성 로직을 캡슐화하는 생성 패턴입니다. 패턴은 클라이언트가 직접 객체를 생성하지 않고, 팩토리 클래스를 통해 객체를 생성합니다. 이는 클라이언트와 구체적인 객체 생성 클래스 사이의 의존성을 줄여줍니다.
    의존성 역전 원칙은 "고수준 모듈은 저수준 모듈에 의존하면 되고, 추상화에 의존해야 한다."라는 원칙입니다. , 구체적인 클래스에 의존하는 것이 아니라, 인터페이스나 추상 클래스에 의존하게 하는 것입니다.
    팩토리 패턴에서는 객체 생성을 담당하는 팩토리 클래스를 통해 원칙을 구현합니다. 클라이언트는 구체적인 클래스를 직접 참조하지 않고, 팩토리 클래스에 객체 생성을 요청합니다. 이로 인해 객체 생성을 위해 클라이언트가 구체적인 클래스에 의존하지 않게 되며, 의존성이 역전되는 것입니다.