목차

소프트웨어 제품은 수명이 존재합니다. 그건 제가 담당하고 있던 외부 사용자용 OpenAPI 서비스도 마찬가지였는데요, 이번 글에서는 레거시 시스템을 새로운 차세대 시스템으로 전환하면서 느낀 점을 적어보려 합니다.

10년이 더 넘은 이 시스템은 많은 것들이 낡은 상태였습니다. 차세대 프로젝트이니 Spring 버전도 최신으로 올리고 AOP나 Security 등 기존에는 사용하지 않고 있던 기술도 도입하며 큰 변경이 있을 예정이었습니다.

하지만 단 하나 타협할 수 없었던 영역이 있습니다.

바로 호환성입니다.

외부 사용자는 변화를 달갑게 여기지 않을 수 있다

제가 운영하던 레거시 시스템은 독자적인 규격의 XML 양식을 사용하고 있었습니다. 읽기도 어렵고, 요청 본문을 작성하기도 번거로웠습니다. 마음 같아서는 XML을 싹 다 걷어내고 싶었습니다.

새롭게 연동하는 외부 사용자들은 대부분 웹 표준인 JSON 방식을 선호하는 편이었기도 했구요. 하지만 레거시라는 이유만으로 기존에 동작하던 기능을 없애버리면, 잘 쓰고 있던 외부 사용자는 대응개발을 해야 하고, 그건 곧 누군가에게 비용이 됩니다.

이해관계에 따라서 이러한 비용을 역으로 요구하는 경우도 있었습니다. 그래서 내부 결정을 통해 리뉴얼 방향성을 아래와 같이 잡았습니다.

효율적이고 유지보수하기 좋은 시스템을 만들되, 외부 사용자에게는 가능한 바뀐지 모르게 만들 것

두 마리 토끼 잡기

방향성이 잡히고 설계 단계에서 가장 먼저 진행한건 개발자들이 불필요한 부분을 신경쓰지 않게 만들기 였습니다.

레거시 시스템에는 인증이나 예외처리를 위한 코드들이 전부 서비스 로직에 녹아있었는데요, 반복되는 부분들을 공통 영역으로 분리한다면 유지보수하기 훨씬 좋은 시스템이 될 것 같았습니다. 개발자들은 비즈니스 로직에만 집중하면 되니까요.

  • 인증/인가 로직 → Spring Security
  • 예외처리 → ControllerAdvice
  • 성공/실패 기록 로깅 → AOP
  • API 응답 생성 → ResponseBodyAdvice

동시에 외부 호환성을 유지하기 위해 가장 신경썼던건 API 응답을 생성하는 부분입니다.

레거시 시스템은 독자적인 XML 양식을 사용하고 있었어서 Spring 프레임워크에서 기본적으로 제공하는 XML 파서를 사용할 수 없었습니다. 그래서 XML, JSON이 호환되면서 요청/응답 본문이 Java 객체로 변환될 수 있도록 설계해야 했는데요, AI의 도움을 가장 많이 받은 부분이기도 합니다.

Accept 헤더값에 따라 외부 사용자가 원하는 응답 형태로 내려주도록 ResponseBodyAdvice에서 구현할 수 있었습니다.

<Root>
  <Set id="product">
    <Rows>
      <Row>
        <itemCode>PD123456</itemCode>
        <price>12000</price>
      </Row>
    </Rows>
  </Set>
</Root>

{ "product": { "itemCode": "PD123456", "price": 12000 } }
class ProductUpdateRequest {
    class Product {
        private String itemCode;
        private Integer price;
    }
}
@RestControllerAdvice
public class XmlResponseAdvice implements ResponseBodyAdvice<Object> {

    @Override
    public boolean supports(MethodParameter returnType,
                            Class<? extends HttpMessageConverter<?>> converterType) {
        ...
    }

    @Override
    public Object beforeBodyWrite(
                ...
        ) {
            // some custom logic

이렇게 기존 외부 사용자들은 아무것도 바꾸지 않아도 되고 새로운 외부 사용자들은 Accept 헤더만 변경해주면 JSON 형태로 API를 연동할 수 있게 되었습니다.

이대로면 외부 사용자들이 신규 API로 전환하는데에 큰 무리가 없어 보였습니다. 그런데 또 다른 문제가 수면 위로 올라오기 시작했습니다.

API Documentation

레거시 API는 그 문서도 엑셀로 관리되고 있었는데요, API 요청/응답 스펙이 변경될 때 마다 문서를 수정해서 외부 사용자에게 전달해 줘야만 했습니다.

프로젝트에서 신규 기능이나 일부 스펙들이 변경되면서 실제 API 스펙과 문서의 괴리가 커져만 갔고, 최신화된 문서를 요청하는 외부 사용자들의 이메일이 쌓여가게 되면서 업무에 병목이 생기기 시작했습니다.

이메일로 엑셀 문서를 공유하는 오래된 업무 방식 자체를 바꾸고 싶었습니다. 보기 편한 UI로 제공되어 외부 사용자 경험에도 훨씬 좋고, 별도로 문서를 관리하지 않아도 되니 업무에 대한 부담도 훨씬 줄어들 것이라고 판단했기 때문입니다.

그렇게 개발자 포털을 새롭게 만들게 되었습니다. Docusaurus라는 오픈소스를 활용해서 Swagger와 연동하니 생각보다 빠르게 결과물이 나오더군요.

처음에는 엑셀문서를 웹 방식의 API 문서로 변경하는 데에서 시작했지만 공지사항이나 변경이력 등 필요한 기능을 하나둘 입혀나갔습니다.

결과적으로는 진작 왜 도입하지 않았을까 하는 생각이 들 정도로 만족스러웠습니다.

문서는 Swagger와 함께 자동으로 관리되어 운영 부담이 낮고, 외부 사용자도 변경이력이나 공지사항을 웹에서 즉각적으로 확인이 가능하니 업무 효율성 측면에서도 훨씬 좋았습니다.

마치며

기술을 새롭게 가져가는 일도 중요하지만, 이미 쓰고 있는 외부 사용자에게 비용을 전가하지 않는 방향으로 바꾸는 일 역시 서비스를 운영하는 개발자에게는 중요한 것 같습니다.

물론 때로는 과감한 결단이 필요하기도 합니다. 엑셀 문서를 버리고 웹 방식으로 전환한 것 처럼요.

전환 비용, 비즈니스 연속성, 사용자 경험.

다양한 관점에서 얻거나 잃게될 부분을 저울질하며 그 중도를 찾아가는 일이 서비스 운영자에게 주어진 하나의 과제가 아닐까 합니다.