인가
Authorization
방법
누구인지 확인된 다음, 그 사람이 지금 요청한 일을 해도 되는지 요청 하나하나마다 다시 판단하는 절차입니다.
등장 배경
로그인 화면을 붙이고 나면 문을 잠갔다는 기분이 듭니다. 실제로 잠긴 것은 정문 하나뿐인데, 안에 들어온 사람이 어느 방이든 열 수 있다면 그 자물쇠는 별 의미가 없습니다. 서비스가 한 사람의 데이터만 다루던 시절에는 이 구분이 필요 없었습니다. 들어온 사람의 데이터가 곧 전부였기 때문입니다.
여러 팀이 같은 서비스에 각자의 자료를 올리면서 사정이 달라졌습니다. 페이지덱에서 실제로 났던 일이 그렇습니다. 문서 공유 링크가 /doc/1042 같은 모양이었고, 태오가 만든 화면은 그 링크를 연 사람이 해당 문서의 참여자인지를 확인하지 않았습니다. 숫자를 1041 로 바꾸면 남의 팀 회의록이 그대로 열렸습니다. 로그인은 멀쩡히 통과한 사용자였습니다. 빠진 것은 이 사람이 이 문서를 볼 자격이 있는지를 묻는 한 줄이었습니다.
인가는 이 질문을 따로 세운 절차입니다. 누구인지는 접속할 때 한 번 정해지지만, 무엇을 해도 되는지는 요청마다 달라집니다. 같은 사람이 같은 순간에 A 문서는 읽을 수 있고 B 문서는 열 수 없으며, 읽을 수는 있어도 지우지는 못할 수 있습니다.
사용 절차
인가는 요청이 들어올 때마다 세 가지를 맞춰 보는 방식으로 돌아갑니다. 누가, 무엇에, 어떤 동작을 하려는가입니다.
- 주체를 받습니다. 인증이 확정해 넘긴 신원을 그대로 씁니다. 여기서 다시 누구인지 묻지 않습니다.
- 대상과 동작을 확정합니다. 1042번 문서인지 1041번 문서인지, 읽기인지 삭제인지를 구분합니다. 같은 문서라도 읽기는 되고 삭제는 안 되는 경우가 흔해서, 대상만으로 판단하면 절반만 막힙니다.
- 규칙과 대조합니다. 이 사람이 이 대상에 대해 이 동작을 할 자격이 있는지를 미리 정해 둔 규칙에서 찾습니다. 자격이 있으면 요청을 처리하고, 없으면 거절합니다.
거절할 때도 두 갈래가 있습니다. 권한이 없다고 알려 주는 쪽과 그런 것이 아예 없다고 답하는 쪽입니다. 비공개 프로젝트라면 뒤쪽을 씁니다. 권한이 없다는 답 자체가 그 번호의 문서가 존재한다는 사실을 알려 주기 때문입니다.
규칙을 어디에 적어 두느냐가 다음 문제입니다. 사람마다 권한을 직접 붙이는 방식은 구성원이 늘면 무너져서, 보통 역할 기반 접근 제어를 씁니다. 관리자·편집자·열람자 같은 역할에 권한을 묶고, 사람에게는 역할만 붙입니다. 45명에게 20종류의 권한을 일일이 붙이면 900개의 결정을 관리해야 하지만, 역할이 네 개면 관리할 것은 역할 네 개와 사람 45명의 배정뿐입니다.
적합한 상황과 한계
사람마다 보이는 것이 달라지는 서비스라면 모든 요청에 걸립니다. 문제는 필요 여부가 아니라 검사를 어디에 두느냐입니다. 화면·API·데이터 조회의 세 층 가운데 반드시 지켜야 하는 곳은 API 층입니다. 화면은 사용자 쪽에서 그려지는 것이라 마음대로 건드릴 수 있고, 주소를 직접 입력하면 화면을 거치지 않고 요청이 들어오기 때문입니다.
권한의 기본값은 최소 권한 원칙이 정합니다. 지금 하는 일에 필요한 만큼만 주고 애매하면 주지 않는다는 규칙입니다. 반대로 하면 편하지만, 계정 하나가 뚫린 날의 피해 범위가 그 계정이 가진 권한만큼 넓어집니다.
한계는 세 군데에서 드러납니다. 첫째, 규칙이 늘어나면 전체를 아는 사람이 사라집니다. 역할 여섯 개에 자원 종류 열 개가 맞물리면 확인할 조합만 예순 가지입니다. 둘째, 자동 검사 도구가 잘 못 잡습니다. 알려진 공격 패턴은 찾아내지만, 검사 한 줄이 통째로 빠진 자리는 오류처럼 보이지 않아서 모의 침투 테스트처럼 사람이 시나리오를 짜야 드러납니다. 실제로 웹에서 가장 많이 터지는 취약점을 추린 OWASP Top 10에서 이 누락이 오랫동안 첫 자리에 있었습니다. 셋째, 값이 듭니다. 문서 목록 한 장에 100건을 보여 주려면 판단도 100번이라, 규칙이 복잡할수록 목록 화면이 먼저 느려집니다.
실무 용례
"이 창구에 인가 검사가 빠졌어요. 문서 번호만 바꾸면 남의 팀 회의록이 열립니다."
로그인한 사용자면 아무 문서나 열린다는 지적이고, 서버 쪽에 자격 확인을 넣어야 한다는 뜻입니다.
"권한을 사람마다 주지 말고 역할로 묶읍시다. 마흔다섯 명한테 스무 가지를 일일이 못 붙여요."
개인별 권한 관리가 감당할 수 있는 규모를 넘었으니 역할 단위로 바꾸자는 제안입니다.
"화면에서 버튼만 숨겨 놨습니다. 서버 쪽은 아직 그대로예요."
보이지 않게만 했을 뿐 요청 자체는 여전히 처리된다는 고백입니다.
페이지덱이 인가를 제대로 손본 것은 공유 링크 사고 직후였습니다. 규원이 그 주 기능 일정을 미루고 권한 검사를 먼저 넣으라고 했습니다. 태오는 문서를 꺼내는 자리마다 흩어져 있던 조건문을 한곳으로 모아, 문서를 읽는 모든 경로가 같은 검사를 지나가게 바꿨습니다. 검사를 여러 군데에 나눠 두면 새 화면을 만들 때 한 곳을 빠뜨리게 되기 때문입니다.
민서는 권한이 없는 사람이 링크를 열었을 때 무엇을 보여 줄지를 맡았습니다. 오류 화면만 띄우면 잘못 들어온 동료가 다음에 무엇을 해야 할지 알 수 없어서, 문서 소유자에게 열람을 요청하는 버튼을 함께 놓았습니다.
흔한 오해
버튼을 숨기면 막은 것이라는 오해가 가장 많습니다. 삭제 버튼이 눈앞에서 사라지니 끝난 것처럼 보입니다. 하지만 버튼은 그림일 뿐이고, 요청은 버튼 없이도 보낼 수 있습니다. 주소를 직접 입력하거나 예전에 쓰던 요청을 그대로 다시 보내면 서버는 아무것도 모른 채 처리합니다. 그래서 사고가 조용히 일어납니다. 화면이 멀쩡히 막혀 있으니 팀은 막았다고 믿고, 실제로 열린 통로는 아무도 보지 않는 자리에 남습니다. 화면에서 감추는 일은 인가가 아니라 안내입니다.
두 번째는 인가를 한 번 정해 두면 끝나는 설정으로 보는 것입니다. 역할과 규칙을 처음 짤 때 고민을 많이 하니 그때 끝났다고 느낍니다. 실제로 흔들리는 쪽은 사람입니다. 팀을 옮기고 프로젝트가 끝나고 외부 협력사 계정이 남습니다. 권한은 줄 때만 요청이 오고 회수는 아무도 요청하지 않아, 손대지 않으면 한 방향으로 쌓입니다. 1년이 지나면 마케팅으로 옮긴 사람이 아직 운영 데이터를 볼 수 있는 상태가 되고, 그 상태는 사고가 나기 전까지 드러나지 않습니다.
자주 헷갈리는 용어
| 용어 | 무엇에 답하는가 | 인가와의 차이 |
|---|---|---|
| 인증 | 접속한 상대가 누구인가 | 순서상 앞에 오고 횟수도 적습니다. 인증은 접속할 때 한 번 통과하면 그 세션 내내 유효하지만, 인가는 요청마다 대상과 동작을 놓고 다시 판단합니다 |
같이 보면 좋은 페이지
마지막 업데이트 2026-09-16