생각날 때 쓰는 개발일기
Blog Post
1. ASCII ART?
ASCII ART?
아스키 아트(ASCII Art)란 아스키 코드 0x20~0x7e에 포함되는 문자, 기호를 사용한 그림을 말한다. 텍스트 아트, 문자그림으로도 불리며, 영문 이름 첫자를 줄인 AA로 지칭되기도 한다.
2. ASCII Art Generator를 통하여 텍스트 기반 배너 생성
3. Spring Boot banner.txt 파일 생성
src/main/resources/banner.txt
위 경로에 banner.txt 생성 후, 2번 과정에서 생성한 텍스트 저장
Spring Boot Custom Banner 사용하기
2024/03/23
spring
현재 진행하고 있는 프로젝트에서는 클라이언트(단말기)가 요청하는 다양한 PG수단에 대한 인증 및 승인 요청에 대하여 일관적인 API를 제공하여야 한다. API 요청에 대한 인증 및 검증 그리고 로그 정보를 관리할 필요가 있어 앞단에 API Gateway를 아키텍쳐를 구상하였다.
먼저 API Gateway에서 안정적인 보안을 위해서 HTTP 프로토콜에서의 다양한 인증 방식을 리뷰해 보았다.
HTTP Authentication
일반적인 웹 페이지에서 많이 사용되며 매 요청마다 인증 정보를 HTTP Header에 첨부하는 방법이다.
• 사용자의 아이디와 패스워드를 직접 첨부
• RFC2045-MIME variant of Base64 방식으로 Encoding한다
HTTP Header
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
SSL
단방향 HTTPS 프로토콜 제공. 서버에서 SSL 인증서를 설치하고 HTTPS 프로토콜을 제공한다.
OAuth 2.0
클라이언트의 인증을 위해 클라이언트 ID와 클라이언트 Secret과 같은 키를 발급하고 이를 통해 토큰을 발급하는 방법. 사용자에 대한 인증을 시작으로 사용에 대한 각 API마다 Authorization(허가)를 관리 할 수도 있다. OPEN API를 제공하는 많은 API Provider가 사용하고 있는 방식이다.
• 서비스가 제공하는 API에 일관적인 인증방법을 제시한다.
• 인증시에 참조됐던 정보는 이후 API 호출에 중복적으로 호출하지 않아도 된다.
RSA 암호화 및 Signature 검증
API Key를 발급하고 요청파라미터와 조합하여 Hashing 한 값을 비교하는 방법
• 서비스가 제공하는 API중 보안이 강력하게 필요한 API에 선택적으로 적용할 수 있다.
• API Key를 이용한 Signature 생성을 클라이언트에 위임하게 된다.
요청 정보 암호화
HTTP Request에 포함되는 요청정보를 암호화해서 전달하도록 한다.
• UTF-8 Encoding
• 암호화
ACL기법
특정 API는 private 하게 제공할 수 있어야 한다.
• 지정된 Domain만 접근 가능
• 지정된 IP만 접근 가능API 요청에 대한 검증을 위해 API Key(대칭키)는 각 시스템 상호간의 서버에서만 알 수 있는 정보이여야만 한다. 클라이언트/서버간 요청/응답 정보에서는 Sniping 으로 인해 탈취될 수 있기 때문에 API Key를 첨부해서는 안된다.
API Key는 노출될 수 없기 때문에 인증대상(값)을 선별하고 API Key와 조합하여 해싱된 Signature를 생성할수 있어야 한다.
API Gateway의 인증
API 검증을 위한 인증 수단 제공
기본적으로 API Gateway에서는 클라이언트의 요청에 대해서 아래와 같이 다양한 PG Provider와 연동할수 있도록 일관적인 API를 제공한다.
내부적으로 각 PG Provider와 승인내역에 대한 검증절차를 가지지만 PG Provider별로 인증/보안스펙이 상이하고 API Gateway에서 2차적으로 일관적인 API 검증방식을 제공하면 좋을 것이다.
Signature 생성을 위한 알고리즘
인증 대상값을 통해 String Data를 생성하고 API Key를 통해 아래와 같이 Hashing 하도록 한다.
String Data 생성
UTF-8 Encoding
HMAC (해시 기반 메세지 인증 코드)
• 짧고 고정 길이이다.
• 중복을 방지할 수 있다.
• 메세지 구조를 숨길 수 있다.
SHA-256
SHA256을 통한 HMAC 해싱값이 현재 MD5 / SHA1에 비해 보안적으로 유리하다.
HMAC_MD5("key", "The quick brown fox jumps over the lazy dog") = 0x80070713463e7749b90c2dc24911e275HMAC_SHA1("key", "The quick brown fox jumps over the lazy dog") = 0xde7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9HMAC_SHA256("key", "The quick brown fox jumps over the lazy dog") = 0xf7bc83f43053
Base64 Encoding - RFC 4648
최종적으로 해싱이 완료된 Binary를 최종적으로 클라이언트/서버간 전달할수 있도록 Base64로 인코딩하여 문자열을 획득한다.
API 요청 및 Signature 생성에 대한 가이드
클라이언트 개발자가 만약 위와 같은 API 명세를 참고하여 API를 클라이언트와 연동한다면 API Reference를 통해 가이드를 하면 모든것이 해결될까? 개인적인 경험으로는 REST API 뿐만 아니라, 이외의 API를 배포할 때에는 상세한 API Reference보다는 아래의 방식이 가장 효과가 좋았다.
• 각 플랫폼별 클라이언트에서 사용할수 있는 SDK를 개발하여 배포하면 가장 좋지만, 비용이 많이 든다.
• 클라이언트의 플랫폼이 다양해 SDK배포에 제한이 있다면, API Reference에서는 상세한 예제 및 샘플코드를 첨부하도록 한다.
예를들면 위의 Signature 문자열을 생성하기 위한 예제를 살펴보면 아래와 같다.
• Signature을 생성하기 위한 절차를 처음 소개할때부터 그림으로 한눈에 볼수 있으면 좋을것 이다.
Signature 생성규약
예를 들어, 아래와 같이 API Key를 문자열인 4044cac130913f94a5d4979e0401500e 라고 가정하고, 인증이 필요한 요청정보는 Alphabetical 순서로 append 하여 조합합니다.API Key4044cac130913f94a5d4979e0401500eAPI Parameter 중 인증대상정보를 Append944542050178560694342P1510100001
데이터 문자열인 944542050178560694342P1510100001 를 UTF-8 Encoding을 이용해 Binary 로 변환하면 아래와 같은 값(HEX 문자열)이 됩니다.
3934343534323035303137383536303639343334325031353130313030303031
3934343534323035303137383536303639343334325031353130313030303031 값(HEX 문자열)을 위의 API Key 문자열인 4044cac130913f94a5d4979e0401500e 을 통해 HMAC-SHA256로 해싱하면, 아래와 같은 값(HEX 문자열)이 되며,
a6f6c3bfb4d30326db6285c0488e67616b2754f23c946582734d157501cd2c77
해싱된 바이너리를 Base64 Encoding 하면 아래와 같은 Signature 문자열을 획득할수 있습니다.
pvbDv7TTAybbYoXASI5nYWsnVPI8lGWCc00VdQHNLHc=
정리를 하면, 944542050178560694342P1510100001 인 String Data를 위와 같은 규약으로 4044cac130913f94a5d4979e0401500e 문자열의 API Key와 HMAC-SHA256 방식으로 해싱하게 되면 아래와 같은 Signature 문자열을 얻을 수 있어야 합니다.
pvbDv7TTAybbYoXASI5nYWsnVPI8lGWCc00VdQHNLHc=문서 내에서는 ‘RFC4648 방식으로 Base64 인코딩하라’라고 간단히 기술했으나, 이것의 내부적인 의미는 다음과 같습니다.
• http://www.ietf.org/rfc/rfc4648.txt
위와 같이 각 플랫폼별로 SDK 및 샘플코드를 제공하는것이 제한된다면, Signature 생성을 위해 필요한 값의 예제를 주고 각 Step별로 기대값을 가이드하면 클라이언트 개발자가 API를 보다 효율적으로 연동하는 사례가 많았다.
구현하기
지금까지는 API 요청에 대한 검증을 위한 스펙을 간단하게 정의해보았고, 외부에 이를 공유하기 위한 효율적인 방법을 제시해 보았다. 이어서 Spring MVC를 통해 애플리케이션을 개발한다면 API요청에 대한 검증을 어떻게 처리하며, 각 API에 공통적으로 적용하기 위한 예제를 살펴보도록 하겠다.
API검증을 위한 공통 비지니스로직 적용
현재 API Gateway에는 아래와 같은 공통적인 요구사항이 있다고 가정해보자.
• API 요청 클라이언트가 인증된 클라이언트인지 체크
• 각 API 요청정보를 명세된 Signature 값을 통해 검증
• 클라이언트에 대한 인증이 성공적이라면, 자주 참조하는 클라이언트의 세션정보를 캐싱한다.
아래와 같이 Controller의 Method Parameter에 @ValidSignature 어노테이션과 DeviceSession 클래스를 정의하면, API요청에 대한 Signature 검증을 하고 정상적이면 DeviceSession에 필요한 Cached Data를 간단하게 전달받을 수 있습니다.
@RequestMapping(value = "/auth/v1/authentication", method = RequestMethod.POST, headers = {"Content-Type=application/json"})public Response authentication(@RequestBody AuthenticationRequest request, @ValidSignature DeviceSession deviceSession) { LOGGER.info(request.toString()); AuthenticationResponse response = authenticationService.authentication(request); return new ResponseObject<>(response);}
MDCFilter / DeviceInterceptor
요청 정보에 대한 MDC 값을 획득하고, IP정보와 같은 공통적인 수집사항은 Inteceptor를 정의하여 확인할수 있도록 한다.
HandlerMethodArgumentResolver 등록
org.springframework.web.method.support.HandlerMethodArgumentResolver 인터페이스를 구현한 Bean을 등록한다.
@ValidSignature
API 요청에 대한 Signature를 검증한다.
DeviceSession
인증이 성공된 요청에 대해 캐싱된 세션정보 Controller의 Method Argument를 통해 전달한다.
Summary
지금까지 클라이언트에서 다양한 Back-End 시스템에 직접 연동하는것이 제한이 될때 필요한 시스템 구성을 살펴보았고 이를 API Gateway의 역할이라고 설명하였다. API Gateway에서 일관적인 API를 제공할 때 API 요청에 대한 검증을 위한 스펙은 각 시스템의 상황에 맞게 정의하면 될 것 이다.
중요한 것은 유행하는 아키텍쳐를 수립하기 보다는 어떠한 문제가 있으며 이를 해결해나가기 위한 방법이 어떠한 것들이 있는지 작은 단위부터 접근해 나가는것이 좋을듯 하다.
References
[스크랩] API Gateway 의 인증 및 API 요청에 대한 검증
2022/07/23
architecture
이 문서는 API Gateway 패턴에 대해 키워드 위주로 요약하였다.
Monolithic Architecture 와 Micro Service Architecture
API Gateway Design이 왜필요한지를 이해하려면 Monolithic Architecture 와 Micro Service Architecture에 대한 이해가 먼저 필요하다. 아래의 조대협씨의 블로그에 매우 잘정리해가 되어있으니, 참고하면 좋을듯 하다.
• http://bcho.tistory.com/948
Monolithic Architecture
하나의 애플리케이션에 모든 기능이 구현되어 있는 아키텍쳐
Micro Service Architecture
하나의 애플리케이션을 구성하기 위한 기능을 여러 컴포넌트/서비스로 분리한 구조이다.컴포넌트/서비스 단위로 데이터가 분리되고 빌드 또는 Deploy시에도 서로 영향이 없어야 한다.
API Gateway?
Micro Service Architecture 가 탄생하면서 이를 보다 효율적으로 이용하기 위해 나타난 Design이다.하나의 애플리케이션에서 여러 분산된 서비스를 이용하다보니 다양한 문제들이 발생되는데 이를 해결하기 위해 API Gateway가 탄생되었다.
Micro Service Architecture 에서 이슈되는 문제와 API Gateway를 통해 이를 어떻게 해결해나가는지 살펴보도록 하자.
API Gateway의 공통기능
Authentication / Authorization
• OAuth2.0 : accessToken / refreshToken
• One Time Token
• JSON Web Token : http://jwt.io/
• Spring Security
Logging
• API Request Logging / Audit
• Metering / Charge
• QoS (Limit)
Orchestration(Mash-Up)
• 여러개의 API를 하나로 묶어 Mash-Up에 구성할수 있는 기능
And so on…
• Message Transformation
• Message Format (Protocol) Transformation
API Gateway로 얻을수 있는것
클라이언트 이슈
• 각 클라이언트에 최적화된 API를 제공할 수 있다.
• 여러 서비스를 호출하는 로직을 클라이언트에서 API 게이트웨이로 옮겨 클라이언트를 간소화할 수 있다.
• 요청, 라운드 트립(round-trip)의 수를 줄일 수 있다. 예를 들어, API 게이트웨이는 클라이언트가 한 번의 라운드 트립으로 여러 서비스에서 데이터를 받아올 수 있다. 더 적은 요청은 부하를 줄이고 사용자 경험을 높힐 수 있다는 의미다. API 게이트웨이는 모바일 애플리케이션에서는 필수다.
벡엔드
• 분산시스템. 집중적으로 트래픽이 몰리는 서비스만 스케일 아웃 할 수 있다.
• 독립적으로 서비스별로 유연하게 배포가 가능하다.
• 특정 서비스의 배포로 인한 다른 서비스에 대한 영향도가 줄어든다.
• 컴포넌트 확장에도 유연
• 조직이 일하는 프로세스나 규칙에도 영향을 미칠 수 있다.
주의해야할점
• 추가적인 API 콜로 인한 네트워크 성능 이슈
• 서비스간 트랜잭션 처리
• 테스팅의 복잡도
Referenceshttp://microservices.io/patterns/apigateway.htmlhttp://techblog.netflix.com/2012/07/embracing-differences-inside-netflix.htmlhttp://devcafe.nhncorp.com/index.php?mid=intro&act=dispWikiContent&vid=APIgatewayhttp://wiki-camp.appspot.com/%5B%EB%B2%88%EC%97%AD%5D_%ED%8C%A8%ED%84%B4%3A_API_Gatewayhttp://bcho.tistory.com/948http://bcho.tistory.com/1005http://bcho.tistory.com/999https://www.polarisoffice.com/d/2RP8vZUY
[스크랩] API Gateway 패턴
2022/07/23
architecture
Gradle은 2017년 4월에 3.5 버전을 릴리즈하면서 Build Cache의 특징을 소개하면서 Gradle의 빌드 속도가 드라마틱하게(?) 향상되었다고 발표하였다. Build Cache는 Gradle 3.5에 베타 테스트를 위해 포함된 기능으로 Gradle Tasks의 결과를 로컬에서 재사용하는 것뿐만 아니라 빌드 머신사이에도 Remote로 Tasks의 결과의 캐시가 공유되 빌드 타임을 줄여준다고 한다.
Gradle에서는 다음 버전에서 Build Cache를 정식으로 릴리즈하기 위해 아래와 같이 사용자들의 피드백을 요구했는데 내용은 아래와 같다.
프로젝트에서 아래의 옵션을 통해 두 번째 빌드 타임 좀 확인해볼래?
$ gradle --build-cache clean assemble$ gradle --build-cache clean assemble
Remote Cache도 함 사용해봐!
Remote로 캐시를 공유할려면 backend가 필요한데 예제를 줄테니 참고하렴. 그런데 Gradle Enterprise에서는 이미 제공하고 있음
피드백을 줘!
아무튼 직접 사용해보고 피드백을 주면 너의 프로젝트의 빌드 타임을 줄이는데 많은 도움이 될거임(..)
Gradle v4.0 Release
Gradle Enterprise 그리고 Gradle의 빌드 속도에 불만이 있던 사용자들이 피드백을 잘 줬는지 이전 버전이 발표된지 두 달만에 v4.0이 릴리즈 되었다. Gradle v4.0의 다양한 Feature들은 아래의 링크를 통해 확인할 수 있으며 이 글에서는 Build Cache를 통한 빌드 성능의 향상에 대해 살펴보도록 하겠다.
- Dependencies를 병렬처리로 다운로드가 가능하다.- Build Cache가 Production에 적용가능한 수준으로 향상되었다....https://docs.gradle.org/4.0/release-notes.html#new-and-noteworthy
Gradle은 Maven보다 100배이상 빠르다?
Gradle에서는 아래와 같은 일반적인 시나리오에서 빌드 성능에 대한 테스트 결과를 공개하였다. 테스트에 사용된 하드웨어는 Dell XPS 15, I7-4712HQ CPU @ 2.30GHz, 16GB of RAM, SSD, Linux Min 18.1 이다.https://gradle.org/gradle-vs-maven-performance/
Scenario: Java Library
Apache Commons Lang 3를 Maven에서 Gradle로 변경하여 테스트한 결과이다. 테스트를 실행한 결과는 Gradle이 약 1.7배 정도 빠르며 Build Cache로 인한 빌드는 약 72배이상 빠르다.
Scenario: Small multi-project build
50개의 소스 파일과 50개의 테스트를 가지고 있는 모듈 10개로 구성된 프로젝트를 테스트한 결과이다.
Scenario: Medium multi-project build
100개의 소스 파일과 100개의 테스트를 가지고 있는 모듈 100개로 구성된 프로젝트를 테스트한 결과이다.
Scenario: Large multi-project build
100개의 소스 파일과 100개의 테스트를 가지고 있는 모듈 500개로 구성된 프로젝트를 테스트한 결과이다.
Scenario: Large monolithic application
마지막으로 흔치는 않지만 모든 소스 코드가 하나의 모듈에 구성된 프로젝트의 테스트 결과이다.
결과를 요약하면 아래와 같다.
• 모든 결과를 비추어 볼때 Gradle은 모든 시나리오에서 적어도 2배 이상 빠르다.
• 변경 사항을 반영한 빌드에서는 Gradle이 Maven에 비해 10~100배 빠르며, 하위 프로젝트가 많을수록 더욱 유리하다.
Your Turn
사실 이전의 Gradle의 빌드 타임은 체감상으로도 Maven 비해 느리게 느껴졌다. 위의 그래프에서 Gradle의 이전 버전이 포함되지 않은 점이 이를 증명해준다. v4.0에서 Maven보다 100배이상 빠르다는 표현은 과장되어 보이지만 Build Cache의 안정화로 인해 Gradle의 빌드 타임이 대폭 향상된 것은 사실이다. 구구절절 설명이 길었지만 Gradle을 v4.0으로 업그레이드하고 직접 빌드와 테스트를 실행하는 것을 추천한다.
Gradle Wrapper를 통해 업그레이드
$ ./gradlew wrapper --gradle-version=4.0 --distribution-type=bin
Homebrew로 업그레이드
$ brew upgrade gradle==> Upgrading 1 outdated package, with result:gradle 4.0==> Upgrading gradle==> Using the sandbox==> Downloading https://services.gradle.org/distributions/gradle-4.0-all.zip==> Downloading from https://downloads.gradle.org/distributions/gradle-4.0-all.zip######################################################################## 100.0% /usr/local/Cellar/gradle/4.0: 169 files, 71.8MB, built in 48 seconds
업데이트된 버전을 확인해보자
$ gradle --version------------------------------------------------------------Gradle 4.0------------------------------------------------------------...
설치하기
아직 Gradle을 설치하지 않았다면 Homebrew를 통해 설치하거나 수동으로 직접 Download 하여 설치할 수도 있다.
$ brew update && brew install gradle
Referenceshttps://gradle.org/gradle-vs-maven-performance/https://blog.gradle.org/introducing-gradle-build-cachehttps://gradle.org/install/
[스크랩] Gradle은 정말 Maven보다 100배나 빠를까?
2022/07/23
basic
tool