@Transactional 메소드 내에서 @Transactional(propagation = Propagation.REQUIRED_NEW) 메소드를 실행하게되면 어떤 일이 발생할까

트랜잭셔널 메소드에서 새로운 트랜잭션을 시작하면 어떤일이 발생하는지 알아보자.


1. 애플리케이션 시작 시 작업

1-1. 트랜잭션 관리자 등록

  • 애플리케이션 시작 시 트랜잭션 관리자가 등록된다.
  • 트랜잭션 전파 정책(Propagation)을 처리할 수 있도록 AOP 프록시가 생성된다.

1-2. AOP 프록시 생성

  • @Transactional이 적용된 메소드에 대해 프록시가 생성된다.
  • 각각의 메소드가 호출될 때 전파 정책을 해석하도록 설정된다.

2. 부모 매소드 실행(@Transactional, REQUIRED 전파 정책)

2-1. 트랜잭션 시작

  • 부모 메소드가 호출되면 프록시가 트랜잭션 관리자를 통해 트랜잭션을 시작
  • 트랜잭션 전파 정책 Propagation.REQUEIRED의 기본 동작에 따라 기존 트랜잭션이 없으면 새 트랜잭션을 시작.
  • 데이터베이스 연결이 확보되고, auto-commit이 비활성화됨

2-2. 비지니스 로직 실행 중 자식 메소드 호출

  • 부모 메소드 내에서 Propagation.REQUIRED_NEW가 적용된 자식 메소드가 호출됨.

3.자식 메소드 실행(@Transactional, Propagation.REQUIRED_NEW)

3-1. 부모 트랜잭션 일시 중단

  • 자식 메소드가 호출되면 부모 트랜잭션이 일시중단 상태로 변경됨.
  • 일시 중단된 트랜잭션은 컨텍스트에 보관되며, 자식 메소드가 끝날때까지 대기.

3-2. 새로운 트랜잭션 시작

  • 자식 메소드는 항상 별도의 트랜잭션에서 실행
    • 트랜잭션 관리자가 새로운 데이터베이스 연결을 확보하거나 기존 연결을 재사용 하여 별도 트랜잭션을 시작.
    • 새로운 트랜잭션은 부모 트랜잭션과 독립적으로 커밋 또는 롤백될 수 있다.

3-3. 비지니스 로직 실행

  • 자식 메소드의 비지니스 로직이 새로운 트랜잭션 내에서 실행됨.
  • 데이터베이스 작업은 자식 트랜잭션의 컨텍스트에서만 적용됨.

3-4. 자식메소드 종료

  • 자식 메소드 실행이 끝나면 아래와 같은 동작 발생
    • 정상종료시, 커밋
    • 예외 발생시 자식 트랜잭션롤백

4. 부모 메소드 재개

4-1. 부모 트랜잭션 복구

  • 자식 메소드 실행이 끝난 후, 무보 트랜잭션이 일시중단 상태에서 복구됨.
  • 부모 트랜잭션은 자식 트랜잭션과는 독립적으로 계속 진행됨.

4-2. 부모 메소드 비지니스 로직 실행(남은 작업)

  • 부모 메소드의 나머지 비지니스 로직 실행.
  • 데이터베이스 작업은 부모 트랜잭션 컨텍스트에 반영.

4-3 부모 메소드 종료

  • 부모 메소드 종료되면 아래와 같은 동작 발생
    • 정상 종료시 커밋
    • 예외 발생시 부모 트랜잭션 롤백

5. 특이 케이스

5-1. 자식 트랜잭션 커밋 후 부모 트랜잭션 롤백

  • 부모 트랜잭션이 나중에 롤백 되더라도 자신 트랜잭션은 독립적으로 커밋 되었기 때문에 영향을 받지 않는다.

5-2. 자식 트랜잭션 롤백 후 부모 트랜잭션 정상 종료

  • 자식 트랜잭션이 실패하면 부모 트랜잭션은 이를 감지할 수 없다.
    • 단, 예외를 명시적으로 처리한다면 감지시킬 수 있다.
    • 부모 트랜잭션은 독립적으로 커밋 또는 롤백된다.

정리:

  1. 부모 메소드(@Transactional, Propagation.REQUIRED)가 호출되며 트랜잭션이 시작됨.
  2. 자식 메소드(@Transactional, Propagation.REQUIRED_NEW)가 호출되면 부모 트랜잭션 일시중단.
  3. 자식 메소드는 새로운 트랜잭션에서 실행되며 독립적으로 커밋 또는 롤백됨
  4. 자식 메소드 실행 후, 부모 트랜잭션이 북구되어 남은 로직 실행
  5. 자식과 부모 트랜잭션은 서로 독립정이며, 서로의 성공 여부에 영향을 주지 않음.

이런 구조로 트랜잭션간의 독립성이 보장되며, 필요 시점에 새로운 트랜잭션을 생성해 데이터 무결성을 관리하는데 도움이 된다.

반응형

@Transactional 어노테이션이 있는메소드, 스프링 시작부터 메소드 시작까지의 작업

@Transactional 어노테이션이 있는 메소드가 실행될때 어떤 일이 일아날까.
스프링 시작부터 메소드가 실행되고 종료될때까지 어떤일 일어나는지 알아보자.


1.어플리케이션 시작시 작업

1-1.트랜잭션 관리자 등록

  • Spring Boot는 자동 설정(Auto Configuration)을 통해 적절한 트랜잭션 관리자를 등록한다.
    • 에를들어, JPA를 사용하는 경우 JpaTransactionManager를 기본으로 등록한다.
  • 이 관리자는 트랜잭션의 시작, 커밋, 롤백 등을 담당함.

1-2.AOP 프록시 생성

  • @EnableTransactionManagement 또는 자동 설정에 의애 트랜잭션 메소드가 AOP프록시로 감싸진다.
  • 스프링은 빈 스캐닝 중 @Transactional이 붙은 메소드를 확인하고, 해당 메소드가 실행될 때 트랜잭션 관리가 적용되도록 프록시 객체를 생성한다.
    • 기본적으로 CGLIB 또는 JDK 동적 프록시를 사용한다.

2.메소드 실행 시 작업

2-1.프록시를 통한 메소드 호출

  • 트랜잭션 메소드를 호출하면 실제 메소드를 실행하기 전에 프록시 객체가 인터셉트한다.
  • 프록시는 트랜잭션 설정과 관리작업을 수행한 후 실제 메소드를 호출한다.

2-2.트랜잭션 동작 정의 확인

  • 프록시는 메소드에 선언된 @Transactional송성을 확인한다.
    • 트랜잭션 전파(Porpagation)
    • 격리수준(Isolation Level)
    • 읽기 전용(Read-only)
    • Timeout
    • 롤백 정책(Rollback Rules)

2-3.트랜잭션 시작

  • 트랜잭션 관리자는 트랜잭션을 시작한다.
    • 트랜잭션 전파 전책에 따라 새 트랜잭션을 생성하거나 기존 트랜잭션에 참여한다.
  • 데이터베이스 커넥션을 확보하고(필요시), auto-commit이 비 활성화 된다.

3.실제 메소드 실행

3-1.비지니스 로직 실행

  • 트랜잭션 컨텍스트 내에서 실제 메소드가 실행됨.
  • 데이터베이스의 CRUD 작업이 발생하면, 변경 사항은 트랜잭션 컨텍스트 내에 보류됨

3-2.예외 처리

  • 메소드 실행 중 예외가 발생하면, 프록시는 롤백 정책을 참조하여 트랜잭션 롤백 여부를 결정.
    • 기본적으로 RuntimeExceptionError 가 발생하면 롤백됨.
    • checked exception은 명시적으로 롤백 설정이 없으면 커밋됨.

4.메소드 실행 완료 후 작업

4-1. 트랜잭션 커밋 또는 롤백

  • 메소드 실행이 성공적으로 끝나면 트랜잭션 관리자는 트랜잭션을 커밋한다.
    • 데이터베이스 변경 사항이 확정되고, 커넥션이 반환된다.
  • 예외가 발생한 경우 롤백 작업이 수행된다.
    • 변경된 데이터는 폐기되며, 트랜잭션이 중단됨.

4-2.리소스 정리

  • 트랜잭션이 종료되면 사용된 데이터베이스 커넥션 및 기타 리소스가 pool로 반환된다.
  • 트랜잭션 컨텍스트와 관련된 쓰레드 로컬 데이터가 정리된다.

5.애플리케이션 종료 시 작업

  • 트랜잭션 관리자는 애플리케이션 종료 시 등록된 리소스를 정리하며, 사용중인 데이터베이스 연결이나 트랜잭션 관련 매니저를 닫는다.

정리

  1. 애플리케이션 시작 : 트랜잭션 관리자 설정, AOP프록시 생성
  2. 메소드 호출시 :
    • 프록시가 트랜잭션을 시작, 트랜잭션 속성 확인
    • 메소드를 실행하며 예외 여부에 따라 커밋 또를 롤백을 결정
  3. 메소드 실행 후 : 트랜잭션이 종료되고 리소스 반환
  4. 애플리케이션 종료시 : 트랜잭션 관련 리소스 정리
반응형

스프링 부트 어플리케이션이 실행되면 어떤 일들이 일어나는가.

Spring Boot Application이 시직되면 내부에서 일어나는 일에 대해 정리한다.

1.JVM 및 Main 메서드 시작

  • JVM 이 애플리케이션을 실행하며 main메서드를 호출
  • Spring Boot 애플리케이션은 @SpringBootApplication 어노테이션이 붙은 클래스의 main메서드를 시작점으로 잡는다.

2.SpringApplication 초기화

  • SpringApplication.run() 메서드가 호출되며 스프링 애플리케이션 컨텍스트가 초기화됨
  • 주요 작업
    • 애플리케이션 타입 결정(Servlet, Reactive, None)
    • 배너 출력 여부 설정
    • 기본 프로퍼티 및 환경 로딩

3.Environment 생성 및 설정

  • Environment 객체가 생성되어 시스템 속성, 환경 변수, 프로파일 등이로그됨
  • 외부설정(ex: application.properties, application.yml)이 읽혀지고 환경 변수와 병합됨.

4.Application Context 생성

  • Spring Boot 는 실행 모드에 따라 적절한 컨텍스트를 선택함.
    • AnnotationConfigServletWebserverApplictionContext (웹 어플리케이션)
    • AnnotationConfigReactiveWebServerApplicationContext (리액티브 어플리케이션)
    • AnnotationConfigApplictionContext (비 웹 어플리케이션)
  • 이 컨택스트는 어플리케이션의 모든 빈(bean) 및 설정을 관리함

5.CommandLineRunner 및 ApplicationRunner등록

  • ApplicationContext 초기화 중에 CommandLineRunnerApplicationRunner 인터페이스를 구현한 빈들이 등록됨
  • 이 빈들은 애플리캐이션 초기화가 완료된 후 추가 작업을 실행할 수 있음.

6.자동설정(Auto Configuration)

  • Spring Boot는 @EnableAutoConfiguration을 통해 여러 자동 설정 클래스(AutoConfiguration)을 활성화함.
  • 자동 설정은 클래스 패스 및 환경 변수를 기반으로 애플리케이션에 필요한 빈을 자동으로 구성함.
    • Ex) DB Connection 설정, Web server 설정, Spring Security 설정 등

7.빈(Bean) 등록 및 DI(의존성 주입)

  • 스프링 애플리캐이션 컨텍스트 내에서 모등 @Component, @Service. @Repository, @Controller 등의 빈을 스캔하여 등록
  • 등록된 빈들 간의 의존성을 주입(생성자, 세터, 필드 기반)
  • 프로파일 조건에 따라 특정 빈만 활성화될 수도 있음.

8.내장 웹서버 시작(Optional)

  • 웹 어플리케이션인 경우, Spring Boot는 내장된 톰캣, 제티, 언더토우 등을 통해 HTTP서버를 시작
    • HTTP 포트, SSL설정 등이 적용됨.
  • 서블릿 컨테이너가 초기화 되고 DispatcherSErvlet이 설정됨.

9.Spring MVC 또는 WebFlux 설정(웹 애플리케이션인경우)

  • DispatcherServlet을 통해 요청을 처리하는 기본 매핑을 설정
  • HandlerMapping,HandlerAdapter,ViewReolver등을 초기화 하여 웹 요청에 필요한 구성요소를 준비

10.이밴트 발행 및 리스너 실행

  • Spring Boot는 애플리케이션 실행 과정에서 여러 이벤트를 발행함.
    • ApplicationStartingEvent
    • ApplicationEnvironmentPreparedEvent
    • ApplicationPreparedEvent
    • ApplicationStartedEvent
    • ApplicationReadyEvent
  • 위 이벤트를 통해 특정 시점에 사용자 정의 작업을 실행할 수 있음.

11.애플리케이션 준비 완료

  • 애플리케이션 컨택스트 초기화가 완료되고, 모든 빈이 생성되고 초기화됨
  • CommandLineRunnerApplicationRunner구현체가 실행됨.
  • ApplicationReadyEvent 가 발행되며 애플리케이션이 요청을 처리할 준비가 완료됨

12.애플리케이션 실행 상태 유지

  • Spring Boot는 실행 상태를 유지하며 HTTP요청을 대기하거나 비웹 애플리케이션에서는 작업을 지속함.
  • 내부적으로 애플리케이션 컨택스트는 필요에 따라 라이프 사이클을 관리함.

13.애플리케이션 종료

  • 애플리캐이션 종료시 Spring Boot는 ApplicationContext를 닫으며 빈의 destroy() 메서드 호출 및 리소스 정리를 수행
  • ApplicationFailedEvent 가 발행될 경우 애플리케이션 시패를 기록

Spring Boot Application으 LifeCycle에 대해 간략하게 정리 해 보았다.
Spring 기반의 서비스를 운영 / 개발 하는 회사라면 자주 나오는 질문이니 숙지하고 있으면 좋다.
세부 내용까지는 힘들더라도 1~12번 넘버링 되어있는 순서만이라도 기억하면 좋다.

반응형

Jetbrain Blog의 번역 글입니다. 원본은 아래 주소에 접속하여 확인 해 주세요 
https://blog.jetbrains.com/kotlin/2023/11/kotlin-multiplatform-development-roadmap-for-2024/ 

 

Kotlin Multiplatform Development Roadmap for 2024 | The Kotlin Blog

To equip you with the best cross-platform development experience, JetBrains aims to deliver a host of further improvements to the core Kotlin Multiplatform technology, Compose Multiplatform, KMP tooling, and KMP libraries in 2024.

blog.jetbrains.com


Kotlin Multiplatform Development Roadmap for 2024

더보기

With the recently achieved stability of Kotlin Multiplatform, development teams worldwide can now seamlessly and confidently adopt it in production. However, this is just the beginning for KMP and its ecosystem. To equip you with the best cross-platform development experience, JetBrains aims to deliver a host of further improvements to the core Kotlin Multiplatform technology, Compose Multiplatform, KMP tooling, and KMP libraries in 2024. Read on to learn what we’re planning and our priorities in these areas.

최근 완성된 코틀린 멀티플랫폼의 안정성 덕분에, 세계의 많은 개발팀들은 이제 장애물 없이 코플린 멀티 플랫폼을 프로덕션에 자신있게 적용할 수 있게 되었다.  하지만 이는 단지 KMP(Kotlin Multiplatform)과 에코시스템을 시작하는것일 뿐이다. 최고의 크로스 플랫폼 개발을 경험을 갖추게 하기 위해서, 2024년에 JetBrains는 핵심 코틀린 펄티플랫폼기술, 컴포즈 멀티 플랫폼, KMP도구와 라이브러리 같은 미래의 발전을 주도할것이다. 이 분야에서 무엇을 배워야하고, 어떤 순서로 배뭐야할지 알아보자. 

Compose Multiplatform

더보기

We’re dedicated to making Compose Multiplatform a framework that allows creating beautiful and performant applications that look the same way on all supported platforms. Right now, our main focus is to get Compose for iOS to Beta, but we’re also working on other things. Here’s what we plan to do:

  • Make all Jetpack Compose core APIs and components multiplatform.
  • Improve rendering performance on iOS.
  • Make scrolling and text editing in Compose for iOS apps behave the same as in iOS native apps.
  • Implement a common API for sharing all types of resources.
  • Integrate with iOS and Desktop accessibility APIs.
  • Provide a solution for multiplatform navigation.

Many of the aforementioned improvements benefit Compose for Desktop, as well. In addition, we’re working on improving its stability and evolving it according to the feedback from those who use it in production.

We’ll also continue to explore what’s possible with Compose for Web, specifically with Wasm. Our nearest goal is to promote it to Alpha, which includes:

  • Allowing you to port your existing apps and reuse all of your common code.
  • Supporting different screen sizes, orientations, and densities.
  • Supporting input from a mouse, touchscreen, physical keyboard, or onscreen keyboard.
  • Improving performance and binary size.

 

우리는 컴포즈 멀티플랫폼을 만들기 위해 헌신했다. 컴포즈 멀티플랫폼은 우리가 지원하는 모든 플랫폼에서 어플리케이션이 동일하게 동작하고 동일하게 보이도록지원해주는 아름답고 효율적인 프레임워크이다. 지금 당장 우리가 집중하고 있는것은 iOS를 위한 컴포즈 Beta 버전이다. 하지만 우리는 다른것들도 진행하고있다. 아래는 우리의계획이다. 

  • 모든 Jetpack Compose 코어API와 멀티플랫폼 컴포넌트 제작
  • iOS에서의 랜더링 퍼포먼스 향상
  • iOS 앱용 컴포즈에서의 스크롤링, 문자 수정(text edting) 동작을 iOS네이티브 앱과 동일하게 만들기
  • 모든 타입의 리소스를 공유할 수 있는 공통API 구현
  • iOS와 데스크탑의 접근성 API 통합
  • 멀티플렛폼 네비게이션을 위한 소루션 제공

앞서 말한 많은 개선사항은 컴포즈 for 데스크탑에도 역시 도움이 된다. 더욱이, 우리는 제품 사용자들의 피드백을 통해서 안정성 향상과 새로운 기능 향상 작업도 진행하고있다.

우리는 또한 컴포즈 for Web, 특히 Wasm에 대한 작업도 지속하고있다. 우리의 가장 가까운 목표는 컴포트 for Web을 알파 버전으로 만드는 것이다. 알파버전엔 다음이 포함된다. 

  • 이미 존재하는 앱들의 포팅기능, 공통코드의 재사용 기능.
  • 다양한 화면 사이즈(size, orientation, densitie) 지원,
  • 마우스, 터치스크린, 키보드, 스크린 키보드 지원
  • 퍼포먼스와 용량 향상.
  •  

Tooling

We’re committed to providing a great IDE experience for Kotlin Multiplatform. That means not only investing in the core platform and, for example, migrating Kotlin IDE plugin to K2 compiler frontend, but also providing a single tool (Fleet) for all Kotlin Multiplatform targets and codebases where you integrate it, eliminating the need to constantly switch between different IDEs.

We plan to quickly iterate over your feedback about using Fleet for Kotlin Multiplatform development  to make sure that we have everything you need for your development experience to be great. Among other things, we’re going to deliver in the following areas:

  • Enhanced support for Compose Multiplatform, including live preview for common code and visual debugging tools.
  • The IDE helping you with project configuration.
  • Unified and enhanced debugging experience for all parts of your Multiplatform project.

우리는 Kotlin Multiplatform을 위한 훌륭한 IDE 환경을 제공하기 위해 최선을 다하고 있습니다. 이는 Kotlin IDE plugin을 K2 compiler frontend 마이그레이팅 하는것 같은 코어 플랫폼 뿐만 아니라 개발자들이 통합하게 될 모든 Kotlin Multiplatform 타겟과 코드베이스를 위한 싱글툴(Fleet)을 제공하여 끊임없는 IDE변경을 제거한다는 의미입니다. 

우리는 Fleet for Kotlin Multiplatform development의 사용성에 대한 피드백을 빠르고 반복적으로 처리하여 개발자들에게 훌륭한 개발 경험을 제공하려고 합니다. 이런 행위들 사이에서 우리는 아래와 같은것들을 제공할 것 입니다.

  • 공통 코드를 위한 라이브 프리뷰와 시각적 디버깅 툴을 포함한 컴포즈 멀티플랫폼 서포트 증가
  • IDE의 프로젝트 configuration 도움
  • 멀티플랫폼 프로젝트의 모든 부분에서 통합되고 향상된 디버깅 경험 제공.

Multiplatform core

더보기

One of the popular Kotlin Multiplatform scenarios is sharing code with the iOS target. We want to focus on the development experience of iOS developers who work with Kotlin Multiplatform frameworks in their codebases.

The main initiative in this area is a direct Kotlin-to-Swift export. It will eliminate the Objective-C bottleneck, allowing for broader Swift language support and more natural exporting of APIs. Additionally, we are creating tools specifically for Kotlin library authors. These tools are designed to improve the compatibility and user-friendliness of Kotlin APIs when exported to Swift. We’re also paying close attention to tooling. The IDE and build systems are essential parts of the developer experience, and our goal is to ensure that the Swift Export integrates smoothly.

Our other initiatives include speeding up Kotlin/Native compilation, enhancing CocoaPods integration, and introducing support for exporting your framework with SwiftPM.

We also plan to continue exploring ways to improve the build setup of Kotlin Multiplatform applications. With Kotlin 1.9.20, we released huge improvements in the Gradle Multiplatform DSL, making it easier to read and write. We will continue to gradually improve it. In addition, we’re experimenting with Amper, a new project configuration tool focused on usability, onboarding, and IDE support.

Kotlin Multiplatform의 가장 유명한 시나리오 중 하나는 iOS 타겟괴 코드를 쉐어 하는 것 이다. 코드 베이스에서 코틀린 멀티플랫폼 프레임워크를 사용하는 iOS개발자의 경험에 중점을 두고 있다. 

이 분야에서의 주요 계획은 Kotlin-to-Swift의 직접 번역(direct export)이다.  이를 통해 Object-C 보틀렉을 제거와 광범위한 Swift언어 지원, 자연스러운 API exporting이 가능해진다. 더욱이, 우리는 코틀린 라이브러리 개발자들을 위한 도구(tool)들을 만들었다. 이 도구들은 Swift로 export될 때  Kotlin API의 호환성과 사용자친화성을 개선하도록 디자인 되다. 우리는 툴링(tooling)에도 세심한 주의를 기울이고 있다. IDE와 빌드 시스템은 개발자 경험의 중요한 부분입니다. 우리의 목표는 Swift Export를 부드럽게 만드는 것 이다. 

우리의 또 다른 우선순위는 Kotlin/Native 컴파일의 속도 증가, CocoaPods의 강화, SwiftPM을 사용한프레임워크 exporting 서포트 소개 를 포함하고 있다. 

우리는 또한 코틀린 멀티 플랫폼 어플리케이션의 빌드 셋업 향상을 위한 방법도 지속적으로 탐험할 계획이다. Kotlin1.9.20애서 우리는 Gradle Multiplatform DSL의 거대한 향상을 릴리즈하여 읽고, 쓰기 쉽게 만들었다. 우리는 계속적으로 향상시킬 예정이다. 더욱이 우리는 Amper라는 실험을 하고있다. Amper는 사용성, 온보딩, IDE서포트에 초점을 맞춘 새로운 프로젝트 configuration tool이다. 

Library ecosystem

더보기

As the Kotlin Multiplatform ecosystem is growing fast, the backward compatibility of the libraries becomes crucial. To ensure it, the JetBrains team and library creators must work together. Here’s our plan:

  • Improve the klib format so library creators can leverage their knowledge of building JVM libraries.
  • Implement the same code-inlining behavior in Kotlin Multiplatform libraries as for the JVM.
  • Provide a tool that ensures that your multiplatform library public API hasn’t changed in an incompatible way.

We’re also going to improve the publishing process for KMP libraries. Specifically, we plan to:

  • Make it possible to build and publish a KMP library without having a Mac machine.
  • Provide templates and extensive guidelines for creating and publishing a KMP library.

Even though Kotlin Multiplatform is now stable, we’re planning significant updates. But don’t worry: Libraries built with the current format will still work with newer Kotlin versions.

코틀린 멀티플랫폼의 에코시스템이 빠르게 성장함에 따라 라이브러리들의 이전 버전과의 호환성이 중요해졌다. 호환성을 위해서 JetBrains 팀과 라이브러리 제작자들은 함께 일해야만한다. 아래는 우리의 계획이다. 

  • klib format 발전으로 라이브러리 크리에이터들이 그들의 JVM라이브러리 빌드 지식을 향상시킬 수 있다.
  • 코틀린 멀티플랫폼의 code-inlining 행동이 JVM에서의 행동과 동일하도록 구현한다. 
  • 멀티플랫폼 라이브러리의 퍼블릭 API들이 호환되지 않는 방향으로 변경되지 않게 하는 도구를 제공한다. 

우리는 또한 KMP라이브러리의 퍼플리싱 프로세스 향상할 것이다. 특히, 아래와 같은 계획이다. 

  • Mac 없이 KMP라이브러리를 빌드하고 배포할 수 있게 만든다.
  • KMP라이브러리를 생성하고, 배포하기 위한 템플릿과 광범위한 가이드라인을 제공한다. 

Read more

반응형

https://www.clien.net/service/board/cm_keyboard/15249685

 

이런 조건을 만족하는 블루투스 키보드 있을까요? : 클리앙

안녕하십니까, 데스크톱에는 리얼포스 R2 45g를 사용 중입니다. 키보드에 이돈을 쓰는게 맞나 고민 많이 했는데 키감도 너무 좋고 생긴것도 고급스럽고 (청색-회색 키캡) 거진 2년 가까이 타이핑

www.clien.net

 

위글의 댓글에 추천된 키보드들의 사양을 정리해본다. (내기준에서 중요하다고 생각하는 사양이다.)

제조사 이름 인터넷최저가 무게 키보드 방식 런타임 멀티페어링 비고
키크론 K3 124000 396g 적축 34h 3 모양이좀
newPhy f1 118500 350 적축 안나옴 안나옴 키배열구림
filco 마제스터치2 컨버터블 텐키리스 165000   적축   4 건전지써야함
한성 GK893B Sports  145000 830 무접점 100h 3  
앱코 KN01 BT 119000 840 무접점   3  
               
               

 

결국 무게때문에 키크론을 사야할듯하다.

반응형

심심해서 nginx에 대해서 검색하고있었는데 비기너스 가이드 beginners_guide가 번역된곳이 없는거같아서 번역해본다.

영어실력이 미천하니 참고로만 봐주시면 좋겠다.

원본 링크 http://nginx.org/en/docs/beginners_guide.html

글 작성일 2021.06.08

목차

  • 시작, 멈춤, 리로딩 설정
  • 설정파일(컨피그파일) 구조
  • 정적파일(Static content) 제공
  • 간단한 프록시 서버 만들기
  • FaxtCGI Proxing 세팅

이 가이드는 nginx에 대한 기본적인 소개화 함께 nginx를 이용해서 수행할 수 있는 간단한 작업에 대해서 서술하고있다. 글을 읽는 사람의 시스템에 이미 nginx가 설치 되어있다고 가정하고 설명을한다. nginx가 아직 설치되지 않았다면 ** 인스톨 페이지 ** 를 참조하도록하라. 이 가이드는 nginx를 시작하는법과 멈추는법, 설정(configuration)을 리로드 하는법, 설정파일의 구조 설명, nginx가 정적 컨텐츠(static content)를 제공하도롱 설정하는법에 대한 설명, nginx를 프록시 서버로 설정하는법, FastCGI 애플리케이션으로 세팅 하는법에 대해 설명한다.

nginx는 하나의 마스터 프로세스와 몇개의 워커 프로세스를 가진다. 마스터 프로세스의 주된 목정은 설청파일을 읽고, 수행하는것과 워커프로세스를 관리하는것이다. 워커 프로세스는 실제 요청을 수행한다. nginx는 워커 프로세스 사이의 효율적인 요청(request)분배를 위해서 이벤트 기반 모델, OS 종속적인 메카니즘을 사용한다. 워커 프로세스의 숫자는 설청 파일에 정의되어있고 주어진 설정량 만큼으로 고정될수 도 있고 사용 가능한 CPU 코어 숫자에 따라서 자동으로 조정될 수 도 있다. (자세한 사항은 워커 프로세스 를 참조하라)

nginx와 모듈들의 동작 방식은 설정파일에 정의되어있다. 설정파일의 디폴트 이름은 nginx.conf이고, /usr/local/nginx/conf, /etc/nginx, /usr/local/etc/nginx의 경로에 위치한다.

시작, 멈춤, 리로딩 설정 Nginx Start / Stop / Configuration 리로드

nginx 시작을 위해선 실행 가능한 파일을 실행시켜야한다. 일단 nginx가 실행되면 -s 옵션을 이용하여 실행파일을 호출해서 제어할 수 있다.
아래와 같은 문법을 사용하면된다.

nginx -s signal

signal은 아래 중 하나가 될 수 있다.

  • stop -- 빠른 종료(fast shutdown)
  • quit -- 적절한 종료(graceful shutdown)
  • reload -- 설정파일 리로드
  • reopen -- log 파일 재 오픈

예를 들어서 워커 프로세스들이 현재 수행중인 요청을 완료할때가지 기다린 후 nginx프로세스를 종료하길 원한다면 아래와 같이 명령어를 실행하면된다.

nginx -s quit

|위 명령어는 nginx를 실행시킨 계정과 같은 계정에서 실행해야 동작한다.|

설정파일의 변화는 nginx에 리로드 명령어를 보내거나 재시작 하기 전까지는 적용되지 않는다. 설정파일을 리로드 하기 위해선 아래의 명령어를 사용한다.

nginx -s reload

마스터 프로세스가 설정을 리로드 하라는 신호를 받으면 마스터 프로세스는 새 설정의 문법 검사(syntax validity)를 수행하고 새로운 설정을 적용하려고 시도한다. 설정 적용에 성공하면 마스터 프로세스는 새로운 워커 프로세스를 실행시키고, 이전 워커 프로세스들에게는 종료 메시지를 보낸다. 설정 적용에 실패하면 마스터 프로세스는 설정을 롤백하고 이전 설정으로 작업을 진행한다. 종료 메시지를 받은 이전 워커 프로세스들은 새로운 컨넥션을 받는것을 중지하고 현재 요청을 완료한 후 종료된다.

요청(signal)은 kill같은 Unix툴에 의해서 전송될 수 도 있다. 이경우 요청은 주어진 Process Id를 참조하여 직접 프로세스에 전달된다. nginx의 마스터 프로세스의 process ID는 default로 nginx.pid 파일에 적혀저있고, 기본 경로는 /usr/local/nginx/logs 또는 /var/run에 있다. 예를들어 마스터 프로세스의 process ID 가 1628일 경우 nginx를 적절한종료(graceful shutdown)하기위해서 아래의 명령어로 QUIT 요청(signal)을 보낼 수 있다.

kill -s QUIT 1628

실행중인 nginx 프로세스를 리스트화 해서 보기위해서는 ps유틸을 사용할 수 있다.

ps -ax | grep nginx

nginx에 요청을 보내는 방법에 대한 더 자세한 정보를 원한다면 Controlling nginx 문서를 참조하라

설정파일(컨피그파일) 구조 Configuration File's Structure

nginx는 모듈로 구성되어있고, 각 모둘들은 설정파일에 명시된 지시(directives) 따라 컨트롤된다. 지시(directives)들은 간단한(simpmle) 지시 들과 블럭 지시들로 나뉘어진다. 간단한 지시는 스페이스(공백)로 나뉘어진 이름과 파라미터로 구성되어있고 마지막에 세미콜론(;)으로 끝난다. 블럭 지시는 간단한 지시와 같은 구조로 되어있으나 세미콜론으로 끝나지않고 중괄호({})로 둘려싸여진 추가적인 지시(instructions)들의 셋을 가지고있다. 블럭 지시는 중괄호 안에 다른 지시를 가지고 있을 수 있고, 이를 컨텍스트(context) 라고 부른다.(ex, events, http, server, location).

설정파일 의 컨텍스트 밖에 위치한 지시들은 main컨텍스트로 간주된다. event 와 http 지시는 main 컨텍스트에 위치하고, server 컨텍스트는 http 컨텍스트, location 컨텍스트는 server 컨텍스트에 위치한다.

# 표시 뒤의 글자들은 주석이된다.

정적파일(Static content) 제공 Serving Static Content

웹서버의 중요한 역할은 (이미지나 정적 html같은)file을 제공하는것이다. 우리는 요청에 따라서 적절한 위치에서 파일을 제공하는 예제를 구현해볼 것이다.
HTML파일은 /data/www에서 제공하고, 이미지 파일은 /data/images 에서 제공하도록 하자. 이렇게 하기위해선 설정파일을 수정해야한다. http블럭에 있는 server블럭에 두 경로를 세팅해보자.

먼저 /data/www 디렉토리를 만들고 index.html 파일을 만들어서 적절한 글자를 좀 써두자. 그리고 /data/images 디렉토리를 만들고 적절한 이미지 몇개를 넣어두자.

다음으로 설정파일을 열자. 디폴트 설정파일에 이미 server 블럭예제가 들어있다. 대부분 주석처리가 되어있다. 이제 모든 블럭의 주석처리하고 새로운 server 블럭을 만들어보자.

http {
    server {
    }
}

일반적으로 설정파일엔 몇개의 server블록이 포트번호와 서버 이름으로 구별되어있다. nginx가 어떤 서버가 요청을 수행할지 결정하면 서버브럭 내에 정의된 위치 지시문(location directives)의 파라미터에 대해 리퀘스트 헤더에 지정된 URI를 테스한다.

아래의 location블럭을 server블럭에 추가해보자.

location / {
    root / data/www;
}

이 location블럭은 리퀘스트의 URI와 비교할 "/" 프리픽스를 지정했다. 매칭되는 리퀘스트에서 URI는ㄴ root 지정된 root 경로를 추가하게된다. 즉, /data/www를 추가하여 요청된 파일을 로컬 파일 시스템의 경로로 연결한다. 매칭되는 location 블럭이 여러개 있다면 nginx는 가장 긴 프리픽스를 선택하게된다. 위의 location블럭은 프리픽스의 길이가 1이기때문에 다른 모든 location블럭이 일치되지 않는 경우에만 사용되게 된다.

이제 두번째 location 블럭을 추가해보자.

location /images/ {
    root /data;
}

위 블럭은 리퀘스트가 /images/로 시작되는 경우에 매칟된다. (/images/로 시작되는 요청은 location / 에도 매칭 되지만 /의 길이가 더 짧기때문에 /images/로 매칭된다.)

server블럭의 결과는 아래와 같을 것이다.

server {
    location / [
        root /data/www;
    }

    location /images/ {
        root /data;
    }
}

이 블럭은 이미 스탠다드 포트인 80포트의 요청을 리슨(listen)하는 서버의 설정으로 동작하게된다. 그리고 로컬 머신에서 'http://localhost/"에 연결할 수 있게 된다. /images/로 시작되는 URI 리퀘스트에 대한 응답으로 서버는 /data/images 디렉토리의 파일을 전송해줄것이다. 예를 들어서 "http://localhost/images/example.png" 리퀘스트에 대한 요청으로 nginx는 /data/images/example.png 파일을 전송해줄것이다. 만약에 해당 파일이 없다면 nginx는 404에러를 넘겨준다. URI가 /images/로 시작되지 않는 요청에대해서는 /data/www 디렉토리로 매핑한다. 예를들어서 "http://localhost/some/example.html" 이라는 요청을 받으면 nginx는 /data/www/some/example.html 파일을 전송한다.

새로운 설정 파일을 적용하기위해서, 아직 nginx를 실행하지 않았다면 시작하도록하고, 이미 시작했다면 reload 시그널을 nginx의 마스터 프로세스에 보내주면 된다.

nginx -s reload

만일 예상대로 동작하지 않는 경우엔 access.log파일과 error.log파일에서 원인을 찾을 수 있다. 해당 파일은 /usr/local/nginx/logs 또는 /var/log/nginx 디펙토리에 있다.

간단한 프록시 서버 만들기 Setting Up a Simple Proxy Server

nginx가 자주 사용되는 방식 중 하나는 프로식 서버로써 사용하는것이다. 프록시서버란 리퀘스트를 받은 후 프록시된 서버로 해당 리퀘스트를 전달해주고, 프록시된 서버가 돌려준 응답을 다시 요청한 클라이언트에게 돌려주는 서버이다.

이제 우리는 기본적인 프로식서버 설정을 할 것이다. 이 프록시 서버는 로컬 디렉토리에서 이미지와 파일 리쿼스트만 받고 다른 모든 요청들은 프록시(된) 서버로 넘긴다. 이 예에서 두 서버 모두 하나의 nginx인스턴스에 정의될 것이다.

먼저 프록시(된) 서버를 만든다. nginx의 설정 파일에 아래의 내용을 추가해서 server블럭 하나를 더 만든다.

server {
    listen 8080;
    root /data/up1;

    location / {
    }
}

이제 이코드로인해서 8080포트를 리슨 하는 단순한 서버가 만들어졌다.(이전엔 listen이 없었기때문에 스탠다드 포트인 80을 사용하고 있었다.)
이 서버는 모든 리퀘스트를 로컬 파일 시스템의 /data/up1 디렉토리로 매핑한다. 해당 디렉토리를 생성하고 index.html 파일을 넣어두자. root는 server 컨텍스트에 위치해 있다는 점을 기억해두자. 이런 root는 location블럭이 root를 가지고 있지 않을경우 사용된다.

다음으로 이전섹션에서 사용한 server 설정을 사용해자. 해당 설정을 수정해서 프록시 서버 설정으로 변환해보자. 첫번째 location 블럭 안에 프로토콜과 함께 proxy_pass 명령을 만들자. 이름과 프록시 될 서버의 포트를 파라미터로 설정해둔다. (우리의 예제에서는 http://localhost:8080이다)

server {
    location / {
        proxy_pass http://localhost:8080;
    }

    location /images/ {
        root /data;
    }
}

우리는 두번째 location 블럭을 수정할 예정이다. 현재는 /images/ 프리픽스를 가진 요청은 /data/images 디렉토리에 매핑되고있다. 이제 요청에 일반적인 파일 확장자를 가진 요청이 있는경우 매칭되게 만들기 위해서 location 블럭은 아래와 같이 변경된다.

location ~ \.(gif|jpg|png)$ {
    root /data/images;
}

파라미터는 정규식이다. URI가 .gif, .jpg, .png 로 끝날경우 모두 매칭된다. 정규식은 반드시 ~ 로 시작해야한다. 이제 일치하는 리퀘스트는 /data/images 디렉토리에 매핑되게 된다.

nginx가 요청을 수행하기위해서 location 블럭을 선택할때 먼저 location 명령어가 특정한 프리픽스를 가지고 있는지 확인한다. 앞서 말한것처럼 가장 긴 프리픽스를 가진 location을 기억하고있고, 정규표현식을 체크한다. 만일 정규표현식에 매칭되는 location이 있다면 해당 로케이션을 선택하고 없는 경우엔 기억하고있던 location을 선택한다.

우리가만든 프록시 서버의 설정을 아래와 같다.

server {
    location / {
        proxy_pass http://localhost:8080;
    }

    location ~ \.(gif|jpg|png)$ {
        root /data/images;
    }
}

이 서버는 .gif, .jpg, .png로 끝나는 요청을 필터링하고 (URI를 root명령어의 파라미터로 추가해서 )/data/images 디렉토리로 매핑할 것이다. 그리고 다른 모든 요청은 이미 설정해놓은 프록시드 서버로 전달한다.

새로운 설정을 적용하기위해서 nginx에 리로드 시그널을 보내야한다. 이전 섹션에서 사용한 명령어를 사용한다.

nginx엔 프록시 서버 설정에 사용가능한 다양한 설정 명령어들이 있다.

FaxtCGI Proxing 세팅 Setting Up FastCGI Proxying

nginx는 리퀘스트를 FastCGI 서버로 라우팅 하기위해서도 사용된다. FastCGI서버는 어플리케이션을 실행하는 다양한 프로그래밍 언어와 프레임워크로 만들어진 서버를 말한다.

FastCGI 서버와 함께 사용하는 대부분의 nginx 설정은 proxy_pass 명령어 대신 fastcgi_pass명령어를 사용한다. 그리고 fastcgi_param명령어를 이용해서 FastCGI 서버에 파라미터를 전달한다. FastCGI서버가 localhost:9000으로 접근 가능하다고 가정해보자. 이전 섹션에서 기본으로 사용한 프록시 설정을 변경해보자. proxy_pass 명령어를 fastcgi_pass명령어로 변환하고 파라미터를 localhost:9000으로 변환한다. PHP에서는 스크립트 이름을 정의하기 위새허 SCRIPT_FILENAME 파라미터를 사용한다. 그리고 QUERY_STRING 파라미터를 이용해서 리퀘스트 파라미터를 전달한다. 변경된 설정은 아래와 같다.

server {
    location / {
        fastcgi_pass  localhost:9000;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param QUERY_STRING    $query_string;
    }

    location ~ \.(gif|jpg|png)$ {
        root /data/images;
    }
}

이제 이설정이 서버가 스태틱 이미지 요청을 제외한 모든 요청을 FastCGI프로토콜을 통해서 프록시된 서버인 localhost:9000으로 보내게된다.

반응형

모든 내용을 번역하기는 좀 시간이 부족해서 어노테이션 설명의 첫문단만 번역함.

원문.

docs.spring.io/spring-framework/docs/current/reference/html/testing.html#integration-testing

 

Testing

The classes in this example show the use of named hierarchy levels in order to merge the configuration for specific levels in a context hierarchy. BaseTests defines two levels in the hierarchy, parent and child. ExtendedTests extends BaseTests and instruct

docs.spring.io

 

3.4.1. Spring Testing Annotations

The Spring Framework provides the following set of Spring-specific annotations that you can use in your unit and integration tests in conjunction with the TestContext framework. See the corresponding javadoc for further information, including default attribute values, attribute aliases, and other details.

스프링 프레임워크는 다음와 같은 스프링 특화 어노테이션을 제공한다. 이 어노테이션들은 유닛테스트 혹은 통합테스트를 할때 테스트 프레임워크(TestContext framework)와의 연결을 위해서 사용된다. 디폴트값, 속성, 등 더많은 정보를 위해서는 대응되는 javadoc을 보도록 하라.

 

Spring’s testing annotations include the following:

스프링의 테스팅 어노테이션은 아래를 포함한다.

 

@BootstrapWith

@BootstrapWith is a class-level annotation that you can use to configure how the Spring TestContext Framework is bootstrapped. Specifically, you can use @BootstrapWith to specify a custom TestContextBootstrapper. See the section on bootstrapping the TestContext framework for further details.

@BootstrapWith는 클래스 레벨 어노테이션이다. 어떻게 스프링 테스트 프레이워크가 부트스트랩 되는지를 정의한다. 특히, @BootstrapWith를 사용하면 커스텀 테스트 컨텍스트 부트스트랩퍼를 지정할 수 있다. 더 많은 정보를 위해서 bootstrapping the TestContext framework  를 참조하도록 하라.

 

@ContextConfiguration

@ContextConfiguration defines class-level metadata that is used to determine how to load and configure an ApplicationContext for integration tests. Specifically, @ContextConfiguration declares the application context resource locations or the component classes used to load the context.

@ContextConfiguration은 클래스 레벨 메타데이터를 정의한다. 메타데이터는 통합 테스트를 위한 어플리케이션 컨텍스트를 어떻게 구성 하고, 로드 하는지를 정의한다. 특히, @ContextConfiguration은 어플리케이션 컨텍스트 리소스의 위치(location) 혹은 컨텍스트를 로드할때 사용되는 클래스의 컴포넌트를 선언한다.

 

@WebAppConfiguration

@WebAppConfiguration is a class-level annotation that you can use to declare that the ApplicationContext loaded for an integration test should be a WebApplicationContext. The mere presence of @WebAppConfiguration on a test class ensures that a WebApplicationContext is loaded for the test, using the default value of "file:src/main/webapp" for the path to the root of the web application (that is, the resource base path). The resource base path is used behind the scenes to create a MockServletContext, which serves as the ServletContext for the test’s WebApplicationContext.

@WebAppConfiguration은 클래스 레벨 어노테이션이다. @WebAppConfiguration은 통합 테스트를 위한 어플리케이션 컨텍스트가 WebApplicationContext여야 하는 경우 사용된다. @WebAppConfiguration가 사용되는 유일한 이유는 테스트를 할때WebApplicationContext가 로드되었다는것을 보장해주고, 웹 어플리케이션의 루트 패스인 "file:src/main/webapp"를 디폴트 값으로 사용하는것을 보장하는 것이다. 리소스의 베이스 패스는 Mock서블렛 컨텍스트를 생성하기위해서 사용되며 Mock서블렛 컨텍스트는 WebApplicationContext의 테스트에 사용되는 서블렛 컨텍스트 역할을 수행한다.

 

@ContextHierarchy

@ContextHierarchy is a class-level annotation that is used to define a hierarchy of ApplicationContext instances for integration tests. @ContextHierarchy should be declared with a list of one or more @ContextConfiguration instances, each of which defines a level in the context hierarchy. 

@ContextHierachy는 클래스레벨 어노테이션이다. @ContextHierarchy는 통합 테스트시 어플리케이션 컨텍스트의 인스턴스의 계층을 정의하기위해 사용된다. @ContextHierachy는 하나 이상의 @ContextConfiguration인스턴스와 함께 정의 되어야한다. 이때 사용되는 각 @ContextConfiguration가 컨텍스트 계층 레벨을 정의한다. 

 

@ActiveProfiles

@ActiveProfiles is a class-level annotation that is used to declare which bean definition profiles should be active when loading an ApplicationContext for an integration test.

@ActiveProfiles는 클래스 레벨 어노테이션이다. @ActiveProfiles는 통합 테스트시 어플리케이션 컨텍스를 로딩할때 어떤 빈 정의 프로파일이 활성화 되어야하는지를 정의한다. 

 

@TestPropertySource

@TestPropertySource is a class-level annotation that you can use to configure the locations of properties files and inlined properties to be added to the set of PropertySources in the Environment for an ApplicationContext loaded for an integration test.

 

 

 

반응형

Iterator

컬렉션에 저장된 요소를 읽어오는 방법을 표준화한것.
다음의 메소드를 포함하고있다.

  • hasNext() : 읽어올 다음 요소가 있는지 확인하는메소드. 다음 요소가 있다면 true, 없다면 false를 반환
  • next(): 다음 데이터를 리턴
  • remove() : next()로 읽어온 요소를 제거.
반응형

Interface VS Abstract

Abstract class(추상 클래스)

  • 클래스 구현 내부에 추상 메서드가 하나 이상 포함되거나 abstract로 정의된 경우.
  • Abstract class의 특징
    • new 연산자를 사용하여 객체르 생성할 수 없다.
      • 단일 상속만이 가능하다.
      • Abstract 클래스는 동일한 부모를 가지는 클래스를 묶는 개념으로 상속을 통하여 기능을 확장시키는것이 목적이다.

Interface

  • 모든 메소드가 추상 메소드이다.
  • Java 8 이후에서는 default 키워드를 이용하면 메소드를 구현할 수 도 있다.
  • static final필드만 가질 수 있다.
  • new 연산자를 사용하여 객체를 생성할 수 없다.
  • 다중상속이 가능하다.
  • 구현 객체가 같은 동작을 한다는것을 보장하려는 목적으로 사용된다.

Abstract class와 Interface의 공통점

  • 선먼만 있고 구현 내용은 없는 클래스이다.
  • 인스턴스화가 불가능하다.
  • 상속 / 구현한 클래스를 이용해서 객체를 생성해야한다.

Abstract class와 Interface의 차이점

  • Abstract class - 단일상송 / Interface - 다중 상속
  • Abstract 의 목적은 상속을 이용하여 기능을 확장시키는 것이다.
  • Interface의 목적은 메소드가 구현됨을 보장하는것이다.
반응형

WAS의 동작방식

  • WAS

    • Web Server와는 다르게 DB조회 등 다양한 로직 처리를 요구하는 동적인 컨텐츠를 담당.
    • 웹 컨테이너, 혹은 서블릿 컨티에너라고 불림.
    • 분산 트랜잭션, 보안, 메시징, 스레드 처리 등의 기능을 처리하는 분산환경에서 사용
    • Tomcat, JBoss 등이 대표직인 WAS이다.
  • 동작 방식

    1. Web Server 의 클라이언트의 요청에 맞는 Servlet을 메모리에 올린다.
    2. web.xml에을 참조해 해당 Servlet에 대한 Thread를 생성한다.
    3. HttpServletRequest와 HttpServletResponse 객체를 생성하고 그에 맞는 doGet 또는 doPost 메소드를 호출해 생성된 동적 페이지를 Response 객체에 담아 WAS에 전달한다. ex) doGet(HttpServletRequest request, HttpServletResponse response)가 리턴하는 Response 객체를 WAS에 전달.
    4. WAS는 HttpResponse 형태로 바꾸어 WebServer에 전달하고 생성된 스레드와 HttpServletRequest, HttpServletResponse 객체를 제거한다.

    참고자료 : https://new-be.tistory.com/3

반응형

'프로그래밍 > 면접대비문제' 카테고리의 다른 글

이터레이터(Iterator)  (0) 2021.01.11
Interface VS Abstract  (0) 2021.01.11
JVM의 메모리 영역  (0) 2021.01.11
DB정규화  (0) 2021.01.11
MVC란?  (0) 2021.01.11

+ Recent posts