17. 비밀 번호 암호화 시 어떤 알고리즘을 사용 하였나요?
"저희 시스템에서는 사용자의 비밀번호 보안을 위해 BCrypt 알고리즘을 사용하는 `BCryptPasswordEncoder`를 사용했습니다. BCrypt는 솔트(Salt)를 사용한 해시 함수의 일종으로, 솔트는 암호화된 비밀번호에 임의의 문자열을 추가하여, 동일한 비밀번호라도 다른 해시 값을 생성합니다. 이 방식은 레인보우 테이블 공격 같은 일반적인 해킹 기법의 효율을 크게 떨어뜨립니다.
`BCryptPasswordEncoder`는 스프링 시큐리티에서 제공하는 클래스로, 비밀번호를 안전하게 암호화하고, 사용자가 입력한 비밀번호와 저장된 해시 값을 비교하는 기능을 제공합니다. 각 비밀번호에 대해 유니크한 솔트를 생성하고, 이를 해시 과정에 사용함으로써, 해시 충돌의 위험을 줄이고 보안성을 높입니다.
저희는 사용자의 비밀번호를 데이터베이스에 저장할 때 `BCryptPasswordEncoder`를 통해 암호화하여 저장하고, 로그인 시에는 입력받은 비밀번호를 같은 방식으로 암호화한 뒤 저장된 해시 값과 비교합니다. 이를 통해 사용자의 비밀번호를 보호하며, 시스템의 보안성을 강화했습니다."
꼬리 질문 > 비밀번호를 암호화 하셨는데 그렇다면 대칭형과 비 대칭형 암호화 알고리즘에 대해 설명해주세요.
"비밀번호 암호화에 사용된 BCrypt는 해시 함수의 일종으로, 암호화 과정에서만 사용되며, 암호화된 비밀번호를 복호화할 수 없는 단방향 암호화 방식에 속합니다. 이와는 별개로, 암호화 알고리즘에는 대칭형과 비대칭형이라는 두 가지 주요 유형이 있습니다.
대칭형 암호화 알고리즘은 암호화와 복호화 과정에서 같은 키를 사용하는 방식입니다. 대표적인 예로 AES(Advanced Encryption Standard)가 있습니다. 대칭형 암호화는 처리 속도가 빠르고 효율적이라는 장점이 있어, 대량의 데이터를 빠르게 암호화해야 할 때 자주 사용됩니다. 하지만, 키 관리가 중요한 이슈가 되며, 키가 노출될 경우 보안이 쉽게 위협받을 수 있습니다.
비대칭형 암호화 알고리즘은 암호화와 복호화 과정에서 서로 다른 키(공개 키와 개인 키)를 사용합니다. RSA가 이에 속합니다. 비대칭형 암호화는 한 쪽 키로 암호화하면, 다른 쪽 키로만 복호화할 수 있어, 키 배포의 문제를 해결하고 보다 안전한 데이터 전송을 가능하게 합니다. 주로 디지털 서명, SSL/TLS 같은 안전한 통신에서 사용됩니다. 처리 속도는 대칭형에 비해 느리지만, 보안성이 높다는 장점이 있습니다.
비밀번호 저장에는 대칭형이나 비대칭형 암호화 대신 일반적으로 단방향 해시 함수를 사용하는데, 이는 한 번 암호화된 데이터를 원래의 형태로 복호화할 수 없어 비밀번호와 같은 민감한 정보를 안전하게 저장하는 데 적합합니다. 사용자의 비밀번호를 검증할 때는 사용자가 입력한 비밀번호를 같은 해시 함수로 처리하여 저장된 해시 값과 비교함으로써 인증 과정을 수행합니다."
꼬리 질문 > 비밀번호 암호화 라이브러리를 사용하셨네요. password 암호화 시에 salt가 무엇이고, 어떤 역할을 하지 설명해주세요.
"네, 비밀번호 암호화 시에는 `salt`라는 개념이 중요한 역할을 합니다. Salt는 비밀번호를 해시하기 전에 비밀번호에 추가되는 임의의 데이터로, 주로 비밀번호의 보안을 강화하기 위해 사용됩니다. Salt의 주요 역할은 두 가지입니다:
첫 번째는, 해시 충돌 방지입니다. 사용자가 간단하거나 일반적인 비밀번호를 선택했을 경우, 그 해시 값은 예측 가능하고 해킹이 쉬워질 수 있습니다. Salt를 비밀번호에 추가하면, 심지어 같은 비밀번호라도 서로 다른 salt 값 때문에 다른 해시 값을 생성하게 됩니다. 이로써 해시 충돌을 방지하고, 해커가 미리 계산된 해시 값(레인보우 테이블 공격 등)을 이용한 공격을 어렵게 만듭니다.
두 번째는 비밀번호의 복잡성 증가입니다. Salt를 추가함으로써 비밀번호 자체의 복잡성이 증가하게 됩니다. 이는 단순히 비밀번호만을 대상으로 한 공격을 더욱 어렵게 만들며, 특히 같은 비밀번호를 사용하는 다른 사용자의 계정이 존재하더라도, 각각의 계정마다 다른 salt를 사용함으로써 각 계정의 해시 값이 달라지게 만듭니다.
비밀번호와 salt를 결합한 뒤, 이를 해시 함수에 입력하여 최종적으로 저장되는 해시 값을 얻습니다. 이때 salt는 데이터베이스에 비밀번호의 해시 값과 함께 저장되어야 하며, 사용자가 로그인을 시도할 때마다 해당 salt를 사용하여 입력된 비밀번호를 해시하고, 이를 저장된 해시 값과 비교함으로써 인증 과정을 수행합니다.
결과적으로, salt는 비밀번호 기반 인증 시스템에서 비밀번호의 보안을 강화하는 데 매우 중요한 요소입니다."
꼬리 질문 > 로그아웃은 어떻게 구현 하였으며 비밀 번호 업데이트 시 로그아웃 되어야 하는 이유는 무엇 인가요?
"로그아웃 기능은 사용자의 세션 또는 인증 토큰을 무효화하는 과정을 통해 구현됩니다. 저희 시스템에서는 사용자의 인증 상태 관리를 위해 JWT(JavaScript Web Token)를 사용하고, 이 토큰을 Redis에 저장하여 세션 관리를 하고 있습니다. 사용자가 로그아웃을 요청할 때, 해당 사용자의 토큰을 Redis에서 삭제함으로써 토큰을 무효화합니다. 이 방식은 서버에서 토큰의 유효성을 실시간으로 관리할 수 있게 해주며, 로그아웃 요청이 들어온 순간부터 해당 토큰으로는 더 이상 인증을 할 수 없도록 합니다.
비밀번호 업데이트 시 로그아웃이 필요한 이유는 보안과 관련이 있습니다. 비밀번호가 변경되면, 이전에 발급된 인증 토큰은 더 이상 유효하지 않게 됩니다. 만약 비밀번호 변경 후에도 기존 토큰이 계속 유효하다면, 누군가가 이전 토큰을 가지고 있을 경우 계정에 계속 접근할 수 있는 문제가 생깁니다. 따라서, 비밀번호 변경 시 기존의 모든 세션을 종료하고 로그아웃 처리를 함으로써, 사용자는 다시 로그인하고 새로운 토큰을 받아야만 합니다. 이 과정을 통해 계정의 보안을 강화하고, 비밀번호 변경이 보안에 미치는 영향을 즉각적으로 반영할 수 있습니다.
실제 구현에서는 비밀번호 변경 로직에 토큰 삭제 명령을 포함시켜, 비밀번호가 변경될 때 자동으로 사용자를 로그아웃 시키고, Redis에서 해당 사용자의 토큰을 삭제하는 방식을 적용했습니다. 이를 통해 사용자의 데이터 보안을 한층 더 강화할 수 있습니다."
18. Circuit Breaker를 구현하실 때 설정한 Failure Rate와 임계치에 대해 설명해주세요.
"Circuit Breaker 패턴을 구현할 때, 시스템의 안정성과 탄력성을 보장하기 위해 Failure Rate(실패율)와 임계치를 설정하는 것이 중요합니다. 저희 프로젝트에서는 서비스 간 호출에서 발생할 수 있는 잠재적인 실패를 관리하고, 이를 기반으로 시스템을 보호하기 위해 Circuit Breaker를 도입했습니다.
저희가 설정한 Failure Rate는 특정 시간 동안 외부 시스템 호출에 대한 실패 비율로 정의됩니다. 예를 들어, 50%로 설정했다면, 전체 호출의 50%가 실패할 경우 Circuit Breaker가 작동하게 됩니다. 이러한 실패율 계산은 일정 시간 동안의 요청을 기반으로 하며, 이 시간 범위를 '슬라이딩 윈도우'라고 합니다.
임계치 설정에 있어서는, 실패율이 설정된 임계값을 초과했을 때 Circuit Breaker가 'Open' 상태로 전환되도록 합니다. 예를 들어, 임계치를 50%로 설정했다면, 최근 일정 시간 동안의 호출 중 50% 이상이 실패했을 때 서비스 호출을 차단하고, 대체 로직을 실행하게 됩니다. 'Open' 상태는 일정 시간 동안 유지되며, 이후 'Half-Open' 상태로 전환하여 일부 요청에 대한 성공 여부를 통해 시스템의 회복 상태를 판단합니다.
저희는 실패율 임계치와 Circuit Breaker의 상태 전환 로직을 세심하게 설계하여, 외부 시스템과의 통신에서 발생할 수 있는 예기치 않은 문제로부터 시스템을 보호하고, 서비스의 가용성을 유지할 수 있도록 했습니다. 이를 통해, 시스템 전반의 안정성과 사용자 경험을 개선하는 데 기여했습니다."
꼬리 질문 > Circuit Breaker와 Retry에 대한 설명과 프로젝트에 적용된 사례는 무엇 인가요?
"저희 프로젝트에서는 대규모 주문 처리 시스템의 안정성과 탄력성을 보장하기 위해 Circuit Breaker와 Retry 패턴을 적용했습니다. 특히, 피크 타임에 발생할 수 있는 대량의 주문 요청을 효과적으로 관리하기 위해 이 두 패턴을 활용했습니다.
Circuit Breaker 패턴을 도입함으로써, 시스템이 과부하 상태에 이르지 않도록 주문 처리 서비스에 대한 요청을 일시적으로 차단했습니다. 실패율이 설정된 임계값을 초과하면, 추가 요청을 일정 시간 동안 차단하여 시스템이 안정화될 시간을 제공했습니다. 이후 서비스가 다시 정상적으로 작동할 수 있음을 확인한 후, 요청 처리를 재개했습니다.
Retry 패턴은 일시적인 네트워크 문제나 서비스 지연과 같은 일시적 장애에 대응하기 위해 사용되었습니다. 설정된 재시도 횟수와 지연 간격에 따라 자동으로 요청을 재시도하여, 일시적인 문제로 인한 주문 실패를 최소화했습니다.
이러한 방식으로 대규모 주문 트래픽 처리 시, 시스템의 가용성을 유지하고, 사용자 경험에 미치는 영향을 최소화할 수 있었습니다. Circuit Breaker와 Retry 패턴의 적용은 잠재적인 시스템 장애를 예방하고, 대규모 주문 트래픽 상황에서도 서비스의 안정적인 운영을 보장하는 데 핵심적인 역할을 했습니다."
19. Redis가 제공하는 자료구조에 대해 아는 만큼 설명해주세요.
"Redis는 고성능 키-값 저장소로, 다양한 자료구조를 지원하여 다목적 캐싱 및 메시징 시스템, 실시간 애플리케이션 등에 널리 사용됩니다. Redis가 제공하는 주요 자료구조로는
1. Strings (문자열): 가장 기본적인 데이터 타입으로, 텍스트 또는 이진 데이터(예: 이미지)를 저장할 수 있습니다. 카운터나 공유 상태 등 간단한 값 저장에 사용됩니다.
2. Lists (리스트): 문자열 요소의 순서 있는 시퀀스를 제공합니다. 리스트의 양쪽 끝에 요소를 추가하거나 삭제할 수 있어, 큐나 스택으로 사용될 수 있습니다.
3. Sets (집합): 중복을 허용하지 않는 문자열 컬렉션으로, 요소의 유니크성을 보장합니다. 집합 간의 연산(교집합, 합집합, 차집합)을 지원하여, 태그 시스템이나 유니크 아이템 관리에 유용합니다.
4. Sorted Sets (정렬된 집합): 각 요소가 스코어와 연결되어 있어, 스코어에 따라 정렬된 상태를 유지합니다. 리더보드나 우선순위 큐 등 순서가 중요한 데이터 관리에 적합합니다.
5. Hashes (해시): 문자열 필드와 값의 매핑을 저장합니다. 객체나 구조체 같은 데이터를 저장하는 데 사용되며, 각 필드를 개별적으로 접근할 수 있습니다.
6. Bitmaps (비트맵): 비트 단위의 연산을 지원하는 데이터 구조로, 간단한 플래그 세팅, 카운팅 등에 활용됩니다. 효율적인 메모리 사용이 가능합니다.
7. HyperLogLogs (하이퍼로그로그): 대규모 데이터 세트에서 유니크한 아이템의 개수를 추정하는 데 사용되는 확률적 자료구조입니다. 대량의 데이터를 다룰 때 메모리 사용을 최소화합니다.
8. Streams (스트림): Redis 5.0에서 추가된 자료구조로, 메시지 스트림을 처리하기 위한 데이터 타입입니다. 시간 순서대로 여러 메시지를 저장하고, 여러 컨슈머가 메시지를 소비할 수 있도록 설계되었습니다.
이러한 다양한 자료구조를 통해 Redis는 높은 유연성과 성능을 제공하며, 다양한 애플리케이션의 요구사항을 충족시킬 수 있습니다."
꼬리 질문 > Redis 와 같은 in-memory DB를 재고관리 시스템에 사용 시 어떤 이점이 있나요?
"Redis와 같은 in-memory 데이터베이스를 재고관리 시스템에 사용하면 다음과 같은 이점을 얻을 수 있습니다:
1. 빠른 데이터 처리 속도: Redis는 모든 데이터를 메모리에 저장하고 처리하기 때문에, 디스크 기반 데이터베이스보다 훨씬 빠른 읽기/쓰기 속도를 제공합니다. 이는 재고 정보의 실시간 업데이트 및 조회를 가능하게 하여, 사용자에게 즉각적인 재고 상태를 제공할 수 있습니다.
2. 확장성: Redis는 데이터를 효율적으로 처리하고, 수평적으로 확장이 가능하여 대량의 재고 데이터 관리에 유리합니다. 또한, 클러스터링을 통해 높은 가용성을 유지할 수 있습니다.
3. 유연한 데이터 구조 지원: Redis는 다양한 데이터 구조를 지원하여, 재고 항목의 수량 관리, 주문 대기열, 사용자 세션 관리 등 다양한 요구사항을 효과적으로 구현할 수 있습니다.
4. 실시간 분석 및 모니터링: Redis의 고성능 덕분에, 재고관리 시스템 내에서 발생하는 모든 이벤트를 실시간으로 분석하고 모니터링할 수 있습니다. 이를 통해 재고 부족, 과잉 재고 등의 문제를 즉각적으로 감지하고 대응할 수 있습니다.
5. 경량화 및 비용 효율성: in-memory 데이터베이스는 상대적으로 경량화되어 있으며, 운영 비용 측면에서도 효율적입니다. 특히, 오픈 소스인 Redis를 사용할 경우, 라이선스 비용 부담 없이 시스템을 구축할 수 있습니다.
6. 간편한 캐싱 솔루션: Redis는 캐싱을 위한 솔루션으로도 널리 사용됩니다. 재고 데이터를 캐시에 저장함으로써, 자주 접근하는 데이터의 빠른 조회가 가능해지고, 백엔드 데이터베이스의 부하를 줄일 수 있습니다.
이러한 이점들로 인해, Redis는 재고관리 시스템에서 높은 성능과 효율성을 보장하는 중요한 역할을 합니다."
20. MSA를 하셨는데 Gateway를 어떻게 구성하셨는지, 인증과 인가는 어떤 방식으로 이루어지는지 설명해주세요.
"저희 프로젝트에서는 마이크로서비스 아키텍처(MSA)를 적용하며, 서비스 간의 효율적인 라우팅과 서비스 발견을 위해 Netflix의 Eureka Server를 사용했습니다. Eureka Server는 서비스 레지스트리 역할을 하여, 각 마이크로서비스의 위치와 상태 정보를 관리하며, 서비스 간의 동적인 서비스 발견과 로드 밸런싱을 가능하게 합니다.
Gateway는 API Gateway 패턴을 적용하여 구성했습니다. 이는 모든 클라이언트 요청의 단일 진입점으로 작동하며, 요청을 적절한 마이크로서비스로 라우팅합니다. Gateway는 인증이나 인가 로직을 직접 처리하지 않고, API 요청과 응답의 라우팅 및 필터링에 집중하여 시스템의 단순성과 확장성을 유지합니다.
인증과 인가는 core 모듈에서 중앙집중식으로 처리됩니다. 사용자가 시스템에 접근을 시도할 때, core 모듈은 사용자의 인증 정보를 검증하고, 적절한 권한이 있는지 확인합니다. 인증은 주로 JWT(JSON Web Tokens)를 사용하여, 사용자의 신원을 확인하고, 토큰 기반의 인증을 제공합니다. 인가 과정에서는 사용자가 요청한 작업을 수행할 수 있는 권한을 가지고 있는지 검사합니다.
이러한 구조를 통해, 저희는 MSA 환경에서 서비스의 독립성을 보장하며, 인증과 인가 로직을 효율적으로 관리할 수 있었습니다. 또한, Eureka Server와 API Gateway의 조합은 서비스의 유연한 관리와 확장성 있는 아키텍처 구축을 가능하게 했습니다."
꼬리 질문 > Eureka Server를 사용하는 주된 이유와 장점은 무엇인가요?
"Eureka Server를 사용하는 주된 이유는 서비스 간의 동적인 서비스 발견과 로드 밸런싱을 가능하게 하기 위함입니다. 마이크로서비스 아키텍처에서 각 서비스는 독립적으로 배포되고 관리되며, 서비스의 위치나 상태가 자주 변경될 수 있습니다. Eureka Server는 서비스 레지스트리로서 모든 서비스 인스턴스의 위치와 상태 정보를 중앙에서 관리하고, 클라이언트가 요청을 보낼 때 현재 사용 가능한 서비스 인스턴스로 요청을 자동으로 라우팅합니다. 이를 통해 서비스 간의 통신이 유연하고 안정적으로 이루어질 수 있습니다. 또한, Eureka Server는 자가 치유 메커니즘을 제공하여, 실패한 인스턴스를 자동으로 감지하고 회복할 수 있도록 지원합니다. 이러한 장점들로 인해 Eureka Server는 마이크로서비스 아키텍처에서 서비스 발견의 복잡성을 줄이고 시스템의 가용성을 높이는 데 기여합니다."
꼬리 질문 > API Gateway에서 인증과 인가 과정을 Core 모듈로 분리하여 처리하는 이유는 무엇인가요?
"API Gateway에서 인증과 인가 과정을 Core 모듈로 분리하여 처리하는 주된 이유는 관심사의 분리(Separation of Concerns)를 통해 시스템의 설계를 더 깨끗하고 관리 가능한 상태로 유지하기 위해서입니다. API Gateway는 주로 라우팅, 로드 밸런싱, 요청 변환과 같은 네트워크 관련 처리에 집중하는 반면, 인증과 인가는 보안 도메인에 속하는 비즈니스 로직입니다. 이 두 가지를 분리함으로써, 각각의 모듈은 자신의 핵심 기능에 집중할 수 있으며, 변경 사항이 발생할 때 서로 영향을 주지 않아 유지 보수성이 향상됩니다.
또한, 인증과 인가 로직을 Core 모듈에 중앙집중화함으로써 보안 로직의 일관성과 재사용성을 보장할 수 있습니다. 모든 인증과 인가 요청이 단일 지점을 통과하게 되므로, 보안 정책의 변경이나 업데이트가 필요할 때 한 곳에서만 수정하면 되며, 이는 전체 시스템의 보안성을 강화하는 데 기여합니다. 또한, 필요한 보안 감사나 로깅도 더 효율적으로 수행할 수 있습니다.
이러한 접근 방식은 또한 시스템의 확장성에도 긍정적인 영향을 미칩니다. 새로운 서비스나 API가 추가될 경우, API Gateway를 통해 라우팅 규칙만 추가하면 되고, 기존의 인증/인가 로직은 그대로 재사용할 수 있습니다. 이는 마이크로서비스 아키텍처의 동적이고 확장 가능한 특성을 지원하는 중요한 요소입니다."
'면접 (Java) > 준비' 카테고리의 다른 글
[면접] 프로젝트 면접 (25~28) (0) | 2024.04.02 |
---|---|
[면접] 프로젝트 면접(21~24) (0) | 2024.04.01 |
[면접] 기초 면접 (25~30) (0) | 2024.03.29 |
[면접] 프로젝트 면접 (13~16) (0) | 2024.03.28 |
[면접] 기초 면접 (19~24) (0) | 2024.03.28 |