IOS 환경에서 발생하는 에러 및 해결 방안

JOO·2022년 1월 23일
0

실전프로젝트

목록 보기
9/12

IOS 환경에서 발생하는 에러 및 해결 방안

실전프로젝트를 진행하면서 여러가지 에러들을 만났지만 가장 해결하기 어려웠던 에러는 안드로이드나 윈도우 환경에서는 잘 작동되지만 IOS환경에서 발생하던 에러들이었다.

1. JWT token이 서버로 전달될 때 ';'이 간헐적으로 생성되는 문제 및 해결 방안

개발을 진행할 때 JWT token을 통해 해당 유저의 권한을 판별하는 코드들이 있다. 백앤드 쪽에서 auth_middleware를 통해 유저의 정보를 판단한 후 권한 유무를 확인하게 되는데, 이때 제대로된 JWT token이 아니라면 '토큰이 유효하지 않습니다.' 라는 메세지와 http status 401 code를 클라이언트 쪽으로 리턴한다.

아래 코드는 auth_middleware 코드

const needLogin = (req, res, next) => {
  try {
    const { authorization } = req.headers;
    if (!authorization) {
      throw customizedError("토큰이 유효하지 않습니다.", 401);
    }
    let [tokenType, tokenValue] = authorization.split(" ");
    console.log(tokenType, tokenValue);
    if (tokenType !== "Bearer") {
      throw customizedError("토큰이 유효하지 않습니다.", 401);
    }
    console.log(tokenType, tokenValue);
    const result = jwt.verify(tokenValue, JWT_SECRET, (error, decoded) => {
      if (error) {
        throw customizedError("토큰이 유효하지 않습니다.", 401);
      }
      return decoded;
    });
    const { userId } = result;
    User.findOne({ where: { userId: userId } }).then((user) => {
      res.locals.user = user;
      next();
    });
  } catch (error) {
    next(error);
  }
};

안드로이드나 윈도우 환경에서는 문제없이 작동되던 코드가 IOS환경에서 요청을 하게되면 아래 코드에서 계속 에러가 발생했다.

const result = jwt.verify(tokenValue, JWT_SECRET, (error, decoded) => {
      if (error) {
        throw customizedError("토큰이 유효하지 않습니다.", 401);
      }

확인해보니 IOS 환경에서 JWT token이 서버로 넘어올 때 가끔 토큰값 뒤에 ';' 세미콜론이 찍혀서 들어오는 경우가 있었다. 모든 IOS 환경에서 발생하는 에러는 아니었고 특정 IOS환경에서만 발생하던 문제였기 때문에 명확한 에러 발생 원인은 찾을 수 없었다.

해결방안으로는 auth_middleware에 도달한 JWT token 값 맨뒤에 ';'이 있다면 없애주는 조건을 넣어서 해결했다.

 if (tokenValue[tokenValue.length - 1] === ";") {
      tokenValue = tokenValue.split(";")[0];
    }

2. 안드로이드, 윈도우 환경에서 업로드한 녹음파일 IOS 환경에서 재생 안되는 현상. (+ IOS환경 녹음파일 1초만 녹음되는 현상)

프로젝트 특성 상 녹음파일 업로드와 재생이 가장 핵심 기능인데, 안드로이드나 윈도우 환경에서 업로드한 녹음파일이 IOS환경에서는 재생이 안되는 에러가 있었다.
(반대로 IOS환경에서 업로드한 녹음파일은 안드로이드나 윈도우 환경에서 이상없이 재생되었다..)

이를 해결 하기 위해 ffmpeg라는 프로그램을 통해 서버로 전달된 파일을 mp3 파일로 컨버팅 한 후 업로드하는 기능을 추가했다.

아래는 ffmpeg 적용한 코드이다.


const convertAndSaveS3 = (ranFileName, location) => {
  const key = location.split(".com/")[1];
  let params = { Bucket: S3_BUCKET_NAME, Key: key };
  return new Promise((resolve, reject) => {
    ffmpeg()
      .input(location)
      .toFormat("mp3")
      .output(ranFileName)
      .on("error", (err) => {
        console.log("An error occurred: " + err.message);
      })
      .on("progress", (progress) => {
        console.log("Processing: " + progress.targetSize + " KB converted");
      })
      .on("end", () => {
        console.log("Processing finished !");
        const fileContent = fs.readFileSync(ranFileName);
        params.Key = `tracks/${ranFileName}`;
        params.Body = fileContent;
        s3.putObject(params, function (err, data) {
          console.log(err, data);
        });
        deleteMp3(ranFileName);
        console.log("업로드!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
        setTimeout(() => {
          console.log("work!");
          resolve();
        }, 500);
      })
      .run();
  });
};

이렇게 mp3파일로 컨버팅 후 업로드하게 되면 IOS 환경에서도 재생이 잘됐지만, IOS환경에서 녹음한 파일이 컨버팅 되는 순간 무조건 1초짜리로 짤리는 현상이 발생됐다.

원인은 알 수 없었지만 IOS환경에서만 발생하는 문제였기 때문에 클라이언트 쪽에서 유저의 접속 디바이스를 판단해 서버로 전달해주고, 만약 아이폰 유저라면 컨버팅을 진행하지 않고, 아이폰 유저가 아니라면 컨버팅을 진행해서 업로드하는 방식으로 문제를 해결하였다.

3. IOS환경에서 접속한 유저가 쿠키에 접근하는 동작을 수행할 때 차단되는 현상

프론트앤드 분들이 로그아웃을 구현할 때 쿠키에 저장되어있던 token을 삭제하는 방식으로 구현했었다. 이렇게 구현하였을 때 역시 안드로이드나 윈도우 환경에서는 아무 문제없이 다시 서비스 이용이 가능했지만, IOS환경에서는 다시 쿠키에 토큰을 저장해야하는 로그인과 같은 기능이 작동되지 않는 문제가 있었다.
(이런 경우에 DB에 저장된 유저정보를 삭제하고 아이폰에 있는 크롬브라우저의 캐시를 삭제해야지만 다시 서비스 이용이 가능했다.)

이번 에러는 콘솔로 확인할 수가 없어서 팀원들끼리 이런저런 가설을 생각해본 결과 IOS는 철저한 보안으로 유명하기 때문에 (외부 접근을 다 막아놓고 애플 생태계에서만 살아가기로 유명하기 때문에) 쿠키에 접근해서 동작을 수행하는 것 자체가 문제가 되는게 아닐까 라는 생각을 했다.

이 가설을 검증하기 위해 쿠키에 저장했던 토큰 정보를 localstorage에 저장해서 사용했더니 IOS환경에서도 전혀 문제없이 작동되었다.

도대체 왜 IOS환경에서만 이렇게 에러가 나는지 모르겠다.

profile
개발공부 기록

0개의 댓글