2023.08.01.화.TIL

heeh·2023년 8월 1일

TIL

목록 보기
55/82
post-thumbnail

CRUD

CRUD는 데이터베이스와 관련된 기본적인 데이터 조작 기능의 약어입니다. CRUD는 Create (생성), Read (읽기), Update (갱신), Delete (삭제)의 네 가지 작업을 가리킵니다. 이를 Java Spring 프레임워크를 이용하여 구현하는 방법을 알아보겠습니다.

  1. 프로젝트 설정:
    Java Spring 프로젝트를 시작하기 전에 Spring Boot를 이용하여 간단하게 프로젝트를 설정합니다.

  2. 데이터베이스 설정:
    Spring 프로젝트에서 데이터베이스에 접근하기 위해 DataSource를 설정합니다. application.properties 또는 application.yml 파일을 이용하여 데이터베이스 연결 정보를 설정합니다.

  3. 엔티티(모델) 생성:
    CRUD 작업을 수행할 데이터베이스 테이블과 연관된 Java 클래스를 생성합니다. 이 클래스를 엔티티 또는 모델이라고 부릅니다.

  4. Repository 인터페이스 생성:
    Spring Data JPA를 이용하여 CRUD 작업을 수행할 Repository 인터페이스를 생성합니다. 이 인터페이스는 JpaRepository를 확장하여 기본적인 CRUD 작업을 지원하는 메서드를 상속받을 수 있습니다.

  5. Service 계층 생성:
    Repository 인터페이스를 사용하여 비즈니스 로직을 처리하는 Service 계층을 생성합니다. 이 곳에서 Repository 메서드를 호출하여 데이터베이스와 상호작용하고 필요한 비즈니스 로직을 구현합니다.

  6. Controller 생성:
    Spring MVC 컨트롤러를 생성하여 클라이언트 요청을 처리합니다. 클라이언트로부터 받은 요청을 Service 계층으로 전달하고 결과를 클라이언트에 반환합니다.

아래는 Spring Boot를 사용하여 간단한 Person 엔티티에 대한 CRUD 예시입니다.

  1. Person 엔티티 생성:
@Entity
public class Person {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String name;
    private int age;
    
    // Getters and Setters
}
  1. PersonRepository 생성:
public interface PersonRepository extends JpaRepository<Person, Long> {
}
  1. PersonService 생성:
@Service
public class PersonService {
    @Autowired
    private PersonRepository personRepository;
    
    public List<Person> getAllPersons() {
        return personRepository.findAll();
    }
    
    public Person getPersonById(Long id) {
        return personRepository.findById(id).orElse(null);
    }
    
    public Person createPerson(Person person) {
        return personRepository.save(person);
    }
    
    public Person updatePerson(Long id, Person updatedPerson) {
        Person person = personRepository.findById(id).orElse(null);
        if (person != null) {
            person.setName(updatedPerson.getName());
            person.setAge(updatedPerson.getAge());
            return personRepository.save(person);
        }
        return null;
    }
    
    public void deletePerson(Long id) {
        personRepository.deleteById(id);
    }
}
  1. PersonController 생성:
@RestController
@RequestMapping("/persons")
public class PersonController {
    @Autowired
    private PersonService personService;
    
    @GetMapping
    public List<Person> getAllPersons() {
        return personService.getAllPersons();
    }
    
    @GetMapping("/{id}")
    public Person getPersonById(@PathVariable Long id) {
        return personService.getPersonById(id);
    }
    
    @PostMapping
    public Person createPerson(@RequestBody Person person) {
        return personService.createPerson(person);
    }
    
    @PutMapping("/{id}")
    public Person updatePerson(@PathVariable Long id, @RequestBody Person updatedPerson) {
        return personService.updatePerson(id, updatedPerson);
    }
    
    @DeleteMapping("/{id}")
    public void deletePerson(@PathVariable Long id) {
        personService.deletePerson(id);
    }
}

이제 위와 같이 설정하면 /persons 엔드포인트를 통해 CRUD 작업을 수행할 수 있습니다. 예를 들어, /persons로 GET 요청을 보내면 모든 사람 목록을 가져오고, POST 요청을 보내면 새로운 사람을 생성하게 됩니다. PUT 요청을 보내면 특정 ID의 사람 정보를 갱신하며, DELETE 요청을 보내면 특정 ID의 사람을 삭제할 수 있습니다.

Request와 Response

Request와 Response는 웹 애플리케이션에서 클라이언트와 서버 사이의 통신을 나타내는 개념입니다. Spring에서는 HTTP 요청(Request)과 HTTP 응답(Response)을 처리하기 위해 여러 방법을 제공합니다.

Request 처리:
HTTP Request는 클라이언트가 서버로 보내는 요청을 의미합니다. Spring에서는 다양한 방법으로 Request를 처리할 수 있습니다.
@PathVariable: URL 경로에 변수를 포함하여 값을 전달하는 방법입니다.

java
@GetMapping("/persons/{id}")
public Person getPersonById(@PathVariable Long id) {
    // ...
}

@RequestParam: 쿼리 파라미터를 사용하여 값을 전달하는 방법입니다.

java
@GetMapping("/persons")
public List<Person> getPersonsByName(@RequestParam String name) {
    // ...
}

@RequestBody: HTTP 요청의 본문(body)에 JSON 형태로 데이터를 담아서 전달하는 방법입니다.

  java
@PostMapping("/persons")
public Person createPerson(@RequestBody Person person) {
    // ...
}

Response 처리:
HTTP Response는 서버가 클라이언트로 보내는 응답을 의미합니다. Spring에서는 메서드의 반환 값을 Response로 보내거나 ResponseEntity를 사용하여 보다 세밀한 컨트롤이 가능합니다.

반환 값 활용:
메서드의 반환 값으로 Spring은 자동으로 해당 값에 맞는 HTTP 응답을 생성합니다. 반환 값이 객체인 경우 JSON으로 변환하여 응답합니다.

java
@GetMapping("/persons/{id}")
public Person getPersonById(@PathVariable Long id) {
  // ... (서비스 로직)
  return person; // JSON으로 변환되어 응답됨
}

ResponseEntity 사용:
ResponseEntity는 응답 본문과 함께 HTTP 상태 코드, 헤더 등을 더 세밀하게 제어할 수 있도록 해줍니다.

java
@PostMapping("/persons")
public ResponseEntity<Person> createPerson(@RequestBody Person person) {
    // ... (서비스 로직)
    return ResponseEntity.status(HttpStatus.CREATED).body(person);
}

위와 같이 작성된 코드에서 HttpStatus.CREATED는 201 Created 상태 코드를 의미하며, body(person)은 응답 본문에 해당 객체를 담아서 전송합니다.

이외에도 다양한 방법으로 Request와 Response를 처리할 수 있으며, Spring은 많은 유틸리티 클래스와 어노테이션을 제공하여 개발자가 편리하게 웹 애플리케이션을 구성할 수 있도록 도와줍니다.

Security

Spring Security는 Spring 기반 웹 애플리케이션에서 보안과 인증(인증 및 권한 부여)을 담당하는 프레임워크입니다. 애플리케이션 보안에 대한 작업들을 추상화하고, 보안에 필요한 다양한 기능들을 제공하여 개발자가 보안에 더 집중하지 않고도 안전한 웹 애플리케이션을 개발할 수 있도록 도와줍니다.

주요 개념:

Authentication(인증): 사용자의 신원 확인을 의미합니다. 주로 아이디와 비밀번호를 사용하여 사용자가 누구인지 확인하는 과정입니다.

Authorization(권한 부여): 인증된 사용자가 특정 리소스 또는 기능에 접근할 수 있는 권한을 결정하는 과정입니다.

Principal(주체): 현재 인증된 사용자를 나타내는 객체를 의미합니다. 주로 UserDetails 객체가 Principal로 사용됩니다.

GrantedAuthority(부여된 권한): 사용자에게 부여된 권한을 나타내는 객체입니다. 보통 'ROLE_'로 시작하는 권한 문자열을 사용합니다.

AuthenticationManager(인증 관리자): 인증을 처리하는 기능을 제공하는 인터페이스입니다. 주로 Spring Security에서 제공하는 구현체를 사용하며, 사용자의 인증 정보를 확인하고 검증합니다.

UserDetailsService(사용자 정보 서비스): 사용자 정보를 가져오는 인터페이스입니다. 주로 사용자 정보를 데이터베이스에서 조회하여 UserDetails 객체로 반환하는 기능을 구현합니다.

UserDetails(사용자 상세 정보): 인증과 관련된 사용자 정보를 담은 객체입니다. 인증에 성공한 사용자의 정보와 권한을 담고 있습니다.

Spring Security 예제:

의존성 추가:
Maven 또는 Gradle 프로젝트의 의존성 파일에 Spring Security를 추가합니다.
Maven:

xml
Copy code
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

Gradle:

gradle
implementation 'org.springframework.boot:spring-boot-starter-security'

사용자 정보와 권한 설정:
Spring Security를 사용하기 위해 사용자 정보와 권한 정보를 설정합니다.

java
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            .withUser("user").password("{noop}password").roles("USER")
            .and()
            .withUser("admin").password("{noop}password").roles("ADMIN");
    }
}

위의 예제에서는 inMemoryAuthentication()을 사용하여 사용자 정보를 메모리에 저장하고 있습니다. 실제 애플리케이션에서는 데이터베이스 등을 사용하여 사용자 정보를 저장하게 됩니다.

URL 접근 권한 설정:
애플리케이션에서 특정 URL에 접근하는데 필요한 권한을 설정합니다.

java
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
  @Override
  protected void configure(HttpSecurity http) throws Exception {
      http.authorizeRequests()
          .antMatchers("/admin/**").hasRole("ADMIN")
          .antMatchers("/user/**").hasRole("USER")
          .anyRequest().authenticated()
          .and()
          .formLogin()
          .and()
          .httpBasic();
  }
}

위의 예제에서는 /admin/로 시작하는 URL은 ADMIN 권한이, /user/로 시작하는 URL은 USER 권한이 필요하며, 다른 모든 요청은 인증만 되어 있으면 접근할 수 있습니다.

커스텀 사용자 정보 서비스:
실제 애플리케이션에서는 사용자 정보를 데이터베이스에서 가져오는 서비스를 구현하여 UserDetails 객체로 반환합니다.

java
@Service
public class CustomUserDetailsService implements UserDetailsService {
    @Autowired
    private UserRepository userRepository;
    
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new UsernameNotFoundException("User not found with username: " + username));
        
        return new org.springframework.security.core.userdetails.User(
            user.getUsername(),
            user.getPassword(),
            getAuthorities(user.getRoles())
        );
    }
    
    private Collection<? extends GrantedAuthority> getAuthorities(Set<Role> roles) {
        return roles.stream()
                .map(role -> new SimpleGrantedAuthority("ROLE_" + role.getName()))
                .collect(Collectors.toList());
    }
}

위의 예제에서는 커스텀 UserDetailsService를 구현하여 사용자 정보를 데이터베이스에서 조회하고 UserDetails 객체로 반환하도록 하였습니다.

사용자 정보 서비스 설정:
커스텀 사용자 정보 서비스를 Spring Security에 설정합니다.

java
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private CustomUserDetailsService userDetailsService;
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }
    
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

위의 예제에서는 auth.userDetailsService(userDetailsService)로 커스텀 사용자 정보 서비스를 설정하고, passwordEncoder()를 사용하여 비밀번호를 암호화합니다.

Spring Security를 사용하여 사용자 인증과 권한 부여를 구현할 수 있습니다. 위의 예제는 간단한 메모리 기반 사용자 정보를 사용하였지만, 실제 애플리케이션에서는 데이터베이스를 연동하여 사용자 정보를 관리하고, 권한 부여 등을 더 복잡하게 설정할 수 있습니다.

profile
공부하자개발하자으쌰으쌰

0개의 댓글