Notice
Recent Posts
Recent Comments
Link
250x250
반응형
«   2025/12   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
Archives
Today
Total
관리 메뉴

백고등어 개발 블로그

REST API 관련 면접 질문 모음 - 실무 완벽 가이드 본문

면접

REST API 관련 면접 질문 모음 - 실무 완벽 가이드

백고등어 2025. 9. 16. 16:41
728x90
반응형

REST API는 현대 웹 개발에서 가장 널리 사용되는 아키텍처 스타일입니다. 백엔드 개발자라면 반드시 알아야 할 필수 개념이며, 면접에서도 자주 다뤄지는 주제예요. 단순히 HTTP 메소드만 아는 것이 아니라, REST의 원칙과 실무에서의 활용법을 제대로 이해해보겠습니다.

1. REST와 RESTful API란 무엇인가요?

**REST(Representational State Transfer)**는 네트워크 아키텍처 원칙의 모음입니다. 자원을 이름으로 구분하여 해당 자원의 상태를 주고받는 모든 것을 의미해요.

REST의 6가지 원칙:

  1. 무상태성(Stateless): 각 요청은 독립적이며 서버는 클라이언트 상태를 저장하지 않음
  2. 클라이언트-서버 구조: 역할이 명확히 분리됨
  3. 캐시 가능(Cacheable): 응답은 캐시될 수 있어야 함
  4. 계층화 시스템(Layered System): 중간 서버(프록시, 게이트웨이)를 둘 수 있음
  5. Uniform Interface: 일관된 인터페이스
  6. Code on Demand: 서버가 클라이언트에 실행 가능한 코드를 전송 (선택사항)

도서관 시스템으로 비유하면, REST는 책(자원)을 체계적으로 분류하고 관리하는 규칙과 같습니다. 각 책은 고유한 번호(URI)가 있고, 대출/반납/조회 같은 행동(HTTP 메소드)이 정해져 있죠.

2. HTTP 메소드별 특징과 사용법을 설명해주세요.

GET: 리소스 조회

  • 안전함(Safe): 서버 상태를 변경하지 않음
  • 멱등성(Idempotent): 여러 번 호출해도 결과가 같음
  • 캐시 가능
GET /users/123
GET /users?page=1&size=10

POST: 리소스 생성, 데이터 처리

  • 안전하지 않음
  • 멱등성 없음 (매번 새로운 리소스 생성 가능)
POST /users
Content-Type: application/json
{
  "name": "김철수",
  "email": "kim@example.com"
}

PUT: 리소스 전체 수정/생성

  • 멱등성 있음 (같은 요청을 여러 번 해도 결과 동일)
PUT /users/123
{
  "name": "김철수",
  "email": "kim@example.com",
  "age": 30
}

PATCH: 리소스 부분 수정

  • 일반적으로 멱등성 있음
PATCH /users/123
{
  "name": "김영희"
}

DELETE: 리소스 삭제

  • 멱등성 있음 (이미 삭제된 리소스를 다시 삭제해도 결과 동일)
DELETE /users/123

3. 상태코드를 언제 사용해야 하나요?

2xx 성공:

  • 200 OK: 일반적인 성공 (GET, PUT, PATCH)
  • 201 Created: 리소스 생성 성공 (POST)
  • 204 No Content: 성공했지만 반환할 내용 없음 (DELETE)

4xx 클라이언트 오류:

  • 400 Bad Request: 잘못된 요청 구문
  • 401 Unauthorized: 인증 필요
  • 403 Forbidden: 접근 권한 없음
  • 404 Not Found: 리소스 없음
  • 409 Conflict: 리소스 상태 충돌

5xx 서버 오류:

  • 500 Internal Server Error: 서버 내부 오류
  • 502 Bad Gateway: 게이트웨이 오류
  • 503 Service Unavailable: 서비스 이용 불가

4. RESTful한 URL 설계 원칙은 무엇인가요?

좋은 URL 설계:

GET /users                  # 사용자 목록 조회
GET /users/123             # 특정 사용자 조회
POST /users                # 새 사용자 생성
PUT /users/123             # 사용자 전체 수정
PATCH /users/123           # 사용자 부분 수정
DELETE /users/123          # 사용자 삭제

GET /users/123/posts       # 특정 사용자의 게시글 목록
POST /users/123/posts      # 특정 사용자의 게시글 생성

나쁜 URL 설계:

GET /getUsers              # 동사 사용 X
POST /user/delete/123      # URL에 행위 포함 X
GET /users/getUserById/123 # 불필요한 정보 포함 X

설계 원칙:

  • 명사 사용, 동사 사용 금지
  • 소문자 사용
  • 하이픈(-) 사용, 언더스코어(_) 지양
  • 복수형 사용 권장
  • 계층 관계를 슬래시(/)로 표현

5. API 버전 관리는 어떻게 해야 하나요?

1. URL 경로에 버전 포함:

GET /v1/users/123
GET /v2/users/123

2. 쿼리 파라미터 사용:

GET /users/123?version=1
GET /users/123?v=2

3. HTTP 헤더 사용:

GET /users/123
Accept: application/vnd.company.v1+json

GET /users/123
Accept: application/vnd.company.v2+json

권장사항:

  • URL 경로 방식이 가장 명확하고 이해하기 쉬움
  • 하위 호환성을 최대한 유지
  • 주요 변경사항이 있을 때만 버전 업
  • 구버전 지원 기간을 명확히 공지

6. API 문서화는 어떻게 해야 하나요?

OpenAPI(Swagger) 사용:

@RestController
@Api(tags = "사용자 관리")
public class UserController {
    
    @GetMapping("/users/{id}")
    @ApiOperation(value = "사용자 조회", notes = "ID로 특정 사용자를 조회합니다")
    @ApiResponse(code = 200, message = "조회 성공")
    @ApiResponse(code = 404, message = "사용자 없음")
    public ResponseEntity<User> getUser(
        @ApiParam(value = "사용자 ID", required = true) @PathVariable Long id) {
        
        User user = userService.findById(id);
        return ResponseEntity.ok(user);
    }
}

문서화에 포함될 내용:

  • API 엔드포인트와 HTTP 메소드
  • 요청/응답 파라미터와 데이터 타입
  • 상태코드와 오류 메시지
  • 인증 방법
  • 사용 예시

7. API 보안은 어떻게 구현하나요?

1. HTTPS 사용: 모든 API 통신을 암호화하여 데이터 보호

2. 인증(Authentication):

@RestController
public class UserController {
    
    @GetMapping("/users/me")
    public ResponseEntity<User> getCurrentUser(
        @RequestHeader("Authorization") String token) {
        
        User user = authService.getUserFromToken(token);
        return ResponseEntity.ok(user);
    }
}

3. 인가(Authorization):

@PreAuthorize("hasRole('ADMIN')")
@DeleteMapping("/users/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
    userService.delete(id);
    return ResponseEntity.noContent().build();
}

4. Rate Limiting:

@RateLimited(requests = 100, timeWindow = "1h")
@GetMapping("/users")
public ResponseEntity<List<User>> getUsers() {
    return ResponseEntity.ok(userService.findAll());
}

5. 입력 검증:

@PostMapping("/users")
public ResponseEntity<User> createUser(@Valid @RequestBody UserRequest request) {
    User user = userService.create(request);
    return ResponseEntity.status(201).body(user);
}

8. 페이징과 필터링은 어떻게 구현하나요?

페이징:

GET /users?page=0&size=20&sort=createdAt,desc
@GetMapping("/users")
public ResponseEntity<Page<User>> getUsers(
    @RequestParam(defaultValue = "0") int page,
    @RequestParam(defaultValue = "20") int size,
    @RequestParam(defaultValue = "id") String sort) {
    
    Pageable pageable = PageRequest.of(page, size, Sort.by(sort));
    Page<User> users = userService.findAll(pageable);
    return ResponseEntity.ok(users);
}

필터링:

GET /users?name=김&age=30&city=서울
@GetMapping("/users")
public ResponseEntity<List<User>> getUsers(
    @RequestParam(required = false) String name,
    @RequestParam(required = false) Integer age,
    @RequestParam(required = false) String city) {
    
    UserSearchCriteria criteria = new UserSearchCriteria(name, age, city);
    List<User> users = userService.findByCriteria(criteria);
    return ResponseEntity.ok(users);
}

9. 오류 응답은 어떻게 처리해야 하나요?

일관된 오류 응답 형식:

public class ErrorResponse {
    private String code;
    private String message;
    private LocalDateTime timestamp;
    private List<FieldError> fieldErrors;
    
    // 생성자, getter, setter
}

@RestControllerAdvice
public class GlobalExceptionHandler {
    
    @ExceptionHandler(UserNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleUserNotFound(UserNotFoundException e) {
        ErrorResponse error = ErrorResponse.builder()
            .code("USER_NOT_FOUND")
            .message("사용자를 찾을 수 없습니다")
            .timestamp(LocalDateTime.now())
            .build();
        
        return ResponseEntity.status(404).body(error);
    }
    
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ErrorResponse> handleValidationError(MethodArgumentNotValidException e) {
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors()
            .stream()
            .map(error -> new FieldError(error.getField(), error.getDefaultMessage()))
            .collect(Collectors.toList());
        
        ErrorResponse error = ErrorResponse.builder()
            .code("VALIDATION_FAILED")
            .message("입력값 검증에 실패했습니다")
            .fieldErrors(fieldErrors)
            .timestamp(LocalDateTime.now())
            .build();
        
        return ResponseEntity.badRequest().body(error);
    }
}

10. API 성능 최적화 방법은 무엇인가요?

1. 캐싱:

@GetMapping("/users/{id}")
@Cacheable(value = "users", key = "#id")
public ResponseEntity<User> getUser(@PathVariable Long id) {
    User user = userService.findById(id);
    return ResponseEntity.ok(user);
}

2. 압축:

server.compression.enabled=true
server.compression.mime-types=application/json,application/xml,text/html,text/xml,text/plain

3. 필요한 필드만 반환:

@GetMapping("/users")
public ResponseEntity<List<UserSummary>> getUsers() {
    List<UserSummary> users = userService.findAllSummary();
    return ResponseEntity.ok(users);
}

4. 비동기 처리:

@PostMapping("/users/bulk")
public ResponseEntity<String> createUsersBulk(@RequestBody List<UserRequest> requests) {
    String jobId = userService.createUsersAsync(requests);
    return ResponseEntity.accepted().body(jobId);
}

@GetMapping("/jobs/{jobId}")
public ResponseEntity<JobStatus> getJobStatus(@PathVariable String jobId) {
    JobStatus status = jobService.getStatus(jobId);
    return ResponseEntity.ok(status);
}

핵심 정리

REST API는 단순히 HTTP 메소드와 JSON을 사용하는 것 이상의 의미가 있습니다. 자원 중심의 설계, 무상태성, 일관된 인터페이스 등의 원칙을 이해하고 실무에 적용하는 것이 중요해요.

면접에서는 이론적 지식뿐만 아니라 실제 API를 설계하고 구현했던 경험, 성능 최적화나 보안 이슈를 어떻게 해결했는지에 대한 구체적인 사례를 물어볼 가능성이 높습니다. 실무에서 겪었던 문제와 해결 과정을 정리해두세요.

728x90
반응형