기술면접 문제 - 답변 형식으로 정리
Spring Security의 구조와 JWT 발급 과정에 대해 설명해주실 수 있을까요?
Spring Security는 강력한 인증과 권한 부여를 위한 표준 프레임워크로, 다양한 보안 기능을 제공합니다. JWT(JSON Web Token)는 웹 표준(RFC 7519)으로서, 두 당사자 사이에서 안전하게 정보를 JSON 객체로 전송하기 위해 디자인된 컴팩트하고 자가 수용적인 방식입니다.
Spring Security의 구조
Spring Security는 필터 기반의 보안을 제공합니다. 요청이 들어올 때마다, Spring Security는 체인을 형성하는 여러 필터를 통해 이 요청을 처리합니다. 주요 구성 요소는 다음과 같습니다:
- AuthenticationManager: 인증 메커니즘의 진입점으로, 주어진 Authentication 객체를 인증하는 데 사용됩니다.
- AuthenticationProvider: AuthenticationManager가 사용하는 구현체로, 실제 인증 작업을 수행합니다.
- UserDetailsService: 사용자의 상세 정보를 로드하는 데 사용되며, 주로 사용자 정보를 데이터베이스에서 불러오는 데 사용됩니다.
- SecurityContextHolder: 인증 정보를 저장하는 곳으로, 현재 스레드에서 인증된 사용자의 세부 사항에 접근할 수 있도록 합니다.
- FilterChain: HTTP 요청과 응답에 대한 보안 처리를 하는 여러 필터들의 연결 고리입니다.
JWT 발급 과정
JWT의 발급은 사용자가 로그인하는 순간부터 시작됩니다. 사용자가 인증 정보(일반적으로 사용자 이름과 비밀번호)를 전송하면, Spring Security는 이를 처리하여 유효한 경우 토큰을 생성하고 반환합니다. 이 과정은 다음 단계로 이루어집니다:
- 인증 요청: 사용자가 자신의 로그인 정보를 서버에 전송합니다.
- 인증 처리: AuthenticationManager를 사용하여 전송된 인증 정보를 처리합니다.
- JWT 생성: 인증이 성공하면, 사용자의 세부 사항을 기반으로 JWT를 생성합니다. 이 때, 토큰에는 사용자 ID, 권한 등 필요한 정보가 포함됩니다.
- JWT 서명: 생성된 JWT에 서명은 보통 HMAC SHA-256 알고리즘을 사용하여 이루어집니다. 서명은 토큰이 서버에서 생성된 것임을 검증하고, 중간에 변경되지 않았음을 보장합니다.
- 토큰 발급: 서명된 토큰을 사용자에게 발급하고, 사용자는 이 토큰을 이용하여 이후 요청에서 인증 정보를 서버에 전송합니다.
JWT를 사용함으로써 서버는 세션을 유지할 필요가 없어 서버 자원을 효율적으로 사용할 수 있습니다. 클라이언트는 발급 받은 토큰을 저장해 두고 서버에 요청할 때마다 이 토큰을 이용해 자신을 인증할 수 있습니다.
N+1 문제의 발생 이유와 해결 방법에 대해 설명해주실 수 있을까요? 해결 방법은 3가지 이상 말씀해주시면 좋습니다.
N + 1 문제는 주로 ORM(Object-Relational Mapping) 도구를 사용할 때 발생하는 데이터베이스 성능 문제로 ORM을 사용하면 개발자는 객체 지향 언어를 사용하여 데이터베이스를 더 쉽게 다룰 수 있지만, ORM이 데이터를 객체로 변환하는 과정에서 비효율적인 쿼리 발생이 문제가 될 수 있습니다.
예를 들어, 한 개의 부모 객체에 여러 자식 객체가 연결되어 있을 때, 부모 객체를 조회하고 각 부모에 연결된 자식 객체들을 개별적으로 조회하게 되면, 부모 객체 1개를 가져오는 쿼리(N)와 자식을 불러오는 쿼리(1)가 발생하여 전체적으로 N+1 개의 쿼리가 발생하게 됩니다. 이는 데이터베이스에 부담을 주고 애플리케이션의 성능을 저하시킵니다.
N+1 문제의 해결 방법
1. 조인 사용(Join Fetch)
- ORM에서 제공하는 조인 기능을 사용하여 부모와 자식 객체를 함께 조회하는 하나의 쿼리를 생성합니다. 이 방법을 사용하면 데이터베이스에 보내는 쿼리 수가 크게 줄어들어 성능이 향상됩니다. JPA에서는 JOIN FETCH 구문을 사용할 수 있습니다.
2. 배치 페치(Batch Fetching)
- 연관된 객체들을 일정량의 그룹으로 나누어 한 번에 로딩하는 기법으로 Hibernate에서는 @BatchSize 어노테이션을 사용하여 한 번의 쿼리로 지정된 수의 연관 객체들을 불러올 수 있습니다. 이는 네트워크 라운드 트립과 쿼리 실행 횟수를 줄여 성능을 향상시킵니다.
3. 서브 셀렉트(Subselect)
- 주 쿼리의 결과를 기반으로 추가 쿼리를 실행하는 방법으로 특정 조건에 따라 동적으로 연관 데이터를 불러와야 할 때 유용합니다. 부모 쿼리가 실행된 후, 해당 결과를 사용하는 서브 쿼리가 자동으로 실행되어 연관된 데이터를 불러옵니다.
이러한 기법들을 적절히 조합하여 사용하면, ORM을 사용하면서도 데이터베이스 성능 저하 문제를 효과적으로 해결할 수 있습니다. 각 프로젝트의 요구 사항과 데이터 접근 패턴을 고려하여 가장 적합한 해결책을 선택하는 것이 중요합니다.
즉시로딩과 지연로딩은 각각 언제 사용하면 좋은지 설명해주실 수 있을까요?
즉시로딩(Eager Loading)과 지연로딩(Lazy Loading)은 ORM(Object-Relational Mapping)을 사용하는 환경에서, 특히 JPA(Java Persistence API)와 같은 기술에서 데이터 접근 방식을 정의하는 두 가지 중요한 전략입니다. 이 두 전략은 데이터를 로드하는 시점과 방식을 다룹니다.
즉시로딩(Eager Loading)
즉시로딩은 연관된 엔티티나 컬렉션을 최초 로드 시 함께 로드하는 방식입니다. 예를 들어, 사용자 엔티티를 조회할 때 사용자의 모든 주문 정보를 함께 조회합니다.
사용 시점:
- 관련된 데이터가 항상 필요할 때 적합합니다. 예를 들어, 사용자 정보와 함께 그 사용자의 프로필 정보가 항상 필요한 경우에 적절합니다.
- 어플리케이션의 성능이 연관된 모든 데이터를 한 번에 가져오는 것으로 더 향상될 때 사용합니다.
- 데이터 양이 많지 않고, 관리가 용이할 때 사용하는 것이 좋습니다.
지연로딩(Lazy Loading)
지연로딩은 필요한 시점에만 연관된 데이터를 로드하는 방식입니다. 예를 들어, 사용자 엔티티를 조회할 때 사용자의 주문 정보는 접근하는 순간에만 데이터베이스에서 로드됩니다.
사용 시점:
- 관련된 데이터가 항상 필요하지 않을 때 적합합니다. 사용자 정보만 필요하고, 주문 정보는 특정 조건에서만 필요한 경우 지연 로딩을 사용합니다.
- 메모리 사용을 최적화하고, 초기 로드 시간을 줄일 수 있습니다.
- 시스템의 전반적인 응답 속도를 향상시키고자 할 때 유리합니다.
즉시로딩과 지연로딩은 각각의 사용 사례에 따라 선택해야 합니다. 즉시로딩은 사용자 경험을 개선할 수 있는 경우에 유리하며, 지연로딩은 시스템의 성능 최적화가 중요할 때 효과적입니다. 사용하는 데이터의 양과 빈도, 그리고 어플리케이션의 성능 요구 사항을 고려하여 적절한 로딩 전략을 선택하는 것이 중요합니다.
Spring bean container 생성부터 스프링 종료까지의 사이클에 대해 알려주실 수 있을까요? @PostConstruct, @PreDestroy 어노테이션의 역할도 함께 알려주시면 좋습니다.
Spring Framework는 객체의 전체 수명 주기를 관리하는 강력한 컨테이너를 제공합니다. 이 컨테이너는 Spring Bean의 생성, 구성, 관리, 그리고 소멸을 책임집니다. 이 과정은 매우 체계적으로 진행되며, @PostConstruct와 @PreDestroy 어노테이션은 이 생명주기 중 특정 시점에 특정 작업을 수행하도록 하는 데 사용됩니다.
Spring Bean Container의 생명주기
- Bean 정의 로드: Spring 컨테이너는 클래스패스, 설정 파일, 어노테이션 등을 통해 Bean 정의를 로드합니다.
- Bean 인스턴스화: Bean 정의에 따라 Spring 컨테이너는 객체를 인스턴스화합니다.
- 의존성 주입: 컨테이너는 Bean의 속성에 설정된 의존성을 주입합니다. 이는 생성자 주입, 세터 주입 또는 필드 주입을 통해 이루어질 수 있습니다.
- Bean 초기화: 모든 Bean의 속성이 설정되고 의존성이 주입된 후, 컨테이너는 Bean의 초기화를 진행합니다. 이 때 @PostConstruct 어노테이션이 붙은 메서드가 실행됩니다. 이 메서드는 Bean이 생성되고, 모든 필요한 속성이 설정된 직후에 호출되므로 초기화 로직을 실행하는 데 적합합니다.
- Bean 사용: 초기화된 Bean은 이제 애플리케이션에서 사용할 준비가 완료됩니다. 애플리케이션이 실행되는 동안 Bean은 요청을 처리하고 작업을 수행합니다.
- Bean 소멸: 애플리케이션이 종료되거나, 컨테이너가 종료되면 Bean은 소멸 과정을 거칩니다. 이때 @PreDestroy 어노테이션이 붙은 메서드가 실행되어, 필요한 정리 작업을 수행할 수 있습니다. 이 메서드는 컨테이너가 Bean을 제거하기 전에 호출됩니다.
@PostConstruct 및 @PreDestroy 어노테이션
- @PostConstruct: 이 어노테이션은 메서드에 적용되어, 의존성 주입이 완료된 후에 실행되어야 하는 초기화 작업을 정의합니다. 예를 들어, 데이터베이스 연결을 시작하거나, 필요한 리소스를 미리 로드하는 작업을 구현할 수 있습니다.
- @PreDestroy: 이 어노테이션은 메서드에 적용되어, Bean이 소멸되기 전에 필요한 정리 작업을 정의합니다. 예를 들어, 열린 파일 핸들을 닫거나, 네트워크 연결을 정리하는 등의 작업을 수행할 수 있습니다.
이러한 어노테이션들은 Spring의 생명주기 관리의 중요한 부분을 차지하며, 개발자가 자원 관리를 효율적으로 수행할 수 있도록 도와줍니다.
AOP, Interceptor, Filter 의 차이점, Request가 들어올때 거치는 순서, 각 역할들의 장점을 설명해주실 수 있을까요?
AOP(Aspect-Oriented Programming), 인터셉터(Interceptor), 필터(Filter)는 모두 애플리케이션의 요청 처리 파이프라인에서
중요한 역할을 하며, 각각의 목적과 기능이 다릅니다. 이들은 요청이 처리되는 과정에서 다양한 처리 단계에 적용되어 애플리케이션의 유지보수성, 재사용성, 분리성을 향상시킵니다.
요청 처리 순서
- 필터(Filter): HTTP 요청이 서블릿에 도달하기 전에 처리됩니다. 필터는 디스패처 서블릿(Dispatcher Servlet)에 도달하기 전에 요청을 가로채어 전처리 및 후처리를 할 수 있습니다.
- 인터셉터(Interceptor): 필터 다음에 위치하며, 스프링의 컨트롤러가 요청을 처리하기 전후로 추가적인 작업을 수행할 수 있습니다. 인터셉터는 스프링의 컨텍스트 내에서 실행되므로 스프링의 빈에 접근할 수 있습니다.
- AOP(Aspect-Oriented Programming): 인터셉터 이후에 실행되며, 메서드 호출 자체를 가로채어 메서드 실행 전후, 예외 발생 시 등 다양한 시점에서 추가적인 로직을 실행할 수 있습니다.
각 역할과 장점
- 필터(Filter)
- 역할: 서블릿 단계 이전에 요청을 처리하여 인코딩 설정, 보안 검사, 로그 기록 등의 작업을 수행합니다.
- 장점: 웹 애플리케이션에 대한 요청 및 응답을 가장 먼저 처리하므로, 보안과 관련된 공통적인 작업을 중앙에서 관리할 수 있습니다.
- 인터셉터(Interceptor)
- 역할: 스프링 MVC의 컨트롤러가 요청을 처리하기 전후에 특정 로직을 실행합니다. 데이터 추가, 권한 검사, 로깅 등을 수행할 수 있습니다.
- 장점: 스프링의 빈에 접근할 수 있어, 스프링의 기능을 활용한 다양한 고급 작업을 수행할 수 있습니다. 또한, 구체적인 컨트롤러의 로직 실행 전후에 동작하기 때문에 미세한 제어가 가능합니다.
- AOP(Aspect-Oriented Programming)
- 역할: 애플리케이션 전반에 걸쳐 흩어진 관심사(로깅, 트랜잭션 관리 등)를 모듈화하여 관리합니다.
- 장점: 비즈니스 로직과 분리하여 관심사를 모듈화함으로써 코드의 재사용성을 높이고, 유지보수성을 개선합니다. 메서드 단위의 세밀한 작업 수행이 가능하며, 다양한 시점에서 공통적인 작업을 처리할 수 있습니다.
이 세 가지 기술은 스프링 애플리케이션에서 중요한 역할을 하며, 적절히 사용될 때 강력한 유연성과 효율성을 제공합니다. 각 기술의 목적과 장점을 이해하고 애플리케이션의 요구사항에 따라 적절하게 선택하여 사용하는 것이 중요합니다.
NoSQL과 RDBMS의 특징과 차이점에 대해서 장, 단점을 들어 설명해주세요.
NoSQL(Not Only SQL) 데이터베이스와 RDBMS(Relational Database Management System)는 데이터를 저장하고 관리하는 데 사용되는 두 가지 주요 유형의 데이터베이스 시스템입니다. 이 둘은 설계 철학, 데이터 모델링, 성능, 확장성, 유연성 등 여러 면에서 서로 다릅니다.
차이점
데이터 저장 방식
- RDBMS
- 특징: 데이터를 테이블 형태로 저장하며, 모든 데이터는 미리 정의된 스키마에 따라 열과 행으로 구성된다.
- 제약 사항: 데이터를 저장하기 전에 스키마를 미리 정의하고, 모든 데이터 입력이 이 스키마에 맞추어져야 한다. 이는 데이터베이스 설계 초기에 많은 계획과 정밀함을 요구한다.
- 장점: 복잡한 쿼리 처리와 데이터 무결성을 보장하는 데 강점을 가진다.
- 단점: 스키마 수정이 어렵고, 유연성이 부족하여 빠른 데이터 구조 변화에 적응하기 어렵다.
- NoSQL
- 특징: 데이터를 key-value, document, wide-column, graph 등 다양한 형태로 저장할 수 있다.
- 유연성: 스키마가 없거나 유연하여, 데이터를 추가할 때 즉시 새로운 필드를 도입할 수 있고, 모든 데이터를 일관된 구조로 저장할 필요가 없다. 이는 동적이고 빠르게 변화하는 데이터 구조에 적합하다.
- 장점: 데이터 구조의 유연성이 뛰어나고, 스키마 변경이 간편하여 빠른 개발이 가능하다.
- 단점: 일관성 유지에 문제가 있을 수 있으며, 복잡한 트랜잭션이나 조인이 필요한 경우 처리가 어렵다.
스키마 관리
- RDBMS
- 고정 스키마: 스키마 변경이 필요할 때 데이터베이스를 전체적으로 수정하거나 일시적으로 서비스를 중단해야 할 수도 있다. 이는 운영 중인 대규모 시스템에서는 큰 리스크와 비용을 수반한다.
- 단점: 유연하지 않은 스키마로 인해 빠른 비즈니스 변경에 적응하기 어렵다.
- NoSQL
- 유연한 스키마 관리: 필드 추가가 자유롭고, 데이터 구조의 변경이 간단하여 신속한 개발과 반복적인 업데이트가 가능하다.
- 장점: 신속한 개발 주기와 변화하는 요구사항에 빠르게 대응할 수 있다.
쿼리(Query)
- RDBMS
- SQL 사용: 구조화된 쿼리 언어(SQL)를 사용하여 복잡한 쿼리와 조인을 수행할 수 있으며, 데이터의 관계를 효과적으로 관리할 수 있다.
- 장점: 데이터의 복잡한 관계와 집계를 효율적으로 처리할 수 있다.
- 단점: 유연하지 않은 쿼리 언어로 인해 비구조적 데이터 처리에 한계가 있다.
- NoSQL
- 유연한 쿼리: UnQL(Unstructured Query Language)과 같은 비구조화된 쿼리 언어를 사용하여, 구조화된 쿼리보다 자유롭게 데이터에 접근할 수 있다. 이는 개발의 유연성을 증가시키지만, 복잡한 조인이나 관계를 표현하는 데는 한계가 있다.
- 장점: 비구조화된 데이터 처리에 강점을 보인다.
- 단점: SQL만큼 강력한 쿼리 기능이 부족하며, 조인과 같은 관계형 데이터 처리에 어려움이 있다.
확장성(Scalability)
- RDBMS
- 수직 확장: 고성능의 서버로 확장해야 하며, 이는 비용이 많이 드는 작업이다. 수평 확장은 가능하지만, 구현이 복잡하고 비용이 많이 든다.
- 단점: 비용이 많이 들고, 복잡한 수평 확장으로 인해 확장성에 제약이 있다.
- NoSQL
- 수평 확장: 서버를 추가하기만 하면 되므로, 확장이 용이하고 비용 효율적이다. 이는 대규모 분산 시스템에서 특히 유리하며, 클라우드 기반 환경에 잘 맞는다.
- 장점: 비용 효율적이고 유연한 확장이 가능하여 대규모 트래픽 처리에 적합하다.
결론
RDBMS는 정교한 쿼리와 데이터 무결성이 중요한 비즈니스 애플리케이션에 적합한 반면, NoSQL은 빠른 읽기/쓰기 속도와 확장성이 요구되는 대규모 분산 환경에서 유리합니다. 각각의 선택은 애플리케이션의 요구사항, 데이터의 유형, 예상되는 트래픽 양, 개발 및 운영 환경에 따라 달라집니다.
mvc 패턴에 대해서 설명해주세요.
MVC(Model-View-Controller) 패턴은 소프트웨어 엔지니어링에서 사용되는 아키텍처 패턴으로, 애플리케이션의 로직, 사용자 인터페이스, 데이터 관리를 세 가지 주요 구성 요소로 분리합니다. 이 패턴의 목적은 관심사의 분리를 통해 애플리케이션의 유지보수성, 확장성 및 유연성을 향상시키는 것입니다.
구성 요소
- 모델(Model): 애플리케이션의 데이터 구조를 나타내며, 데이터와 비즈니스 로직을 처리합니다. 모델은 데이터베이스, 파일, 또는 다른 소스에서 데이터를 저장하고 검색하는 메커니즘을 관리하며, 데이터가 변경되었을 때 뷰에 이를 알려주는 역할을 합니다.
- 뷰(View): 사용자에게 정보를 표시하는 방법을 정의합니다. 뷰는 모델에서 데이터를 받아 사용자에게 보여주는 출력 포맷을 담당하며, 일반적으로 HTML, CSS, JavaScript 등을 사용하여 구현됩니다. 뷰는 사용자의 입력을 받아 컨트롤러에 전달하는 인터페이스 역할도 수행할 수 있습니다.
- 컨트롤러(Controller): 사용자의 입력을 받고 처리하는 역할을 합니다. 컨트롤러는 사용자의 액션을 감지하고, 모델을 업데이트하거나, 사용자의 요청에 따라 특정 뷰를 호출하여 응답합니다. 컨트롤러는 모델과 뷰 사이의 상호작용을 조정하는 중재자 역할을 수행합니다.
장점
- 유지보수성: 관심사의 분리로 인해 코드의 재사용성과 유지보수성이 향상됩니다.
- 확장성: 개별 컴포넌트(모델, 뷰, 컨트롤러)를 독립적으로 확장할 수 있어, 대규모 애플리케이션 개발에 유리합니다.
- 유연성: 새로운 유형의 뷰를 쉽게 추가할 수 있으며, 비즈니스 로직이 사용자 인터페이스로부터 분리되어 있어 다양한 사용자 인터페이스 디자인을 적용할 수 있습니다.
단점
- 복잡성: 간단한 애플리케이션에 MVC 패턴을 적용하면 과도한 구조로 인해 오히려 개발과 유지보수가 복잡해질 수 있습니다.
- 학습 곡선: MVC 아키텍처를 처음 접하는 개발자는 각 구성 요소의 역할과 상호작용을 이해하는 데 시간이 필요할 수 있습니다.
MVC 패턴은 웹 애플리케이션 및 소프트웨어 개발에서 널리 사용되며, 특히 복잡하고 큰 규모의 프로젝트에서 그 효과를 발휘합니다. 이 패턴을 이해하고 적용하는 것은 현대 웹 개발자에게 중요한 기술 중 하나입니다.
RDBMS의 정규화에 대해 설명해주세요.
정규화(Normalization)는 관계형 데이터베이스 관리 시스템(RDBMS)에서 데이터의 구조를 최적화하는 과정입니다.
데이터베이스 설계에서 정규화를 수행하는 목적은 중복을 최소화하고, 데이터 무결성을 유지하며, 데이터 조작을 효율화하는 데 있습니다.
정규화를 통해 데이터베이스의 갱신 이상(Update Anomalies)을 방지하고, 데이터를 보다 체계적으로 관리할 수 있습니다.
정규화의 주요 단계 : 정규화 과정은 주로 다음과 같은 일련의 '정규형' 단계로 구분됩니다:
- 제1정규형 (1NF):
- 모든 열은 원자적인 값을 가져야 합니다. 즉, 각 필드는 반복되는 그룹이나 배열을 포함할 수 없으며, 단일 값을 가져야 합니다.
- 예: 주문 테이블에서 한 행에 여러 상품을 나열하는 대신, 각 상품마다 별도의 행을 사용합니다.
- 제2정규형 (2NF):
- 이미 1NF를 만족해야 합니다.
- 모든 비주요 열이 기본 키에 완전 함수적 종속을 해야 합니다. 즉, 기본 키의 일부가 아닌 전체 키에 의해서만 결정되어야 합니다.
- 예: 주문번호와 상품번호가 복합 키인 주문 테이블에서 상품 이름은 상품번호에만 종속되어야 합니다.
- 제3정규형 (3NF):
- 이미 2NF를 만족해야 합니다.
- 모든 비주요 열이 기본 키에 이행적으로 종속되지 않아야 합니다. 즉, 비주요 열이 다른 비주요 열에 의존하지 않아야 합니다.
- 예: 직원 테이블에서 직원의 부서 번호에 따라 관리자가 결정되고, 관리자의 전화번호가 있을 경우, 관리자의 전화번호는 직원의 부서 번호에 이행적 종속이므로 별도의 테이블로 분리해야 합니다.
- 보이스/코드 정규형 (BCNF):
- 이미 3NF를 만족해야 하며, 모든 결정자가 후보 키여야 합니다.
- 예: 학생과 강의실이 여러 과목에 대한 정보를 담고 있는 경우, 각 과목과 관련된 학생과 강의실 정보를 분리하여 관리합니다.
- 제4정규형 (4NF) 및 제5정규형 (5NF):
- 다중값 종속과 조인 종속성을 해결하여 더욱 복잡한 이상 현상을 제거합니다.
정규화의 장단점
- 장점:
- 데이터의 중복을 줄여 저장 공간을 효율적으로 사용합니다.
- 데이터 무결성을 보장합니다.
- 갱신, 삽입, 삭제 이상을 최소화하여 데이터베이스의 일관성을 유지합니다.
- 단점:
- 과도한 정규화는 쿼리 성능에 영향을 줄 수 있습니다. 조인 연산이 많아질수록 쿼리 성능이 저하될 수 있습니다.
- 데이터베이스 설계가 복잡해질 수 있으며, 관리가 어려워질 수 있습니다.
정규화는 데이터베이스 설계의 중요한 부분으로, 적절한 수준에서 정규화를 수행하는 것이 중요합니다. 너무 적게 하면 데이터 이상이 생길 수 있고, 너무 많이 하면 성능 문제가 발생할 수 있습니다.
'항해 99' 카테고리의 다른 글
RDBMS의 정규화 (0) | 2024.04.24 |
---|---|
WIL-11 (1) | 2024.04.21 |
NoSQL & RDBMS (0) | 2024.04.17 |
쿠키(Cookie)와 세션(Session) (0) | 2024.04.16 |
HTTP, HTTPS / HTTP 메서드 (0) | 2024.04.15 |