최신글

CS

[정보처리기사] 결합도, 응집도

결합도, 응집도 결합도(Coupling)란? 모듈과 모듈 사이의 의존 정도 한 모듈의 변경이 다른 모듈에 얼마나 영향을 주는지를 나타냄 낮을수록 좋다 결합도 종류 (내·공·외·제·스·자) 내용 결합도 (Content) 다른 모듈의 내부 데이터나 로직을 직접 참조/수정 공통 결합도 (Common) 여러 모듈이 공통 데이터 영역(전역 변수) 사용 외부 결합도 (External) 외부 파일, 외부 인터페이스, 외부 포맷 공유 제어 결합도 (Control) 제어 신호(flag, mode)를 전달해 동작 제어 스탬프 결합도 (Stamp) 배열, 구조체, 객체 등 자료 구조 전체 전달 자료 결합도 (Data) 필요한 데이터 값만 전달 (가장 이상적) 응집도(Cohesion)란? 모듈 내부 요소들 간의 관련성 하나의 모듈이 얼마나 하나의 목적에 집중되어 있는지 높을수록 좋다 응집도 종류 (기·순·통·절·시·논·우) 기능적 응집도 (Functional) 하나의 명확한 기능만 수행 (최고) 순차적 응집도 (Sequential) 한 기능의 출력이 다음 기능의 입력 통신적 응집도 (Communicational) 동일한 데이터를 사용하는 기능들 묶음 절차적 응집도 (Procedural) 실행 순서 때문에 묶인 기능들 시간적 응집도 (Temporal) 같은 시간대에 실행되는 기능들 (초기화, 종료) 논리적 응집도 (Logical) 논리적으로 유사한 기능들 (입출력 처리 등) 우연적 응집도 (Coincidental) 관련 없는 기능들이 묶임 (최악)

2026년 02월 02일 14:23

CS

[정보처리기사] 소프트웨어 테스트

Software Test 소프트웨어 테스트란? 소프트웨어가 요구사항에 맞게 동작하는지 확인하는 과정 오류(Error) 및 결함(Bug)을 발견하기 위한 활동이며 결함이 없음을 증명하는 활동이 아님 살충제 패러독스: 동일한 테스트 케이스를 반복해서 수행하면 새로운 결함을 더 이상 발견하지 못하는 현상 파레토의 법칙: 소프트웨어 테스트에서는 전체 결함의 대부분이 소수의 모듈에 집중되어 발생 테스트의 목적 오류 및 결함 발견 소프트웨어 품질 향상 신뢰성 확보 생명주기 단계별 테스트 (V-모델 기준) 테스트 단계별 정리 단위 테스트 (Unit Test) 대상: 함수, 클래스, 단일 모듈 수행자: 개발자 목적: 모듈 내부 로직의 정확성 검증 특징 - 내부 구조를 고려한 테스트 - 구현 직후 수행 - 화이트박스 테스트 중심 통합 테스트 (Integration Test) 대상: 여러 모듈의 결합 수행자: 개발자 또는 테스트 담당자 목적: 모듈 간 인터페이스 오류 검출 특징 - 상위·하위 모듈 연동 테스트 - 스텁(Stub)과 드라이버(Driver) 사용 시스템 테스트 (System Test) 대상: 전체 시스템 수행자: 테스트 담당자 목적: 시스템 요구사항 충족 여부 검증 특징 - 실제 환경과 유사한 조건 - 기능 테스트 + 비기능 테스트 포함 - 블랙박스 테스트 중심 인수 테스트 (Acceptance Test) 대상: 완성된 시스템 수행자: 사용자 목적: 요구사항 만족 여부 최종 확인 특징 - 사용자 관점 테스트 - 계약 기준에 따라 수행 - 블랙박스 테스트 - 알파, 베타 테스트 테스트 관점에 따른 분류 블랙박스 테스트 (Black Box Test) 특징 - 내부 구조를 고려하지 않음 - 입력과 출력만을 기준으로 테스트 - 사용자 관점 테스트 적용 단계 - 시스템 테스트 - 인수 테스트 대표 기법 - 동치 분해: 입력 값을 유효한 그룹과 무효한 그룹으로 나누어 각 그룹에서 대표 값을 선택해 테스트 - 경계값 분석: 입력 값의 최소값·최대값 등 경계 부근에서 오류가 발생하기 쉬운 점을 집중 테스트 - 원인–결과 그래프: 입력 조건(원인)과 출력 결과(결과)의 논리적 관계를 그래프로 표현하여 테스트 케이스 도출 화이트박스 테스트 (White Box Test) 특징 - 내부 구조를 고려하여 테스트 - 코드 흐름과 분기 구조 확인 - 개발자 관점 테스트 적용 단계 - 단위 테스트 대표 기법 - 기초 경로 검사: 프로그램의 제어 흐름 그래프를 기반으로 독립적인 모든 실행 경로를 최소 한 번 이상 테스트 - 제어 구조 테스트: 프로그램의 순차, 선택, 반복 구조가 올바르게 동작하는지 검사 스텁과 드라이버 스텁 (Stub) 하위 모듈을 대신하는 가짜 모듈 호출 당하는 모듈 하향식 통합 테스트에서 사용 드라이버 (Driver) 상위 모듈을 대신하는 가짜 모듈 호출 하는 모듈 상향식 통합 테스트에서 사용 테스트 커버리지 (Test Coverage) 테스트가 프로그램을 얼마나 실행했는지를 측정하는 기준 테스트의 충분성을 판단하는 지표 주요 커버리지 종류 구문 커버리지: 모든 문장이 한 번 이상 실행되었는지 분기 커버리지: 모든 조건의 참/거짓이 실행되었는지 조건 커버리지: 조건식 내 각 조건이 실행되었는지 테스트 오라클 (Test Oracle) 테스트 결과가 올바른지 판단하기 위한 기준 테스트 실행 결과를 기대 결과(Expected Result) 와 비교하여 성공 또는 실패를 판정 목적: 테스트 결과의 옳고 그름 판단 특징 - 자동 또는 수동으로 판정 가능 - 모든 테스트에는 오라클이 존재해야 테스트 수행 가능 - 오라클이 없으면 테스트 결과의 정확성 판단 불가 회귀 테스트 (Regression Test) 프로그램 수정 또는 변경 이후 기존 기능이 정상적으로 동작하는지 확인하는 테스트 목적: 수정으로 인해 발생할 수 있는 부작용(Side Effect) 검출 특징 - 기존 테스트 케이스를 재사용 - 변경된 부분 및 영향 범위 중심으로 수행 - 유지보수 단계에서 주로 수행 정적 테스트 / 동적 테스트 정적 테스트 (Static Test) 프로그램을 실행하지 않고 검토 코드 또는 문서 기반 테스트 종류 - 워크스루(Walkthrough): 개발자가 주도하며 설명하면서 검토 - 인스펙션(Inspection): 전문가가 참여하는 공식적인 검토 동적 테스트 (Dynamic Test) 프로그램을 실제로 실행하여 테스트 실행 결과를 기반으로 오류 검출 알파 테스트 / 베타 테스트 알파 테스트 개발자 환경에서 수행 사용자 참여 가능 내부 검증 목적 베타 테스트 실제 사용자 환경에서 수행 배포 전 최종 검증

2026년 01월 30일 16:22

CS

[정보처리기사] 소프트웨어 생명주기

소프트웨어 개발 전반 요약 (V-모델 기준) V-model 개발 단계(왼쪽)와 테스트 단계(오른쪽)를 1:1로 대응시킨 모델 각 단계의 산출물을 대응되는 테스트 단계에서 검증 요구사항 분석 ↔ 인수 테스트 요구사항 분석 시스템이 무엇을 해야 하는지 정의 기능 요구사항 정의 비기능 요구사항 정의 (성능, 보안, 신뢰성 등) 산출물 요구사항 명세서 유스케이스 다이어그램(선택) 인수 테스트 사용자 관점에서 수행 요구사항 충족 여부 확인 시스템 설계 ↔ 시스템 테스트 시스템 설계 전체 시스템 구조 설계 서브시스템 구성 외부 인터페이스 정의 산출물 시스템 설계서 유스케이스 다이어그램 컴포넌트 다이어그램 배치 다이어그램 시스템 테스트 전체 시스템 기능 테스트 성능, 보안 등 비기능 테스트 포함 아키텍처 설계 ↔ 통합 테스트 아키텍처 설계 주요 컴포넌트 구조 설계 컴포넌트 간 상호작용 정의 데이터 흐름 정의 산출물 아키텍처 설계서 컴포넌트 다이어그램 상위 수준 시퀀스 다이어그램 통합 테스트 모듈 및 컴포넌트 간 연동 테스트 인터페이스 오류 검출 스텁과 드라이버 사용 모듈 설계 ↔ 단위 테스트 모듈 설계 클래스 내부 구조 설계 메서드와 속성 정의 알고리즘 정의 산출물 상세 클래스 다이어그램 상세 시퀀스 다이어그램 모듈 설계서 단위 테스트 함수 또는 클래스 단위 테스트 내부 구조를 고려한 테스트 개발자가 직접 수행 구현 구현 설계 내용을 기반으로 소스 코드 작성 산출물 프로그램 코드 테스트 단계 요약

2026년 01월 29일 15:41

CS

[정보처리기사] Diagram & UML

Diagram & UML Diagram이란? 설계 시 모두가 같은 의미로 이해하기 위해 사용하는 그림 시스템을 시각적으로 표현하는 의사소통 도구 UML이란? Diagram을 그리기 위한 객체지향 모델링 언어 Unified Modeling Language 그림 기호와 의미를 표준화한 약속 UML의 구성요소 (사관다) UML은 다음 3가지로 구성된다. ① 사물 (Things) 관계의 대상이 되는 요소 구·행·그·주 - 구조: 시스템의 개념적, 물리적 요소 표현 - 행동: 시간과 공간에 따른 요소들의 행위 표현 - 그룹: 요소들을 그룹으로 묶어서 표현 - 주해: 부가적인 설명이나 제약조건 표현 ② 관계 (Relationships) 사물과 사물 사이의 연결 방식 연·집·포·일·의·실 - 연관(—): 2개 이상의 사물이 서로 관련되어 있음 - 집합(◇—): 하나의 사물이 다른 사물에 포함되어 있는 관계 - 포함(◆—): 포함하는 사물의 변화가 포함되는 사물에게 영향 미침 - 일반화(—▷): 하나의 사물이 다른 사물에 비해 더 일반적인지 구체적인지 표현 - 의존(--→): 사물 사이에 연관이 있으나 필요에 의해 서로에게 영향을 주는 짧은 시간 동안만 연관 유지 - 실체화(--▷) : 사물이 할 수 있거나 해야 하는 기능 (행위, 인터페이스) 로 서로를 그룹화 할 수 있는 관계 ③ 다이어그램 (Diagram) 사물 + 관계를 그림으로 표현한 결과물 정적 다이어그램, 동적 다이어그램으로 구성 정적 다이어그램: 구조 표현 클·객·컴·배·복·패 - 클래스 (Class): 클래스 사이 관계 표현 - 객체 (Object): 인스턴스를 특정 시점의 객체와 객체사이의 관계로 표현 - 컴포넌트 (Component): 컴포넌트 간 관계 표현 - 배치 (Deployment): 물리적 요소들의 위치 - 복합체 구조 (Composite Structure): 복합 구조 가지는 경우 그 내부 구조 표현 - 패키지 (Package): 모델 요소들을 그룹화한 패키지들의 관계 동적 다이어그램: 동작/순서 표현 유·시·커·상·활·호·타 - 유스케이스 (Use Case): 사용자의 요구 분석, 액터, 유스케이스로 구성 - 시퀀스 (Sequence): 시스템, 객체들이 주고받는 메시지 - 커뮤니케이션 (Communication): 메시지 뿐만이 아니라 객체들 관의 연관까지 표현 - 상태 (State): 객체의 상태가 어떻게 변하는지 표현 - 활동 (Activity): 시스템이 어떤 기능을 수행하는지 - 상호작용 개요 (Interaction Overview): 상호작용 다이어그램 간의 제어흐름 표현 - 타이밍 (Timing): 객체 상태 변화, 시간 제약을 명시적으로 표현 ※ Use Case 다이어그램 전용 관계 연관 (Association): 액터 ↔ 유스케이스 연결 포함 (Include): 항상 수행되는 공통 기능 확장 (Extend): 조건부로 수행되는 기능 일반화 (Generalization): 액터 또는 유스케이스 간 상속 관계

2026년 01월 29일 15:08

프론트엔드

토큰 만료(401)와 인터셉터 재설계 기록

백오피스를 마이그레이션하면서 가장 먼저 마주한 문제는 401이었다. 단순한 인증 에러처럼 보였지만, 실제로는 인증 흐름 전반을 다시 설계해야 하는 문제였다. 이번 글은 기존 코드를 그대로 사용하는 대신, Axios 인터셉터와 토큰 갱신 전략을 처음부터 다시 설계한 과정에 대한 기록이다. 기존 코드 사용으로 시작한 인터셉터 초기에는 기존 프로젝트의 Axios 인터셉터를 그대로 가져와 사용했다. 기능 자체는 동작했지만, 내부 동작 원리를 충분히 이해한 상태는 아니었다. 코드 리뷰에서 “구조를 이해하고 다시 설계해보자”는 피드백을 받았고, 그 시점에서 인터셉터의 전체 인증 흐름을 다시 정리하기 시작했다. 마침 면접 당시 받았던 질문이 떠올랐다. 사실 이번 인턴 면접에서 토큰 기반 인증에 관한 질문이 있었고, 한 페이지에서 여러 요청이 동시에 401이 발생하면 어떻게 처리할 것인가? 그때는 명확히 답하지 못했지만, 이번에 실제로 같은 상황을 마주하게 되었다. 첫 문제: 401 이후 403 예상 시나리오는 다음과 같았다. 오래된 at로 api 호출 서버가 401 던짐 인터셉터가 refresh 호출 새 토큰으로 요청 재시도 … 되어야 하는데 accessToken 만료 → 401 자동 refresh 호출 → 403 원인을 확인해보니 accessToken과 refreshToken의 만료 시간이 동일하게 설정되어 있었다. accessToken이 만료되는 시점에는 이미 refreshToken도 만료된 상태였다. at가 만료되었을 때 rt도 만료가되어 refresh를 할 수 있는 시간이 없었던 것이다. accessToken 만료 → refresh 요청 시도 근데 refreshToken도 이미 만료 → 403 그래서 당연히 403이 나는 구조였다. 근데 백엔드를 바꿔달라고 할 수가 없는 상황 이걸 계기로 오랜만에 조금 머리를 굴려보았다. 자동 재발급 전략 재설계 처음에는 이런 식의 자동 로직을 생각했다. accessToken 만료 5분 전에 자동으로 refresh 수행 하지만 백오피스 특성상, 사용자가 아무 행동을 하지 않아도 토큰을 갱신하는 방식은 적절하지 않았다. 그래서 방향을 바꿨다. 사용자가 실제 api 요청 시 만료 시간이 5분 이하라면 그때 refresh 하자 즉 활성 사용자만 재발급 → 비활성 사용자 세션은 종료 동시 요청 문제 → Pending Queue 도입 다음 문제는 이거였다. 이거는 내가 면접 때 질문을 받고 대답을 못했던 그 문제이기도 한데 A API 요청 시 → 토큰 만료 → refresh 시작 그 사이에 B API 요청 → 또 토큰 만료 → refresh 또 호출 이러면 refresh api가 동시에 여러번 호출되며 경합이 발생한다. 그래서 필수적으로 refresh 중엔 다른 요청을 멈춰서 줄세우는 로직이 필요하였다. 그것이 바로 pending queue ~~내가 자료구조 수업에서 듣고 코테 풀때만 쓰던 큐를 진짜 써보는 날이 오다니~~ 요약하자면 refresh 중이면 → 요청을 queue 에 쌓아둠 refresh 끝나면 → queue에 있던 요청들을 새 토큰으로 재요청 이렇게 하면 동시 재발급 요청 문제는 해결된다. 로그아웃 중복 실행 문제 refresh 실패 시 로그아웃을 처리하도록 구성했지만, 동시에 여러 API가 실패할 경우 alert가 여러 번 표시되는 문제가 발생했다. 이를 방지하기 위해 isLoggingOut 상태를 추가하여 로그아웃이 한 번만 실행되도록 제어했다. 또한 이 상태값이 persist에 저장되지 않도록 설정하여 재로그인 이후 정상 동작하도록 수정했다. 최종 Axios 인터셉터 구조 정리 최종적으로 인터셉터 구조는 다음과 같이 정리되었다. 요청 시 Authorization 자동 주입 만료 5분 이하 → refresh 시도 refresh 중에는 pending queue 대기 refresh 실패 → 단일 로그아웃 처리 상태 관리는 zustand와 연계 정리하자면.. 이번에 인터셉터를 처음부터 설계하면서 느낀 점: 토큰 구조를 이해해야 한다 세션 만료 UX까지 고려해야 한다 동시 요청 문제까지 잡아야 한다 상태관리까지 연계해야 한다 인터셉터는 그냥 훅 두 개가 아니라 프로젝트의 전체 인증 흐름을 담당하는 중요한 부분임을 깨달았다. 그리고 무엇보다 절대… 생각 안하고 코드 복붙부터 시작하지 말자.

2025년 11월 20일 00:33