본문 바로가기

개발 회고

[솔데스크] 풀스택 과정 14주-2 총59회차 ‘회고’ | JSON(0305)

[서론]

○● 0305 새로웠던 것


1. xml과 json의 차이점

XML(Extensible Markup Language)과 JSON(JavaScript Object Notation)은 모두 데이터를 표현하는 데 사용되는 형식이지만, 다음과 같은 차이점이 있습니다:

  1. 구문(Syntax):
    • XML은 태그를 사용하여 데이터를 표현합니다. 태그는 시작 태그(<tag>)와 종료 태그(</tag>)로 이루어져 있으며, 태그 사이에 데이터가 위치합니다.
    • JSON은 중괄호({})와 대괄호([])를 사용하여 데이터를 표현합니다. 중괄호는 객체를 나타내고, 대괄호는 배열을 나타냅니다. 객체는 "key": "value" 쌍으로 이루어져 있습니다.
  2. 가독성(Readability):
    • JSON은 구조가 간단하고 직관적이기 때문에 일반적으로 XML보다 더 가독성이 높습니다.
    • XML은 여는 태그와 닫는 태그가 있기 때문에 데이터를 이해하기 위해 더 많은 시각적 잡음이 발생할 수 있습니다.
  3. 크기(Size):
    • JSON은 XML에 비해 데이터를 더 적은 문자로 표현할 수 있습니다. 이는 JSON이 더 간결하고 경량이기 때문입니다.
    • XML은 더 많은 태그와 구문을 사용하기 때문에 더 많은 용량을 차지할 수 있습니다.
  4. 확장성(Extensibility):
    • XML은 이름 공간(namespace)을 지원하여 데이터의 확장성을 높일 수 있습니다. 이를 통해 다양한 종류의 데이터를 구조화하고 표현할 수 있습니다.
    • JSON은 XML에 비해 확장성이 제한적이지만, 더 간단하고 직관적인 구조로 인해 작은 규모의 데이터나 웹 애플리케이션에 적합합니다.
  5. 데이터 타입(Data Types):
    • JSON은 기본적으로 문자열, 숫자, 불리언, 배열, 객체, null을 지원합니다.
    • XML은 데이터를 표현하는 데 필요한 태그를 사용하므로 JSON에 비해 데이터 타입이 더 유연하고 다양할 수 있습니다.
  6. 웹 애플리케이션에서의 사용:
    • JSON은 JavaScript의 일부이기 때문에 JavaScript에서 쉽게 처리할 수 있습니다. 따라서 웹 애플리케이션에서는 JSON이 더 널리 사용됩니다.
    • XML은 HTML과 같은 마크업 언어이기 때문에 웹 문서를 작성하는 데 주로 사용되지만, 최근에는 JSON의 인기로 인해 데이터 교환 형식으로서의 사용이 줄어들고 있습니다.

요약하면, JSON은 더 간결하고 가벼우며 직관적인 데이터 형식으로서 많은 웹 애플리케이션에서 선호되지만, XML은 확장성과 다양성 측면에서 더 유연한 데이터 표현 방식입니다.

 

2. xml파일인 api를 썼는데 로그가 json이랑 비슷하게 나와서 에러가 안떴음.

다만 한글로 된 부분이 깨져서 그부분은 디코딩하니까 보임

 // UTF-8로 디코딩하여 문자열을 제대로 표시
	    String decodedResult = new String(result.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);

 

3. api쪽에서 파일이 잘못 되서도 안 불러와 질 수 있다는 걸 알게 됐음.

 

 

[본론]

 

○● 0305 내용 정리

 

● JSON

 

○○○●●● 랜덤 고양이 사진 api

 

function showCat() {
$.ajax({
     type: "GET",    →   GET방식
     url: "https://api.thecatapi.com/v1/images/search",    →   API 주소 입력
     data: {},    →   GET방식에선 {} 비워두기
     success: function (response) {    →   response는 API 주소에서 나온 값(JSON 방식)
          let imgUrl = response[0]['url'];    →   response의 첫번째 값의 url값을 imgUrl이라고 하자
          $("#img-cat").attr("src", imgUrl); } }) }    →   img-cat이라는 id를 가진 요소에 "src" 속성을 추가하고 값은 imgUrl로 한다
(기존의 src="주소"의 값이 대체된다)

 

++ get과 post 방식의 차이점

 

HTTP 프로토콜에서 GET과 POST는 서버로 데이터를 전송하는 두 가지 주요 방법입니다. 이 두 방식은 목적과 사용하는 상황에 따라 다르며, 다음은 각 방식의 주요 차이점입니다:

  1. 데이터 전송 방식:
    • GET: 데이터를 URL의 쿼리 문자열에 포함하여 전송합니다. 이는 주로 검색 쿼리와 같은 간단한 데이터 전송에 사용됩니다.
    • POST: 데이터를 HTTP 요청의 본문(body)에 포함하여 전송합니다. 이 방식은 주로 민감한 정보(비밀번호, 신용 카드 정보 등)나 대량의 데이터를 전송할 때 사용됩니다.
  2. 데이터 길이 제한:
    • GET: URL의 길이에 제한이 있으므로 전송할 수 있는 데이터의 양에 제한이 있습니다. 대개 약 2048자(브라우저마다 상이)로 제한됩니다.
    • POST: HTTP 요청 본문에 데이터를 포함하므로 데이터의 길이에 대한 제한이 없습니다. 따라서 더 많은 양의 데이터를 전송할 수 있습니다.
  3. 보안:
    • GET: 데이터가 URL에 노출되므로 보안에 취약합니다. 예를 들어, 사용자 이름과 비밀번호를 URL에 포함하는 것은 보안 상의 위험을 초래할 수 있습니다.
    • POST: 데이터가 HTTP 요청의 본문에 포함되므로 URL에 노출되지 않습니다. 따라서 보안적으로 더 안전합니다.
  4. 캐싱:
    • GET: 동일한 URL에 대한 GET 요청은 캐시될 수 있으므로 동일한 요청에 대해 서버에 다시 요청하지 않고 캐시된 응답을 사용할 수 있습니다.
    • POST: POST 요청은 보안 및 무결성 문제로 인해 캐시되지 않으므로 항상 서버로 전송됩니다.
  5. Idempotent:
    • GET: 동일한 요청을 여러 번 보내더라도 동일한 결과를 반환해야 합니다. 즉, 여러 번 요청해도 서버 상태가 변경되지 않아야 합니다.
    • POST: 요청을 여러 번 보내더라도 서버의 상태가 변경될 수 있습니다. POST 요청은 일반적으로 서버의 상태를 변경하기 위해 사용됩니다.

이러한 차이점들을 고려하여 데이터를 전송하는 방식을 선택할 수 있습니다. 일반적으로는 데이터의 양이 적고 보안적인 이슈가 없는 경우에는 GET을 사용하고, 보안적인 이슈가 있거나 대량의 데이터를 전송해야 할 때는 POST를 사용하는 것이 좋습니다.

 

 

○○○●●● 국립중앙의료원_전국 약국 정보 조회 서비스 api 

 

사용하려고 했으나......데이터 중에서 데이터 타입이 맞지 않아서 500 error가 떴는데  수정할 수가 없어서 

다른 api 활용할 예정       


api에서 제공하는 데이터 타입은 xml

                   {
                        "dutyAddr": "서울특별시 강남구 선릉로86길 17  (대치동)",
                        "dutyName": "테헤란건강약국",
                        "dutyTel1": "02-556-4166",
                        "dutyTime1c": 2200,
                        "dutyTime1s": "0900",
                        "dutyTime2c": 2200,
                        "dutyTime2s": "0900",
                        "dutyTime3c": 2200,
                        "dutyTime3s": "0900",
                        "dutyTime4c": 2200,
                        "dutyTime4s": "0900",
                        "dutyTime5c": 2200,
                        "dutyTime5s": "0900",
                        "dutyTime6c": 2000,
                        "dutyTime6s": "0900",
                        "dutyTime7c": 1930,
                        "dutyTime7s": 1530,
                        "dutyTime8c": 1930,
                      "dutyTime

": 1530,
                        "hpid": "C1100829",
                        "postCdn1": "061",
                        "postCdn2": "92 ",
                        "rnum": 6,
                        "wgs84Lat": 37.5035670052591,
                        "wgs84Lon": 127.051066236605
                    },{
                        "dutyAddr": "서울특별시 강남구 역삼로 310  (역삼동)",
                        "dutyEtc": "공휴일은 운영여부 개인사정으로 변동될 수 있어 전화확인 후 방문부탁드립니다.",
                        "dutyMapimg": "선릉역3번출구e마트2층",
                        "dutyName": "한솔인유로온누리약국",
                        "dutyTel1": "02-3453-8171",
                        "dutyTime1c": 2000,
                        "dutyTime1s": "0900",
                        "dutyTime2c": 2000,
                        "dutyTime2s": "0900",
                        "dutyTime3c": 2000,
                        "dutyTime3s": "0900",
                        "dutyTime4c": 2000,
                        "dutyTime4s": "0900",
                        "dutyTime5c": 2000,
                        "dutyTime5s": "0900",
                        "dutyTime6c": 1630,
                        "dutyTime6s": "0900",
                        "dutyTime7c": 1300,
                        "dutyTime7s": 1000,
                        "dutyTime8c": 1300,
                        "dutyTime8s": 1000,
                        "hpid": "C1100257",
                        "postCdn1": "062",
                        "postCdn2": "17 ",
                        "rnum": 26,
                        "wgs84Lat": 37.49923572317221,
                        "wgs84Lon": 127.0484199572856
                    },

 

 

 

 

GuestController.java

package com.peisia.spring;

import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;

import javax.servlet.http.HttpSession;

import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.client.RestTemplate;

import com.peisia.dto.GuestDto;
import com.peisia.service.GuestService;
import com.peisia.spring.atmosphere.AtmosphereDto;
import com.peisia.spring.mi.vo.kw.KWeatherDto;
import com.peisia.spring.pharmacy.PharmacyDto;

import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j;

@Log4j
@RequestMapping("/guest/*")
@AllArgsConstructor
@Controller
@SessionAttributes("x")			// 1. 이 어노테이션을 붙이고					
public class GuestController {
		
	private GuestService service;
	private final ResourceLoader resourceLoader; 
	
	@GetMapping("/getList")								
	public void getList(@RequestParam(value="currentPage", defaultValue="1") int currentPage, Model model) {							
		 ArrayList<GuestDto> list = service.getList(model, currentPage);
		    int totalPage = service.getTotalPage(); // 총 페이지 수 가져오기
		    model.addAttribute("list", list);
		    model.addAttribute("totalPage", totalPage);
	}								
	
	@GetMapping({"/read", "/modify"})
	public void read(@RequestParam("bno") Long bno, Model model) {
		log.info("컨트롤러 ==== 글번호 ==============="+bno);
		model.addAttribute("read",service.read(bno));
	}
	
	@GetMapping("/del")
	public String del(@RequestParam("bno") Long bno) {
		log.info("컨트롤러 ==== 글번호 ==============="+bno);
		service.del(bno);
		return "redirect:/guest/getList?currentPage=1";	// 책 p.245 참고
	}
	
	@PostMapping("/write")
	public String write(GuestDto gvo) {
		service.write(gvo);
		return "redirect:/guest/getList?currentPage=1";	// 책 p.245 참고
	}
	
	@GetMapping("/write")	// 책 p.239 /write 중복이지만 이건 글쓰기 화면을 위한 url 매핑
	public void write() {
		
	}
	
	@PostMapping("/modify")
	public String modify(GuestDto gvo) {
		service.modify(gvo);
		return "redirect:/guest/getList?currentPage=1";
	}
	
	@GetMapping("/aaa")	
	public void sessionExample(HttpSession session) {	
		session.setAttribute("cat","고양이");
	}	
	
	// 스프링 세션 사용하기
	@GetMapping("/a")							
	public void a(HttpSession s, Model m) {							
		s.setAttribute("a", "개");						
		// 2. 모델에 x 키로 고양이 저장. ( 세션에도 x 키로 고양이가 저장됨 )						
		m.addAttribute("x","고양이");						
	}		
	
	
	@RequestMapping("/weatherList")			
	public void w(Model m) {			
		//// 우리나라 공공 api ////		
		//인코딩 인증키		
		String API_KEY = "QFOfiZ8YJEQdpbWKTs92CQy3%2BGIv8uusBFVx9FEd4A%2Fn9cxgi3F2E4lnC%2F%2FbUWtk01Gb5OYaHyxVqKfVARKBmQ%3D%3D";	
		//페이지 개수 많은 목록
		String API_URL = "http://apis.data.go.kr/1360000/AsosDalyInfoService/getWthrDataList?numOfRows=10&pageNo=1&dateCd=DAY&startDt=20240303&endDt=20240303&stnIds=108&dataCd=ASOS&dataType=JSON&serviceKey=" + API_KEY;
		

				// * 주의 * https 아님 http 임. https 는 인증관련 복잡한 처리를 해야함.
		RestTemplate restTemplate = new RestTemplate();		
				
		//// **** 중요 **** uri		
		URI uri = null; //java.net.URI 임포트 하셈		
		try {		
			uri = new URI(API_URL);	
		} catch (URISyntaxException e) {		
			e.printStackTrace();	
		}		
				
//		String s = restTemplate.getForObject(uri, String.class); //		
//		log.info("====== 우리나라 날씨 잘 나오나? "+s);		
		
		KWeatherDto kw = restTemplate.getForObject(uri, KWeatherDto.class); // 자기 클래스로 바꾸시오..
		log.info("==== json ==== : 우리나라 날씨 잘 나오냐? : "+kw.response.body.dataType);
		String location = kw.response.body.items.item.get(0).stnNm;
		String tMin = kw.response.body.items.item.get(0).minTa;
		String tMax = kw.response.body.items.item.get(0).maxTa;
		String ddara = String.format("==== json ==== : 어제의 날씨입니다~ 어제 %s 의 최저기온은 %s 도 최고 기온은 %s 였습니다. 날씨였습니다.", location, tMin, tMax);
		log.info(ddara);
		m.addAttribute("location", location);
		m.addAttribute("tMin", tMin);
		m.addAttribute("tMax", tMax);
		
//		return "redirect:/guest/wea";
	}			
	
	//약국 정보 불러오는 api 설정
	@RequestMapping("/pharmacy")	
	public void pharmacy(Model m){
		//// 우리나라 공공 api ////		
		//인코딩 인증키		
		String API_KEY = "QFOfiZ8YJEQdpbWKTs92CQy3%2BGIv8uusBFVx9FEd4A%2Fn9cxgi3F2E4lnC%2F%2FbUWtk01Gb5OYaHyxVqKfVARKBmQ%3D%3D";	
		String API_URL = "http://apis.data.go.kr/B552657/ErmctInsttInfoInqireService/getParmacyFullDown?pageNo=1&numOfRows=30&serviceKey=" + API_KEY;
		
	    RestTemplate restTemplate = new RestTemplate();        
	            
	    // URI로 변환
	    URI uri;
	    try {        
	        uri = new URI(API_URL);    
	    } catch (URISyntaxException e) {        
	        e.printStackTrace();    
	        return; // 예외 발생 시 종료
	    }        

	    // RestTemplate을 사용하여 API에 GET 요청을 보내고 응답을 받습니다.
	    String result = restTemplate.getForObject(uri, String.class);
	 // UTF-8로 디코딩하여 문자열을 제대로 표시
	    String decodedResult = new String(result.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
		log.info("====== 잘 나오나? "+decodedResult);
		PharmacyDto ph = restTemplate.getForObject(uri, PharmacyDto.class); // 자기 클래스로 바꾸시오..
		String dutyName = ph.response.body.items.item.dutyName;
		String dutyAddr= ph.response.body.items.item.dutyAddr;
		
		//월요일 진료시간(c)
		int dutyTime1c = ph.response.body.items.item.dutyTime1c;
		//화요일 진료시간(c)
		int dutyTime2c = ph.response.body.items.item.dutyTime2c;
		//수요일 진료시간(c)
		int dutyTime3c = ph.response.body.items.item.dutyTime3c;
		//목요일 진료시간(c)
		int dutyTime4c = ph.response.body.items.item.dutyTime4c;
		//금요일 진료시간(c)
		int dutyTime5c = ph.response.body.items.item.dutyTime5c;
		//토요일 진료시간(c)
		int dutyTime6c = ph.response.body.items.item.dutyTime6c;
		//일요일 진료시간(c)
		int dutyTime7c = ph.response.body.items.item.dutyTime7c;
		//공휴일 진료시간(c)
		int dutyTime8c = ph.response.body.items.item.dutyTime8c;

//////ssssssss
		
		//월요일 진료시간(s)
		String dutyTime1s = ph.response.body.items.item.dutyTime1s;
		//화요일 진료시간(s)
		String dutyTime2s = ph.response.body.items.item.dutyTime2s;
		//수요일 진료시간(s)
		String dutyTime3s = ph.response.body.items.item.dutyTime3s;
		//목요일 진료시간(s)
		String dutyTime4s = ph.response.body.items.item.dutyTime4s;
		//금요일 진료시간(s)
		String dutyTime5s = ph.response.body.items.item.dutyTime5s;
		//토요일 진료시간(s)
		String dutyTime6s = ph.response.body.items.item.dutyTime6s;
		//토요일 진료시간(s)
		int dutyTime7s = ph.response.body.items.item.dutyTime7s;
		//토요일 진료시간(s)
		int dutyTime8s = ph.response.body.items.item.dutyTime8s;
		//예외 설정(s)
		int dutyTime = ph.response.body.items.item.dutyTime;
		//약국 세부 사항
		String dutyInf  = ph.response.body.items.item.dutyInf;


		//
//		String phar = String.format("==== json ==== : 약국 데이터 어제 %s 의 최저기온은 %s 도 최고 기온은 %s 였습니다. 날씨였습니다.", location, tMin, tMax);
//		log.info(phar);
		m.addAttribute("dutyName", dutyName);
		m.addAttribute("dutyAddr", dutyAddr);
		m.addAttribute("dutyTime1c", dutyTime1c);
		m.addAttribute("dutyTime2c", dutyTime2c);
		m.addAttribute("dutyTime3c", dutyTime3c);
		m.addAttribute("dutyTime4c", dutyTime4c);
		m.addAttribute("dutyTime5c", dutyTime5c);
		m.addAttribute("dutyTime6c", dutyTime6c);
		m.addAttribute("dutyTime7c", dutyTime7c);
		m.addAttribute("dutyTime8c", dutyTime8c);
		
		m.addAttribute("dutyTime1s", dutyTime1s);
		m.addAttribute("dutyTime2s", dutyTime2s);
		m.addAttribute("dutyTime3s", dutyTime3s);
		m.addAttribute("dutyTime4s", dutyTime4s);
		m.addAttribute("dutyTime5s", dutyTime5s);
		m.addAttribute("dutyTime6s", dutyTime6s);
		m.addAttribute("dutyTime7s", dutyTime7s);
		m.addAttribute("dutyTime8s", dutyTime8s);
		m.addAttribute("dutyTime", dutyTime);
		m.addAttribute("dutyInf", dutyInf);
	}
	
}

 

pharmacy.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:set var="cp" value="${pageContext.request.contextPath}" />
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	약국 데이터 불러왔어요.
	<!-- dutyName-기관명 -->
	<!-- dutyAddr-주소 -->
	<!-- dutyEtc-비고(외래 진료 시간) -->

	기관명:${dutyName} 주소:${dutyAddr}
	<hr>
	월요일 진료 시간(c):${dutyTime1c}
	<hr>
	화요일 진료 시간(c):${dutyTime2c}
	<hr>
	수요일 진료 시간(c):${dutyTime3c}
	<hr>
	목요일 진료 시간(c):${dutyTime4c}
	<hr>
	금요일 진료 시간(c):${dutyTime5c}
	<hr>
	토요일 진료 시간(c):${dutyTime6c}
	<hr>
	일요일 진료 시간(c):${dutyTime7c}
	<hr>
	공휴일 진료 시간(c):${dutyTime8c}
	<hr>
	
	
	월요일 진료 시간(s):${dutyTime1s}
	<hr>
	화요일 진료 시간(s):${dutyTime2s}
	<hr>
	수요일 진료 시간(s):${dutyTime3s}
	<hr>
	목요일 진료 시간(s):${dutyTime4s}
	<hr>
	금요일 진료 시간(s):${dutyTime5s}
	<hr>
	토요일 진료 시간(s):${dutyTime6s}
	<hr>
	일요일 진료 시간(s):${dutyTime7s}
	<hr>
	공휴일 진료 시간(s):${dutyTime8s}
	<hr>
	공휴일 진료 시간(s) 예외:${dutyTime}
	<hr>
	약국 정보:${dutyInf}
	<hr>
	
	<a href="${cp}/">뒤로가기</a>
</body>
</html>

 

 

[결론]
 
* JSON 기초 강의 수강

 

*작업파일


 0305
1) JSON 기초