← 홈

🍃

⌘K
🤖
Claude Code AI 도구
🤗
Hugging Face AI 도구
🦜
LangChain AI 도구
🧠
Keras AI 도구
🦙
Ollama AI 도구
🐍
Python 프로그래밍 언어
🟨
JavaScript 프로그래밍 언어
🔷
TypeScript 프로그래밍 언어
⚛️
React 프로그래밍 언어
🐹
Go 프로그래밍 언어
🦀
Rust 프로그래밍 언어
📊
MATLAB 프로그래밍 언어
🗄️
SQL 프로그래밍 언어
⚙️
C/C++ 프로그래밍 언어
Java 프로그래밍 언어
🟣
C# 프로그래밍 언어
🍎
Swift 프로그래밍 언어
🟠
Kotlin 프로그래밍 언어
Next.js 프로그래밍 언어
💚
Vue.js 프로그래밍 언어
🔥
Svelte 프로그래밍 언어
🎨
Tailwind CSS 프로그래밍 언어
💚
Node.js 프로그래밍 언어
🌐
HTML 프로그래밍 언어
🎨
CSS/SCSS 프로그래밍 언어
🐘
PHP 프로그래밍 언어
💎
Ruby 프로그래밍 언어
🔴
Scala 프로그래밍 언어
📊
R 프로그래밍 언어
🎯
Dart 프로그래밍 언어
💧
Elixir 프로그래밍 언어
🌙
Lua 프로그래밍 언어
🐪
Perl 프로그래밍 언어
🅰️
Angular 프로그래밍 언어
🚂
Express.js 프로그래밍 언어
🐱
NestJS 프로그래밍 언어
🛤️
Ruby on Rails 프로그래밍 언어
◼️
GraphQL 프로그래밍 언어
🟪
Haskell 프로그래밍 언어
💚
Nuxt.js 프로그래밍 언어
🔷
SolidJS 프로그래밍 언어
htmx 프로그래밍 언어
💻
VS Code 개발 도구
🧠
PyCharm 개발 도구
📓
Jupyter 개발 도구
🧠
IntelliJ IDEA 개발 도구
💚
Neovim 개발 도구
🔮
Emacs 개발 도구
🔀
Git DevOps & CLI
🐳
Docker DevOps & CLI
☸️
Kubernetes DevOps & CLI
☁️
AWS CLI DevOps & CLI
🔄
GitHub Actions DevOps & CLI
🐧
Linux 명령어 DevOps & CLI
💻
Bash 스크립팅 DevOps & CLI
🌐
Nginx DevOps & CLI
📝
Vim DevOps & CLI
🔨
Makefile DevOps & CLI
🧪
Pytest DevOps & CLI
🪟
Windows DevOps & CLI
📦
패키지 매니저 DevOps & CLI
🍎
macOS DevOps & CLI
🏗️
Terraform DevOps & CLI
🔧
Ansible DevOps & CLI
Helm DevOps & CLI
🔨
Jenkins DevOps & CLI
🔥
Prometheus DevOps & CLI
📊
Grafana DevOps & CLI
💻
Zsh DevOps & CLI
🐟
Fish Shell DevOps & CLI
💙
PowerShell DevOps & CLI
🔄
Argo CD DevOps & CLI
🔀
Traefik DevOps & CLI
☁️
Azure CLI DevOps & CLI
☁️
Google Cloud CLI DevOps & CLI
📟
tmux DevOps & CLI
🔧
jq DevOps & CLI
✂️
sed DevOps & CLI
📊
awk DevOps & CLI
🌊
Apache Airflow DevOps & CLI
🔢
NumPy 데이터베이스 & 데이터
🐼
Pandas 데이터베이스 & 데이터
🔥
PyTorch 데이터베이스 & 데이터
🧠
TensorFlow 데이터베이스 & 데이터
📈
Matplotlib 데이터베이스 & 데이터
🐘
PostgreSQL 데이터베이스 & 데이터
🐬
MySQL 데이터베이스 & 데이터
🍃
MongoDB 데이터베이스 & 데이터
🔴
Redis 데이터베이스 & 데이터
🔍
Elasticsearch 데이터베이스 & 데이터
🤖
Scikit-learn 데이터베이스 & 데이터
👁️
OpenCV 데이터베이스 & 데이터
Apache Spark 데이터베이스 & 데이터
🪶
SQLite 데이터베이스 & 데이터
Supabase 데이터베이스 & 데이터
🔵
Neo4j 데이터베이스 & 데이터
📨
Apache Kafka 데이터베이스 & 데이터
🐰
RabbitMQ 데이터베이스 & 데이터
🔤
Regex 유틸리티
📝
Markdown 유틸리티
📄
LaTeX 유틸리티
🔐
SSH & GPG 유틸리티
🌐
curl & HTTP 유틸리티
📜
reStructuredText 유틸리티
🚀
Postman 유틸리티
🎬
FFmpeg 유틸리티
🖼️
ImageMagick 유틸리티
🔍
ripgrep 유틸리티
🔍
fzf 유틸리티
📗
Microsoft Excel 오피스 애플리케이션
📘
Microsoft Word 오피스 애플리케이션
📙
Microsoft PowerPoint 오피스 애플리케이션
📝
한컴 한글 한컴오피스
📽️
한컴 한쇼 한컴오피스
📊
한컴 한셀 한컴오피스
📄
Google 문서 Google Workspace
📊
Google 스프레드시트 Google Workspace
📽️
Google 프레젠테이션 Google Workspace
🔌
Cadence Virtuoso EDA & 하드웨어
⚙️
Synopsys EDA EDA & 하드웨어
💎
Verilog & VHDL EDA & 하드웨어
LTSpice EDA & 하드웨어
🔧
KiCad EDA & 하드웨어
📝
Notion 생산성 도구
💎
Obsidian 생산성 도구
💬
Slack 생산성 도구
🎮
Discord 생산성 도구
🎨
Figma 디자인 도구
📘
Confluence Atlassian
📋
Jira Atlassian
🃏
Jest 테스팅
Vitest 테스팅
🎭
Playwright 테스팅
🌲
Cypress 테스팅
🌐
Selenium 테스팅
💙
Flutter 모바일 개발
📱
React Native 모바일 개발
🍎
SwiftUI 모바일 개발
📱
Expo 모바일 개발
🐍
Django 웹 프레임워크
FastAPI 웹 프레임워크
🌶️
Flask 웹 프레임워크
🍃
Spring Boot 웹 프레임워크
🍸
Gin 웹 프레임워크
Vite 빌드 도구
📦
Webpack 빌드 도구
esbuild 빌드 도구
🐘
Gradle 빌드 도구
🪶
Maven 빌드 도구
🔧
CMake 빌드 도구
🎮
Unity 게임 개발
🤖
Godot 게임 개발
🔌
Arduino 임베디드 & IoT
🔍
Nmap 보안
🐕
Datadog 모니터링
📖
Swagger/OpenAPI 문서화
검색 결과가 없습니다
EN KO

기초

애플리케이션 설정

메인 클래스
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
application.properties
# Server
server.port=8080

# Database
spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
spring.datasource.username=user
spring.datasource.password=pass

# JPA
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

# Logging
logging.level.root=INFO
logging.level.com.example=DEBUG

CLI 명령어

./mvnw spring-boot:run Maven으로 실행
./gradlew bootRun Gradle로 실행
./mvnw package JAR 빌드
java -jar app.jar JAR 실행

컨트롤러

REST 컨트롤러

기본 컨트롤러
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;

@RestController
@RequestMapping("/api/users")
public class UserController {

    @GetMapping
    public List<User> getAll() {
        return userService.findAll();
    }

    @GetMapping("/{id}")
    public User getById(@PathVariable Long id) {
        return userService.findById(id);
    }

    @PostMapping
    public User create(@RequestBody User user) {
        return userService.save(user);
    }

    @PutMapping("/{id}")
    public User update(@PathVariable Long id, @RequestBody User user) {
        return userService.update(id, user);
    }

    @DeleteMapping("/{id}")
    public void delete(@PathVariable Long id) {
        userService.delete(id);
    }
}
요청 매개변수
// Path variable
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) { ... }

// Query params
@GetMapping("/search")
public List<User> search(
    @RequestParam String name,
    @RequestParam(defaultValue = "0") int page,
    @RequestParam(required = false) String sort
) { ... }

// Request body
@PostMapping
public User create(@RequestBody @Valid UserDto dto) { ... }

// Headers
@GetMapping
public String get(@RequestHeader("Authorization") String token) { ... }

서비스

서비스 레이어

서비스 클래스
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserService {

    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public List<User> findAll() {
        return userRepository.findAll();
    }

    public User findById(Long id) {
        return userRepository.findById(id)
            .orElseThrow(() -> new NotFoundException("User not found"));
    }

    @Transactional
    public User save(User user) {
        return userRepository.save(user);
    }
}

JPA 및 리포지토리

엔티티

JPA 엔티티
import jakarta.persistence.*;
import java.time.LocalDateTime;

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, length = 100)
    private String name;

    @Column(unique = true)
    private String email;

    @Enumerated(EnumType.STRING)
    private Status status;

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
    private List<Post> posts;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "department_id")
    private Department department;

    @CreatedDate
    private LocalDateTime createdAt;

    // Getters and setters
}

리포지토리

JPA 리포지토리
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

public interface UserRepository extends JpaRepository<User, Long> {

    // Derived queries
    List<User> findByName(String name);
    List<User> findByNameContaining(String name);
    Optional<User> findByEmail(String email);
    List<User> findByStatusOrderByCreatedAtDesc(Status status);

    // Custom query
    @Query("SELECT u FROM User u WHERE u.status = :status")
    List<User> findActiveUsers(@Param("status") Status status);

    // Native query
    @Query(value = "SELECT * FROM users WHERE email LIKE %?1%", nativeQuery = true)
    List<User> searchByEmail(String email);
}

유효성 검사

Bean 유효성 검사

DTO 유효성 검사
import jakarta.validation.constraints.*;

public class UserDto {

    @NotBlank(message = "Name is required")
    @Size(min = 2, max = 100)
    private String name;

    @NotNull
    @Email(message = "Invalid email")
    private String email;

    @Min(0)
    @Max(150)
    private Integer age;

    @Pattern(regexp = "^\\+?[0-9]{10,14}$")
    private String phone;

    @NotEmpty
    private List<String> roles;
}
예외 핸들러
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, String>> handleValidation(
            MethodArgumentNotValidException ex) {
        Map<String, String> errors = new HashMap<>();
        ex.getBindingResult().getFieldErrors().forEach(error ->
            errors.put(error.getField(), error.getDefaultMessage())
        );
        return ResponseEntity.badRequest().body(errors);
    }

    @ExceptionHandler(NotFoundException.class)
    public ResponseEntity<String> handleNotFound(NotFoundException ex) {
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ex.getMessage());
    }
}

보안

Spring Security

보안 설정
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .csrf(csrf -> csrf.disable())
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/public/**").permitAll()
                .requestMatchers("/api/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            )
            .sessionManagement(session -> session
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            )
            .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
        return http.build();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

테스팅

단위 및 통합 테스트

컨트롤러 테스트
@WebMvcTest(UserController.class)
class UserControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private UserService userService;

    @Test
    void shouldGetAllUsers() throws Exception {
        when(userService.findAll()).thenReturn(List.of(new User("John")));

        mockMvc.perform(get("/api/users"))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$[0].name").value("John"));
    }
}
통합 테스트
@SpringBootTest
@AutoConfigureMockMvc
class UserIntegrationTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    void shouldCreateUser() throws Exception {
        String json = "{\"name\":\"John\",\"email\":\"john@example.com\"}";

        mockMvc.perform(post("/api/users")
            .contentType(MediaType.APPLICATION_JSON)
            .content(json))
            .andExpect(status().isCreated());
    }
}