-
2025년 1월 3째주HM's Dairy/WIL 2025. 1. 19. 02:14
암호화(Encryption) 알고리즘
AES256 (Advanced Encryption Standard)
- 암호화와 복호화에 같은 키를 사용 (Secret Key 1개)
- 대칭키 (Symmetric Key)
- 데이터를 못 보게 숨기기 위한 목적 (기밀성)
키가 노출되면?
→ 모든 암호화된 데이터를 복호화할 수 있음
→ DB에 저장된 모든 민감정보가 노출될 수 있음RSA2048 (Rivest-Shamir-Adleman)
- 암호화와 복호화에 다른 키를 사용
- 비대칭키 (Asymmetric Key)
- 공개키(Public Key)와 개인키(Private Key)가 한 쌍
- 안전하게 키를 교환하고 전자서명을 하기 위한 목적
1. 데이터 암호화/복호화
암호화: 공개키(Public Key) 사용
- 누구나 공개키로 암호화 가능
- 공개키는 모두에게 공개됨
복호화: 개인키(Private Key) 사용
- 개인키를 가진 사람만 복호화 가능
- 개인키는 서버만 비밀리에 보관
예시) AES 키 교환에 사용
- AES의 비밀키를 RSA 공개키로 암호화해서 전송
- 서버만 개인키로 복호화 가능
- 안전하게 AES 키를 공유
2. 전자서명/검증
서명: 개인키(Private Key) 사용
- 개인키로 데이터를 서명
- 서버만 서명 가능 (개인키 소유)
검증: 공개키(Public Key) 사용
- 공개키로 서명을 검증
- 누구나 검증 가능
예시) 전자서명에 사용
- 서버가 개인키로 데이터에 서명
- 클라이언트는 공개키로 위변조 여부 검증 가능해시(Hash) 알고리즘
HMAC-SHA256 (Hash-based Message Authentication Code Secure Hash Algorithm)
- HS256 : HMAC-SHA256의 JWT 표준 약자
- HmacSHA256 : Java에서 사용하는 알고리즘 이름
- 데이터가 변조되지 않았다는 것을 확인하는 서명 방식
- 데이터 변조 여부를 검증하여 데이터 무결성을 확인하기 위한 목적
- JWT에서 주로 사용되는 서명 방식
키가 노출되면?
→ 공격자가 JWT 토큰을 위조할 수 있음
→ 다른 사용자로 가장 가능Bcrypt
- 비밀번호 전용 해시 함수
- 매번 다른 salt를 자동 생성해서 해시에 포함
예시)
비밀번호: "password123"
- 1차 해시: $2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy
- 2차 해시: $2a$10$WlBmu.HwuiFPQtzE7OBoM.hp.hjQb7Xr1L8FV9O0e/gBxwChFyPU.
같은 비밀번호인데 해시값이 다름 (salt가 달라서)
하지만 검증은 가능 (salt가 해시값 안에 포함됨)
초당 수십번 정도만 해시 가능하도록 설계 → 해커가 무차별 대입 공격하기 어려움인코딩 (Encoding)
- 입력 데이터 : Hello
- 비밀키 : myKey123
Base64
- 바이너리 데이터를 64개 문자로 표현
- 데이터 크기가 약 33% 증가
예시) Hello → SGVsbG8=
장점 : 적은 용량 증가
- 3바이트 → 4글자로 변환
- 저장/전송할 때는 Base64 (효율적인 용량)
단점 : 사람이 읽기 어려움
- 바이트 경계가 불분명
- A-Z, a-z, 0-9, +, / 사용 (64개 문자)
- 특수문자가 섞여있고 패딩(=)이 붙을 수 있어서 파싱이 더 복잡
- 길이가 약 1.33배로 증가
주 용도
- JWT 토큰 (헤더.페이로드.서명)
- 이메일 첨부파일
- 이미지 데이터 URIHex
- 바이너리 데이터를 16진수로 표현
- 데이터 크기가 100% 증가
예시) Hello → 48656C6C6F
장점 : 사람이 읽기 쉬움
- 0-9, a-f만 사용 (16개 문자)
- 숫자와 알파벳이 명확히 보여서 읽기 쉬움
- 각 바이트가 2자리로 명확히 구분됨 (48 65 6C 6C 6F)
- 개발자가 디버깅할 때 바이트 단위로 확인하기 좋음
- 로그에서 문제를 찾을 때 패턴 파악이 쉬움
단점 : 저장 공간 많이 사용
- 1바이트 → 2자리 16진수로 변환
- 길이가 2배로 증가
주 용도
- 해시값 표현 (SHA256, MD5 등)
- 디버깅/로깅
- 바이너리 데이터 분석Base64 와 Hex 는 알고리즘의 결과를 표현하는 방식이다.
단순히 바이트 데이터를 문자열로 표현하기 때문에 어떤 알고리즘의 결과로도 표현할 수 있다.
스트림(Stream)과 버퍼(Buffer)
1. 주요 차이점
데이터 처리 방식
- Stream: 데이터를 연속적 흐름으로, 청크(chunk) 단위로 순차 처리
- Buffer: 데이터를 일정 크기의 메모리에 모아두고 한 번에 처리
메모리 사용
- Stream: 필요한 만큼만 메모리 사용 (대용량 데이터 처리에 효율적)
- Buffer: 처리할 데이터를 모두 메모리에 적재 (더 많은 메모리 사용)
접근 방식
- Stream: 순차적 접근만 가능 (단방향)
- Buffer: 임의 접근 가능 (앞뒤로 자유롭게 이동)
2. String vs StringBuffer vs StringBuilder
String
- 불변(Immutable) 객체
- 문자열 수정시 매번 새로운 객체 생성
- 메모리 사용이 비효율적
- 문자열 연산이 적을 때 사용
StringBuffer
- 가변(Mutable) 객체
- Thread-safe (synchronized)
- 멀티스레드 환경에서 안전
- String보다 효율적
- 속도: StringBuilder보다 느림
StringBuilder
- 가변(Mutable) 객체
- Not Thread-safe (no synchronization)
- 단일 스레드에서 가장 빠름
- StringBuffer보다 빠름
- 멀티스레드 환경에서는 부적합
3. 성능 비교
- String: 매우 비효율적 (매번 새 객체 생성)
- StringBuilder: 가장 빠름 (단일 스레드에 최적화)
- StringBuffer: StringBuilder보다 약간 느림 (스레드 동기화 때문)
4. 실무 사용 가이드
- 단일 스레드 환경: StringBuilder 사용
- 멀티스레드 환경: StringBuffer 사용
- 스프링에서는 요청당 하나의 스레드 할당 (Thread-per-Request)이므로 StringBuffer 를 함수 내에서 사용한다면 상관 없다.
- 문자열 연산이 적은 경우: String 사용
5. 주의사항
- String은 불변성 때문에 문자열 연산이 많은 경우 성능 저하
- StringBuffer는 thread-safe 보장을 위해 약간의 성능 희생
- StringBuilder는 성능은 좋지만 thread-safe하지 않음
- 대용량 데이터 처리시 Stream 방식 권장
- 메모리 제약이 있는 환경에서는 Buffer 사용 주의
'HM's Dairy > WIL' 카테고리의 다른 글
2025년 2월 2째주 (0) 2025.02.08