REST API

hyena_leeΒ·2023λ…„ 1μ›” 31일
0

TIL

λͺ©λ‘ 보기
28/42
post-thumbnail

πŸŒ– REST API의 탄생

RESTλŠ” Representational State TransferλΌλŠ” μš©μ–΄μ˜ μ•½μžλ‘œμ„œ 2000년도에 둜이 ν•„λ”© (Roy Fielding)의 λ°•μ‚¬ν•™μœ„ λ…Όλ¬Έμ—μ„œ 졜초둜 μ†Œκ°œλ˜μ—ˆμŠ΅λ‹ˆλ‹€. 둜이 필딩은 HTTP의 μ£Όμš” μ €μž 쀑 ν•œ μ‚¬λžŒμœΌλ‘œ κ·Έ λ‹Ήμ‹œ μ›Ή(HTTP) μ„€κ³„μ˜ μš°μˆ˜μ„±μ— λΉ„ν•΄ μ œλŒ€λ‘œ μ‚¬μš©λ˜μ–΄μ§€μ§€ λͺ»ν•˜λŠ” λͺ¨μŠ΅μ— μ•ˆνƒ€κΉŒμ›Œν•˜λ©° μ›Ήμ˜ μž₯점을 μ΅œλŒ€ν•œ ν™œμš©ν•  수 μžˆλŠ” μ•„ν‚€ν…μ²˜λ‘œμ¨ RESTλ₯Ό λ°œν‘œν–ˆλ‹€κ³  ν•©λ‹ˆλ‹€.

🌎 REST ꡬ성

μ‰½κ²Œ 말해 REST APIλŠ” λ‹€μŒμ˜ κ΅¬μ„±μœΌλ‘œ μ΄λ£¨μ–΄μ ΈμžˆμŠ΅λ‹ˆλ‹€. μžμ„Έν•œ λ‚΄μš©μ€ λ°‘μ—μ„œ μ„€λͺ…ν•˜λ„λ‘ ν•˜κ² μŠ΅λ‹ˆλ‹€.

  • μžμ›(RESOURCE) - URI
  • ν–‰μœ„(Verb) - HTTP METHOD
  • ν‘œν˜„(Representations)

🌞 REST 의 νŠΉμ§•

1) Uniform (μœ λ‹ˆνΌ μΈν„°νŽ˜μ΄μŠ€)
Uniform InterfaceλŠ” URI둜 μ§€μ •ν•œ λ¦¬μ†ŒμŠ€μ— λŒ€ν•œ μ‘°μž‘μ„ ν†΅μΌλ˜κ³  ν•œμ •μ μΈ μΈν„°νŽ˜μ΄μŠ€λ‘œ μˆ˜ν–‰ν•˜λŠ” μ•„ν‚€ν…μ²˜ μŠ€νƒ€μΌμ„ λ§ν•©λ‹ˆλ‹€.

2) Stateless (λ¬΄μƒνƒœμ„±)
RESTλŠ” λ¬΄μƒνƒœμ„± 성격을 κ°–μŠ΅λ‹ˆλ‹€. λ‹€μ‹œ 말해 μž‘μ—…μ„ μœ„ν•œ μƒνƒœμ •λ³΄λ₯Ό λ”°λ‘œ μ €μž₯ν•˜κ³  κ΄€λ¦¬ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. μ„Έμ…˜ μ •λ³΄λ‚˜ 쿠킀정보λ₯Ό λ³„λ„λ‘œ μ €μž₯ν•˜κ³  κ΄€λ¦¬ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— API μ„œλ²„λŠ” λ“€μ–΄μ˜€λŠ” μš”μ²­λ§Œμ„ λ‹¨μˆœνžˆ μ²˜λ¦¬ν•˜λ©΄ λ©λ‹ˆλ‹€. λ•Œλ¬Έμ— μ„œλΉ„μŠ€μ˜ μžμœ λ„κ°€ 높아지고 μ„œλ²„μ—μ„œ λΆˆν•„μš”ν•œ 정보λ₯Ό κ΄€λ¦¬ν•˜μ§€ μ•ŠμŒμœΌλ‘œμ¨ κ΅¬ν˜„μ΄ λ‹¨μˆœν•΄μ§‘λ‹ˆλ‹€.

3) Cacheable (μΊμ‹œ κ°€λŠ₯)
REST의 κ°€μž₯ 큰 νŠΉμ§• 쀑 ν•˜λ‚˜λŠ” HTTPλΌλŠ” κΈ°μ‘΄ μ›Ήν‘œμ€€μ„ κ·ΈλŒ€λ‘œ μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έμ—, μ›Ήμ—μ„œ μ‚¬μš©ν•˜λŠ” κΈ°μ‘΄ 인프라λ₯Ό κ·ΈλŒ€λ‘œ ν™œμš©μ΄ κ°€λŠ₯ν•©λ‹ˆλ‹€. λ”°λΌμ„œ HTTPκ°€ 가진 캐싱 κΈ°λŠ₯이 적용 κ°€λŠ₯ν•©λ‹ˆλ‹€. HTTP ν”„λ‘œν† μ½œ ν‘œμ€€μ—μ„œ μ‚¬μš©ν•˜λŠ” Last-Modifiedνƒœκ·Έλ‚˜ E-Tagλ₯Ό μ΄μš©ν•˜λ©΄ 캐싱 κ΅¬ν˜„μ΄ κ°€λŠ₯ν•©λ‹ˆλ‹€.

4) Self-descriptiveness (자체 ν‘œν˜„ ꡬ쑰)
REST의 또 λ‹€λ₯Έ 큰 νŠΉμ§• 쀑 ν•˜λ‚˜λŠ” REST API λ©”μ‹œμ§€λ§Œ 보고도 이λ₯Ό μ‰½κ²Œ 이해 ν•  수 μžˆλŠ” 자체 ν‘œν˜„ ꡬ쑰둜 λ˜μ–΄ μžˆλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€.

5) Client - Server ꡬ쑰
REST μ„œλ²„λŠ” API 제곡, ν΄λΌμ΄μ–ΈνŠΈλŠ” μ‚¬μš©μž μΈμ¦μ΄λ‚˜ μ»¨ν…μŠ€νŠΈ(μ„Έμ…˜, 둜그인 정보)등을 직접 κ΄€λ¦¬ν•˜λŠ” ꡬ쑰둜 각각의 역할이 ν™•μ‹€νžˆ κ΅¬λΆ„λ˜κΈ° λ•Œλ¬Έμ— ν΄λΌμ΄μ–ΈνŠΈμ™€ μ„œλ²„μ—μ„œ κ°œλ°œν•΄μ•Ό ν•  λ‚΄μš©μ΄ λͺ…확해지고 μ„œλ‘œκ°„ μ˜μ‘΄μ„±μ΄ μ€„μ–΄λ“€κ²Œ λ©λ‹ˆλ‹€.

6) κ³„μΈ΅ν˜• ꡬ쑰
REST μ„œλ²„λŠ” 닀쀑 κ³„μΈ΅μœΌλ‘œ ꡬ성될 수 있으며 λ³΄μ•ˆ, λ‘œλ“œ λ°ΈλŸ°μ‹±, μ•”ν˜Έν™” 계측을 μΆ”κ°€ν•΄ κ΅¬μ‘°μƒμ˜ μœ μ—°μ„±μ„ λ‘˜ 수 있고 PROXY, κ²Œμ΄νŠΈμ›¨μ΄ 같은 λ„€νŠΈμ›Œν¬ 기반의 쀑간맀체λ₯Ό μ‚¬μš©ν•  수 있게 ν•©λ‹ˆλ‹€.

🎨 REST APIλ₯Ό λ””μžμΈν•˜λŠ” 방법

REST APIλ₯Ό μž‘μ„±ν•  λ•ŒλŠ” λͺ‡ 가지 μ§€μΌœμ•Ό ν•  κ·œμΉ™λ“€μ΄ μžˆμŠ΅λ‹ˆλ‹€. 둜이 필딩이 λ…Όλ¬Έμ—μ„œ μ œμ‹œν•œ REST 방법둠을 보닀 더 μ‹€μš©μ μœΌλ‘œ μ μš©ν•˜κΈ° μœ„ν•΄ λ ˆμ˜€λ‚˜λ₯΄λ“œ λ¦¬μ°¨λ“œμŠ¨(Leonard Richardson)은 REST APIλ₯Ό 잘 μ μš©ν•˜κΈ° μœ„ν•œ 4단계 λͺ¨λΈμ„ λ§Œλ“€μ—ˆμŠ΅λ‹ˆλ‹€.

REST μ„±μˆ™λ„ λͺ¨λΈμ€ 총 4단계(0~3단계)둜 λ‚˜λˆ„μ–΄μ§‘λ‹ˆλ‹€.

μ•žμ„œ μ΄μ•ΌκΈ°ν•œ 둜이 필딩은 이 λͺ¨λΈμ˜ λͺ¨λ“  단계λ₯Ό μΆ©μ‘±ν•΄μ•Ό REST API라고 λΆ€λ₯Ό 수 μžˆλ‹€κ³  μ£Όμž₯ν–ˆμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ μ‹€μ œλ‘œ μ—„λ°€ν•˜κ²Œ 3λ‹¨κ³„κΉŒμ§€ 지킀기 μ–΄λ ΅κΈ° λ•Œλ¬Έμ— 2λ‹¨κ³„κΉŒμ§€λ§Œ μ μš©ν•΄λ„ 쒋은 API λ””μžμΈμ΄λΌκ³  λ³Ό 수 있고, 이런 경우λ₯Ό HTTP API 라고도 λΆ€λ¦…λ‹ˆλ‹€.

REST μ„±μˆ™λ„ λͺ¨λΈ - 0단계
REST μ„±μˆ™λ„ λͺ¨λΈμ— λ”°λ₯΄λ©΄, 0λ‹¨κ³„μ—μ„œλŠ” λ‹¨μˆœνžˆ HTTP ν”„λ‘œν† μ½œμ„ μ‚¬μš©ν•˜κΈ°λ§Œ 해도 λ©λ‹ˆλ‹€. λ¬Όλ‘  이 경우, ν•΄λ‹Ή APIλ₯Ό REST API라고 ν•  μˆ˜λŠ” μ—†μœΌλ©°, 0λ‹¨κ³„λŠ” REST APIλ₯Ό μž‘μ„±ν•˜κΈ° μœ„ν•œ κΈ°λ³Έ λ‹¨κ³„μž…λ‹ˆλ‹€.

ν—ˆμ€€μ΄λΌλŠ” μ΄λ¦„μ˜ 주치의의 μ˜ˆμ•½ κ°€λŠ₯ν•œ μ‹œκ°„μ„ ν™•μΈν•˜κ³ , μ–΄λ–€ νŠΉμ • μ‹œκ°„μ— μ˜ˆμ•½ν•˜λŠ” 상황을 예둜 λ“€μ–΄ λ³΄κ² μŠ΅λ‹ˆλ‹€.

**κ²°λ‘ , REST API 섀계 μ‹œ κ°€μž₯ μ€‘μš”ν•œ ν•­λͺ©μ€ λ‹€μŒμ˜ 2κ°€μ§€λ‘œ μš”μ•½ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

첫 번째, URIλŠ” μ •λ³΄μ˜ μžμ›μ„ ν‘œν˜„ν•΄μ•Ό ν•œλ‹€.
두 번째, μžμ›μ— λŒ€ν•œ ν–‰μœ„λŠ” HTTP Method(GET, POST, PUT, DELETE)둜 ν‘œν˜„ν•œλ‹€.

✏️ REST API 쀑심 κ·œμΉ™

1) URIλŠ” μ •λ³΄μ˜ μžμ›μ„ ν‘œν˜„ν•΄μ•Ό ν•œλ‹€. (λ¦¬μ†ŒμŠ€λͺ…은 λ™μ‚¬λ³΄λ‹€λŠ” λͺ…사λ₯Ό μ‚¬μš©)

>GET /members/delete/1

μœ„μ™€ 같은 방식은 RESTλ₯Ό μ œλŒ€λ‘œ μ μš©ν•˜μ§€ μ•Šμ€ URIμž…λ‹ˆλ‹€. URIλŠ” μžμ›μ„ ν‘œν˜„ν•˜λŠ”λ° 쀑점을 두어야 ν•©λ‹ˆλ‹€. delete와 같은 ν–‰μœ„μ— λŒ€ν•œ ν‘œν˜„μ΄ λ“€μ–΄κ°€μ„œλŠ” μ•ˆλ©λ‹ˆλ‹€.

2) μžμ›μ— λŒ€ν•œ ν–‰μœ„λŠ” HTTP Method(GET, POST, PUT, DELETE λ“±)둜 ν‘œν˜„
μœ„μ˜ 잘λͺ» 된 URIλ₯Ό HTTP Methodλ₯Ό 톡해 μˆ˜μ •ν•΄ 보면

DELETE /members/1

으둜 μˆ˜μ •ν•  수 μžˆκ² μŠ΅λ‹ˆλ‹€.
νšŒμ›μ •λ³΄λ₯Ό κ°€μ Έμ˜¬ λ•ŒλŠ” GET, νšŒμ› μΆ”κ°€ μ‹œμ˜ ν–‰μœ„λ₯Ό ν‘œν˜„ν•˜κ³ μž ν•  λ•ŒλŠ” POST METHODλ₯Ό μ‚¬μš©ν•˜μ—¬ ν‘œν˜„ν•©λ‹ˆλ‹€.

νšŒμ›μ •λ³΄λ₯Ό κ°€μ Έμ˜€λŠ” URI

GET /members/show/1 (x)
GET /members/1 (o)

νšŒμ›μ„ μΆ”κ°€ν•  λ•Œ

>GET /members/insert/2 (x)  - GET λ©”μ„œλ“œλŠ” λ¦¬μ†ŒμŠ€ 생성에 λ§žμ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
POST /members/2       (o)

[μ°Έκ³ ]HTTP METHOD의 μ•Œλ§žμ€ μ—­ν• 
POST, GET, PUT, DELETE 이 4κ°€μ§€μ˜ Methodλ₯Ό 가지고 CRUDλ₯Ό ν•  수 μžˆμŠ΅λ‹ˆλ‹€.


πŸ”΄URI 섀계 μ‹œ μ£Όμ˜ν•  점

1) μŠ¬λž˜μ‹œ κ΅¬λΆ„μž(/)λŠ” 계측 관계λ₯Ό λ‚˜νƒ€λ‚΄λŠ” 데 μ‚¬μš©
http://restapi.example.com/houses/apartments
http://restapi.example.com/animals/mammals/whales
2) URI λ§ˆμ§€λ§‰ 문자둜 μŠ¬λž˜μ‹œ(/)λ₯Ό ν¬ν•¨ν•˜μ§€ μ•ŠλŠ”λ‹€.
URI에 ν¬ν•¨λ˜λŠ” λͺ¨λ“  κΈ€μžλŠ” λ¦¬μ†ŒμŠ€μ˜ μœ μΌν•œ μ‹λ³„μžλ‘œ μ‚¬μš©λ˜μ–΄μ•Ό ν•˜λ©° URIκ°€ λ‹€λ₯΄λ‹€λŠ” 것은 λ¦¬μ†ŒμŠ€κ°€ λ‹€λ₯΄λ‹€λŠ” 것이고, μ—­μœΌλ‘œ λ¦¬μ†ŒμŠ€κ°€ λ‹€λ₯΄λ©΄ URI도 달라져야 ν•©λ‹ˆλ‹€. REST APIλŠ” λΆ„λͺ…ν•œ URIλ₯Ό λ§Œλ“€μ–΄ 톡신을 ν•΄μ•Ό ν•˜κΈ° λ•Œλ¬Έμ— ν˜Όλ™μ„ 주지 μ•Šλ„λ‘ URI 경둜의 λ§ˆμ§€λ§‰μ—λŠ” μŠ¬λž˜μ‹œ(/)λ₯Ό μ‚¬μš©ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

http://restapi.example.com/houses/apartments/ (X)
http://restapi.example.com/houses/apartments  (0)

3) ν•˜μ΄ν”ˆ(-)은 URI 가독성을 λ†’μ΄λŠ”λ° μ‚¬μš©
URIλ₯Ό μ‰½κ²Œ 읽고 ν•΄μ„ν•˜κΈ° μœ„ν•΄, λΆˆκ°€ν”Όν•˜κ²Œ κΈ΄ URI경둜λ₯Ό μ‚¬μš©ν•˜κ²Œ λœλ‹€λ©΄ ν•˜μ΄ν”ˆμ„ μ‚¬μš©ν•΄ 가독성을 높일 수 μžˆμŠ΅λ‹ˆλ‹€.

4) 밑쀄(_)은 URI에 μ‚¬μš©ν•˜μ§€ μ•ŠλŠ”λ‹€.
글꼴에 따라 λ‹€λ₯΄κΈ΄ ν•˜μ§€λ§Œ 밑쀄은 보기 μ–΄λ ΅κ±°λ‚˜ 밑쀄 λ•Œλ¬Έμ— λ¬Έμžκ°€ 가렀지기도 ν•©λ‹ˆλ‹€. 이런 문제λ₯Ό ν”Όν•˜κΈ° μœ„ν•΄ 밑쀄 λŒ€μ‹  ν•˜μ΄ν”ˆ(-)을 μ‚¬μš©ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€.(가독성)

5) URI κ²½λ‘œμ—λŠ” μ†Œλ¬Έμžκ°€ μ ν•©ν•˜λ‹€.
URI κ²½λ‘œμ— λŒ€λ¬Έμž μ‚¬μš©μ€ ν”Όν•˜λ„λ‘ ν•΄μ•Ό ν•©λ‹ˆλ‹€. λŒ€μ†Œλ¬Έμžμ— 따라 λ‹€λ₯Έ λ¦¬μ†ŒμŠ€λ‘œ μΈμ‹ν•˜κ²Œ 되기 λ•Œλ¬Έμž…λ‹ˆλ‹€. RFC 3986(URI 문법 ν˜•μ‹)은 URI μŠ€ν‚€λ§ˆμ™€ 호슀트λ₯Ό μ œμ™Έν•˜κ³ λŠ” λŒ€μ†Œλ¬Έμžλ₯Ό κ΅¬λ³„ν•˜λ„λ‘ κ·œμ •ν•˜κΈ° λ•Œλ¬Έμ΄μ§€μš”.

RFC 3986 is the URI (Unified Resource Identifier) Syntax document

6) 파일 ν™•μž₯μžλŠ” URI에 ν¬ν•¨μ‹œν‚€μ§€ μ•ŠλŠ”λ‹€.
http://restapi.example.com/members/soccer/345/photo.jpg (X)
REST APIμ—μ„œλŠ” λ©”μ‹œμ§€ λ°”λ”” λ‚΄μš©μ˜ 포맷을 λ‚˜νƒ€λ‚΄κΈ° μœ„ν•œ 파일 ν™•μž₯자λ₯Ό URI μ•ˆμ— ν¬ν•¨μ‹œν‚€μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. Accept headerλ₯Ό μ‚¬μš©ν•˜λ„λ‘ ν•©μ‹œλ‹€.

GET / members/soccer/345/photo HTTP/1.1 Host: restapi.example.com Accept: image/jpg

###🟒 λ¦¬μ†ŒμŠ€ κ°„μ˜ 관계λ₯Ό ν‘œν˜„ν•˜λŠ” 방법

REST λ¦¬μ†ŒμŠ€ κ°„μ—λŠ” μ—°κ΄€ 관계가 μžˆμ„ 수 있고, 이런 경우 λ‹€μŒκ³Ό 같은 ν‘œν˜„λ°©λ²•μœΌλ‘œ μ‚¬μš©ν•©λ‹ˆλ‹€.

/λ¦¬μ†ŒμŠ€λͺ…/λ¦¬μ†ŒμŠ€ ID/관계가 μžˆλŠ” λ‹€λ₯Έ λ¦¬μ†ŒμŠ€λͺ…

ex)    GET : /users/{userid}/devices (일반적으둜 μ†Œμœ  β€˜hasβ€™μ˜ 관계λ₯Ό ν‘œν˜„ν•  λ•Œ)

λ§Œμ•½μ— 관계λͺ…이 λ³΅μž‘ν•˜λ‹€λ©΄ 이λ₯Ό μ„œλΈŒ λ¦¬μ†ŒμŠ€μ— λͺ…μ‹œμ μœΌλ‘œ ν‘œν˜„ν•˜λŠ” 방법이 μžˆμŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ μ‚¬μš©μžκ°€ β€˜μ’‹μ•„ν•˜λŠ”β€™ λ””λ°”μ΄μŠ€ λͺ©λ‘μ„ ν‘œν˜„ν•΄μ•Ό ν•  경우 λ‹€μŒκ³Ό 같은 ν˜•νƒœλ‘œ μ‚¬μš©λ  수 μžˆμŠ΅λ‹ˆλ‹€.

GET : /users/{userid}/likes/devices (관계λͺ…이 μ• λ§€ν•˜κ±°λ‚˜ ꡬ체적 ν‘œν˜„μ΄ ν•„μš”ν•  λ•Œ)

4-4. μžμ›μ„ ν‘œν˜„ν•˜λŠ” Colllectionκ³Ό Document
Collectionκ³Ό Document에 λŒ€ν•΄ μ•Œλ©΄ URI 섀계가 ν•œ μΈ΅ 더 μ‰¬μ›Œμ§‘λ‹ˆλ‹€. DOCUMENTλŠ” λ‹¨μˆœνžˆ λ¬Έμ„œλ‘œ 이해해도 되고, ν•œ 객체라고 μ΄ν•΄ν•˜μ…”λ„ 될 것 κ°™μŠ΅λ‹ˆλ‹€. μ»¬λ ‰μ…˜μ€ λ¬Έμ„œλ“€μ˜ 집합, κ°μ²΄λ“€μ˜ 집합이라고 μƒκ°ν•˜μ‹œλ©΄ μ΄ν•΄ν•˜μ‹œλŠ”λ° 쒀더 νŽΈν•˜μ‹€ 것 κ°™μŠ΅λ‹ˆλ‹€. μ»¬λ ‰μ…˜κ³Ό λ„νλ¨ΌνŠΈλŠ” λͺ¨λ‘ λ¦¬μ†ŒμŠ€λΌκ³  ν‘œν˜„ν•  수 있으며 URI에 ν‘œν˜„λ©λ‹ˆλ‹€. 예λ₯Ό μ‚΄νŽ΄λ³΄λ„λ‘ ν•˜κ² μŠ΅λ‹ˆλ‹€.

http:// restapi.example.com/sports/soccer

μœ„ URIλ₯Ό λ³΄μ‹œλ©΄ sportsλΌλŠ” μ»¬λ ‰μ…˜κ³Ό soccerλΌλŠ” λ„νλ¨ΌνŠΈλ‘œ ν‘œν˜„λ˜κ³  μžˆλ‹€κ³  μƒκ°ν•˜λ©΄ λ©λ‹ˆλ‹€. μ’€ 더 예λ₯Ό λ“€μ–΄λ³΄μžλ©΄

http:// restapi.example.com/sports/soccer/players/13

sports, players μ»¬λ ‰μ…˜κ³Ό soccer, 13(13번인 μ„ μˆ˜)λ₯Ό μ˜λ―Έν•˜λŠ” λ„νλ¨ΌνŠΈλ‘œ URIκ°€ μ΄λ£¨μ–΄μ§€κ²Œ λ©λ‹ˆλ‹€. μ—¬κΈ°μ„œ μ€‘μš”ν•œ 점은 μ»¬λ ‰μ…˜μ€ 볡수둜 μ‚¬μš©ν•˜κ³  μžˆλ‹€λŠ” μ μž…λ‹ˆλ‹€. μ’€ 더 직관적인 REST APIλ₯Ό μœ„ν•΄μ„œλŠ” μ»¬λ ‰μ…˜κ³Ό λ„νλ¨ΌνŠΈλ₯Ό μ‚¬μš©ν•  λ•Œ λ‹¨μˆ˜ λ³΅μˆ˜λ„ μ§€μΌœμ€€λ‹€λ©΄ μ’€ 더 μ΄ν•΄ν•˜κΈ° μ‰¬μš΄ URIλ₯Ό 섀계할 수 μžˆμŠ΅λ‹ˆλ‹€.

profile
μ‹€μˆ˜λ₯Ό λ‘λ €μ›Œ 말고 계속 도전 ν•˜λŠ” 개발자의 μ—¬μ •!

0개의 λŒ“κΈ€