paint-brush
효율적인 백엔드, 우수한 성능: 웹 서비스 최적화에 대한 심층 분석~에 의해@sergeidzeboev
890 판독값
890 판독값

효율적인 백엔드, 우수한 성능: 웹 서비스 최적화에 대한 심층 분석

~에 의해 Sergei Dzeboev8m2023/11/21
Read on Terminal Reader

너무 오래; 읽다

웹 서비스의 백엔드 최적화는 단순히 코드와 알고리즘을 개선하는 것 이상으로 확장됩니다. 서비스 효율성을 높이는 핵심은 데이터베이스 상호 작용을 최적화하는 것입니다. 이는 ORM 쿼리의 미세 조정, 플랫 데이터 클래스 사용, 데이터를 Hot, Warm 또는 Cold로 적절하게 분류하고 효과적인 캐싱 전략을 사용하여 달성할 수 있습니다. 이러한 단계를 통해 보다 효율적이고 반응성이 뛰어나며 성능이 뛰어난 웹 서비스를 얻을 수 있습니다.
featured image - 효율적인 백엔드, 우수한 성능: 웹 서비스 최적화에 대한 심층 분석
Sergei Dzeboev HackerNoon profile picture
0-item


웹 서비스의 백엔드 최적화는 항상 성능 향상을 목표로 하며, 그 핵심 측면은 데이터 처리 속도를 높이는 것입니다. 이 프로세스에는 리소스를 보다 효율적으로 사용하고 요청에 대한 시스템의 응답 시간을 최소화하기 위한 많은 중요한 개선 사항이 포함됩니다. 이 기사에서는 웹 서비스 속도를 크게 높일 수 있는 몇 가지 입증된 기술을 공유하겠습니다.


개선을 위해 무엇에 집중해야 합니까?

많은 프로그래머는 애플리케이션을 더 빠르게 만들기 위해 코드와 알고리즘을 최적화하고 적절한 데이터 구조 와 최적의 작업을 선택하는 데 중점을 둡니다. 이는 일반적으로 성능 향상으로 이어지며 종종 최적화된 코드의 속도가 향상되지만 크게 향상되지는 않습니다.


약간의 증가는 메모리 작업의 고유한 속도에 따른 것이며 원래 코드가 매우 비효율적이지 않은 한 상당한 개선을 기대해서는 안 됩니다. 그러나 시간이 많이 걸리는 특정 작업, 특히 입력-출력 작업은 최적화를 위해 우선순위를 지정해야 합니다.


파일 작업이든 데이터베이스와 상호 작용하든 이러한 작업의 실행 시간은 메모리 내 작업과 비교할 때 항상 눈에 띕니다. 파일에서 데이터를 읽는 프로세스에 큰 영향을 미칠 수는 없지만 데이터베이스 작업은 직접 제어할 수 있습니다. 개발자로서 귀하는 이러한 상호 작용을 크게 개선할 수 있는 모든 능력을 갖추고 있습니다.


데이터베이스 작업을 더욱 효율적으로 만들어 백엔드 서비스 성능을 크게 향상시킬 수 있는 다음 전략을 살펴보겠습니다.


쿼리 최적화

오늘날 데이터베이스 상호 작용을 위해 ORM(객체 관계형 매핑) 시스템을 활용하지 않는 백엔드 웹 서비스를 찾는 것은 거의 없습니다. 최고의 결과를 목표로 한다면 ORM 사용자 정의를 고려해보세요. ORM은 효율적이고 오류가 없지만 일반적인 용도로 설계되었습니다. 이러한 광범위한 적용 가능성은 종종 높은 성능을 희생하면서 발생합니다.


ORM은 다양한 데이터베이스와 호환되도록 만들어졌으므로 프로젝트를 위해 선택한 데이터베이스의 특정 이점이 누락될 수 있습니다. 예를 들어, 여기에 설명된 것처럼 고유한 데이터베이스 기능을 활용하면 데이터베이스 상호 작용 속도를 최대 30배까지 크게 향상시킬 수 있습니다.


ORM이 제공하는 기본 쿼리에만 의존하는 대신 자신만의 최적화된 쿼리를 만드는 것이 좋습니다. 사용자 지정 쿼리는 특히 여러 조인과 관련된 시나리오에서 더 나은 성능을 발휘하는 경우가 많습니다.


다음은 조인 쿼리를 사용하여 성능을 향상시킬 수 있는 방법에 대한 Spring JPA의 간단한 예입니다.

 @Transactional @Lock(LockModeType.PESSIMISTIC_READ) @Query(value = """ SELECT e FROM EmployeeRecord e LEFT JOIN DepartmentRecord d ON e.departmentId = d.id WHERE e.departmentId = :departmentId; """) List<EmployeeRecord> findEmployeesByDepartmentId(Integer departmentId);


플랫 클래스 사용

중첩된 개체와 깊은 계층 구조 시스템이 포함된 복잡한 클래스를 사용하면 시스템 성능이 크게 저하될 수 있습니다. 특히 구조의 모든 클래스가 완전히 활용되지 않는 경우 전체 중첩 구조에 대해 데이터베이스를 쿼리할 필요가 없는 경우가 많습니다.


지연 초기화는 중첩된 개체에 대한 불필요한 쿼리를 완화하는 데 도움이 되지만, 중첩된 개체가 필요하지만 모든 데이터가 필요한 것은 아닌 경우 문제가 발생합니다. 이 딜레마에 대한 해결책은 플랫 데이터 클래스를 사용하는 것입니다.


데이터베이스에서 필요한 필드 데이터만 수집하도록 설계된 클래스를 만들어야 합니다. 그런 다음 필요한 모든 조인을 통합하는 사용자 지정 데이터베이스 쿼리를 사용하여 실제로 필요한 필드만 선택합니다.


이 접근 방식은 쿼리 속도를 향상시킬 뿐만 아니라 데이터베이스에서 서비스로의 데이터 트래픽을 줄여줍니다.


예를 들어 Spring JPA의 NamedParameterJdbcTemplate을 사용하면 필요한 필드가 있는 기본 클래스를 생성할 수 있습니다.

 public record EmployeeDepartment(Integer employeeId, String employeeName, String departmentName) { }


다음으로 간단한 스크립트를 사용하여 기본 테이블과 조인된 테이블에서 필요한 필드만 수집합니다.

 public List<EmployeeDepartment> employeeDepartments() { return template.query(""" SELECT employees.employee_id, employees.employee_name, departments.department_name FROM employees LEFT JOIN departments ON employees.department_id = departments.department_id; """, new MapSqlParameterSource(), employeeDepartmentMapper); }


이 접근 방식을 사용하면 로드가 크게 줄어들고 데이터 작업이 훨씬 더 효율적으로 수행됩니다.


핫 데이터 정의

데이터 작업의 다음 중요한 단계는 데이터 유형을 정의하는 것입니다. 기본 유형은 핫 데이터입니다.


핫데이터(Hot Data)는 서비스가 실시간으로 처리하는 데이터이다. 웹 서비스 응답의 관련성은 즉각적인 응답성에 따라 달라지므로 이 데이터는 캐시될 수 없습니다. 따라서 이 데이터는 항상 최신 상태여야 합니다. 이 서비스는 Hot Data와 일관되게 작동하여 지속적으로 새로운 값을 기록하고 시기적절한 업데이트를 위해 정보를 추출합니다.


핫 데이터를 최대한 효율적으로 사용하려면 해당 데이터가 저장되는 테이블을 최대한 컴팩트하게 유지하는 것이 중요합니다.


  • 가능한 한 적은 열을 유지하세요.

    테이블에는 적극적으로 사용되는 필드만 포함되어야 하며 다른 모든 데이터는 관련 행의 ID만 유지하면서 별도의 테이블에 저장되어야 합니다. 이 접근 방식을 사용하면 이 데이터로 인해 기본 테이블에 과도한 부담을 주지 않고 보고 목적 등 필요할 때 사용되지 않는 모든 필드에 액세스할 수 있습니다.


  • 가능한 한 적은 행을 유지하세요.

    더 이상 필요하지 않은 라인을 저장하지 마십시오. 대신 보관 테이블로 이동하세요. 이 접근 방식을 사용하면 아카이브의 모든 기록 데이터를 보존하면서 쿼리가 필요한 행을 더 빠르게 찾을 수 있습니다. 간단한 작업으로 이 프로세스를 자동화하면 데이터 보관에 대한 참여가 최소화됩니다.


  • 색인을 최신 상태로 유지

    인덱스를 구축하는 것을 잊지 마세요. 인덱스는 빠른 데이터 검색에 매우 중요하며 프로그래머가 간과하는 경우가 많습니다. 적절한 인덱싱을 사용하면 데이터베이스의 검색 시간과 메모리 소비를 크게 줄일 수 있습니다. 복합 인덱스를 포함하여 조인과 관련된 조건과 열 모두에 대한 인덱스를 작성해야 합니다.


  • 외래 키 사용을 포기하세요

    외래 키를 사용하면 관련 테이블에 키가 있는지 확인하기 위해 데이터베이스에 추가 로드가 발생하므로 특히 데이터를 쓸 때 데이터 작업 속도가 느려집니다. 오해하지 마세요. 이러한 테이블에 외래 키를 저장하는 것이 가능하고 때로는 필요할 수도 있지만 키를 단순히 일반 값으로 저장하는 것이 더 좋습니다.


이러한 간단한 방법을 사용하면 테이블의 효율성과 유용성을 극대화할 수 있습니다.


웜 데이터 정의

웜 데이터는 응답을 준비하는 데 사용되는 데이터이지만 관련성이 중요한 영향을 미치지는 않습니다. 예로는 제품 설명이나 사용 가능한 액세서리 목록이 있습니다. 이러한 데이터를 저장하는 동안 테이블 크기를 면밀히 모니터링할 필요가 더 이상 없습니다. 그러나 이러한 테이블은 조인에 자주 사용되므로 이러한 테이블에 대한 인덱스 생성을 간과하지 않는 것이 중요합니다.


  • 캐시 웜 데이터

    Warm Data의 주요 장점은 캐시 가능성입니다. 요청이 이루어지면 데이터를 메모리에 저장하여 데이터베이스 호출 수를 줄이고 계산 속도를 높일 수 있습니다. 그러나 캐시에는 정기적인 업데이트가 필요하다는 점을 기억하십시오.


  • 합리적인 TTL(Time To Live) 설정

    올바른 작동을 위해 올바른 TTL(Time To Live)을 설정하십시오. 일반적으로 사용자가 웹사이트에서 결정을 내리고 주문하는 데 걸리는 평균 시간에 맞춰 약 90초의 TTL이면 충분합니다. 항상 서비스 요구 사항에 따라 TTL을 조정하세요.


  • 더 작은 클래스를 사용하여 Warm Data 저장

    캐싱을 위해서는 컴팩트 클래스를 사용하세요. 본격적인 쿼리가 이루어지고 테이블의 모든 데이터가 수집되는 경우에도 모든 것을 캐시에 저장하지 마십시오. 꼭 필요한 데이터만 저장하세요. 이 접근 방식은 백엔드 서비스의 메모리 소비를 크게 줄입니다.


Warm Data 설정에는 많은 시간이 필요하지 않으며 궁극적으로 실질적인 결과를 얻을 수 있습니다.


콜드 데이터 정의

콜드 데이터는 거의 변경되지 않지만 대응에 필요한 데이터를 말합니다. 이러한 데이터의 예로는 매장 이름이나 주소가 있습니다. 이 데이터는 거의 변경되지 않으며 응답의 관련성에 최소한의 영향을 미칩니다.


  • 콜드 데이터를 캐시하거나 파일에 저장

    이 데이터 유형은 항상 캐시되어야 합니다. 이러한 데이터가 크기가 커서 메모리에 넣는 것이 불가능할 경우 데이터베이스에서 해당 데이터를 언로드하고 바로 사용할 수 있는 형식으로 파일에 저장하는 것이 좋습니다. 카테고리별로 나누고 가장 자주 사용하는 카테고리만 선택하면 메모리 사용량을 줄이는 데 도움이 됩니다. 또한 이 접근 방식은 네트워크를 통해 작업할 필요가 없으므로 데이터베이스에서 데이터를 가져오는 것보다 속도가 눈에 띄게 향상됩니다.


  • 트리거 시 캐시 업데이트

    이러한 캐시의 TTL(Time To Live)은 일반적으로 24시간으로 설정됩니다. 캐시를 계속 업데이트하려면 작업을 예약하거나 이 데이터의 변경 사항을 모니터링하고 캐시 업데이트를 시작하는 트리거를 만들어야 합니다. 예를 들어 콜드 데이터를 게시하거나 업데이트하기 위해 엔드포인트가 호출되는 경우 캐시를 업데이트하려면 트리거가 활성화되어야 합니다.


Cold Data를 효과적으로 관리하는 것 역시 대응 효율성을 최적화하여 전체 시스템 성능을 향상시키는 중요한 부분입니다.


결론

결론적으로, 웹 서비스의 백엔드 최적화는 코드 및 알고리즘 최적화에만 달려 있는 것이 아닙니다. 데이터베이스 상호 작용을 향상하면 서비스의 효율성과 전반적인 성능이 향상됩니다. ORM(Object-Relational Mapping) 쿼리 미세 조정, 플랫 데이터 클래스 활용, 데이터 유형의 정확한 정의, 캐싱 전략 채택과 같은 기술을 구현하면 서비스 성능을 크게 향상시킬 수 있습니다. 이러한 조치를 통해 웹 서비스는 궁극적으로 효율성, 응답성 및 전반적인 기능 향상을 달성하게 됩니다.


주요 단계 :

  1. 데이터베이스 쿼리를 최적화하고 ORM 구현에만 의존하지 마십시오.
  2. 플랫 클래스를 사용하면 메모리 사용량을 줄이고 응답 속도를 높일 수 있습니다.
  3. 데이터 유형을 Hot, Warm, Cold로 분류하여 정의합니다.
  4. 정의된 각 데이터 유형에 맞는 특정 전략을 사용합니다.