SpringSecurity : 로그인 필터
0. 로그인 과정 1. 로그인 요청 (POST) 2. DelegatingFilterProxy가 요청을 가로챔 3. SecurityFilterChain 내부 여러 필터 중, UsernamePasswordAuthenticationFilter가 실행되어 요청을 받음. 4. AuthenticationManager가 인증을 시도, UserDetailService에서 사용자 정보를 조회 5. 인증 성공하면 SecurityContext에 사용자 정보를 저장하고, JWT를 발급해 응답.  * 용어 설명Delegating Filter Proxy : 건물 입구 보안 게이트.  - 서블릿 컨테이너(Tomcat)에 등록되는 첫 번재 필터. - 들어오는 모든 요청을 Spring Security 필터 체인(SecurityFilt..
2025.03.13
SpringSecurity : 회원가입 로직
JPA를 활용하여 Entity 생성 및 회원가입 로직을 구현한다. 엔티티 생성 및 파일 생성 1. 회원 Entity 생성 (UserEntity)@Entity@Getter@Setterpublic class UserEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; private String username; private String password; private String role;} 2. UserRepository 생성@Repositorypublic interface UserRepository extends JpaRepository {} 3. application.proper..
2025.03.12
SpringSecurity : SecurityConfig 클래스 작성
Spring Security 6.2.1 버전 기준! 1. 어노테이션 추가 (@Configuration, @EnableWebSecurity)@Configuration@EnableWebSecuritypublic class SecurityConfig {} @Configuration : 스프링 설정 관련 클래스임을 나타내는 어노테이션@EnableWebSecurity : SpringSecurity를 활성화해주는 어노테이션, 시큐리티 관련 설정을 커스텀할 수 있게 하는 역할 2. SecurityFilterChain 작성 @Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {} 스프링 시큐리티는 필터를 기반으로 동작한다. 모든..
2025.03.09
no image
SpringSecurity : 프로젝트 만들기, 의존성 추가 (시큐리티, JWT)
인텔리제이 얼티메이트 기준으로 작성  1. 프로젝트 만들기(1)JDK 17Java 17 버전  (2) dependencies 설정LombokSpring WebJPAMySQL DriverSpring Security  2. 의존성 주입 (build.gradle) dependencies {// implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-web' compileOnly 'org.projectlomb..
2025.03.04
API 명세서 작성하기
참고 링크https://it-roheerumi.tistory.com/31
2025.01.29
no image
h2 데이터베이스 입력칸 모두 빈 칸으로 나올 때 해결법
어느날 h2 데이터베이스를 실행했는데, 원래는 기본으로 저 입력란에 모두 영어로 뭐라뭐라 나와 있어야 하는데 모두 비어있었다. 도움말, 설정 다 둘러봤지만 도움은 안됨..   해결책은 간단하다 Setting Name: 부분에  Generic H2 (server)를 손수 입력해주면 뿅 하고 나타난다.  나머지 아래는 위와 같이 입력하면 된다. jdbc url 부분은 본인 데이터베이스 경로를 입력해준다.
2025.01.27
no image
Spring : 프레임워크, 의존성 주입 방법
프레임워크란?개발자가 일정 규칙과 구조 안에서 코드를 작성하도록 돕는 도구복잡한 로직을 단순화하거나 생략할 수 있도록 해 코드 재사용성, 유지보수성을 높임객체 생성, 의존성 관리 등 잡다한 부분을 자동화하여 필요한 비즈니스 로직에 집중할 수 있게 해준다. (생산성 증가) Spring 프레임워크 특징POJO (Plain Old Java Object)특별한 인터페이스나 클래스를 상속받지 않고 순수한 자바 객체를 사용해 개발 진행한다.이는 코드 재사용성, 독립성을 높임의존성 주입의존성 주입을 통해 객체 간 결합도를 낮춘다.AOP (관점 지향 프로그래밍)횡단 관심사 분리(Cross-Cutting Concerns)하여 핵싱 기능들이 수행될 때 수반해야할 부수 기능들을 모듈화할 수 있도록 도움트랜잭션 관리선언적 트..
2024.10.28
Cookie, Session, HTTP
HTTP란?HyperText Transfer Protocol웹에서 데이터를 주고 받을 때 지켜야 할 통신 규약!대표적 HTTP 메서드 : GET, POST, PUT, DELETEURL : 요청을 보낼 때, 어디로 요청을 보낼지에 대한 정보.헤더(Header): 요청 보낼 때 필요한 추가 정보 (ex. 브라우저 종류, 언어 설정 등본문(Body) : POST의 경우, 서버에 보낼 데이터를 본문에 포함시킬 수 있음.비연결성 : 요청과 응답이 종료되면 서로의 상태를 기억하지 않는다!무 상태: 서버가 클라이언트 상태를 저장하지 않는다. => 쿠키와 세션이 필요     Cookie 쿠키란?웹 서버가 만들어 클라이언트의 브라우저에 저장하는 작은 데이터 조각클라이언트 요청 시 상황에 따라 서버로 같이 전송브라우저가 ..
2024.10.14
JSP 특징, 장단점, Scriptlet 등
JSP란?서버 측에서 동적으로 HTML, XML등의 문서를 생성하기 위해 사용하는 자바 기반 기술HTML 문서에서 Java코드를 작성할 수 있도록 혼합JSTL등의 태그 라이브러리가 지원되어 편의성 향상작성된 후 서블릿으로 변환된 후 실행      JSP 구성 요소지시자 페이지 설정 관련 정보 지정을 위해 사용스크립트 요소(스크립트릿, 표현식, 선언부)문서 내용을 동적으로 생성하기 위해 사용기본객체요청과 응답을 읽고 처리하기 위해 기본으로 생성되어 있음표현언어(Expression Language)JSP를 더 간편하게 작성하기 위해 사용       JSP 태그스크립트릿 : 자바 코드를 작성하는 구간 (메서드 영역) 선언: 변수와 메서드를 선언하는 구간(클래스 영역)표현식: 특정 값이나 결과물을 문자열로 출력..
2024.10.08
Java Servlet 특징, 생명주기, 처리방식 등
Servlet?Server + Applet의 합성어Servlet은 웹 애플리케이션 개발에서 동적 웹페이지 생성클라이언트의 요청을 해석하고 응답을 생성하는 서버측 요소자바 코드 안에 HTML을 포함주로 HTTP 프로토콜을 사용해 클라이언트와 상호작용Apache Tomcat과 같은 웹서버에서 실행된다!      Servlet 생명주기0. Servlet 인스턴스가 없을 경우, Servlet 클래스를 불러오고, 웹컨테이너에 의해 Servlet 인스턴스를 초기화, 생성함.  1. init()Servlet이 처음 로드될 때 한 번만 호출된다. 따라서 여러 변수나 조건들을 초기화하는 기능을 한다.  2. service()클라이언트의 요청을 처리할 때마다 호출되며, 요청 메서드(GET, POST 등)에 따라 적절한 처..
2024.10.06

SpringSecurity : 로그인 필터

친환경 개발자
|2025. 3. 13. 00:39

 

0. 로그인 과정

 

1. 로그인 요청 (POST)

 

2. DelegatingFilterProxy가 요청을 가로챔

 

3. SecurityFilterChain 내부 여러 필터 중, UsernamePasswordAuthenticationFilter가 실행되어 요청을 받음.

 

4. AuthenticationManager가 인증을 시도, UserDetailService에서 사용자 정보를 조회

 

5. 인증 성공하면 SecurityContext에 사용자 정보를 저장하고, JWT를 발급해 응답.

 

 

* 용어 설명

Delegating Filter Proxy : 건물 입구 보안 게이트. 

 - 서블릿 컨테이너(Tomcat)에 등록되는 첫 번재 필터.

 - 들어오는 모든 요청을 Spring Security 필터 체인(SecurityFilterChain) 각 검문소로 전달.

 

SecurityFilterChain : 보안 게이트 내부의 여러 개의 보안 검문소가 모인 곳

 - 여러 보안 검문소가 모인 곳

 - Spring Security에서 여러 개의 보안 필터가 순차적으로 실행되는 체인

 - 로그인 요청, JWT 인증, CSRF 보호 등 여러 보안 검사를 담당하는 필터들을 포함

 - 필터 종류 : UsernamePasswordAuthenticationFilter(아이디/비번 로그인 검사),

                      BasicAuthenticationFilter(HTTP Basic 인증 검사),

                      BearerTokenAuthenticationFilter(JWT 토큰 검사)

 

 

UsernamePasswordAuthenticationFilter : 신분증과 비밀번호 확인하는 보안요원 

 - /login 요청을 가로채서 아이디(username)와 비밀번호(password)를 확인

 - AuthenticationManager 에게 검증을 요청

 

AuthenticationManager : 보안요원이 확인한 정보를 최종 검토하는 보안 관리 부서

 - 검증을 직접 하지는 않고, UserDetailService를 통해 DB에서 사용자 정보를 조회함.

 

UserDetailService : 회사의 사원 정보 조회 시스템

 - DB에서 username을 기반으로 사용자 정보를 조회

 - JWT방식에서는 CustomUserDetailService로 직접 구현.

 - loadUserByUsername 메서드.

 

 

 

1. LoginFilter 구현

 

JWT 기반 인증을 사용하기 때문에, 이전에 formLogin()을 비활성화했다.

따라서 UsernamePasswordAuthenticationFilter 대신 우리가 직접 커스텀한 로그인 필터를 구현해야 한다.

 

여기서 username과 password를 추출하고,

UsernamePasswordAuthenticationToken을 생성하여 AuthenticationManager에 인증 요청을 보낸다.

public class LoginFilter extends UsernamePasswordAuthenticationFilter {

    private final AuthenticationManager authenticationManager;

    public LoginFilter(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }

    // 요청을 가로채 권한 검증
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {

        // 클라이언트 요청에서 username과 password 추출
        String username = obtainUsername(request);
        String password = obtainPassword(request);

        // 인증을 위해 스프링 시큐리티의 인증 토큰 생성
        UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(username, password, null);

        // AuthenticationManager에게 토큰을 넘겨 인증을 요청
        return authenticationManager.authenticate(authToken);
    }

    // 로그인 성공 시 실행
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) throws IOException {
		
    }

    // 실패시 실행
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException {

    }
}

 

 

2. SecurityConfig에 로그인필터 등록

    // AuthenticationManager Bean 등록
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
        return configuration.getAuthenticationManager();
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .csrf((auth) -> auth.disable())
            .formLogin((auth) -> auth.disable())
            .httpBasic((auth) -> auth.disable())
            .authorizeHttpRequests((auth) -> auth
                .requestMatchers("/login", "/", "/join").permitAll()
                .anyRequest().authenticated())
            .sessionManagement((session) -> session
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                
                
        // 커스텀한 필터를 등록
        // 생성자 파라미터인 authenticationManager를 추가 등록해줘야 에러 안남.
        http.addFilterAt(new LoginFilter(authenticationManager(authenticationConfiguration), jwtUtil), UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }

 

 

 

SpringSecurity : 회원가입 로직

친환경 개발자
|2025. 3. 12. 23:54

 

JPA를 활용하여 Entity 생성 및 회원가입 로직을 구현한다.

 

엔티티 생성 및 파일 생성

 

1. 회원 Entity 생성 (UserEntity)

@Entity
@Getter
@Setter
public class UserEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String username;
    private String password;
    private String role;
}

 

2. UserRepository 생성

@Repository
public interface UserRepository extends JpaRepository<UserEntity, Integer> {

}

 

3. application.properties

spring.jpa.hibernate.ddl-auto=create

 

최초 실행시에만 테이블 생성을 위해 create로 설정.

이후에는 none으로 수정할 것.

 

 

 

회원가입 로직 흐름

회원가입 api 요청[FE] - JoinController - JoinService - UserRepository - DB

 

1. JoinDTO 생성

@Setter
@Getter
public class JoinDTO {
    private String username;
    private String password;
}

 

 

2. JoinController

@Controller
@ResponseBody
public class JoinController {

	// 의존성 주입
    private final JoinService joinService;
    public JoinController(JoinService joinService) {
        this.joinService = joinService;
    }

    @PostMapping("/join")
    public String join(JoinDto joinDto) {
        System.out.println(joinDto.getUsername());
        joinService.joinProcess(joinDto);

        return "joined successfully";
    }
}

 

 

3. JoinService

@Service
public class JoinService {

    private final UserRepository userRepository;
    private final BCryptPasswordEncoder bCryptPasswordEncoder;

    public JoinService(UserRepository userRepository, BCryptPasswordEncoder bCryptPasswordEncoder) {

        this.userRepository = userRepository;
        this.bCryptPasswordEncoder = bCryptPasswordEncoder;
    }

    public void joinProcess(JoinDto joinDto) {

        // 이미 존재하는 username인지 확인
        Boolean isExist = userRepository.existsByUsername(joinDto.getUsername());

        if (isExist) {
            return;
        }

		// DB에 저장하기 위한 바구니 (UserEntity) 생성
        UserEntity user = new UserEntity();

        user.setUsername(joinDto.getUsername());
        // 비밀번호는 암호화하여 저장!
        user.setPassword(bCryptPasswordEncoder.encode(joinDto.getPassword()));
        user.setRole("ROLE_ADMIN");	// 임시로 ADMIN 권한 부여

        userRepository.save(user);
    }
}

 

 

4. UserRepository

@Repository
public interface UserRepository extends JpaRepository<UserEntity, Integer> {
    Boolean existsByUsername(String username);	// 해당 username을 가진 유저가 존재하는지
}

 

 

Spring Security 6.2.1 버전 기준!

 

1. 어노테이션 추가 (@Configuration, @EnableWebSecurity)

@Configuration
@EnableWebSecurity
public class SecurityConfig {
}

 

@Configuration : 스프링 설정 관련 클래스임을 나타내는 어노테이션

@EnableWebSecurity : SpringSecurity를 활성화해주는 어노테이션, 시큐리티 관련 설정을 커스텀할 수 있게 하는 역할

 

2. SecurityFilterChain 작성 

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
}

 

스프링 시큐리티는 필터를 기반으로 동작한다. 모든 요청을 시큐리터 필터를 통과하도록 하며, 필터들을 묶어 관리하는 것을 SecurityFilterChain 이라고 함.

 

* 주요 역할: 로그인했는지 확인, 권한이 있는지 확인, CORS, 세션관리 등

 

 

 

3. CSRF(Cross-Site Request Forgery) 비활성화 

http.csrf((auth) -> auth.disable());

 

CSRF 공격이란 사용자가 의도하지 않은 요청을 서버가 처리하도록 유도하는 공격이다.
Spring Security는 기본적으로 CSRF 공격을 방어하지만, JWT 방식의 인증 시스템에서는 CSRF 보호가 필요하지 않기 때문에 stateless 상태이고, 따라서 CSRF 보호가 필요 없음.

 

 

 

4. formLogin, httpBasic 비활성화

http.formLogin((auth) -> auth.disable());
http.httpBasic((auth) -> auth.disable());

 

JWT 방식으로 인증하기 때문에 일반적 로그인 방식인 폼로그인을 사용하지 않고,

Authorization 헤더에 username과 password를 Base64 인코딩하는 방식인 HTTP Basic도 사용하지 않음.

 

 

 

5. 특정 경로별 접근 권한 설정 

http.authorizeHttpRequests((auth) -> auth
            // 로그인, 메인페이지, 가입페이지는 다 들어갈 수 있게
            .requestMatchers("login", "/", "/join").permitAll()
            // 관리자 페이지는 관리자 권한 가진 사람만
            .requestMatchers("/admin").hasRole("ADMIN")
            // 나머지는 막기
            .anyRequest().authenticated());

 

- permitAll() : 모든 사용자가 로그인하지 않아도 접근가능

- hasRole("권한명") : 특정 권한명을 가진 사용자만 접근 가능

- anyRequest().authenticated() : 위에서 지정한 경로 외에는 모두 로그인해야만 접근 가능

 

 

 

6. 세션 STATELESS 설정

http.sessionManagement((session) -> session
        .sessionCreationPolicy(SessionCreationPolicy.STATELESS));

 

Spring Security에서는 기본적으로 세션을 생성하여 사용자를 인증하고 관리하나,

 

여기서는JWT 기반 인증 시스템에서는 세션을 사용하지 않고, 토큰을 기반으로 인증하는 방식을 선택.

 

SessionCreationPolicy.STATELESS 설정을 통해 Spring Security가 세션을 생성하지 않도록 설정하여,

 

JWT를 활용한 완전한 무상태(Stateless) 방식의 인증 시스템을 구축할 수 있음

 

 

 

7. 필터체인 반환

return http.build();

 

build() 를 사용해 설정한 시큐리티 필터 체인을 반환한다.

 

 

 

 

8. 비밀번호 암호화 설정

@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
    return new BCryptPasswordEncoder();
}

 

BCryptPasswordEncoder는 Salt 기법을 사용해 같은 비밀번호도 다른 해시 값을 생성하는 암호화 기법을 사용함.

 

 

 

 

전체 코드

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    // 비밀번호를 hash로 암호화하여 검증. 암호화에 사용할 메서드 구현
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }


    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws  Exception {
        // csrf disable
        http
                .csrf((auth)  -> auth.disable());
                
        // form 로그인 방식 disable
        http
                .formLogin((auth) -> auth.disable());

        // http basic 인증 방식 disable
        http
                .httpBasic((auth) -> auth.disable());

        // 특정 경로에 인가작업
        http.authorizeHttpRequests((auth) -> auth
                // 로그인, 메인페이지, 가입페이지는 다 들어갈 수 있게
                .requestMatchers("login", "/", "/join").permitAll()
                // 관리자 페이지는 관리자 권한 가진 사람만
                .requestMatchers("/admin").hasRole("ADMIN")
                // 나머지는 막기
                .anyRequest().authenticated());

        // 세션 statless 상태로 설정
        http
                .sessionManagement((session) -> session
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS));


        return http.build();
    }


}



 

인텔리제이 얼티메이트 기준으로 작성

 

 

1. 프로젝트 만들기

(1)

JDK 17

Java 17 버전

 

 

(2) dependencies 설정

Lombok

Spring Web

JPA

MySQL Driver

Spring Security

 

 

2. 의존성 주입 (build.gradle)

 

dependencies {
//	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'org.springframework.boot:spring-boot-starter-security'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	compileOnly 'org.projectlombok:lombok'
//	runtimeOnly 'com.mysql:mysql-connector-j'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	testImplementation 'org.springframework.security:spring-security-test'
	testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

	implementation 'io.jsonwebtoken:jjwt-api:0.12.3'
	implementation 'io.jsonwebtoken:jjwt-impl:0.12.3'
	implementation 'io.jsonwebtoken:jjwt-jackson:0.12.3'
}

 

mysql connector j 와 starter-data-jpa 의존성은 실행 시 에러 발생할 수 있어 우선 주석 처리

 

 

3. Controller 2개 만들기

 

(1) AdminController

package com.jwt.springjwt.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@ResponseBody
public class AdminController {

    public String adminP() {
        return "Admin Controller";
    }
}

 

 

 

 

(2) MainController

package com.jwt.springjwt.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@ResponseBody
public class MainController {

    @GetMapping("/")
    public String mainP() {

        return "Main Controlelr";
    }
}

 

 

 

4. 시큐리티 실행 확인

 

이런 문구가 나오면 시큐리티 기본 설정 및 정상 실행 성공

API 명세서 작성하기

친환경 개발자
|2025. 1. 29. 11:34

 

참고 링크

https://it-roheerumi.tistory.com/31

 

어느날 h2 데이터베이스를 실행했는데, 원래는 기본으로 저 입력란에 모두 영어로 뭐라뭐라 나와 있어야 하는데

 

모두 비어있었다.

 

도움말, 설정 다 둘러봤지만 도움은 안됨..

 

 

 

해결책은 간단하다

 

Setting Name: 부분에  Generic H2 (server)를 손수 입력해주면 뿅 하고 나타난다.

 

 

나머지 아래는 위와 같이 입력하면 된다. jdbc url 부분은 본인 데이터베이스 경로를 입력해준다.

프레임워크란?

  • 개발자가 일정 규칙과 구조 안에서 코드를 작성하도록 돕는 도구
  • 복잡한 로직을 단순화하거나 생략할 수 있도록 해 코드 재사용성, 유지보수성을 높임
  • 객체 생성, 의존성 관리 등 잡다한 부분을 자동화하여 필요한 비즈니스 로직에 집중할 수 있게 해준다. (생산성 증가)

 

Spring 프레임워크 특징

  1. POJO (Plain Old Java Object)
    특별한 인터페이스나 클래스를 상속받지 않고 순수한 자바 객체를 사용해 개발 진행한다.
    이는 코드 재사용성, 독립성을 높임

  2. 의존성 주입
    의존성 주입을 통해 객체 간 결합도를 낮춘다.

  3. AOP (관점 지향 프로그래밍)
    횡단 관심사 분리(Cross-Cutting Concerns)하여 핵싱 기능들이 수행될 때 수반해야할 부수 기능들을 모듈화할 수 있도록 도움

  4. 트랜잭션 관리
    선언적 트랜잭션 관리를 통해 데이터의 무결성, 안정성을 유지할 수 있게 돕는다!
    메서드가 수행되다가 예외가 발생하면 메서드 실행 전 상태로 데이터 상태를 복원해준다.

 

 

 

 

의존성 주입이란?

객체가 필요한 의존성을 직접 생성하지 않고, 외부 다른 클래스에서 주입받는 방식.

특정 구현체에 고정되지 않고, 다양한 구현체로 쉽게 변경이 가능해 유연성이 높아지고,

다른 환경에서도 재사용하기 쉽기 때문에 재사용성이 좋아진다.

 

의존관계 역전

상위 클래스가 하위 클래스에 의존하지 않고 인터페이스나 추상 클래스에 의존하도록 함으로써, 상위 모듈이 하위 모듈 변화에 영향을 덜 받도록 하는 방식

이 방식은 코드 유연성과 확장성을 높이고 의존성을 쉽게 관리할 수 있다.

 

// 인터페이스
public interface PaymentService {
    void processPayment();
}

// 인터페이스를 구현한 클래스 A
public class CreditCardPaymentService implements PaymentService {
    @Override
    public void processPayment() {
        System.out.println("Processing credit card payment...");
    }
}

// 주문서비스
public class OrderService {
	// 인터페이스에 의존
    private PaymentService paymentService;
	
    // 결제서비스를 신용카드 대신 현금으로 교체해도 해당 코드를 수정하지 않아도 됨!
    public OrderService(PaymentService paymentService) {
        this.paymentService = paymentService;
    }

    public void placeOrder() {
        System.out.println("Placing order...");
        paymentService.processPayment();
    }
}

 

 

위 코드에서 OrderService는 PaymentService 인터페이스에 의존하므로, 실제 구현을 쉽게 변경할 수 있음. CreditCardPaymentService 대신 다른 결제 서비스로 교체해도 OrderService의 코드는 수정할 필요가 없어진다!

 

 

Spring에서 의존성을 주입하는 방법

1. XML설정 파일을 통한 방법

<!-- applicationContext.xml -->
<beans xmlns="http://www.springframework.org/schema/beans" ...>
    <bean id="paymentService" class="com.example.CreditCardPaymentService"/>
    <bean id="orderService" class="com.example.OrderService">
        <constructor-arg ref="paymentService"/>
    </bean>
</beans>

 

2. 어노테이션을 이용한 방법

@Service
public class OrderService {
    private final PaymentService paymentService;

    @Autowired
    public OrderService(PaymentService paymentService) {
        this.paymentService = paymentService;
    }

    public void placeOrder() {
        System.out.println("Placing order...");
        paymentService.processPayment();
    }
}

 

3. Java Config를 통한 방법

@Configuration
public class AppConfig {
    @Bean
    public PaymentService paymentService() {
        return new CreditCardPaymentService();
    }

    @Bean
    public OrderService orderService() {
        return new OrderService(paymentService());
    }
}

Cookie, Session, HTTP

친환경 개발자
|2024. 10. 14. 23:59

HTTP란?

  • HyperText Transfer Protocol

  • 웹에서 데이터를 주고 받을 때 지켜야 할 통신 규약!

  • 대표적 HTTP 메서드 :
    GET, POST, PUT, DELETE

  • URL : 요청을 보낼 때, 어디로 요청을 보낼지에 대한 정보.

  • 헤더(Header): 요청 보낼 때 필요한 추가 정보 (ex. 브라우저 종류, 언어 설정 등
  • 본문(Body) : POST의 경우, 서버에 보낼 데이터를 본문에 포함시킬 수 있음.

  • 비연결성 : 요청과 응답이 종료되면 서로의 상태를 기억하지 않는다!

  • 무 상태: 서버가 클라이언트 상태를 저장하지 않는다.
     => 쿠키와 세션이 필요

 

 

 

 

 

Cookie

 

쿠키란?

  • 웹 서버가 만들어 클라이언트의 브라우저에 저장하는 작은 데이터 조각

  • 클라이언트 요청 시 상황에 따라 서버로 같이 전송

  • 브라우저가 바뀌면 쿠키는 남아있지 않음

 

목적

  • 클라이언트의 정보를 저장하여 활용할 필요가 있을 때
  • 사용자의 패턴 분석을 위해

  • 맞춤 광고, 장바구 등

특징

  • 서버가 아닌 사용자 브라우저에 저장됨

  • 하나의 쿠키는 약 4K
  • 유효기간을 설정할 수 있음

  • 클라이언트 측에 저장되므로 보안에 상대적으로 취약

 

Session

 

세션이란?

  • 사용자가 웹 서버에 접속한 상태를 하나의 단위로 봄
  • 서버 측에서 사용자 상태를 관리하는 방법
  • sessionId를 통해 각 세션을 구분하며, 이는 보통 쿠키로 관리됨

  • 이론상으로는 메모리의 제한이 없이 생성이 가능함

 

목적

  • 사용자 인증 상태 유지(로그인 상태 유지 등)



특징

  • 서버 측에 저장됨

  • 유효기간을 설정할 수 있으며, 만료되면 데이터 사라짐.

  • 서버의 메모리를 사용하므로, 사용자가 늘어나면 부담이 될 수 있음

  • 쿠키에 비해 보안성이 좋음

 

 

 

 

요청과 응답 과정

 

1. 사용자가 웹사이트에 방문

 

2. 서버에 세션 생성, 쿠키 생성하여 클라이언트에 응답 시 돌려줌

 

3. 클라이언트에 쿠키가 저장되며 세션ID가 함께 저장

 

4. 다음 요청 시 가지고 있던 쿠키를 함께 전달

 

5. 세션을 통한 상태 유지 (장바구니, 로그인 상태 등을 계속 유지함)

JSP 특징, 장단점, Scriptlet 등

친환경 개발자
|2024. 10. 8. 23:52

JSP란?

  • 서버 측에서 동적으로 HTML, XML등의 문서를 생성하기 위해 사용하는 자바 기반 기술


  • HTML 문서에서 Java코드를 작성할 수 있도록 혼합


  • JSTL등의 태그 라이브러리가 지원되어 편의성 향상


  • 작성된 후 서블릿으로 변환된 후 실행

 

 

 

 

 

 

JSP 구성 요소

  • 지시자 
    페이지 설정 관련 정보 지정을 위해 사용


  • 스크립트 요소(스크립트릿, 표현식, 선언부)
    문서 내용을 동적으로 생성하기 위해 사용


  • 기본객체
    요청과 응답을 읽고 처리하기 위해 기본으로 생성되어 있음

  • 표현언어(Expression Language)
    JSP를 더 간편하게 작성하기 위해 사용

 

 

 

 

 

 

 

JSP 태그

  • 스크립트릿 : 자바 코드를 작성하는 구간 (메서드 영역) 
    <% %>

  • 선언: 변수와 메서드를 선언하는 구간(클래스 영역)
    <%! %>

  • 표현식: 특정 값이나 결과물을 문자열로 출력하는 태그
    <%= %>

  • 주석 : 주석 작성 구간
    <%--   --%>

  • 지시자 : JSP 페이지에 대한 설정들을 지정할 수 있는 구간
    <%@ %>

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>제목</title>
</head>
<body>
	HTML 본문 구간
	<br>
	<%!
    // 변수, 메서드 선언 !!
	int a = 1;

	static void method(int a) {
		a = a + 1;
	}
	%>

	<%
	System.out.println("자바 코드 작성 가능한 영역");
	%>

	<%="문자열 출력 가능"%>

	<%-- 주석 작성 구간 --%>


</body>
</html>

 

 

 

 

 

 

지시자

 

  • page 지시자: JSP 페이지에 대한 전반적 속성을 정의한다
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page import="java.util.*" %>
  • include 지시자: 다른 JSP페이지나 파일을 현재 JSP 페이지에 삽입할 때 사용
<%@ include file="header.jsp" %>
  • taglib 지시자: JSTL등과 같은 태그 라이브러리 사용시 선언해야 함
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

Servlet?

  • Server + Applet의 합성어

  • Servlet은 웹 애플리케이션 개발에서 동적 웹페이지 생성

  • 클라이언트의 요청을 해석하고 응답을 생성하는 서버측 요소

  • 자바 코드 안에 HTML을 포함

  • 주로 HTTP 프로토콜을 사용해 클라이언트와 상호작용

  • Apache Tomcat과 같은 웹서버에서 실행된다!

 

 

 

 

 

 

Servlet 생명주기

0. Servlet 인스턴스가 없을 경우, Servlet 클래스를 불러오고, 웹컨테이너에 의해 Servlet 인스턴스를 초기화, 생성함.

 

 

1. init()

Servlet이 처음 로드될 때 한 번만 호출된다. 따라서 여러 변수나 조건들을 초기화하는 기능을 한다.

 

 

2. service()

클라이언트의 요청을 처리할 때마다 호출되며, 요청 메서드(GET, POST 등)에 따라 적절한 처리를 담당.

doGet(), doPost, doRegist() 등의 메소드가 호출된다!

 

 

3. destroy()

서버 종료되거나 Servlet이 더 이상 사용되지 않을 때 호출되고, 리소스 정리 등 종료 작업을 처리

 

 

 

 

 

 

GET vs POST 요청의 차이

항목 GET POST
용도 서버에서 데이터를 가져올 때 사용 서버에 데이터를 보낼 때 사용
파라미터 전송 방식 URL에 쿼리스트링 형태로 전송 요청 body에 포함하여 전송
보안 데이터가 URL에 노출됨 본문에 데이터가 포함되어 비교적 안전
데이터 크기 제한적 (대략 2048자 내외) 대용량 데이터 전송 가능
캐싱 브라우저에 의해 캐싱될 수 있음 일반적으로 캐싱되지 않음

 

 

 

요청과 응답 처리

 

요청(HttpServletRequest 객체)

  • 클라이언트로부터 전달된 요청 정보를 읽어들이는 역할.
  • 요청 파라미터, 헤더, 쿠키 등의 정보를 받을 수 있다.

 

응답(HttpServletResponse 개체)

  • 요청을 처리한 후 클라이언트에 전송할 응답 정보를 작성하는 데 사용.
  • HTML, JSON, 상태 코드, 헤더, 쿠키 등을 포함할 수 있다.
// GET 요청 처리
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String parameter = request.getParameter("name");
    response.setContentType("text/html");
    PrintWriter out = response.getWriter();
    out.println("<h1>안녕하세요 " + parameter + "</h1>");
}

// POST 요청 처리
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String parameter = request.getParameter("name");
    response.setContentType("text/html");
    PrintWriter out = response.getWriter();
    out.println("<h1>안녕하세요 " + parameter + " (POST)</h1>");
}

 

 

 

 

 

- 포워드 방식

  • 서버 내부에서 요청을 처리한 후 알아서 새로운 웹페이지로 전달
  • 따라서 URL의 변화가 없고, 클라이언트는 이를 인지할 수 없음.
response.sendRedirect("newPage.jsp");

 

 

-리다이렉트 방식

  • 요청을 받은 후 처리를 완료하고 클라이언트에게 또다시 해당 URL로 요청하도록 응답을 보냄
  • 클라이언트는 해당 응답을 받고 그에 맞는 URL을 재요청함.
  • 따라서 URL의 변화가 있다.
RequestDispatcher dispatcher = request.getRequestDispatcher("nextServlet");
dispatcher.forward(request, response);