나만의 학습 기록

최종 목적은 기술 블로그💩

백엔드 공부

API(3) - API의 다양한 인증 방식

밈밍민믹 2026. 4. 22. 17:04

요즘은 날씨가 쌀쌀하고 미세먼지도 많은지 코도 맵고 목도 칼칼하더라고요? 다들 감기 조심하고 마스크 쓰고 다니세요! 다시 날이 좀 풀리면 좋겠습니다. 한강 아니면 공원에서 피크닉 하고 싶은데 못해서 한이네요..ㅠㅠ

 

저번 시간에는 JSON API에 대해 알아보았는데요. 이번 시간에는 API의 다양한 인증 방식에 대해 알아보도록 할겁니다. 다른 편과 달리 인증 방식 5가지에 대해서 알아갈 예정이니 글이 많이 길 예정입니다. 잘 따라와주시면 감사하겠습니다.


API 인증

API 접근하려는 사용자 또는 애플리케이션의 신원을 확인하는 과정입니다. 즉, 서버가 클라이언트의 신원을 확인하고, 해당 요청이 신뢰할 수 있는 사용자로부터 온 것인지 검증하는 과정이라고 볼 수 있습니다.

 

 

API에서 인증이 필요한 이유

API에서 인증이 필요한 이유는 보안과 신뢰성을 확보하기 위해서입니다.

예를 들어 로그인한 사용자만 자신의 정보를 조회할 수 있어야 하고, 관리자만 특정 데이터를 삭제할 수 있다고 할 경우에 만약 인증 없이 모든 API를 호출할 수 있다면, 악의적인 사용자가 타인의 정보를 조회하거나 데이터를 임의로 수정하는 문제가 발생할 수 있습니다.

 

또한 인증은 단순히 사용자를 구분하는 역할에 그치지 않습니다. 

어떤 사용자가 어떤 요청을 보냈는지 추적할 수 있게 해주며, 서비스의 안정성과 데이터 보호 측면에서도 매우 중요합니다. 특히 API는 웹, 모바일, 외부 서비스 등 다양한 클라이언트와 연결될 수 있기에 서버 입장에서는 요청을 보낸 주체가 누구인지 확인하는 과정이 반드시 필요합니다.

 

즉, API 인증은 민감한 데이터와 기능을 보호하고, 허용된 사용자만 서비스에 접근할 수 있도록 하기 위한 기본적인 보안 장치입니다.

 

인증과 인가 차이

그렇다면 API 인증 방식으 학습하기 앞서 인증과 인가를 구분할 필요가 있습니다.

 

인증(Authentication)은 요청을 보낸 사용자가 누구인지 확인하는 과정입니다. 예를 들어 로그인 화면에서 아이디와 비밀번호를 입력해 사용자를 확인하는 과정이 인증에 해당합니다.

 

반면 인가(Authorization)인증된 사용자가 어떤 권한을 가지고 있는지 확인하는 과정입니다. 예를 들어 일반 사용자는 게시글 조회만 가능하고, 관리자는 삭제까지 가능하도록 구분하는 것은 인가에 해당합니다.

 

쉽게 얘기하자면,

  • 인증 : 당신은 누구입니까?
  • 인가 : 당신은 무엇을 할 수 있습니까?

 

즉, 인증은 사용자의 신원을 확인하는 단계이고, 인가는 그 사용자가 특정 자원에 접근하거나 특정 기능을 수행할 수 있는지 판단하는 단계입니다.

 

API인증 방식

API 인증 방식에는 여러 종류가 존재합니다. 각 방식은 사용자를 확인하는 방법, 서버가 상태를 관리하는 방식, 보안성, 사용 환경에서 차이가 보입니다.

대표적으로 Basic 인증, 쿠키/세션 기반 인증, 토큰 기반 인증, JWT, OAuth 등이 자주 사용됩니다.

 

1. Basic 인증

Basic 인증은 사용자 ID, 비밀번호를 이용하는 인증 방식입니다. 인증 정보는 사용자 "사용자ID: 비밀번호" 형태의 문자열을 Base64로 인코딩한 뒤 Authorization 헤더에 Basic과 함께 담아 서버에 전달합니다.

 

Basic 인증은 구조가 단순하고 구현이 쉽지만, 사용자 이름과 비밀번호가 요청마다 함께 전달되므로, 보안에 매우 민감합니다. 특히 단순 인코딩만 사용하기에 HTTPS 없이 사용하면 인증 정보가 노출될 위험이 큽니다.

 

즉, Basic 인증은 구현은 간단하지만 보안상 한계가 크기에 실제 서비스에서는 단독적으로 사용하기보다 제한적인 환경에서만 사용되는 방식입니다.

Authorization: Basic base64({USERNAME}:{PASSWORD})

 

간단한 코드를 통해 사용하는 방법을 확인해봅시다.

 

1) build.gradle 의존성 추가

스프링 시큐리티를 사용하기 위해 의존성을 추가합니다.

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-security'
}

 

2) SecurityFilterChain 설정 추가

@Configuration
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .csrf(csrf -> csrf.disable())
                .authorizeHttpRequests(auth -> auth
                        .requestMatchers("/public/**").permitAll()
                        .anyRequest().authenticated()
                )
                .httpBasic(Customizer.withDefaults()); // Basic 인증 활성화 역할

        return http.build();
    }

    @Bean
    public UserDetailsService userDetailsService(PasswordEncoder passwordEncoder) {
        UserDetails user = User.builder()
                .username("testuser")
                .password(passwordEncoder.encode("1234"))
                .roles("USER")
                .build();

        return new InMemoryUserDetailsManager(user);
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

securityFilterChain() 메서드는 어떤 요청을 보호할지, 어떤 인증 방식을 사용할지 정하는 부분입니다.

  • csrf(csrf → csrf.disable())은 CSRF 보호를 비활성화한 설정입니다.
  • requestMatchers("/public/**").permitAll()를 통해 해당 경로는 누구나 접근 가능하도록 허용합니다.
  • anyRequest().authenticated()는 그 외의 모든 요청은 인증된 사용자만 접근할 수 있도록 설정합니다.
  • httpBasic(Customizer.withDefaults())를 통해 Basic 인증을 활성화하는 설정입니다.

userDetailsService()를 통해서 테스트를 위해 임의적으로 사용자의 아이디와 비밀번호, 역할을 설정해줬습니다.

passwordEncoder()를 통해 비밀번호를 평문으로 다루는 것이 아닌 암호화해서 저장하고 비교하기 위해서 사용합니다.

 

3) 컨트롤러 작성 및 포스트맨을 통한 테스트

@RestController
public class TestController {

    @GetMapping("/public/hello")
    public String publicHello() {
        return "누구나 접근 가능";
    }

    @GetMapping("/private/hello")
    public String privateHello() {
        return "인증된 사용자만 접근 가능";
    }
}

/public/hello의 경우 인증 없이 접근할 수 있고, /private/hello는 Basic 인증이 성공해야한 접근할 수 있습니다.

 

 

 

Postmae에서의 사용 예시

Postman에서는 Authorization 탭의 Basic Auth를 선택하고 사용자 이름과 비밀번호를 입력하여 /pivate/hello 요청을 보내면 Basic 인증이 정상적으로 동작하는지 확인할 수 있습니다.

 

2. 쿠키/세션/토큰 기반 인증

쿠키와 세션은 함께 자주 언급되지만 서로 같은 개념은 아 닙니다.

 

쿠키(Cookie)클라이언트, 즉 브라우저에 저장되는 작은 데이터입니다.

서버는 응답 시 쿠키를 내려보낼 수 있고, 브라우저는 이후 같은 서버에 요청할 때 해당 쿠키를 함께 전송합니다.

[개발자 모드] → [Application] → [Cookies]를 통해서 확인할 수 있습니다.

 

반면 세션(Session)서버가 사용자 상태를 저장하는 방식입니다.

로그인한 사용자가 누구인지, 어떤 권한을 가지고 있는지와 같은 정보를 서버 측에 저장해두고 관리합니다. 

[개발자 모드] → [Application] → [Session storage]를 통해서 확인할 수 있습니다.

 

 

즉, 쿠키는 클라이언트에 저장되는 값이고, 세션은 서버에 저장되는 로그인 상태 정보입니다.

쿠키/세션 기반 인증에서는 보통 세션 ID를 쿠키에 담아 서버는 이를 통해 클라이언트가 식별합니다.

 

반면 토큰(Token)서버가 사용자를 인증한 뒤 발급하는 문자열 형태의 인증 정보입니다.

클라이언트는 이 토큰을 저장해두었다가 이후 요청을 보낼 때 함께 전달하고, 서버는 해당 토큰이 유효한지 확인하여 사용자를 식별합니다.

 

즉, 쿠키/세션 기반 인증이 서버에 로그인 상태를 저장하는 방식이라면, 토큰 기반 인증은 클라이언트가 인증 정보를 직접 가지고 요청하는 방식이라고 볼 수 있습니다.

 

쿠키 기반 인증의 동작 과정

동작 과정

1. 클라이언트가 페이지를 요청한다.

2. 웹 서버는 쿠키를 생성한다.

3. 생성한 쿠키에 정보를 담은 후 요청한 정보와 같이 클라이언트에게 보낸다.

4. 넘겨 받은 쿠키는 로컬 PC에 저장했다가 다시 서버에 요청 시 함께 헤더에 담아 보낸다.

5. 동일 사이트 재방문 시 클라이언트의 PC에 해당 쿠키가 있는 경우, 요청 페이지와 함께 쿠키를 전송한다.

 

 

세션 기반 인증의 동작 과정

동작 과정

  1. 클라이언트가 페이지를 요청한다.
  2. 서버는 클라이언트마다 개별의 세션 ID를 부여한다.
    • 세션 ID를 담은 세션 쿠키와 함께 응답을 전송한다.
    • 클라이언트는 요청할 때마다 세션 ID가 담긴 쿠키를 함께 전송한다.
  3. 서버는 세션 ID를 확인하고 이를 통해 클라이언트 정보를 가져와 활용한다.

 

토큰 기반 인증의 동작 과정

동작 과정

1. 토큰 기반 인증 시스템은 클랑언트가 서버에 접속을 하면 서버에서 해당 클라이언트에게 인증되었다는 의미로 '토큰'을 부여 받는다.

2. 해당 토큰은 유일하며 토큰을 발급받은 클라이언트는 또 다시 서버에 요청을 보낼 때 요청 헤더에 토큰을 심어서 보낸다.

3. 서버에서는 클라이언트로부터 받은 토큰을 서버에서 제공한 토큰과의 일치 체크하여 인증 과정을 처리하게 된다.

 

앞서 설명했던 Basic 인증과 달리 쿠키·세션·토큰은 하나의 구체적인 인증 방식이라기보다는 인증 정보를 저장하고 전달하는 구조와 관련된 개념입니다. 이제 이러한 개념과 밀접하게 연결되는 JWT와 OAuth에 대해 알아보겠습니다.

 

3. JWT

JWT(Json Web Token)사용자 정보, 권한 정보, 만료 시간과 같은 데이터를 JSON 기반으로 담아 표현하는 토큰 형식입니다. 주로 인증 정보를 안전하게 전달하고 검증하기 위해 사용됩니다.

 

JWT 핵심 용어

용어 설명
토큰(Token) 서버가 사용자를 인증한 뒤 발급하는 문자열 형태의 인증 정보입니다.
클라이언트는 이 값을 저장한 뒤 요청마다 함께 전달합니다.
클레임(Claim) JWT 안에 담기는 정보로 사용자 식별자, 권한, 만료 시간 등의 데이터가 이에 해당합니다.
Payload JWT에서 실제 데이터가 담기는 부분으로 여러 클레임이 해당 영역에 포함됩니다.
Signature 토큰이 위조되거나 변조되지 않았는지 확인하기 위한 서명 값입니다.
서버는 이를 통해 토큰의 유효성을 검증합니다.
Bearer Token HTTP 요청 헤더의 Authorization에 담아 전달하는 토큰 방식입니다.
보통 Authorization: Bearer <토큰값> 형태로 사용합니다.
만료 시간(Expiration Time) 토큰이 언제까지 유효한지를 나타내는 정보입니다.
만료 시간이 지나면 해당 토큰은 더 이상 사용할 수 없습니다.
액세스 토큰(Access Token) 인증에 필요한 API 요청 시 직접 사용되는 토큰입니다. 일반적으로 유효 시간이 짧게 설정됩니다.
리프레시 토큰(Refresh Token) 만료된 액세스 토큰을 다시 발급받기 위해 사용하는 토큰입니다.
보통 액세스 토큰보다 더 길게 유지됩니다.

해당 용어들은 JWT 동작과정과 실제 코드를 구성할때 이용되는 부분들이 존재하여 알아두시는게 좋을 것 같습니다.

 

JWT의 인증과정

  1. 사용자가 ID, PW를 가지고 서버에 로그인 인증을 요청한다.
  2. 서버에서 클라이언트로부터 인증 요청을 받으면 Header Payload와 Signature를 정의합니다.
  3. 위 3개를 각각 Base64로 한번 더 암호화하여 JWT 생성한 후 쿠키에 담아 클라이언트에게 발급합니다.
  4. 클라이언트는 서버로 부터 받은 JWT를 로컬 스토리지에 저장합니다.
  5. 요청시 헤더에 Access Token을 담아 보냅니다.
  6. 서버는 jwt가 내 서버에서 발행한 토큰인지 인증한다.
  7. 일치할 경우 인증에 통과되고 일치하지 않은 경우 통과하지 않는다.
  8. 통과되면 페이로드에 들어있는 유저의 정보들을 골라서 클라이언트에게 돌려준다.
  9. 클라이언트가 서버에 요청을 했는데 기간 만료일 경우 Refresh Token을 이용해서 새로운 Access Token을 발급 받는다.

간단한 예제를 입력하며 사용하는 방법을 알아봅시다.

 

1) build.gradle 의존성 추가하기

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'io.jsonwebtoken:jjwt-api:0.11.5' // JWT 관련 기능 
    runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5' // 기능을 실제로 동작하게 하는 구현체
    runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5' // JSON 형태로 처리할 수 있게 도와주는 모듈
}

 

2) application.yml에 JWT 설정 추가

spring :
	... # 기존 spring 설정들
	
jwt:
  secret: your-very-secret-key-your-very-secret-key-123456
  expiration: 3600000

 

3) 로그인 요청/응답 DTO

// LoginRequest.java

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class LoginRequest {
    private String username;
    private String password;
}

//LoginResponse.java

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class LoginResponse {
    private String accessToken;
}

클라이언트와 서버가 로그인 과정에서 필요한 데이터만 주고받을 수 있도록 DTO를 작성합니다.

LoginRequest는 로그인 요청 시 전달할 사용자 정보를 담고, LoginResponse는 로그인 성공 후 반환할 accessToken을 담는 역할을 합니다.

 

4) JwtTokenProvider.java

@Component
public class JwtTokenProvider {

    @Value("${jwt.secret}")
    private String secretKeyString;

    @Value("${jwt.expiration}")
    private long expiration;

    private SecretKey secretKey;

    @PostConstruct
    public void init() {
        this.secretKey = Keys.hmacShaKeyFor(secretKeyString.getBytes(StandardCharsets.UTF_8));
    }

    public String createToken(Authentication authentication) {
        String username = authentication.getName();
        Date now = new Date();
        Date expiry = new Date(now.getTime() + expiration);

        return Jwts.builder()
                .setSubject(username)
                .setIssuedAt(now)
                .setExpiration(expiry)
                .signWith(secretKey, SignatureAlgorithm.HS256)
                .compact();
    }

    public String getUsername(String token) {
        Claims claims = Jwts.parserBuilder()
                .setSigningKey(secretKey)
                .build()
                .parseClaimsJws(token)
                .getBody();

        return claims.getSubject();
    }

    public boolean validateToken(String token) {
        try {
            Jwts.parserBuilder()
                    .setSigningKey(secretKey)
                    .build()
                    .parseClaimsJws(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}

JwtTokenProvider는 JWT와 관련된 핵심 기능을 담당하는 클래스입니다. 로그인에 성공한 사용자에게 JWT를 발급하고, 이후 요청에서 전달된 토큰이 유효한지 검증하며, 토큰 안에 담긴 사용자 정보를 추출하는 역할을 합니다.

  • init()은 토큰 생성과 검증에 사용할 서명용 키를 초기화하는 메서드입니다.
  • createToken()은 인증된 사용자 정보를 바탕으로 JWT를 생성하는 메서드입니다. 로그인에 성공한 뒤 호출되며, 사용자 이름과 발급 시간, 만료 시간을 포함한 토큰을 만들어서 반환합니다.
  • getUsername()은 전달받은 JWT에서 사용자 이름을 추출하는 메서드입니다. 이후 요청에서 어떤 사용자가 보낸 토큰인지 확인할때 사용됩니다.
  • validateToken()은 JWT가 유효한지 검증하는 메서드입니다. 서명 값이 올바른지, 형식에 문제가 없는지, 만료되지 않았는지 등을 확인하고, 유효하면 true, 문제가 있을 경우 false를 반환합니다.

 

5) JWT 필터 설정

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private final JwtTokenProvider jwtTokenProvider;

    public JwtAuthenticationFilter(JwtTokenProvider jwtTokenProvider) {
        this.jwtTokenProvider = jwtTokenProvider;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {

        String bearerToken = request.getHeader("Authorization");

        if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
            String token = bearerToken.substring(7);

            if (jwtTokenProvider.validateToken(token)) {
                String username = jwtTokenProvider.getUsername(token);

                User user = new User(username, "", Collections.emptyList());

                UsernamePasswordAuthenticationToken authentication =
                        new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());

                authentication.setDetails(
                        new WebAuthenticationDetailsSource().buildDetails(request)
                );

                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }

        filterChain.doFilter(request, response);
    }
}

JwtAuthenticationFilter는 클라이언트가 요청과 함께 보낸 JWT를 확인하고 유효한 토큰이라면 해당 사용자를 인증된 사용자로 등록하는 역할을 합니다.

  • doFilterInternal()은 JWT를 읽어서 실제 인증 상태를 만들어주는 핵심 메서드입니다.

 

6) Security 설정

@Configuration
public class SecurityConfig {

    // 요청마다 JWT를 검사할 필터를 주입받음
    private final JwtAuthenticationFilter jwtAuthenticationFilter;

    public SecurityConfig(JwtAuthenticationFilter jwtAuthenticationFilter) {
        this.jwtAuthenticationFilter = jwtAuthenticationFilter;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                // REST API 테스트를 위해 CSRF 비활성화
                .csrf(csrf -> csrf.disable())

                // Basic 인증 설정
                // 이번 예제의 핵심은 JWT이므로 크게 사용되지는 않음
                .httpBasic(Customizer.withDefaults())

                // 기본 로그인 폼 비활성화
                // JWT는 세션 로그인 방식이 아니라 토큰 기반 인증 방식이기 때문
                .formLogin(form -> form.disable())

                // 세션을 사용하지 않도록 설정
                // JWT 인증에서는 서버가 로그인 상태를 저장하지 않으므로 STATELESS로 설정
                .sessionManagement(session ->
                        session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                )

                // 요청별 접근 권한 설정
                .authorizeHttpRequests(auth -> auth
                        // 로그인 요청은 누구나 접근 가능
                        .requestMatchers("/auth/login").permitAll()

                        // public 경로도 누구나 접근 가능
                        .requestMatchers("/public/**").permitAll()

                        // 그 외 모든 요청은 인증 필요
                        .anyRequest().authenticated()
                )

                // UsernamePasswordAuthenticationFilter보다 먼저 JWT 필터 실행
                // 요청이 들어오면 먼저 JWT를 검사하고 인증 정보를 등록하도록 설정
                .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }

    @Bean
    public UserDetailsService userDetailsService(PasswordEncoder passwordEncoder) {
        // 예제에서는 DB 대신 메모리에 테스트용 사용자 저장
        return new InMemoryUserDetailsManager(
                User.builder()
                        .username("testuser")
                        .password(passwordEncoder.encode("1234"))
                        .roles("USER")
                        .build()
        );
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        // 비밀번호를 암호화해서 저장하고 비교하기 위한 인코더
        return new BCryptPasswordEncoder();
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration)
            throws Exception {
        // 로그인 요청 시 username/password 인증 처리를 담당하는 AuthenticationManager 반환
        return configuration.getAuthenticationManager();
    }
}

 

이후 로그인 컨트롤러를 작성하고 테스트를 진행하면 로그인 성공 시 JWT 토큰 값이 반환되는 것을 확인할 수 있습니다. 클라이언트는 이 토큰을 저장한 뒤 이후 요청마다 Authorization: Bearer {토큰값} 형태로 함께 전달하여 인증이 필요한 API를 사용할 수 있습니다.

 

4. OAuth

인터넷 사용자들이 비밀번호를 제공하지 않고 다른 웹 사이트 상의 자신들의 정보에 대해 웹 사이트나 애플리케이션의 접근 권한을 부여할 수 있는 공통적인 수단으로서 사용되는 접근 위임을 위한 개방형 표준으로 연동되는 외부 웹 애플리케이션인 Facebook, Google, Naver, Kakao 등이 해당 사용자의 인증을 처리해주는 방식으로 일부 정보를 어플리케이션에 제공해줘서 해당 정보로 사용자를 관리한다.

 

OAuth 용어 정리

구분 설명
Resource Owner 웹 서비스를 이용하려는 유저, 자원(개인정보)을 소유하는 자, 사용자

Resource는 개인정보라고 생각하면 된다.
Client 자사 또는 개인이 만든 애플리케이션 서버
Authorization Server 권한을 부여(인증에 사용할 아이템을 제공주는) 해주는 서버

사용자는 이 서버로 아이디와 비밀번호를 넘겨 Authorization Code를 발급 받을 수 있다.
클라이언트는 이 서버로 Authorization Code을 넘겨 Token을 발급 받을 수 있다.
Resource Server 사용자의 개인정보를 가지고 있는 애플리케이션(Kakao, Google, Facebook 등) 회사 서버

클라이언트는 Token을 이 서버로 넘겨 개인정보를 응답 받을 수 있다.
Access Token 자원에 대한 접근 권한을 Resource Owner가 인가하였음을 나타내는 자격증명
Refresh Token
클라이언트는 Authorization Server로 부터 access token과 refresh token을 함께 부여 받는다.

access token은 보안상 만료기간이 짧기 때문ㅇ네 얼마 지나지 않아 만료되면 사용자는 로그인을 다시 시도해야한다.
그러나 refresh token이 있다면 access token이 만료될 때 refresh token을 통해 access token을 재발급 받아 재 로그인 할 필요없게끔 한다.

 

OAuth의 인증 과정

  1. 사용자가 서비스(Client)에 접근하여 로그인을 시도합니다.
  2. 서비스는 OAuth 인증을 위해 필요한 Client ID와 Redirect URI 정보를 준비합니다.
  3. 서비스는 사용자를 Authorization Server의 로그인 페이지로 이동시키며 이때 Client ID와 Redirect URI를 함께 전달합니다.
  4. Authorization Server는 사용자에게 로그인 페이지를 제공합니다.
  5. 사용자는 Authorization Server의 로그인 페이지에서 아이디와 비밀번호를 입력합니다.
  6. 로그인이 성공하면 Authorization Server는 Authorization Code를 발급합니다.
  7. Authorization Server는 미리 등록된 Redirect URI로 사용자를 다시 이동시키면서 발급한 Authorization Code를 함께 전달합니다.
  8. 서비스는 전달받은 Authorization Code를 이용해 Authorization Server에 Access Token 발급을 요청합니다.
  9. Authorization Server는 Authorization Code를 확인한 뒤, 유효하다면 Access Token을 발급합니다.
  10. 서비스는 Access Token을 확보함으로써 사용자 인증을 완료하고, 로그인 성공 상태를 처리합니다.
  11. 이후 사용자는 로그인된 상태에서 서비스를 요청할 수 있습니다.
  12. 서비스는 보호된 자원에 접근하기 위해 Access Token을 포함하여 Resource Server에 API를 호출합니다.
  13. Resource Server는 전달받은 Access Token이 유효한지 검증한 뒤 유효하면 요청된 자원에 대한 처리를 수행합니다.
  14. 검증이 완료되면 Resource Server는 요청된 데이터를 반환하고 서비스는 이를 사용자에게 제공합니다.

 

OAuth의 장단점

장점

  • 서비스 제공자에게 비밀번호를 직접 공유하지 않아 개인정보 유출 위험이 낮습니다.
  • 여러 사이트에서 구글, 페이스북 등 기존 계정으로 편리하게 로그인할 수 있습니다.
  • 특정 권한(읽기 전용 등)을 가진 액세스 토큰을 사용하여 제 3자 애플리케이션의 데이터 접근을 제어할 수 있습니다.
  • 개발자는 복잡한 로그인 인증 방식을 직접 구현하지 않고 OAuth를 통해 사용자 인증을 위임할 수 있습니다.

단점

  • OAuth 프로토콜 자체의 설정이 복잡하여 개발 및 통합 과정에 많은 시간이 소요될 수 있습니다.
  • 자체적인 암호화 기능이 부족하여 SSL/TLS 등 외부 보안 프로토콜에 의존해야 합니다.
  • OAuth 1.0에서 2.0으로 오면서 하위 호환성이 없는 변경 사항이 있어 마이그레이션이 복잡할 수 있습니다.

 


 

이상으로 API 보안에 대해서 정의와 종류에 대해서 알아보았습니다. JWT와 OAuth는 실무에서 자주 쓰이는 개념이니 꼭 알고 계시면 좋겠으며 세션,토큰,쿠키 기반 인증 방식에 대해서도 확실히 아셨으면 좋겠습니다. OAuth의 경우 현재 작성중인 내용이 있어서 코드 예제는 포함하지 않았습니다. 이후 글 작성이 완료되면 링크 걸어놓도록 하겠습니다.

다음 시간에는 gRPC에 대해 알아보도록 합시다. 수고하셨습니다.

 

2026.04.24 - [스프링부트] - 구글 OAuth2.0 - Flutter와 연동하기(1)

 

구글 OAuth2.0 - Flutter와 연동하기(1)

현재 개발을 진행중인 프로젝트에 대해서...추가할 API나 로직을 위주로, 예상 문제 → 해결방법 → 얻게되는 점으로 트러블 슈팅 과정을 작성할 예정입니다. 앞으로 열심히 작성해볼테니 틀린

0110020321.tistory.com