diff --git a/src/main/java/umc/spring/post/config/WebConfig.java b/src/main/java/umc/spring/post/config/WebConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..47fe215d791708e457df46c21a1183000e1921dc
--- /dev/null
+++ b/src/main/java/umc/spring/post/config/WebConfig.java
@@ -0,0 +1,17 @@
+package umc.spring.post.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+public class WebConfig implements WebMvcConfigurer {
+    @Override
+    public void addCorsMappings(CorsRegistry registry) {
+        registry.addMapping("/**")
+                .allowedOrigins("*")
+                .allowedMethods("GET", "POST", "DELETE")
+                .allowCredentials(false)
+                .maxAge(3000);
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/umc/spring/post/config/security/JwtAuthenticationFilter.java b/src/main/java/umc/spring/post/config/security/JwtAuthenticationFilter.java
new file mode 100644
index 0000000000000000000000000000000000000000..bc77b2a20bad8b4929fa9730364acc239cf8f6c9
--- /dev/null
+++ b/src/main/java/umc/spring/post/config/security/JwtAuthenticationFilter.java
@@ -0,0 +1,42 @@
+package umc.spring.post.config.security;
+
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import java.io.IOException;
+
+
+@RequiredArgsConstructor
+@Component
+public class JwtAuthenticationFilter extends OncePerRequestFilter {
+
+    private final JwtTokenProvider jwtTokenProvider;
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
+        String token = resolveToken((HttpServletRequest) request);
+        if (token != null && jwtTokenProvider.validateToken(token)) {
+            Authentication authentication = jwtTokenProvider.getAuthentication(token);
+            System.out.println(authentication);
+            SecurityContextHolder.getContext().setAuthentication(authentication);
+            System.out.println(authentication);
+        }
+        chain.doFilter(request, response);
+    }
+
+    private String resolveToken(HttpServletRequest request) {
+        String bearerToken = request.getHeader("Authorization");
+        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer")) {
+            return bearerToken.substring(7);
+        }
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/umc/spring/post/config/security/JwtTokenProvider.java b/src/main/java/umc/spring/post/config/security/JwtTokenProvider.java
new file mode 100644
index 0000000000000000000000000000000000000000..d96c1f616ca505da13ca7449e793fd52348aed62
--- /dev/null
+++ b/src/main/java/umc/spring/post/config/security/JwtTokenProvider.java
@@ -0,0 +1,95 @@
+package umc.spring.post.config.security;
+
+import io.jsonwebtoken.*;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Component;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Date;
+import java.util.stream.Collectors;
+
+@Component
+public class JwtTokenProvider {
+
+    private final String secretKey;
+
+    public JwtTokenProvider( @Value("${jwt.secret}") final String secretKey) {
+        this.secretKey = secretKey;
+    }
+
+    public TokenInfo generateToken(Authentication authentication) {
+        System.out.println(authentication);
+        String authorities = authentication.getAuthorities().stream()
+                .map(GrantedAuthority::getAuthority)
+                .collect(Collectors.joining(","));
+        System.out.println("auth " + authorities);
+        long now = (new Date()).getTime();
+        Date accessTokenExpiration = new Date(now + 3600000); // 1h
+        Date refreshTokenExpiration = new Date(now + 1209600000); // 14d
+        String accessToken = Jwts.builder()
+                .setSubject(authentication.getName())
+                .claim("auth", authorities)
+                .setExpiration(accessTokenExpiration)
+                .signWith(SignatureAlgorithm.HS256, secretKey)
+                .compact();
+
+        String refreshToken = Jwts.builder()
+                .setExpiration(refreshTokenExpiration)
+                .signWith(SignatureAlgorithm.HS256, secretKey)
+                .compact();
+
+        TokenInfo tokenInfo = new TokenInfo();
+        tokenInfo.setGrantType("Bearer");
+        tokenInfo.setAccessToken(accessToken);
+        tokenInfo.setRefreshToken(refreshToken);
+
+        return tokenInfo;
+    }
+
+    public Authentication getAuthentication(String accessToken) {
+        Claims claims = parseClaims(accessToken);
+        System.out.println("log" + claims);
+        if (claims.get("auth") == null) {
+            throw new RuntimeException("권한 정보가 없는 토큰입니다.");
+        }
+
+        Collection<? extends GrantedAuthority> authorities =
+                Arrays.stream(claims.get("auth").toString().split(","))
+                        .map(SimpleGrantedAuthority::new)
+                        .collect(Collectors.toList());
+
+        UserDetails principal = new User(claims.getSubject(), "", authorities);
+        return new UsernamePasswordAuthenticationToken(principal, "", authorities);
+    }
+
+    public boolean validateToken(String token) {
+        try {
+            Jwts.parserBuilder().setSigningKey(secretKey).build().parseClaimsJws(token);
+            return true;
+        } catch (io.jsonwebtoken.security.SecurityException | MalformedJwtException e) {
+            System.out.println("Invalid JWT Token" + e);
+        } catch (ExpiredJwtException e) {
+            System.out.println("Expired JWT Token" + e);
+        } catch (UnsupportedJwtException e) {
+            System.out.println("Unsupported JWT Token" + e);
+        } catch (IllegalArgumentException e) {
+            System.out.println("JWT claims string is empty." + e);
+        }
+        return false;
+    }
+
+    private Claims parseClaims(String accessToken) {
+        try {
+            return Jwts.parserBuilder().setSigningKey(secretKey).build().parseClaimsJws(accessToken).getBody();
+        } catch (ExpiredJwtException e) {
+            return e.getClaims();
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/umc/spring/post/config/security/Role.java b/src/main/java/umc/spring/post/config/security/Role.java
new file mode 100644
index 0000000000000000000000000000000000000000..2bfb3da667e4a525b102ce30943d24cf46d7f1c0
--- /dev/null
+++ b/src/main/java/umc/spring/post/config/security/Role.java
@@ -0,0 +1,16 @@
+package umc.spring.post.config.security;
+
+public enum Role {
+    USER("ROLE_USER"),
+    ADMIN("ROLE_ADMIN");
+
+    private final String value;
+
+    public String getValue() {
+        return value;
+    }
+
+    Role(String value) {
+        this.value = value;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/umc/spring/post/config/security/SecurityConfig.java b/src/main/java/umc/spring/post/config/security/SecurityConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..1d26fefe2b3c847c306722b1148d3bb0eee61964
--- /dev/null
+++ b/src/main/java/umc/spring/post/config/security/SecurityConfig.java
@@ -0,0 +1,43 @@
+package umc.spring.post.config.security;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.Customizer;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configurers.CsrfConfigurer;
+import org.springframework.security.config.annotation.web.configurers.HttpBasicConfigurer;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.crypto.factory.PasswordEncoderFactories;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.web.SecurityFilterChain;
+import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
+
+@EnableWebSecurity
+@Configuration
+public class SecurityConfig {
+
+    private final JwtAuthenticationFilter jwtAuthenticationFilter;
+
+    @Autowired
+    public SecurityConfig(JwtAuthenticationFilter jwtAuthenticationFilter) {
+        this.jwtAuthenticationFilter = jwtAuthenticationFilter;
+    }
+
+    @Bean
+    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
+        http.httpBasic(HttpBasicConfigurer::disable)
+                .csrf(CsrfConfigurer::disable)
+                .cors(Customizer.withDefaults())
+                .sessionManagement(configurer -> configurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
+                .authorizeHttpRequests(authorize -> authorize.requestMatchers("/**").permitAll())
+                .addFilterBefore(jwtAuthenticationFilter, BasicAuthenticationFilter.class);
+        return http.build();
+    }
+
+    @Bean
+    public PasswordEncoder passwordEncoder() {
+        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/umc/spring/post/config/security/SecurityUtil.java b/src/main/java/umc/spring/post/config/security/SecurityUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..5577af306438c6b9ff3bd963cbb575b3d975a408
--- /dev/null
+++ b/src/main/java/umc/spring/post/config/security/SecurityUtil.java
@@ -0,0 +1,22 @@
+package umc.spring.post.config.security;
+
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import umc.spring.post.data.dto.UserInfoDto;
+
+public class SecurityUtil {
+    public static UserInfoDto getCurrentMemberId() {
+        final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+
+        if (authentication == null || authentication.getName() == null) {
+            throw new RuntimeException("No authentication information.");
+        }
+
+        UserInfoDto userInfoDto = new UserInfoDto();
+        userInfoDto.setUserId(authentication.getName());
+        userInfoDto.setMemberRole(authentication.getAuthorities().stream().toList().get(0).toString().replaceAll("ROLE_", ""));
+
+        return userInfoDto;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/umc/spring/post/config/security/TokenInfo.java b/src/main/java/umc/spring/post/config/security/TokenInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..7f9ad8464b611eb541568221dfd251116130c9b0
--- /dev/null
+++ b/src/main/java/umc/spring/post/config/security/TokenInfo.java
@@ -0,0 +1,52 @@
+package umc.spring.post.config.security;
+
+import lombok.Data;
+
+@Data
+public class TokenInfo {
+    private String grantType;
+    private String accessToken;
+    private String refreshToken;
+    private String email;
+    private String memberRole;
+
+    public String getGrantType() {
+        return grantType;
+    }
+
+    public void setGrantType(String grantType) {
+        this.grantType = grantType;
+    }
+
+    public String getAccessToken() {
+        return accessToken;
+    }
+
+    public void setAccessToken(String accessToken) {
+        this.accessToken = accessToken;
+    }
+
+    public String getRefreshToken() {
+        return refreshToken;
+    }
+
+    public void setRefreshToken(String refreshToken) {
+        this.refreshToken = refreshToken;
+    }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    public String getMemberRole() {
+        return memberRole;
+    }
+
+    public void setMemberRole(String memberRole) {
+        this.memberRole = memberRole;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/umc/spring/post/controller/AuthController.java b/src/main/java/umc/spring/post/controller/AuthController.java
new file mode 100644
index 0000000000000000000000000000000000000000..14fc05b92468625f866aed7ac081b21e3213d58e
--- /dev/null
+++ b/src/main/java/umc/spring/post/controller/AuthController.java
@@ -0,0 +1,37 @@
+package umc.spring.post.controller;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import umc.spring.post.config.security.TokenInfo;
+import umc.spring.post.data.dto.UserInfoDto;
+import umc.spring.post.data.dto.UserJoinDto;
+import umc.spring.post.data.dto.UserLoginDto;
+import umc.spring.post.service.AuthService;
+
+@RestController
+@RequestMapping("/user")
+public class AuthController {
+
+    @Autowired
+    private final AuthService authService;
+
+    public AuthController(AuthService authService) {
+        this.authService = authService;
+    }
+
+    @PostMapping("/login")
+    public TokenInfo login(@RequestBody UserLoginDto userLoginDto) {
+        return authService.login(userLoginDto);
+    }
+
+    @PostMapping("/register")
+    public void register(@RequestBody UserJoinDto userJoinDto) {
+        authService.join(userJoinDto);
+    }
+
+    @GetMapping("/info")
+    public UserInfoDto info() {
+        return authService.info();
+    }
+}
diff --git a/src/main/java/umc/spring/post/service/AuthService.java b/src/main/java/umc/spring/post/service/AuthService.java
new file mode 100644
index 0000000000000000000000000000000000000000..ee097e894d5ea6685aae319d3228ca593aa98b8c
--- /dev/null
+++ b/src/main/java/umc/spring/post/service/AuthService.java
@@ -0,0 +1,15 @@
+package umc.spring.post.service;
+
+
+import umc.spring.post.config.security.TokenInfo;
+import umc.spring.post.data.dto.UserInfoDto;
+import umc.spring.post.data.dto.UserJoinDto;
+import umc.spring.post.data.dto.UserLoginDto;
+
+public interface AuthService {
+    TokenInfo login(UserLoginDto userLoginDto);
+
+    void join(UserJoinDto userJoinDto);
+
+    UserInfoDto info();
+}
diff --git a/src/main/java/umc/spring/post/service/AuthServiceImpl.java b/src/main/java/umc/spring/post/service/AuthServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..1880a4e3ff792acdd8d845e39b59e764208f9e37
--- /dev/null
+++ b/src/main/java/umc/spring/post/service/AuthServiceImpl.java
@@ -0,0 +1,90 @@
+package umc.spring.post.service;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.stereotype.Service;
+
+
+
+import umc.spring.post.data.entity.User;
+import umc.spring.post.config.security.JwtTokenProvider;
+import umc.spring.post.config.security.Role;
+import umc.spring.post.config.security.SecurityUtil;
+import umc.spring.post.config.security.TokenInfo;
+import umc.spring.post.data.dto.UserInfoDto;
+import umc.spring.post.data.dto.UserJoinDto;
+import umc.spring.post.data.dto.UserLoginDto;
+import umc.spring.post.repository.UserRepository;
+
+
+@Service
+public class AuthServiceImpl implements AuthService, UserDetailsService {
+
+    @Autowired
+    private final UserRepository userRepository;
+
+    @Autowired
+    private final PasswordEncoder passwordEncoder;
+
+    @Autowired
+    private final JwtTokenProvider jwtTokenProvider;
+
+    public AuthServiceImpl(UserRepository userRepository, PasswordEncoder passwordEncoder, JwtTokenProvider jwtTokenProvider) {
+        this.userRepository = userRepository;
+        this.passwordEncoder = passwordEncoder;
+        this.jwtTokenProvider = jwtTokenProvider;
+    }
+
+    @Override
+    public TokenInfo login(UserLoginDto userLoginDto) {
+        User user = userRepository.findByUserId(userLoginDto.getUserId()).orElseThrow(() -> new UsernameNotFoundException("아이디 혹은 비밀번호를 확인하세요."));
+
+        boolean matches = passwordEncoder.matches(userLoginDto.getPassword(), user.getPassword());
+        if (!matches) throw new BadCredentialsException("아이디 혹은 비밀번호를 확인하세요.");
+
+        Authentication authentication = new UsernamePasswordAuthenticationToken(user.getUserId(), user.getPassword(), user.getAuthorities());
+
+        TokenInfo tokenInfo = jwtTokenProvider.generateToken(authentication);
+        tokenInfo.setEmail(user.getUserId());
+
+        tokenInfo.setMemberRole(user.getRole().toString());
+        return tokenInfo;
+    }
+
+    @Override
+    public void join(UserJoinDto userJoinDto) {
+        User user = new User();
+        user.setUserId(userJoinDto.getUserId());
+        user.setPassword(passwordEncoder.encode(userJoinDto.getPassword()));
+        user.setUserName(userJoinDto.getUserName());
+        userRepository.save(user);
+    }
+
+    @Override
+    public UserInfoDto info() {
+        UserInfoDto userInfoDto = SecurityUtil.getCurrentMemberId();
+        return userInfoDto;
+    }
+
+    @Override
+    public UserDetails loadUserByUsername(String userId) throws UsernameNotFoundException {
+        return userRepository.findByUserId(userId)
+                .map(this::createUserDetails)
+                .orElseThrow(() -> new UsernameNotFoundException("해당하는 유저를 찾을 수 없습니다."));
+    }
+
+    private UserDetails createUserDetails(User user) {
+        return org.springframework.security.core.userdetails.User.builder()
+                .username(user.getUsername())
+                .password(passwordEncoder.encode(user.getPassword()))
+                .roles(user.getRole().toString())
+                .build();
+    }
+}