이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.

  • 개인 프로젝트에서도 반드시 지켜야 하는 보안 기본선은 무엇인가?
  • 기업 환경에서는 어떤 운영, 감사, 승인 기준이 추가되는가?
  • 작은 서비스에서 시작한 보안 설계를 성장 가능한 구조로 만들려면 무엇을 남겨야 하는가?

개요

개인 프로젝트와 기업 보안의 차이는 “개인은 간단히 처리해도 된다”가 아니다. 차이는 보호해야 할 자산의 규모, 영향 범위, 감사 요구, 운영 인력, 사고 대응 책임에서 나온다. 작은 서비스에서도 비밀번호 원문 저장, HTTPS 미사용, 권한 테스트 부재, 민감 로그 노출은 허용할 수 없다.

개인 프로젝트에서 현실적으로 모든 기업 장비와 프로세스를 갖추기는 어렵다. 그러나 기본선은 있어야 한다. 기업 수준은 이 기본선 위에 승인 흐름, 접근 통제, 중앙 로그, 탐지 규칙, 사고 대응, 보존 정책이 추가된다.

이 문서는 학습자가 “지금 당장 해야 할 것”과 “운영 규모가 커지면 추가해야 할 것”을 구분하게 만드는 지도다.

공격 시나리오

작은 서비스는 보안 장치가 없어서 공격이 쉬운 경우가 많다.

  • 로그인 API에 rate limit가 없어 credential stuffing이 가능하다.
  • 비밀번호는 빠른 해시나 원문으로 저장된다.
  • 관리자 기능은 URL만 알면 접근 가능하거나 프론트 버튼 숨김에 의존한다.
  • 로그에는 token, 이메일, 전화번호, 전체 카드번호가 섞인다.
  • 사고가 난 뒤 어떤 계정이 영향을 받았는지 확인할 감사 로그가 없다.

기업 환경에서도 사고는 난다. 다만 기업은 피해 범위를 줄이고, 누가 무엇을 했는지 복원하며, 재발 방지를 추적할 장치를 요구한다.

취약한 요청/응답 예시

POST /admin/users/1004/role HTTP/1.1
Host: toy.example.com
Cookie: SESSION=member-session
Content-Type: application/json
 
{"role":"ADMIN"}
HTTP/1.1 200 OK
Content-Type: application/json
 
{"id":1004,"role":"ADMIN"}

작은 프로젝트에서 “관리자 페이지 링크를 숨겼으니 괜찮다”고 생각하면 이런 요청이 그대로 성공한다. 기업 환경이라면 관리자 권한, 승인, 감사 로그, 변경 사유가 모두 필요하다.

주제별 핵심 판단

  • 개인 프로젝트도 비밀번호 해시, HTTPS, 안전한 쿠키, 권한 테스트, 민감 로그 마스킹은 기본선이다.
  • 기업 수준은 정책 문서보다 변경 이력, 승인 흐름, 탐지와 대응 시간이 중요해진다.
  • 작은 서비스라도 audit log와 계정 잠금 기준이 없으면 사고를 복원하기 어렵다.
  • 성장 가능한 보안은 나중에 붙이는 장식이 아니라 처음부터 경계를 분리한 구조다.
  • 보안 수준은 “도구 유무”보다 “사고가 났을 때 설명 가능한가”로 평가한다.

수준 비교

항목개인 프로젝트 기본선기업 운영 수준
인증비밀번호 해시, HTTPS, 로그인 실패 제한MFA, 위험 기반 인증, 계정 잠금 정책
인가서버 권한 검사, 소유자 조건 테스트RBAC/ABAC, 승인 흐름, 권한 변경 감사
브라우저HttpOnly Secure SameSite, 기본 CSRFCSP 운영, Origin allowlist, 위반 리포트
API 입력DTO allowlist, Bean Validation보안 테스트 자동화, abuse 탐지
로그민감값 마스킹, traceId중앙 로그, 보존 정책, SIEM 연동
사고 대응세션 무효화와 공지 기준playbook, 담당자, 증거 보존, 재발 추적

개선된 요청/응답 예시

POST /admin/users/1004/role-change-requests HTTP/1.1
Host: api.example.com
Authorization: Bearer admin-token
Content-Type: application/json
X-Request-Id: 8c12
 
{
  "role": "SUPPORT_ADMIN",
  "reason": "temporary customer support",
  "expiresAt": "2026-07-07T00:00:00Z"
}
HTTP/1.1 202 Accepted
Content-Type: application/json
 
{"requestId":"role-change-7781","status":"PENDING_APPROVAL"}

권한 변경은 즉시 반영보다 승인 가능한 요청으로 분리하는 편이 안전하다. 작은 서비스에서는 승인 workflow까지 없더라도 변경 사유와 감사 로그는 남겨야 한다.

방어 설계

  • 처음부터 일반 사용자 API와 관리자 API를 분리한다.
  • 비밀번호 저장은 느린 단방향 해시를 사용한다.
  • 쿠키에는 HttpOnly, Secure, SameSite를 명시한다.
  • 권한 변경, 이메일 변경, 비밀번호 변경, 결제는 감사 이벤트로 남긴다.
  • secret은 git, 이미지, 로그에 남기지 않는다.
  • 운영자가 세션 무효화, token 폐기, 권한 회수를 할 수 있게 만든다.
  • 개인 프로젝트라도 보안 체크리스트를 README나 운영 문서에 남긴다.
  • 기업 수준에서는 승인자, 변경 사유, 만료 시간, 보존 기간, 탐지 규칙을 추가한다.

Spring/HTTP 예시

@PreAuthorize("hasAuthority('user.role.change.request')")
@PostMapping("/admin/users/{userId}/role-change-requests")
public RoleChangeRequestResponse requestRoleChange(@PathVariable Long userId,
                                                   @Valid @RequestBody RoleChangeCommand command,
                                                   Authentication authentication) {
    Long requesterId = ((CustomPrincipal) authentication.getPrincipal()).memberId();
    return roleChangeService.request(userId, requesterId, command);
}

관리자 권한 변경도 바로 DB update로 끝내지 않는다. 누가 요청했고, 어떤 권한을, 왜, 언제까지 부여하려는지 기록하면 개인 프로젝트에서도 기업식 감사 구조로 확장할 수 있다.

운영 로그와 감사 지점

level=INFO event=role_change_requested actor=admin:12 target=member:1004 role=SUPPORT_ADMIN expiresAt=2026-07-07 reason=temporary_customer_support traceId=8c12
level=INFO event=role_change_approved approver=security:3 requestId=role-change-7781 result=applied traceId=8c12

감사 로그는 관리자도 추적 대상이라는 전제를 가진다. 운영자 행위가 더 강한 권한을 가지므로 더 강한 기록이 필요하다.

  • 관리자 로그인과 권한 변경은 일반 로그인보다 오래 보존한다.
  • 민감 데이터 조회에는 조회 사유를 남긴다.
  • 로그에는 개인정보 원문 대신 식별 가능한 내부 id와 traceId를 남긴다.
  • 보안 이벤트는 삭제 권한을 제한하고 별도 저장소를 검토한다.
  • 탐지 규칙은 권한 변경 직후 대량 조회 같은 연쇄 이벤트를 볼 수 있어야 한다.

실전 판단 기준

  • 개인 프로젝트에서도 비밀번호 해시와 권한 테스트는 생략하지 않는다.
  • 로그에 token 원문과 비밀번호가 찍히지 않는지 직접 확인한다.
  • “지금은 작다”는 이유로 신뢰 경계와 권한 경계를 섞지 않는다.
  • 나중에 승인, 감사, 탐지를 붙일 수 있도록 이벤트와 권한 모델을 분리한다.
  • 좋은 판단은 비용을 고려하되 사고 때 설명 가능한 최소 장치를 남기는 것이다.

테스트 포인트

  • 일반 사용자가 관리자 API를 직접 호출했을 때 거부되는지 확인한다.
  • 권한 변경 요청과 실제 적용 이벤트가 모두 감사 로그에 남는지 확인한다.
  • 비밀번호 해시 알고리즘과 cost가 운영 가능한 수준인지 확인한다.
  • 로그에 token, 비밀번호, 전체 개인정보가 남지 않는지 샘플 로그로 확인한다.
  • 권한 변경 후 기존 세션과 token에 새 권한이 어떻게 반영되는지 테스트한다.

위험 신호!

  • “개인 프로젝트라서 괜찮다”며 비밀번호를 원문 또는 빠른 해시로 저장한다.
  • 관리자 페이지 링크를 숨기는 것으로 권한 통제를 대신한다.
  • 운영자가 사용자 데이터를 조회해도 감사 로그가 없다.
  • 권한 변경에 사유, 승인자, 만료 시간이 없다.
  • 사고가 나도 영향 계정 목록을 뽑을 로그가 없다.

확인 질문

확인 질문

  • 개인 프로젝트에서도 생략하면 안 되는 보안 기본선은 무엇인가?
    • HTTPS, 비밀번호 해시, 안전한 쿠키, 서버 권한 검사, 민감 로그 마스킹, 기본 감사 로그다.
  • 기업 수준 보안에서 추가되는 핵심은 무엇인가?
    • 승인 흐름, 중앙 감사 로그, 탐지 규칙, 보존 정책, 사고 대응 책임이다.
  • 작은 서비스가 성장 가능한 보안을 가지려면 무엇을 남겨야 하는가?
    • actor, resource, action, result, reason을 가진 보안 이벤트와 분리된 권한 모델을 남겨야 한다.

참고 문서