이번 시리즈에서는 카테고리(Category) 관리 API를 구축하는 방법을 다룹니다. Spring Boot와 MyBatis를 사용하여 관리자 전용 카테고리 등록, 수정, 삭제 기능을 구현하고, API의 성능과 유지보수성에 중점을 두어 설계합니다. 이번 글은 카테고리 API의 설계 및 구현 과정과, AOP를 통한 인증 및 권한 관리 방법을 중점적으로 설명합니다.
1. 카테고리 관리의 중요성
게시판에서는 수많은 게시글을 효율적으로 관리하고 사용자 경험을 향상시키기 위해 카테고리 기능이 필수적입니다. 카테고리를 통해 게시글을 논리적으로 분류할 수 있으며, 사용자는 원하는 게시글을 손쉽게 찾을 수 있습니다.
카테고리 관리 API는 특히 다음과 같은 요구 사항을 충족해야 합니다:
- 관리자 권한: 일반 사용자는 접근할 수 없도록 철저한 인증 및 인가를 구현.
- 유연한 확장성: 새로운 카테고리 추가 및 수정이 용이한 구조.
2. 카테고리 관리 API 설계
카테고리 API는 관리자만이 접근할 수 있는 RESTful API로 설계됩니다. 주요 엔드포인트는 다음과 같습니다:
- POST
/categories
: 카테고리 등록 - PATCH
/categories/{categoryId}
: 카테고리 수정 - DELETE
/categories/{categoryId}
: 카테고리 삭제
이 API는 관리자 권한을 요구하며, 각 작업은 AOP를 통해 권한 체크 후 수행됩니다.
3. 카테고리 Controller 구현
CategoryController
는 카테고리 관련 API 엔드포인트를 제공합니다. 여기서는 관리자가 카테고리를 등록, 수정, 삭제할 수 있도록 엔드포인트를 구성합니다.
@RestController
@RequestMapping("/categories")
@RequiredArgsConstructor
@Log4j2
public class CategoryController {
private final CateogryService categoryService;
private final UserService userService;
@PostMapping()
@LoginCheck(roles = {"ADMIN"})
public ResponseEntity<CommonResponse<Void>> registerCategory(
@RequestBody CategoryDTO categoryDTO, HttpSession session) {
String id = SessionUtil.getLoginAdminId(session);
UserDTO memberInfo = userService.getUserInfo(id);
if (memberInfo == null) {
return createUnauthorizedResponse();
}
categoryService.register(memberInfo.getUserId(), categoryDTO);
return createResponse(HttpStatus.CREATED, "CATEGORY_CREATED", "카테고리가 성공적으로 등록되었습니다.", null);
}
@PatchMapping("{categoryId}")
@LoginCheck(roles = {"ADMIN"})
public ResponseEntity<CommonResponse<Void>> updateCategory(
@PathVariable(value = "categoryId") int categoryId,
@RequestBody CategoryRequest categoryRequest, HttpSession session) {
String id = SessionUtil.getLoginAdminId(session);
UserDTO memberInfo = userService.getUserInfo(id);
if (memberInfo == null) {
return createUnauthorizedResponse();
}
CategoryDTO categoryDTO = new CategoryDTO(categoryId, categoryRequest.getName(), CategoryDTO.SortStatus.NEWEST, 10, 1);
categoryService.update(categoryDTO);
return createResponse(HttpStatus.OK, "CATEGORY_UPDATED", "카테고리가 성공적으로 수정되었습니다.", null);
}
@DeleteMapping("{categoryId}")
@LoginCheck(roles = {"ADMIN"})
public ResponseEntity<CommonResponse<Void>> deleteCategory(
@PathVariable(value = "categoryId") int categoryId, HttpSession session) {
String id = SessionUtil.getLoginAdminId(session);
UserDTO memberInfo = userService.getUserInfo(id);
if (memberInfo == null) {
return createUnauthorizedResponse();
}
categoryService.delete(categoryId);
return createResponse(HttpStatus.OK, "CATEGORY_DELETED", "카테고리가 성공적으로 삭제되었습니다.", null);
}
private ResponseEntity<CommonResponse<Void>> createUnauthorizedResponse() {
return createResponse(HttpStatus.UNAUTHORIZED, "AUTH_ERROR", "인증되지 않은 사용자입니다.", null);
}
private <T> ResponseEntity<CommonResponse<T>> createResponse(HttpStatus status, String code, String message, T data) {
return ResponseEntity.status(status)
.body(new CommonResponse<>(status, code, message, data));
}
}
4. CategoryDTO 및 요청 객체
카테고리 데이터는 CategoryDTO
를 통해 전송되며, 카테고리 등록 및 수정을 위한 요청 데이터를 담습니다.
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class CategoryDTO {
public enum SortStatus {
CATEGORIES, NEWEST, OLDEST
}
private int id;
private String name;
private SortStatus sortStatus;
private int searchCount;
private int pagingStartOffset;
}
5. 서비스 레이어: CategoryService
CategoryService
는 비즈니스 로직을 처리하며, 카테고리의 등록, 수정, 삭제를 담당합니다.
public interface CateogryService {
void register(String accountId, CategoryDTO categoryDTO);
void update(CategoryDTO categoryDTO);
void delete(int categoryId);
}
6. MyBatis 매퍼 설정
MyBatis 매퍼를 통해 데이터베이스와 상호작용합니다. 카테고리 데이터를 삽입, 수정, 삭제하는 쿼리를 정의합니다.
<mapper namespace="cohttp://m.example.boardserver.mapper.CategoryMapper">
<insert id="register" parameterType="cohttp://m.example.boardserver.dto.CategoryDTO">
INSERT INTO category(name) VALUES (#{name})
</insert>
<update id="updateCategory" parameterType="cohttp://m.example.boardserver.dto.CategoryDTO">
UPDATE category SET name = #{name} WHERE id = #{id}
</update>
<delete id="deleteCategory">
DELETE FROM category WHERE id = #{id}
</delete>
</mapper>
7. 성능 및 확장성 고려 사항
- DB 쿼리 최적화: 대규모 트래픽에 대응하기 위해 카테고리와 관련된 쿼리는 인덱스를 적절히 설계하여 성능을 최적화합니다. 하지만 지금은 초기 프로토 타입으로 진행된 상황이라. 아직 쿼리 최적화와 대용량에 대응한 REDIS를 적용하는 것은 잠시 보류하겠습니다.
- API 확장성: 향후 카테고리와 관련된 기능이 확장될 가능성을 고려해, 요청/응답 구조를 유연하게 설계하는 것이 중요합니다. 예를 들어, 카테고리 검색, 필터링 기능 추가를 고려할 수 있습니다.
8. 결론
이번 카테고리 관리 API를 구축하여, 게시판 시스템에서 카테고리 생성, 수정, 삭제와 같은 기본적인 관리 기능을 구현했습니다. AOP 기반의 인증 및 권한 관리 방식으로 API 보안성을 강화하였으며, 성능과 확장성을 고려한 설계를 통해 대규모 트래픽 환경에서도 효율적으로 동작하는 구조를 구현했습니다.
'프레임워크 > 자바 스프링' 카테고리의 다른 글
대규모 트래픽 게시판 구축 시리즈 #10: 게시판 검색 API (0) | 2024.09.07 |
---|---|
대규모 트래픽 게시판 구축 시리즈 #9: 게시판 API (0) | 2024.09.07 |
대규모 트래픽 게시판 구축 시리즈 #7: Spring AOP를 활용한 인증 및 인가 (0) | 2024.09.05 |
대규모 트래픽 게시판 구축 시리즈 #6: 유저 API (1) | 2024.09.05 |
대규모 트래픽 게시판 구축 시리즈 #5: MySQL 데이터베이스 연결 설정 (1) | 2024.09.05 |