πŸŒ†
Sunset Archive
GitHubLinkedInBlog
  • litsynp
  • Archives
    • Projects
      • Let's Parking!
      • λ§›μ§‘λͺ¬μŠ€ν„° (JMT Monster)
      • spring-x-demo Projects
    • Articles
      • My Thoughts on GitBook
      • Wake-on-LAN & RDP Setup
    • Learning
      • Languages
        • Rust
          • Useful Links
          • Syntax
          • Pointers
          • Dependencies
          • Logging
          • Phantom Types
          • Iterable
            • Optional Skip
        • Go
          • Useful Links
          • Structures
          • Zero Values
          • Error Handling
          • Dependency Injection
          • Project Layout
        • JavaScript/TypeScript
          • Basics
            • Types
              • [JS] Falsy Values
              • [TS] Types - unknown, any, never
            • Rest Parameters (...)
            • Spread Syntax (...)
            • Destructuing Assignment
            • CJS, AMD, UMD, ESM
          • Advanced
            • Conditional Destructuring Assignment
            • Type Guards
          • Miscellaneous
            • Dependency Injection in JS?
            • ESLint, Prettier, TypeScript
          • Node
            • Useful Links
            • General
              • V8 Engine
              • Version Management: NVM
              • Environment Variables
            • Database
              • Knex
        • C
          • Dynamic Multi-dimensional Arrays
        • Spring
          • General
            • @Import v.s. @ContextConfiguration
            • MessageSource
          • Kotlin+Spring
            • Kotlin Annotations (Use-Site Targets)
            • Handling Null in Request DTO
            • Handling Null in URL
          • Reactive Stack
            • Reactive API with Spring WebFlux
          • Spring Security
            • Google OAuth Setup
          • Spring Batch
            • Bulk Insert
        • Kotlin
          • val/var in Constructor
          • Initializer Blocks
          • Inheritance Modifiers (final, open, abstract)
          • Delegate Pattern
        • Java
          • Serialization
          • Random Number Generation
            • (1) Math.random() v.s. Random
            • (2) Random v.s. ThreadLocalRandom
        • Python
          • Version Management
        • Ruby
          • Installation
          • Getters & Setters
        • Elixir
        • Erlang
        • Flutter
        • AWS
          • AWS CLI
        • Terraform
          • Installation
          • Basics
      • Code
        • OOP
          • The 4 Basic Concepts of OOP
          • The SOLID Principles
          • GRASP
          • Spring POJO
          • Others
        • Functional Programming
          • Currying
          • Higher-Order Function
          • Closure
          • Monad
        • 곡변성, λ°˜κ³΅λ³€μ„±, 무곡변성
        • Others
          • UUID
          • GraphQL
          • Multimedia
            • Streaming
          • Geography
            • μœ„λ„ (Latitude), 경도 (Longitude)
      • Tools
        • Nix
        • Mermaid
          • Flowchart
          • Sequence Diagram
          • Class Diagram
          • Entity Relationship Diagrams
        • VSCode
          • VSCode CLI
          • VSCode Extensions
        • JetBrains
          • IntelliJ - Open Projects in Tabs
          • Delete Leftover IDE Directories
        • vim
          • Commands
      • Books
        • λ‹€μž¬λ‹€λŠ₯ μ½”ν‹€λ¦° ν”„λ‘œκ·Έλž˜λ° (Programming Kotlin)
          • Pt 01. μ½”ν‹€λ¦°μœΌλ‘œ μŠ€ν¬λ¦½νŒ… ν•˜κΈ°
            • Ch 01. μ½”ν‹€λ¦° μ‹œμž‘ν•˜κΈ°
            • Ch 02. Java 개발자λ₯Ό μœ„ν•œ μ½”ν‹€λ¦° ν•„μˆ˜ 사항
            • Ch 03. ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μž
            • Ch 05. μ½œλ ‰μ…˜ μ‚¬μš©ν•˜κΈ°
        • 였브젝트 (Object)
          • Ch.0 λ“€μ–΄κ°€λ©° - ν”„λ‘œκ·Έλž˜λ° νŒ¨λŸ¬λ‹€μž„
          • Ch.1 객체, 섀계
          • Ch.2 객체지ν–₯ ν”„λ‘œκ·Έλž˜λ°
          • Ch.3 μ—­ν• , μ±…μž„, ν˜‘λ ₯
          • Ch.4 섀계 ν’ˆμ§ˆκ³Ό νŠΈλ ˆμ΄λ“œμ˜€ν”„
          • Ch.5 μ±…μž„ ν• λ‹Ήν•˜κΈ°
          • Ch.6 λ©”μ‹œμ§€μ™€ μΈν„°νŽ˜μ΄μŠ€
          • Ch.7 μœ μ—°ν•œ 섀계
          • Ch.8 μ˜μ‘΄μ„± κ΄€λ¦¬ν•˜κΈ°
          • Ch.9 μœ μ—°ν•œ 섀계
          • Ch.10 상속과 μ½”λ“œ μž¬μ‚¬μš©
          • Ch.11 ν•©μ„±κ³Ό μœ μ—°ν•œ 섀계
          • Ch.12 λ‹€ν˜•μ„±
          • Ch.13 μ„œλΈŒν΄λž˜μ‹±κ³Ό μ„œλΈŒνƒ€μ΄ν•‘
          • Ch.14 일관성 μžˆλŠ” ν˜‘λ ₯
          • Ch.15 λ””μžμΈ νŒ¨ν„΄κ³Ό ν”„λ ˆμž„μ›Œν¬
          • End. 마치며 - λ‚˜μ•„κ°€κΈ°
          • ν›„κΈ°
        • ν—€λ“œ 퍼슀트 λ””μžμΈ νŒ¨ν„΄ (Head First Design Patterns)
          • Ch.1 λ””μžμΈ νŒ¨ν„΄ μ†Œκ°œμ™€ μ „λž΅ νŒ¨ν„΄
          • Ch.2 μ˜΅μ €λ²„ νŒ¨ν„΄
          • Ch.3 λ°μ½”λ ˆμ΄ν„° νŒ¨ν„΄
          • Ch.4 νŒ©ν† λ¦¬ νŒ¨ν„΄
          • Ch.5 μ‹±κΈ€ν„΄ νŒ¨ν„΄
          • Ch.6 μ»€λ§¨λ“œ νŒ¨ν„΄
          • Ch.7 μ–΄λŒ‘ν„° νŒ¨ν„΄κ³Ό νΌμ‚¬λ“œ νŒ¨ν„΄
          • Ch.8 ν…œν”Œλ¦Ώ λ©”μ†Œλ“œ νŒ¨ν„΄
          • Ch.9 반볡자 νŒ¨ν„΄κ³Ό μ»΄ν¬μ§€νŠΈ νŒ¨ν„΄
          • Ch.10 μƒνƒœ νŒ¨ν„΄
          • Ch.11 ν”„λ‘μ‹œ νŒ¨ν„΄
          • Ch.12 볡합 νŒ¨ν„΄
        • μ΄νŽ™ν‹°λΈŒ νƒ€μž…μŠ€ν¬λ¦½νŠΈ (Effective TypeScript)
          • Ch.1 νƒ€μž…μŠ€ν¬λ¦½νŠΈ μ•Œμ•„λ³΄κΈ°
            • Item 1 νƒ€μž…μŠ€ν¬λ¦½νŠΈμ™€ μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ 관계 μ΄ν•΄ν•˜κΈ°
            • Item 2 νƒ€μž…μŠ€ν¬λ¦½νŠΈ μ„€μ • μ΄ν•΄ν•˜κΈ°
            • Item 3 μ½”λ“œ 생성과 νƒ€μž…μ΄ κ΄€κ³„μ—†μŒμ„ μ΄ν•΄ν•˜κΈ°
            • Item 4 ꡬ쑰적 타이핑에 μ΅μˆ™ν•΄μ§€κΈ°
            • Item 5 any νƒ€μž… μ§€μ–‘ν•˜κΈ°
          • Ch.2 νƒ€μž…μŠ€ν¬λ¦½νŠΈμ˜ νƒ€μž… μ‹œμŠ€ν…œ
            • Item 6 νŽΈμ§‘κΈ°λ₯Ό μ‚¬μš©ν•˜μ—¬ νƒ€μž… μ‹œμŠ€ν…œ νƒμƒ‰ν•˜κΈ°
            • Item 7 νƒ€μž…μ΄ κ°’λ“€μ˜ 집합이라고 μƒκ°ν•˜κΈ°
            • Item 1-7 Study Summary
            • Item 8 νƒ€μž… 곡간과 κ°’ κ³΅κ°„μ˜ μ‹¬λ²Œ κ΅¬λΆ„ν•˜κΈ°
            • Item 9 νƒ€μž… λ‹¨μ–Έλ³΄λ‹€λŠ” νƒ€μž… 선언을 μ‚¬μš©ν•˜κΈ°
            • Item 10 객체 래퍼 νƒ€μž… ν”Όν•˜κΈ°
            • Item 11 μž‰μ—¬ 속성 체크의 ν•œκ³„ μΈμ§€ν•˜κΈ°
            • Item 12 ν•¨μˆ˜ ν‘œν˜„μ‹μ— νƒ€μž… μ μš©ν•˜κΈ°
            • Item 13 νƒ€μž…κ³Ό μΈν„°νŽ˜μ΄μŠ€μ˜ 차이점 μ•ŒκΈ°
            • Item 14 νƒ€μž… μ—°μ‚°κ³Ό μ œλ„ˆλ¦­ μ‚¬μš©μœΌλ‘œ 반볡 쀄이기
            • Item 15 동적 데이터에 인덱슀 μ‹œκ·Έλ‹ˆμ²˜ μ‚¬μš©ν•˜κΈ°
            • Item 16 number 인덱슀 μ‹œκ·Έλ‹ˆμ²˜λ³΄λ‹€λŠ” Array, νŠœν”Œ, ArrayLikeλ₯Ό μ‚¬μš©ν•˜κΈ°
            • Item 17 λ³€κ²½ κ΄€λ ¨λœ 였λ₯˜ λ°©μ§€λ₯Ό μœ„ν•΄ readonly μ‚¬μš©ν•˜κΈ°
            • Item 18 λ§€ν•‘λœ νƒ€μž…μ„ μ‚¬μš©ν•˜μ—¬ 값을 λ™κΈ°ν™”ν•˜κΈ°
          • Ch.3 νƒ€μž… μΆ”λ‘ 
            • Item 19 μΆ”λ‘  κ°€λŠ₯ν•œ νƒ€μž…μ„ μ‚¬μš©ν•΄ μž₯ν™©ν•œ μ½”λ“œ λ°©μ§€ν•˜κΈ°
            • Item 20 λ‹€λ₯Έ νƒ€μž…μ—λŠ” λ‹€λ₯Έ λ³€μˆ˜ μ‚¬μš©ν•˜κΈ°
            • Item 21 νƒ€μž… λ„“νžˆκΈ°
            • Item 22 νƒ€μž… 쒁히기
            • Item 23 ν•œκΊΌλ²ˆμ— 객체 μƒμ„±ν•˜κΈ°
            • Item 24 일관성 μžˆλŠ” 별칭 μ‚¬μš©ν•˜κΈ°
            • Item 25 비동기 μ½”λ“œμ—λŠ” 콜백 λŒ€μ‹  async ν•¨μˆ˜ μ‚¬μš©ν•˜κΈ°
            • Item 26 νƒ€μž… 좔둠에 λ¬Έλ§₯이 μ–΄λ–»κ²Œ μ‚¬μš©λ˜λŠ”μ§€ μ΄ν•΄ν•˜κΈ°
            • Item 27 ν•¨μˆ˜ν˜• 기법과 라이브러리둜 νƒ€μž… 흐름 μœ μ§€ν•˜κΈ°
          • Ch.4 νƒ€μž… 섀계
            • Item 28 μœ νš¨ν•œ μƒνƒœλ§Œ ν‘œν˜„ν•˜λŠ” νƒ€μž…μ„ μ§€ν–₯ν•˜κΈ°
            • Item 29 μ‚¬μš©ν•  λ•ŒλŠ” λ„ˆκ·ΈλŸ½κ²Œ, 생성할 λ•ŒλŠ” μ—„κ²©ν•˜κ²Œ
            • Item 30 λ¬Έμ„œμ— νƒ€μž… 정보λ₯Ό μ“°μ§€ μ•ŠκΈ°
            • Item 31 νƒ€μž… 주변에 null κ°’ λ°°μΉ˜ν•˜κΈ°
            • Item 32 μœ λ‹ˆμ˜¨μ˜ μΈν„°νŽ˜μ΄μŠ€λ³΄λ‹€λŠ” μΈν„°νŽ˜μ΄μŠ€μ˜ μœ λ‹ˆμ˜¨μ„ μ‚¬μš©ν•˜κΈ°
            • Item 33 string νƒ€μž…λ³΄λ‹€ 더 ꡬ체적인 νƒ€μž… μ‚¬μš©ν•˜κΈ°
            • Item 34 λΆ€μ •ν™•ν•œ νƒ€μž…λ³΄λ‹€λŠ” λ―Έμ™„μ„± νƒ€μž…μ„ μ‚¬μš©ν•˜κΈ°
            • Item 35 데이터가 μ•„λ‹Œ, API와 λͺ…μ„Έλ₯Ό 보고 νƒ€μž… λ§Œλ“€κΈ°
            • Item 36 ν•΄λ‹Ή λΆ„μ•Όμ˜ μš©μ–΄λ‘œ νƒ€μž… 이름 μ§“κΈ°
            • Item 37 곡식 λͺ…μΉ­μ—λŠ” μƒν‘œλ₯Ό 뢙이기
          • Ch.5 any 닀루기
            • Item 38 any νƒ€μž…μ€ κ°€λŠ₯ν•œ ν•œ 쒁은 λ²”μœ„μ—μ„œλ§Œ μ‚¬μš©ν•˜κΈ°
            • Item 39 anyλ₯Ό ꡬ체적으둜 λ³€ν˜•ν•΄μ„œ μ‚¬μš©ν•˜κΈ°
            • Item 40 ν•¨μˆ˜ μ•ˆμœΌλ‘œ νƒ€μž… 단언문 감좔기
            • Item 41 any의 μ§„ν™”λ₯Ό μ΄ν•΄ν•˜κΈ°
            • Item 42 λͺ¨λ₯΄λŠ” νƒ€μž…μ˜ κ°’μ—λŠ” any λŒ€μ‹  unknown을 μ‚¬μš©ν•˜κΈ°
            • Item 43 λͺ½ν‚€ νŒ¨μΉ˜λ³΄λ‹€λŠ” μ•ˆμ „ν•œ νƒ€μž…μ„ μ‚¬μš©ν•˜κΈ°
            • Item 44 νƒ€μž… 컀버리지λ₯Ό μΆ”μ ν•˜μ—¬ νƒ€μž… μ•ˆμ „μ„± μœ μ§€ν•˜κΈ°
          • Ch.6 νƒ€μž… μ„ μ–Έκ³Ό @types
            • Item 45 devDependencies에 typescript와 @types μΆ”κ°€ν•˜κΈ°
            • Item 46 νƒ€μž… μ„ μ–Έκ³Ό κ΄€λ ¨λœ μ„Έ κ°€μ§€ 버전 μ΄ν•΄ν•˜κΈ°
            • Item 47 곡개 API에 λ“±μž₯ν•˜λŠ” λͺ¨λ“  νƒ€μž…μ„ μ΅μŠ€ν¬νŠΈν•˜κΈ°
            • Item 48 API 주석에 TSDoc μ‚¬μš©ν•˜κΈ°
            • Item 49 μ½œλ°±μ—μ„œ this에 λŒ€ν•œ νƒ€μž… μ œκ³΅ν•˜κΈ°
            • Item 50 μ˜€λ²„λ‘œλ”© νƒ€μž…λ³΄λ‹€λŠ” 쑰건뢀 νƒ€μž…μ„ μ‚¬μš©ν•˜κΈ°
            • Item 51 μ˜μ‘΄μ„± 뢄리λ₯Ό μœ„ν•΄ 미러 νƒ€μž… μ‚¬μš©ν•˜κΈ°
            • Item 52 ν…ŒμŠ€νŒ… νƒ€μž…μ˜ 함정에 μ£Όμ˜ν•˜κΈ°
          • Ch.7 μ½”λ“œλ₯Ό μž‘μ„±ν•˜κ³  μ‹€ν–‰ν•˜κΈ°
            • Item 53 νƒ€μž…μŠ€ν¬λ¦½νŠΈ κΈ°λŠ₯λ³΄λ‹€λŠ” ECMAScript κΈ°λŠ₯을 μ‚¬μš©ν•˜κΈ°
            • Item 54 객체λ₯Ό μˆœνšŒν•˜λŠ” λ…Έν•˜μš°
            • Item 55 DOM 계측 ꡬ쑰 μ΄ν•΄ν•˜κΈ°
            • Item 56 정보λ₯Ό κ°μΆ”λŠ” λͺ©μ μœΌλ‘œ private μ‚¬μš©ν•˜μ§€ μ•ŠκΈ°
            • Item 57 μ†ŒμŠ€λ§΅μ„ μ‚¬μš©ν•˜μ—¬ νƒ€μž…μŠ€ν¬λ¦½νŠΈ λ””λ²„κΉ…ν•˜κΈ°
          • Ch.8 νƒ€μž…μŠ€ν¬λ¦½νŠΈλ‘œ λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ν•˜κΈ°
            • Item 58 λͺ¨λ˜ μžλ°”μŠ€ν¬λ¦½νŠΈλ‘œ μž‘μ„±ν•˜κΈ°
            • Item 59 νƒ€μž…μŠ€ν¬λ¦½νŠΈ λ„μž… 전에 @ts-check와 JSDoc으둜 μ‹œν—˜ν•΄ 보기
            • Item 60 allowJS둜 νƒ€μž…μŠ€ν¬λ¦½νŠΈμ™€ μžλ°”μŠ€ν¬λ¦½νŠΈ 같이 μ‚¬μš©ν•˜κΈ°
            • Item 61 μ˜μ‘΄μ„± 관계에 따라 λͺ¨λ“ˆ λ‹¨μœ„λ‘œ μ „ν™˜ν•˜κΈ°
            • Item 62 λ§ˆμ΄κ·Έλ ˆμ΄μ…˜μ˜ 완성을 μœ„ν•΄ noImplicitAny μ„€μ •ν•˜κΈ°
        • Dive Into Design Patterns
          • λ””μžμΈ νŒ¨ν„΄ μ†Œκ°œ
          • μ†Œν”„νŠΈμ›¨μ–΄ λ””μžμΈ 원칙듀
          • λ””μžμΈ νŒ¨ν„΄ λͺ©λ‘
          • μœ μš©ν•œ 링크
        • 가상 λ©΄μ ‘ μ‚¬λ‘€λ‘œ λ°°μš°λŠ” λŒ€κ·œλͺ¨ μ‹œμŠ€ν…œ 섀계 기초 (System Design Interview)
          • Key Points
          • Real Life Systems
          • Engineering Blogs
        • Node.js λ””μžμΈ νŒ¨ν„΄ 바이블 (Node.js Design Patterns 3rd Edition)
        • λ¦¬νŒ©ν„°λ§ 2판 (Refactoring: 2nd Ed.)
          • 1μž₯ λ¦¬νŒ©ν„°λ§: 첫 번째 μ˜ˆμ‹œ
          • 2μž₯ λ¦¬νŒ©ν„°λ§ 원칙
          • 3μž₯ μ½”λ“œμ—μ„œ λ‚˜λŠ” μ•…μ·¨
          • 4μž₯ ν…ŒμŠ€νŠΈ κ΅¬μΆ•ν•˜κΈ°
Powered by GitBook
On this page
  • About
  • @RequestParam
  • @PathVariable
  • More on the matter
  • REF

Was this helpful?

Edit on GitHub
  1. Archives
  2. Learning
  3. Languages
  4. Spring
  5. Kotlin+Spring

Handling Null in URL

About

APIλ₯Ό κ΅¬ν˜„ν•˜λ‹€λ³΄λ©΄ /posts?type=notice 의 ?type=notice, /posts/{id}, μ—μ„œ id처럼 URL을 톡해 값을 μ „λ‹¬ν•˜λŠ” κ²½μš°κ°€ μžˆλ‹€.

Spring MVCμ—μ„œλŠ” μ»¨νŠΈλ‘€λŸ¬μ—μ„œ μš”μ²­μœΌλ‘œ λ“€μ–΄μ˜¨ ν•΄λ‹Ή 값듀을 각각 @RequestParam, @PathVariableμ–΄λ…Έν…Œμ΄μ…˜μ„ μ΄μš©ν•΄ μ°Έμ‘°ν•  수 μžˆλ‹€.

@RequestParam

Java

Spring을 μžλ°”λ‘œ μž‘μ„±ν•  λ•ŒλŠ” λ‹€μŒκ³Ό 같이 μ§„ν–‰ν•  수 μžˆμ—ˆλ‹€.

PostController.java
@GetMapping("/posts")
public ResponseEntity<List<PostResponse>> requestParam(
    @RequestParam(defaultValue = "post", required = false) String type) {

    return ResponseEntity.ok()
        .body(postSearchService.search(type));
}

type은 μ‹€μ œλ‘œ null이 λ“€μ–΄μ˜¬ μˆ˜λ„ μžˆλ‹€. required=falseλ₯Ό μ „λ‹¬ν•΄μ„œ ν•„μˆ˜κ°’μ΄ μ•„λ‹˜μ„ λͺ…μ‹œν•œλ‹€. (λ””ν΄νŠΈλŠ” false)

defaultValue둜 기본값을 전달할 수 μžˆλ‹€. (""둜 κ°μ‹Έμ€˜μ•Ό ν•œλ‹€.)

Kotlin

μ½”ν‹€λ¦°μ—μ„œλŠ” μ–Έμ–΄ μ°¨μ›μ—μ„œ νƒ€μž… 뒀에 ?λ₯Ό λΆ™μ΄λŠ” κ²ƒμœΌλ‘œ nullable νƒ€μž…κ³Ό non-nullable νƒ€μž…μ„ κ΅¬λΆ„ν•˜κ³  (μ™„μ „νžˆ λ‹€λ₯Έ νƒ€μž…μ΄ λœλ‹€), ν•¨μˆ˜μ—μ„œ λ””ν΄νŠΈ 값을 μ§€μ›ν•œλ‹€. λ””ν΄νŠΈ 값은 이런 μ‹μœΌλ‘œ 전달할 수 μžˆλ‹€.

fun speak(sentence: String = "Bow wow!") {
    println(sentence)
}

sentence둜 아무것도 μ „λ‹¬λ˜μ§€ μ•ŠμœΌλ©΄ = λ’€μ˜ λ””ν΄νŠΈ 값이 λ“€μ–΄κ°€κ²Œ λœλ‹€.

κ·Έλ ‡λ‹€λ©΄ μŠ€ν”„λ§μ—μ„œλ„ 이 κΈ°λŠ₯을 μ‘μš©ν•΄μ„œ PostController 예제λ₯Ό λ‹€μŒκ³Ό 같이 μž‘μ„±ν•˜λ©΄ μ–΄λ–¨κΉŒ?

PostController.kt
@GetMapping("/posts")
fun requestParam(
    @RequestParam type: String? = "post"
): ResponseEntity<List<PostResponse>> {
    return ResponseEntity.ok()
        .body(postSearchService.search(type))
}

κ·ΈλŸ¬λ‚˜ μ΄λ ‡κ²Œ ν•˜κ²Œ 되면 μ‹€μ œλ‘œλŠ” typeμ—λŠ” null이 λ“€μ–΄κ°„λ‹€.

Spring의 ArgumentResolver (RequestParamArgumentResolver)λ₯Ό 거치며, type에 μ• μ΄ˆμ— null이 λ“€μ–΄κ°„ μ±„λ‘œ μ‹œμž‘ν•˜λ―€λ‘œ, λ””ν΄νŠΈ 값이 μ‚½μž…λ˜μ§€ μ•ŠλŠ” 것이닀.

λ”°λΌμ„œ λ‹€μŒκ³Ό 같이 μ§„ν–‰ν•˜λ©΄ λœλ‹€.

PostController.kt
@GetMapping("/posts")
fun requestParam(
    @RequestParam(defaultValue = "post", required = false) type: String?
): ResponseEntity<List<PostResponse>> {
    return ResponseEntity.ok()
        .body(postSearchService.search(type))
}

required = true

또 ν•˜λ‚˜ 짚고 λ„˜μ–΄κ°ˆ 뢀뢄이 μžˆλ‹€. required μ˜΅μ…˜μ— κ΄€ν•œ λ‚΄μš©μ΄λ‹€. required와 defaultValue 유무의 μ‘°ν•©μœΌλ‘œ 4κ°€μ§€κ°€ λ‚˜μ˜€λŠ”λ°, 각 μƒν™©μ—μ„œ 였λ₯˜λ₯Ό μΌλΆ€λŸ¬ λ°œμƒμ‹œμΌœλ³΄μž. (500이 λ‚˜μ˜€λ©΄ μ›μΉ˜ μ•ŠλŠ” 상황이 λ˜λŠ”κ±°λ‹€!)

1번 상황 - defaultValue μ—†μŒ, required=true, non-nullable

type의 λ””ν΄νŠΈ 값을 μ—†μ• κ³ , λ°˜λ“œμ‹œ 전달받도둝 ν•˜κ³  μ‹Άλ‹€. required=trueλ₯Ό λ„£κ³  non-nullable νƒ€μž…μœΌλ‘œ ν•˜λ©΄ 될까?

@RequestParam(required = true) type: String

μΌλΆ€λŸ¬ 였λ₯˜λ₯Ό λ°œμƒμ‹œν‚€κΈ° μœ„ν•΄ μ΄λ ‡κ²Œ λ””ν΄νŠΈκ°’μ„ μ•ˆλ„£κ³  μš”μ²­ν•΄λ³΄μž.

curl -i http://localhost:8080/posts

자, μ΄λ ‡κ²Œ μ „λ‹¬ν•˜λ©΄ 500이 μ•„λ‹Œ 400 Bad Requestκ°€ λ°˜ν™˜λœλ‹€.

βœ… λ°”λžŒμ§ν•˜λ‹€! λ‚˜λ¨Έμ§€ 상황도 κ³„μ†ν•΄μ„œ ν™•μΈν•΄λ³΄μž.

2번 상황 - defaultValue μ—†μŒ, required=false, nullable

@RequestParam(required = false) type: String?

type을 μ „λ‹¬ν•˜μ§€ μ•ŠμœΌλ©΄ null이 λ“€μ–΄κ°€κ³ , type을 μ „λ‹¬ν•˜λ©΄ ν•΄λ‹Ή κ°’μœΌλ‘œ μ΄ˆκΈ°ν™”λœλ‹€. λ‘˜ λ‹€ 였λ₯˜κ°€ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€.

βœ… λ°”λžŒμ§ν•˜λ‹€.

3번 상황 - defaultValue 있음, required=true, non-nullable

@RequestParam(defaultValue = "post", required = true) type: String

type을 μ „λ‹¬ν•˜μ§€ μ•ŠμœΌλ©΄ λ””ν΄νŠΈ κ°’ "post"κ°€ λ“€μ–΄κ°€κ³ , type을 μ „λ‹¬ν•˜λ©΄ ν•΄λ‹Ή κ°’μœΌλ‘œ μ΄ˆκΈ°ν™”λœλ‹€. λ‘˜ λ‹€ 였λ₯˜κ°€ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€.

βœ… λ°”λžŒμ§ν•˜λ‹€.

4번 상황 - defaultValue 있음, required=false, nullable

@RequestParam(defaultValue = "post", required = false) type: String?

3번 상황과 λ™μΌν•˜κ²Œ λ™μž‘ν•œλ‹€. λ‹€λ§Œ μ»¨νŠΈλ‘€λŸ¬μ—μ„œ ν•΄λ‹Ή 값을 μ‚¬μš©ν•  λ•Œ null이 λ“€μ–΄κ°€μ§€ μ•Šμ•˜μŒμ—λ„ λΆˆκ΅¬ν•˜κ³  null 체크λ₯Ό ν•΄μ€˜μ•Ό ν•œλ‹€.

🫀 λΆˆνŽΈν•˜λ‹€.

잘 λ˜λŠ” 예제λ₯Ό μ•Œμ•„λ΄€μœΌλ‹ˆ 이제 required와 nullable을 λ‹€λ₯΄κ²Œ 만 ν˜Όμ’… μΌ€μ΄μŠ€λ₯Ό μ•Œμ•„λ³΄μž. (κΆκΈˆν•˜λ‹ˆκΉŒ!)

5번 상황 - defaultValue μ—†μŒ, required=true, nullable

@RequestParam(required = true) type: String?

4번 상황과 λ™μΌν•˜κ²Œ λ™μž‘ν•˜λ©°, ν•΄λ‹Ή 값을 μ‚¬μš©ν•  λ•Œ null이 λ“€μ–΄κ°€μ§€ μ•Šμ•˜μŒμ—λ„ null 체크λ₯Ό ν•΄μ€˜μ•Ό ν•œλ‹€.

근데 λ¬Έμ œκ°€ μžˆλ‹€. required=true인데 type을 μ „λ‹¬ν•˜μ§€ μ•Šμ•„λ„ 였λ₯˜κ°€ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€.

ν•„μˆ˜κ°’μœΌλ‘œ λ§ˆν‚Ήν•˜κΈ° μœ„ν•΄ required=true둜 μ„€μ •ν•œ 것인데 ν•„μˆ˜κ°’ 체킹이 μ•ˆλœλ‹€λ‹ˆ...

❌ λ”μ°ν•˜λ‹€.

6번 상황 - defaultValue μ—†μŒ, required=false, non-nullable

@RequestParam(required = false) type: String

type을 μ „λ‹¬ν•˜λ©΄ 문제 없이 λ™μž‘ν•œλ‹€. 그런데 μ „λ‹¬ν•˜μ§€ μ•Šμ•˜λ‹€λ©΄ λ‹€μŒκ³Ό 같이 NullPointerException이 λ°œμƒν•œλ‹€.

java.lang.NullPointerException: Parameter specified as non-null is null: method com.litsynp.kotring.interfaces.PostController.requestParam, parameter type

그리고 500 Errorκ°€ λ°˜ν™˜λœλ‹€.

❌ μ‹€μˆ˜κ°€ μ•„λ‹ˆλΌλ©΄ 이럴 일 μ—†κ² μ§€λ§Œ λ‹Ήμ—°νžˆ 이러면 μ•ˆλœλ‹€.

7번 상황 - defaultValue 있음, required=true, nullable

@RequestParam(defaultValue = "post", required = true) type: String?

5번과 λ™μΌν•˜κ²Œ λ™μž‘ν•˜λ©° λ¬Έμ œλ„ κ°™λ‹€κ³  ν•  수 있. λ””ν΄νŠΈκ°’λ„ 있고 required=true인데 ꡳ이 nullable νƒ€μž…μ„ μ“Έ ν•„μš”κ°€ μžˆμ„κΉŒ?

🫀 λ°”λžŒμ§ν•˜μ§€ μ•Šλ‹€.

8번 상황 - defaultValue 있음, required=false, non-nullable

@RequestParam(defaultValue = "post", required = false) type: String

defaultValueκ°€ 있고, required=false이닀. type은 non-nullable이닀.

πŸ€” μ˜λ„ν•œ λŒ€λ‘œλŠ” λ™μž‘ν•œλ‹€...만 defaultValue만 λΉ λœ¨λ €λ„ 6λ²ˆμ΄λž‘ λ˜‘κ°™μ•„μ§„λ‹€. μ£Όμ˜ν•΄μ•Όκ² λ‹€.

κ²°λ‘ 

defaultValueκ°€ μžˆλŠ” κ²½μš°μ—” λ‹€μŒκ³Ό 같이 ν•˜μž.

  • required=true(λ˜λŠ” false - 였λ₯˜λŠ” μ•ˆλ‚˜μ§€λ§Œ 주의 ν•„)

  • non-nullable (e.g., String)

defaultValueκ°€ μ—†λŠ” κ²½μš°μ—” λ‹€μŒκ³Ό 같이 ν•˜μž.

  • required=false

  • nullable (e.g., String?)

@PathVariable

@PathVariable 에도 required μ˜΅μ…˜μœΌλ‘œ null checking을 μ§„ν–‰ν•  수 μžˆλ‹€.

Java

보톡 @PathVariable은 λ‹€μŒκ³Ό 같이 μ‚¬μš©ν•œλ‹€.

@GetMapping("/posts/{id}")
public ResponseEntity<PostResponse> pathVariable(
    @PathVariable String id) {

    return ResponseEntity.ok()
        .body(postService.findById(id));
}

사싀 μœ„μ˜ 예제λ₯Ό ν™œμš©ν•΄λ„ @PathVariable을 optionalν•˜κ²Œ μ‚¬μš©ν•˜κΈ΄ μ–΄λ ΅λ‹€. /posts둜 μš”μ²­ν•˜λ“ , /posts/둜 μš”μ²­ν•˜λ“ , ν•΄λ‹Ή URL둜 λ§€ν•‘λœ 컨트둀러λ₯Ό μ°Ύμ§€ λͺ»ν•΄ 404 Not Foundκ°€ λ°˜ν™˜λ  것이닀.

@PathVariable에 required μ˜΅μ…˜μ„ μ–΅μ§€λ‘œ λ„£μ–΄λ³΄μžλ©΄ λ‹€μŒκ³Ό κ°™λ‹€.

PostController.java
@GetMapping("/posts/{id}", "/posts/{id}/detail")
public ResponseEntity<*> optionalPathVariable(
    @PathVariable(required = false) String id) {

    if (id) {
        return ResponseEntity.ok()
            .body(postService.findById(id));
    }

    return ResponseEntity.ok()
        .body(postService.findAll());
}

@PathVariable의 경우 defaultValueλŠ” μ§€μ›ν•˜μ§€ μ•ŠλŠ”λ‹€.

Kotlin

Kotlinμ—μ„œλŠ” λ‹€μŒκ³Ό 같이 ν•  수 μžˆκ² λ‹€.

PostController.kt
@GetMapping("/posts/{id}", "/posts/{id}/detail")
fun optionalPathVariable(
    @PathVariable(required = false) id: String?
): ResponseEntity<*> {
    return id?.let {
        ResponseEntity.ok()
            .body(postService.findById(id));
    } ?: ResponseEntity.ok()
        .body(postService.findAll());
}

참고둜 required=true, non-nullable νƒ€μž…μœΌλ‘œ 바꿨을 λ•Œ λ‹Ήμ—°νžˆ idλ₯Ό μ „λ‹¬ν•˜μ§€ μ•ŠμœΌλ©΄ idλ₯Ό μ „λ‹¬ν•˜μ§€ μ•ŠλŠ” 경우의 μ½”λ“œλ₯Ό μ‹€ν–‰μ‹œν‚¬ 수 μ—†μœΌλ―€λ‘œ μ˜λ―Έκ°€ 없을 뿐 μ•„λ‹ˆλΌ 500 Errorλ₯Ό λ°˜ν™˜ν•œλ‹€.

이런 κ²½μš°μ—” κ·Έλƒ₯ λ”°λ‘œ 컨트둀러 λ©”μ†Œλ“œλ₯Ό ν•˜λ‚˜ λ§Œλ“€μž.

More on the matter

    • @RequestHeader에 λŒ€ν•΄μ„œλ„ μ†Œκ°œν•œλ‹€.

REF

    • ν•΄λ‹Ή λΈ”λ‘œκ·Έμ—μ„œ λͺ¨λ“  λ‚΄μš©μ„ μ°Έκ³ ν•œλ‹€.

PreviousHandling Null in Request DTONextReactive Stack

Last updated 9 months ago

Was this helpful?

μ˜€λŠ˜λ„ 끄적끄적 - (Kotlin) Requestμ—μ„œ Nullable? Non-Null?
Yoon Sung's Blog - RequestParam, PathVariable 에 λ””ν΄νŠΈκ°’ λ„£μ–΄μ£ΌκΈ°