알고리즘 문제 풀이, 코딩테스트 준비는 어떤 순서로 해야 할까

알고리즘

취업 준비를 시작하면 가장 먼저 체감하는 벽 중 하나가 코딩테스트다. 처음에는 문제를 많이 풀면 실력이 빨리 늘 것 같지만, 실제로는 어떤 순서로 학습하느냐가 훨씬 중요하다. 구현도 익숙하지 않은 상태에서 DP나 최단경로 문제부터 붙잡으면 금방 막히고, 반대로 쉬운 문제만 반복하면 실전 난이도를 넘기 어렵다. 코딩테스트는 단순 암기보다 문제 해결 패턴을 단계적으로 익히는 과정에 가깝다.

최근 국내외 개발 채용 과정에서는 자료구조와 알고리즘 기반 평가가 여전히 중요한 비중을 차지한다. 특히 백준, 프로그래머스, LeetCode 같은 플랫폼은 문제 유형이 체계적으로 분류되어 있어 학습 순서를 제대로 잡는 것이 효율을 크게 좌우한다.

코딩테스트 준비가 어려운 이유는 문제 수가 아니라 순서 때문이다

많은 초보자가 어려운 알고리즘부터 공부하려고 하지만, 실제로는 구현과 탐색 흐름이 먼저 익숙해져야 이후 단계가 연결된다.

코딩테스트 학습 흐름은 수학 공부 과정과 꽤 비슷하다. 기초 연산이 익숙하지 않은 상태에서 미적분을 공부하면 오래 버티기 어렵듯, 알고리즘도 구현과 탐색 흐름이 먼저 몸에 익어야 한다. 구현, 자료구조, 탐색, 최적화 순서로 사고력을 확장해야 문제를 봤을 때 접근 방향이 보이기 시작한다.

특히 초보자들이 가장 많이 실패하는 부분은 문제 풀이량 자체에 집착하는 것이다. 하루에 몇 문제를 풀었는지가 중요해 보이지만, 실제 실력 차이는 문제를 어떻게 분석했는지에서 나온다. 시간복잡도를 비교하고, 다른 사람 풀이를 해석하고, 왜 특정 알고리즘이 사용됐는지 이해하는 과정이 누적될수록 문제 해결 속도도 함께 올라간다.

STEP 1. 구현과 입출력에 익숙해지는 단계

구현 문제를 안정적으로 해결할 수 있어야 이후 알고리즘 학습이 연결된다.

가장 먼저 해야 할 일은 구현과 입출력에 익숙해지는 것이다. 문자열 처리, 반복문, 배열 순회, 조건 분기 같은 기본 구현이 자연스럽지 않으면 어떤 알고리즘도 제대로 활용하기 어렵다.

좌표 이동, 문자열 뒤집기, 날짜 계산, 배열 회전 같은 문제들은 난이도는 높지 않지만 구현 실력을 크게 끌어올린다. 특히 프로그래머스 레벨 1~2나 백준 브론즈~실버 구간 문제는 구현 감각을 만들기에 적합하다.

이 단계는 보통 2~4주 정도 반복하는 경우가 많다. 빠르게 푸는 것보다 오류 없이 완성하는 경험을 쌓는 편이 훨씬 중요하다. 입력 예외 처리나 인덱스 실수를 줄이는 것만으로도 실전 체감 난이도가 크게 낮아진다.

STEP 2. 시간복잡도와 자료구조 감각을 만드는 단계

시간복잡도를 이해하기 시작하면 문제 접근 방식 자체가 달라진다.

처음에는 O(N), O(N²), O(logN) 정도만 구분할 수 있어도 충분하다. 중요한 것은 수식을 외우는 게 아니라 반복 횟수를 감각적으로 이해하는 것이다.

개념 핵심 의미
O(N) 데이터 개수만큼 반복
O(N²) 이중 반복문 구조
O(logN) 탐색 범위를 절반씩 줄이는 방식

자료구조는 단순 암기보다 “왜 사용하는가”를 중심으로 접근하는 편이 훨씬 효율적이다. 스택은 최근 데이터를 관리할 때 강력하고, 큐는 순차 처리에 적합하며, 해시는 탐색 속도를 줄이는 데 유리하다.

정렬 문제도 이 단계에서 매우 중요하다. 단순히 sort 함수를 사용하는 수준을 넘어 정렬 이후 어떤 정보를 얻을 수 있는지를 이해해야 한다. 실제 코딩테스트에서는 정렬 자체보다 정렬 이후 탐색을 쉽게 만드는 사고가 더 자주 사용된다.

STEP 3. 완전탐색과 재귀로 문제 접근력을 키우는 단계

문제를 여러 단계로 분해하는 사고가 생기기 시작하는 구간이다.

완전탐색은 가능한 모든 경우를 직접 확인하는 방식이다. 비효율적으로 보일 수 있지만, 많은 문제가 완전탐색 기반으로 시작된다. 중요한 것은 무작정 모든 경우를 계산하는 것이 아니라 어떤 기준으로 탐색 범위를 줄일 수 있는지를 배우는 것이다.

재귀는 초보자들이 가장 어려워하는 개념 중 하나다. 하지만 DFS, 백트래킹, 트리 탐색 같은 핵심 알고리즘 대부분이 재귀 사고와 연결된다.

실제로 DFS 개념을 이해한 이후부터 문제 접근 방식이 달라졌다고 말하는 경우가 많다. 이전까지는 문제를 보면 막막했지만, 탐색 흐름을 단계적으로 쪼개기 시작하면서 어디서 분기해야 하는지 보이기 시작한다는 것이다.

  1. 가능한 경우를 먼저 나눈다.
  2. 조건에 맞지 않는 경우를 빠르게 제거한다.
  3. 남은 경우만 끝까지 탐색한다.

이 단계는 보통 3~5주 정도 반복 학습하는 경우가 많다. 정답 여부보다 사고 과정을 복기하는 습관이 훨씬 중요하다.

STEP 4. DP와 그리디로 최적화 문제를 이해하는 단계

DP와 그리디는 모두 최적화를 다루지만 접근 방식은 완전히 다르다.

DP는 작은 문제의 결과를 저장하면서 전체 문제를 해결하는 방식이다. 핵심은 이전 상태를 재사용하는 구조를 이해하는 것이다.

f(n)=f(n−1)+f(n−2)f(n)=f(n-1)+f(n-2)

반면 그리디는 현재 상황에서 가장 좋아 보이는 선택을 반복한다. 하지만 모든 문제가 그리디로 해결되는 것은 아니다. 현재 선택이 전체 최적해를 보장해야만 사용할 수 있다.

많은 초보자들이 DP에서 막히는 이유는 점화식을 공식처럼 외우려고 하기 때문이다. 실제로는 현재 상태와 이전 상태의 연결 관계를 이해하는 편이 훨씬 중요하다.

대표 문제를 반복적으로 접하다 보면 점화식 패턴이 눈에 들어오기 시작한다. 계단 오르기, 배낭 문제, LIS 문제는 대부분의 준비생이 반복적으로 학습하는 대표 유형이다.

STEP 5. 그래프와 실전 모의고사로 마무리하는 단계

실전 단계에서는 알고리즘 자체보다 문제 해석 능력이 훨씬 중요해진다.

그래프 문제는 처음 보면 복잡해 보이지만 실제로는 탐색 구조를 응용하는 경우가 많다. BFS는 최단 거리 탐색에 강력하고, DFS는 경로 탐색과 완전탐색 계열에서 자주 사용된다. 다익스트라는 가중치가 있는 최단경로 문제에서 대표적으로 등장한다.

실제 시험처럼 시간을 정해놓고 문제를 푸는 연습도 반드시 필요하다. 많은 준비생들이 알고리즘 자체보다 시간 압박 때문에 실수한다. 구현 실수나 문제 해석 오류는 실전 점수에 큰 영향을 준다.

기출 기반 반복 학습도 효과적이다. 기업별 기출 유형을 분석하면 자주 등장하는 패턴이 보인다. 구현 비중이 높은 기업도 있고, 그래프와 DP 중심으로 출제하는 곳도 있다.

결국 코딩테스트는 특정 천재만 잘하는 영역이 아니다. 구현부터 탐색, 최적화, 그래프까지 사고 단계를 순서대로 확장한 사람이 훨씬 오래 살아남는다. 알고리즘 공부는 새로운 개념을 외우는 과정이라기보다 문제를 해석하는 사고 습관을 만드는 과정에 가깝다.

해킹 방지 실전 기법

웹 보안

SQL 인젝션, XSS, CSRF는 어떻게 막을까?

관리자 페이지 하나를 급하게 만들고 배포했는데 며칠 뒤 이상한 요청 로그가 쌓이기 시작한다. 게시판에는 알 수 없는 스크립트가 등록되고, 로그인된 관리자 계정으로 의심스러운 요청이 발생한다. 실제 보안 사고 상당수는 거대한 해킹 기술보다 기본적인 입력값 처리 실수에서 시작된다.

웹 보안 입문 단계에서 가장 먼저 이해해야 하는 공격은 SQL 인젝션, XSS, CSRF다. 오래된 취약점처럼 보이지만 지금도 반복적으로 발견된다. 이유는 단순하다. 대부분의 웹 서비스는 결국 사용자 입력을 처리하고, 로그인 상태를 유지하며, 브라우저를 통해 동작하기 때문이다.

중요한 것은 공격 이름을 외우는 것이 아니다. 데이터가 어디로 들어오고, 어떤 방식으로 실행되며, 브라우저와 서버가 어떤 신뢰 관계를 형성하는지 이해해야 실제 보안 구조가 보인다. 웹 보안은 공격 종류 암기보다 데이터 흐름의 신뢰 경계를 이해하는 과정에 더 가깝다.

웹 서비스는 왜 반복해서 같은 공격에 당할까

대부분의 웹 공격은 입력값 검증 실패에서 시작된다. 사용자가 입력한 값을 안전하다고 가정하는 순간 공격 가능성이 열린다.

웹 서비스는 로그인, 검색, 댓글, 게시판, 파일 업로드처럼 끊임없이 외부 입력을 받는다. 문제는 개발자가 예상한 입력만 들어오지 않는다는 점이다. 공격자는 SQL 구문을 넣거나, 자바스크립트 코드를 삽입하거나, 브라우저가 자동 전송하는 인증 정보를 악용한다.

특히 초보 개발 단계에서는 기능 구현 속도가 우선이 되기 쉽다. “나중에 보안 처리하면 된다”는 접근이 반복되면서 취약점이 남는다. 실제 운영 환경에서는 이런 작은 누락 하나가 계정 탈취나 데이터 유출로 이어질 수 있다.

많은 개발자가 프레임워크를 사용하면 자동으로 안전해진다고 생각한다. 하지만 프레임워크는 기본 방어 기능을 제공할 뿐이다. 문자열 연결 방식으로 직접 쿼리를 만들거나, 사용자 입력 HTML을 그대로 출력하면 여전히 취약점이 발생한다.

세 공격 모두 결국 서버와 브라우저가 사용자의 입력을 어디까지 신뢰하느냐에서 시작된다. 실무에서는 “신뢰하지 않는다”가 기본 원칙이다. 사용자의 입력, 브라우저 요청, 쿠키 값, API 파라미터까지 모두 검증 대상이라고 보는 편이 안전하다.

STEP 1. SQL 인젝션은 데이터베이스 구조를 노린다

SQL 인젝션은 사용자 입력을 이용해 데이터베이스 쿼리를 조작하는 공격이다. 가장 오래된 웹 공격 중 하나지만 여전히 매우 위험하다.

예를 들어 로그인 기능에서 문자열 연결 방식으로 쿼리를 만들면 문제가 발생할 수 있다.

SELECT * FROM users 
WHERE id = '$id' AND password = '$password'

공격자가 입력값에 SQL 구문을 삽입하면 조건 자체가 변조될 수 있다. 과거에는 ' OR 1=1 -- 같은 단순한 구문만으로 인증 우회가 발생하는 사례도 많았다.

위험한 이유는 데이터베이스 자체를 직접 건드릴 수 있기 때문이다. 단순 로그인 우회뿐 아니라 사용자 정보 조회, 테이블 삭제, 관리자 계정 생성 같은 문제로 이어질 수 있다.

현재 실무에서 기본 방어 방식은 Prepared Statement다. 쿼리 구조와 사용자 입력 데이터를 분리해 SQL 구문 자체가 변경되지 않도록 만든다.

위험한 방식 안전한 방식
문자열 연결 쿼리 Prepared Statement
Raw Query 직접 조합 Parameter Binding
사용자 입력 직접 삽입 ORM 바인딩 사용

ORM을 사용한다고 해서 무조건 안전해지는 것은 아니다. 대부분의 ORM은 안전한 바인딩 구조를 제공하지만, Raw Query를 직접 작성하거나 문자열 조합을 사용하면 SQL 인젝션 가능성이 다시 생긴다.

실제 보안 점검에서도 관리자 검색 기능이나 내부 운영 도구처럼 “외부 노출이 적다”고 생각한 영역에서 SQL 인젝션이 자주 발견된다. 운영 편의를 위해 빠르게 만든 기능이 오히려 가장 위험해지는 경우가 많다.

STEP 2. XSS는 사용자 브라우저를 공격한다

XSS는 Cross Site Scripting의 약자다. 공격자가 웹 페이지에 스크립트를 삽입해 다른 사용자의 브라우저에서 실행되도록 만드는 공격이다.

대표적으로 게시판이나 댓글 기능에서 많이 발생한다. 사용자가 입력한 HTML이나 스크립트를 검증 없이 그대로 출력하면 브라우저가 실제 코드로 실행할 수 있다.

Stored XSS는 악성 스크립트가 서버에 저장되는 형태다. 게시글이나 댓글에 삽입된 스크립트가 이후 접속하는 모든 사용자 브라우저에서 실행된다. 영향 범위가 매우 크다.

Reflected XSS는 요청 파라미터에 포함된 스크립트가 즉시 반사되어 실행되는 형태다. 주로 검색 기능이나 URL 파라미터에서 자주 발생한다.

XSS가 위험한 이유는 브라우저 세션 자체를 노릴 수 있기 때문이다. 공격자는 쿠키 탈취, 관리자 세션 가로채기, 피싱 페이지 삽입, 악성 API 요청 실행 같은 공격을 수행할 수 있다.

특히 JWT를 localStorage에 저장하는 구조에서는 XSS 위험이 더 커질 수 있다. 스크립트가 localStorage에 접근해 토큰을 탈취할 가능성이 있기 때문이다. 반대로 HttpOnly Cookie 기반 구조는 자바스크립트 접근을 제한할 수 있어 상대적으로 안전하다.

많은 프론트엔드 프레임워크는 자동 이스케이프 기능을 제공한다. React나 Vue 역시 기본 출력에서는 비교적 안전한 편이다. 하지만 React의 dangerouslySetInnerHTML 같은 기능을 사용하거나 HTML 렌더링을 직접 처리하면 XSS 가능성이 다시 생긴다.

기본 방어 원칙은 출력 시 이스케이프다. 사용자 입력 데이터를 HTML로 그대로 출력하지 않고 특수 문자를 변환해 브라우저가 코드로 인식하지 못하게 만들어야 한다.

최근에는 CSP(Content Security Policy)를 함께 적용해 허용되지 않은 스크립트 실행 자체를 제한하는 방식도 많이 사용된다.

STEP 3. CSRF는 로그인 상태를 악용한다

CSRF는 사용자가 이미 로그인되어 있다는 점을 악용하는 공격이다. 사용자가 직접 요청하지 않았는데도 브라우저가 자동으로 인증 정보를 함께 보내는 구조를 이용한다.

예를 들어 사용자가 은행 사이트에 로그인한 상태라고 가정해보자. 동시에 악성 사이트에 접속하면 브라우저는 자동으로 쿠키를 포함한 요청을 전송할 수 있다. 서버가 이를 정상 요청으로 오해하면 송금이나 정보 변경 같은 작업이 실행될 가능성이 생긴다.

CSRF는 “사용자 인증이 이미 되어 있다”는 점을 역으로 이용한다는 점에서 위험하다. 공격자는 비밀번호를 몰라도 사용자의 로그인 상태만 유지되면 공격을 시도할 수 있다.

현재 가장 기본적인 방어 방식은 CSRF Token 사용이다. 서버가 예측 불가능한 토큰을 생성하고 요청마다 함께 검증하는 방식이다. 공격자는 정상 토큰 값을 알 수 없기 때문에 요청 위조가 어려워진다.

최근 브라우저에서는 SameSite Cookie 정책도 중요한 방어 수단이 되고 있다. SameSite 설정을 사용하면 외부 사이트에서 자동으로 쿠키가 전송되는 상황을 제한할 수 있다.

  • CSRF Token은 요청 위조 여부를 검증한다.
  • SameSite Cookie는 외부 사이트 쿠키 전송을 제한한다.
  • Referer와 Origin 검증은 요청 출처를 확인한다.

다만 SameSite만으로 모든 CSRF가 해결되는 것은 아니다. 실무에서는 여러 방어 기법을 함께 사용하는 경우가 많다.

JWT 기반 인증이라고 해서 CSRF 문제가 완전히 사라지는 것도 아니다. JWT를 Cookie에 저장하는 구조라면 브라우저가 자동으로 쿠키를 전송할 수 있기 때문에 여전히 CSRF 방어가 필요하다.

STEP 4. 입력값 검증과 출력 이스케이프를 분리해야 한다

입력값 검증과 출력 이스케이프는 자주 함께 언급되지만 실제 역할은 완전히 다르다. 둘을 혼동하면 보안 처리가 누락되기 쉽다.

입력값 검증은 “허용 가능한 데이터만 받는 과정”이다. 숫자만 입력 가능한 필드라면 숫자 외 문자를 차단하고, 이메일 형식이라면 정규식을 통해 검증하는 식이다.

하지만 입력 검증만으로는 충분하지 않다. 정상 입력처럼 보이는 값도 브라우저 출력 과정에서 위험해질 수 있기 때문이다.

예를 들어 게시글 내용에 <script> 태그가 포함되어 있다면 서버 저장 자체는 가능할 수 있다. 문제는 이를 HTML로 출력할 때 발생한다. 브라우저가 스크립트로 해석하면서 XSS가 실행될 수 있다.

그래서 실무에서는 입력 검증과 출력 이스케이프를 별도로 관리한다. 저장 가능한 데이터 범위를 제한하면서도, 최종 출력 시에는 HTML 특수 문자를 안전하게 변환한다.

프론트엔드 프레임워크가 자동 이스케이프 기능을 제공하더라도 예외 상황은 존재한다. HTML 렌더링 기능이나 Markdown 미리보기 기능처럼 직접 렌더링을 처리하는 영역에서는 별도 보안 처리가 필요하다.

STEP 5. 실무에서는 단일 방어보다 다층 보안을 사용한다

실제 서비스에서는 하나의 보안 기술만으로 공격을 막지 않는다. 여러 계층을 동시에 보호하는 다층 보안 구조를 사용한다.

WAF(Web Application Firewall)는 비정상 요청 패턴을 탐지하고 차단하는 역할을 한다. SQL 인젝션이나 비정상 트래픽을 1차적으로 필터링하는 데 많이 사용된다.

CSP(Content Security Policy)는 브라우저에서 실행 가능한 스크립트 범위를 제한한다. XSS 피해 범위를 줄이는 데 효과적이다.

Rate Limit은 짧은 시간 안에 과도한 요청이 들어오는 상황을 제한한다. 로그인 무차별 대입 공격이나 API 남용 방지에 자주 사용된다.

실무에서는 인증 구조와 세션 관리 정책까지 함께 고려한다. JWT 만료 시간을 짧게 유지하고, Refresh Token을 분리하며, HttpOnly Cookie를 사용하는 이유도 모두 같은 흐름이다.

최근에는 관리자 페이지 접근 제한, MFA 인증, IP 기반 접근 제어 같은 정책까지 함께 적용하는 경우가 많다. 실제 보안은 특정 기술 하나로 해결되지 않는다. 운영 구조 전체를 함께 관리해야 효과가 나온다.

SQL 인젝션

보안 입문자가 가장 자주 하는 위험한 착각

ORM을 사용하면 SQL 인젝션이 완전히 사라진다고 생각하는 경우가 많다. 하지만 Raw Query를 직접 작성하거나 문자열 연결을 사용하면 여전히 취약점이 발생할 수 있다.

HTTPS만 적용하면 모든 공격이 막힌다고 오해하는 경우도 많다. TLS는 통신 보호 역할일 뿐 XSS나 CSRF 자체를 해결하지는 않는다.

관리자 페이지 URL을 숨기면 안전하다고 생각하는 것도 위험하다. 실제 공격자는 크롤링, 브루트포스, 로그 분석 등 다양한 방식으로 관리자 경로를 탐색한다.

또 하나 자주 발생하는 문제는 “내 서비스는 작은 규모라 공격받지 않는다”는 생각이다. 실제 자동화 공격은 규모와 상관없이 인터넷 전체를 대상으로 반복적으로 수행된다.

보안은 특별한 기능이 아니라 기본 설계에 가깝다. 기능 개발 이후 뒤늦게 추가하는 것이 아니라 데이터 흐름과 인증 구조를 처음부터 안전하게 설계하는 접근이 중요하다.

SSL/TLS와 JWT 구조까지 함께 이해하면 웹 보안 흐름이 더 선명해진다

SQL 인젝션, XSS, CSRF 같은 공격을 제대로 이해하려면 결국 인증과 통신 구조까지 함께 볼 필요가 있다. 특히 HTTPS 기반 TLS 암호화, JWT 인증 구조, OAuth 로그인 흐름은 실제 웹 보안의 기본 축에 가깝다.

이전 글인 “암호화와 인증 기초”를 함께 보면 왜 쿠키 보호, 토큰 저장 방식, 인증 요청 구조가 중요한지 훨씬 자연스럽게 연결해서 이해할 수 있다.

암호화와 인증 기초

SSL/TLS, JWT, OAuth는 무엇이 다를까?

HTTPS, JWT, OAuth 같은 보안 용어는 개발을 시작하면 거의 반드시 만나게 된다. 문제는 이름은 익숙한데 역할이 서로 섞여 보인다는 점이다. 어떤 문서는 JWT를 인증이라고 설명하고, 어떤 곳은 OAuth를 로그인이라고 부르며, 또 다른 곳에서는 HTTPS만 적용하면 안전하다고 말한다. 하지만 실제 서비스 구조에서는 세 기술이 서로 다른 계층에서 움직인다.

핵심은 데이터 흐름을 기준으로 이해하는 것이다. TLS는 통신 자체를 보호하고, JWT는 로그인 상태를 유지하며, OAuth는 외부 서비스 권한 위임을 담당한다. 역할만 명확히 구분해도 대부분의 인증 구조가 훨씬 단순하게 보이기 시작한다.

기술 핵심 역할 주 사용 위치
SSL/TLS 네트워크 통신 암호화 HTTPS
JWT 로그인 상태 유지 API 인증
OAuth 외부 권한 위임 소셜 로그인

실제 서비스에서는 OAuth로 로그인을 수행하고, 서버는 자체 JWT를 발급하며, 전체 통신은 TLS 기반 HTTPS 위에서 이루어진다. 이 세 가지는 경쟁 기술이 아니라 하나의 인증 흐름 안에서 동시에 동작한다.

SSL/TLS, JWT, OAuth를 한 문장으로 구분하기

SSL/TLS는 데이터를 안전하게 전송하고, JWT는 로그인 상태를 표현하며, OAuth는 외부 권한 위임을 처리한다. 이 한 줄이 전체 구조의 핵심이다.

TLS는 브라우저와 서버 사이의 통신 내용을 암호화한다. 사용자가 로그인 정보를 입력하거나 결제 데이터를 전송하더라도 네트워크 중간에서 내용을 읽을 수 없게 만드는 역할이다. HTTPS 주소에서 사용하는 핵심 보안 기술도 바로 TLS다.

JWT는 로그인 이후 사용자가 누구인지 서버가 빠르게 확인하기 위해 사용하는 토큰 형식이다. 서버는 매 요청마다 JWT를 검증하면서 사용자의 인증 상태를 확인한다.

OAuth는 외부 서비스 계정을 안전하게 이용하기 위한 권한 위임 방식이다. 대표적으로 “구글로 로그인”, “카카오 로그인” 같은 기능이 OAuth 기반으로 동작한다. 서비스가 사용자의 비밀번호를 직접 저장하지 않아도 된다는 점이 핵심이다.

이 세 기술은 실제 로그인 흐름에서 자연스럽게 연결된다. 사용자가 소셜 로그인을 수행하면 OAuth 인증이 진행되고, 서버는 자체 JWT를 발급한다. 이후 클라이언트와 서버의 모든 요청은 HTTPS 환경에서 보호된다.

SSL/TLS는 데이터를 안전하게 오가게 만드는 기술

TLS는 인터넷 통신 자체를 보호하기 위한 암호화 프로토콜이다. 과거에는 SSL이라는 이름이 널리 사용됐지만 현재 대부분의 서비스는 TLS 기반으로 동작한다.

브라우저에서 HTTPS 주소로 접속하면 가장 먼저 TLS 핸드셰이크가 수행된다. 이 과정에서 서버 인증서 검증, 암호화 방식 협상, 세션 키 생성이 이루어진다. 이후부터는 네트워크 패킷이 암호화된 상태로 전송된다.

이 구조 덕분에 공용 와이파이나 중간 네트워크 장비를 거치더라도 로그인 정보와 쿠키 데이터를 쉽게 탈취하기 어렵다. 실제로 HTTPS가 제대로 적용되지 않았던 초기 웹 환경에서는 세션 쿠키 탈취 공격이 매우 자주 발생했다.

TLS의 역할은 단순 암호화만이 아니다. 서버 신뢰성 검증도 함께 수행한다. 브라우저는 인증서를 통해 “현재 접속한 서버가 실제 서비스 서버인지” 확인한다. 주소창의 자물쇠 표시가 중요한 이유도 여기에 있다.

과거 SSL 2.0과 SSL 3.0은 심각한 취약점이 발견되면서 대부분 폐기되었다. 하지만 여전히 업계에서는 “SSL 인증서”라는 표현이 남아 있다. 실제로는 TLS 인증서를 사용하면서 관습적으로 SSL이라는 이름을 유지하는 경우가 많다.

최근에는 TLS 1.3 사용이 빠르게 확대되면서 보안 수준뿐 아니라 연결 속도까지 개선되었다. CDN과 클라우드 플랫폼에서도 HTTPS 기본 적용이 일반화되면서 TLS는 이제 선택 기능이 아니라 기본 인프라에 가까워졌다.

SSL/TLS

JWT는 로그인 이후 사용자를 식별하는 토큰 구조

JWT는 JSON Web Token의 약자다. 로그인 이후 사용자의 상태를 서버가 확인하기 위해 자주 사용하는 토큰 형식이다.

전통적인 세션 방식에서는 서버가 로그인 상태를 직접 저장했다. 사용자가 많아질수록 세션 저장소 관리 비용이 증가하고 서버 확장도 복잡해진다. JWT는 서버 상태 저장 부담을 줄이기 위해 많이 사용된다.

JWT는 Header, Payload, Signature 세 부분으로 구성된다. Payload에는 사용자 ID, 권한 정보, 만료 시간 같은 데이터가 포함된다. 서버는 Signature를 검증해 토큰이 위변조되지 않았는지 확인한다.

입문 단계에서 가장 자주 발생하는 오해는 “JWT가 암호화 토큰”이라는 생각이다. 실제로 JWT는 기본적으로 인코딩 구조에 가깝다. 따라서 Payload 내부 데이터는 누구나 읽을 수 있다. 비밀번호나 민감한 개인정보를 직접 넣는 것은 매우 위험하다.

실무에서는 Access Token과 Refresh Token을 분리하는 방식이 자주 사용된다. Access Token은 짧은 시간만 유효하도록 만들고, Refresh Token으로 재발급을 처리한다. 토큰 탈취 위험을 줄이기 위한 구조다.

  • localStorage 저장은 구현이 단순하지만 XSS 공격 위험이 존재한다.
  • HttpOnly Cookie는 자바스크립트 접근을 차단해 상대적으로 안전하다.
  • 보안 요구 수준이 높은 서비스일수록 Cookie 기반 인증 구조를 선호하는 경우가 많다.

다만 JWT가 항상 정답은 아니다. 로그아웃 처리나 강제 세션 만료 같은 기능은 오히려 복잡해질 수 있다. 실제 금융 시스템이나 관리자 서비스에서는 여전히 세션 기반 인증을 사용하는 경우도 많다.

OAuth는 비밀번호를 넘기지 않고 권한을 위임하는 방식

OAuth는 인증 시스템이라기보다 권한 위임 프레임워크에 가깝다. 외부 서비스 계정을 안전하게 활용하기 위한 구조라고 보는 편이 정확하다.

대표적인 예가 “구글 계정으로 로그인” 기능이다. 사용자는 직접 구글 로그인 화면에서 인증을 수행하고, 서비스는 인증 결과만 전달받는다. 비밀번호를 직접 저장하거나 처리하지 않아도 되기 때문에 보안 부담이 크게 줄어든다.

OAuth 구조에서는 Access Token이 핵심 역할을 한다. 서비스는 이 토큰을 이용해 외부 API 접근 권한을 확인한다. 예를 들어 프로필 조회, 이메일 읽기, 캘린더 접근 같은 권한 범위를 제한할 수 있다.

최근 서비스들이 “프로필 정보만 동의”, “메일 읽기 권한 허용” 같은 화면을 보여주는 이유도 OAuth의 Scope 구조 때문이다. 사용자는 허용 범위를 직접 선택할 수 있다.

실무에서는 OAuth와 OpenID Connect를 함께 사용하는 경우가 많다. OAuth 자체는 권한 위임 중심이라 사용자 식별 정보가 충분하지 않을 수 있기 때문이다. OpenID Connect는 사용자 인증 계층을 추가해 로그인 기능 구현을 쉽게 만든다.

실제 소셜 로그인 프로젝트에서는 Redirect URI 설정 실수가 자주 발생한다. 검증이 제대로 이루어지지 않으면 공격자가 피싱 페이지로 사용자를 유도할 수도 있다. OAuth는 편리하지만 설정 실수 하나가 큰 취약점으로 이어질 수 있는 구조이기도 하다.

현재 대부분의 소셜 로그인 서비스는 OAuth 2.0과 OpenID Connect 기반으로 동작한다. 구글, 애플, 네이버, 카카오 모두 유사한 구조를 사용한다.

SSL/TLS, JWT, OAuth는 경쟁 관계가 아니라 함께 쓰인다

실제 서비스에서는 이 세 기술이 하나의 흐름 안에서 동시에 동작한다.

  1. 사용자가 카카오 로그인 버튼을 누른다.
  2. OAuth 인증 절차가 진행된다.
  3. 서버가 사용자 정보를 확인한다.
  4. 자체 JWT를 발급한다.
  5. 이후 API 요청마다 JWT를 검증한다.
  6. 전체 통신은 HTTPS(TLS) 위에서 보호된다.

만약 TLS가 적용되지 않았다면 네트워크 중간에서 토큰 탈취가 발생할 수 있다. OAuth 설정이 잘못되면 공격자가 인증 흐름을 가로챌 수도 있다. JWT 만료 시간이 지나치게 길다면 탈취된 토큰이 장기간 악용될 가능성도 커진다.

실제 보안 사고 상당수는 기술 자체보다 역할 혼동이나 운영 설정 실수에서 발생한다. 인증 기술은 단독으로 안전해지는 것이 아니라 여러 계층이 함께 맞물려야 효과가 나온다.

최근에는 Zero Trust 보안 구조가 확산되면서 단순 로그인 여부보다 토큰 검증, 세션 만료, 디바이스 신뢰성 검증까지 함께 관리하는 방향으로 발전하고 있다.

입문자가 가장 자주 하는 보안 오해 정리

HTTPS를 적용했다고 해서 인증 구조 전체가 안전해지는 것은 아니다. TLS는 통신 구간을 보호할 뿐 사용자 권한 자체를 관리하지는 않는다.

JWT를 암호화 기술이라고 오해하는 경우도 많다. JWT는 기본적으로 인코딩 구조이며 Payload 내용을 누구나 확인할 수 있다. 민감 정보를 직접 저장하면 오히려 보안 문제가 커질 수 있다.

OAuth를 “로그인 기능 자체”로 이해하는 것도 흔한 착각이다. 정확히는 외부 권한 위임 구조에 가깝다. 실제 로그인 기능은 OpenID Connect 같은 추가 계층과 함께 구현된다.

“JWT가 세션보다 무조건 최신”이라는 생각 역시 단순화된 접근이다. 서비스 규모와 보안 정책에 따라 세션 방식이 훨씬 안정적일 수도 있다.

결국 중요한 것은 기술 이름이 아니라 데이터 흐름이다. TLS는 통신을 보호하고, JWT는 로그인 상태를 유지하며, OAuth는 외부 권한 위임을 처리한다. 역할을 분리해서 이해하면 인증 아키텍처 전체 구조가 훨씬 명확하게 보이기 시작한다.

보안 기술은 하나의 만능 솔루션으로 해결되지 않는다. 실제 서비스는 여러 계층의 기술이 서로 보완하는 형태로 동작한다. SSL/TLS, JWT, OAuth를 함께 이해해야 하는 이유도 바로 여기에 있다.